#include "arrayList.h" #include "StringHashTable.h" #include "nextField.h" #include "GISParse.h" #include #include #include #include #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; }