#include "arrayList.h"
#include "StringHashTable.h"
#include "nextField.h"
#include "GISParse.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#define MAX_LINE_LENGTH 500
#define PI 3.14159265358979323846
#define RADIUS 6371.0088
/**
* Combines both name and state to create one string in order to
* pass that new string into a the hastable as a key
*/
char *create_key(char *name, char *state)
{
char *key = calloc(strlen(name) + strlen(state) + 1, sizeof(char));
strcpy(key, name);
strcpy(key + strlen(name), state);
return key;
}
char *get_name_and_state(char *line)
{
int i = -1;
char *name, *state, *temp;
while (++i < 4)
{
switch (i)
{
case 0:;
temp = nextField(line);
break;
case 1:;
name = nextField(NULL);
break;
case 3:;
state = nextField(NULL);
break;
default:
temp = nextField(NULL);
break;
}
}
free(temp);
return create_key(name, state);
}
/**
* Given an array of offsets, this method retrives the
* first 5 fields of each record at the specified offset
*/
char **get_details_of(FILE *gis, uint32_t offset)
{
char **details = calloc(9, sizeof(char *)),
*line = calloc(MAX_LINE_LENGTH + 1, sizeof(char)),
*f = NULL;
fseek(gis, offset, SEEK_SET);
fgets(line, MAX_LINE_LENGTH + 1, gis);
int x = -1, i = 0;
while (++x < 11)
{
if (x == 0)
details[i++] = nextField(line);
else if (x < 4 || x == 5 || x >= 7)
details[i++] = nextField(NULL);
else
f = nextField(NULL);
}
free(line);
free(f);
return details;
}
/**
* Gets the longitude and lattitude field of a record at a
* specified offset
*/
char **get_dec_lat_and_long(uint32_t offset, FILE *gis)
{
char **lat_and_long = calloc(2, sizeof(char *)),
*line = calloc(MAX_LINE_LENGTH + 1, sizeof(char)),
*f = NULL;
fseek(gis, offset, SEEK_SET);
fgets(line, MAX_LINE_LENGTH + 1, gis);
int x = -1, i = 0;
while (++x < 11)
{
if (x == 0)
f = nextField(line);
else if (x >= 9)
lat_and_long[i++] = nextField(NULL);
else
f = nextField(NULL);
}
free(line);
free(f);
return lat_and_long;
}
/**
* Alters the string of longitude or lattitude
* found within the GIS file to the desired format
* as specified within the documentation
*/
char **get_readable_lat_and_long(uint32_t offset, FILE *gis)
{
char **dms = calloc(10, sizeof(char *)),
*line = calloc(MAX_LINE_LENGTH + 1, sizeof(char)),
*f = NULL;
fseek(gis, offset, SEEK_SET);
fgets(line, MAX_LINE_LENGTH + 1, gis);
int x = -1, i = 0;
while (++x < 11)
{
if (x == 0)
f = nextField(line);
else if (x == 1 || x == 3)
dms[i++] = nextField(NULL);
else if (x == 7)
{
f = nextField(NULL);
char *d = calloc(3, sizeof(char)),
*m = calloc(3, sizeof(char)),
*s = calloc(3, sizeof(char)),
*dir = calloc(6, sizeof(char));
strncpy(d, f, 2);
strncpy(m, f + 2, 2);
strncpy(s, f + 4, 2);
strncpy(dir, f + 6, 1);
if (!(strcmp(dir, "N")))
dir = "North";
else
dir = "South";
dms[2] = d;
dms[3] = m;
dms[4] = s;
dms[5] = dir;
}
else if (x == 8)
{
f = nextField(NULL);
char *d = calloc(4, sizeof(char)),
*m = calloc(3, sizeof(char)),
*s = calloc(3, sizeof(char)),
*dir = calloc(5, sizeof(char));
strncpy(d, f, 3);
strncpy(m, f + 3, 2);
strncpy(s, f + 5, 2);
strncpy(dir, f + 7, 1);
if (!(strcmp(dir, "W")))
dir = "West";
else
dir = "East";
dms[6] = d;
dms[7] = m;
dms[8] = s;
dms[9] = dir;
}
else
f = nextField(NULL);
}
free(line);
free(f);
return dms;
}
/**
* Calculates the distance between 2 records when
* given the offset of both records
*/
double find_distance_between(uint32_t offset1, uint32_t offset2, FILE *gis)
{
char **d1 = get_dec_lat_and_long(offset1, gis),
**d2 = get_dec_lat_and_long(offset2, gis);
double lat1 = atof(d1[0]) * (PI / 180.0),
lat2 = atof(d2[0]) * (PI / 180.0),
long1 = atof(d1[1]),
long2 = atof(d2[1]),
centralAngle = acos((sin(lat1) * sin(lat2)) + (cos(lat1) * cos(lat2) * cos((long2 - long1) * (PI / 180.0)))),
distance = ((RADIUS * centralAngle));
free(d1);
free(d2);
return distance;
}