/*
* navsys - A Gps/music player for gnu/linux embedded platforms
*
* File describing the basic map information structures
*
* Copyright (C) 2002, Amaury Jacquot
*
* Amaury Jacquot <sxpert@esitcom.org>
*
* This program is free software, distributed under the terms of
* the GNU General Public License
*/
#include <stdio.h>
#include <math.h>
#include <string.h>
#include "tigermap.h"
TigerMap* tigermap_new(void) {
TigerMap* temp;
temp=(TigerMap*)malloc(sizeof(TigerMap));
temp->min=position_new();
temp->min->longitude=180;
temp->min->latitude=90;
temp->max=position_new();
temp->max->longitude=-180;
temp->max->latitude=-90;
temp->features=g_hash_table_new(g_int_hash,g_int_equal);
temp->landmarks=g_hash_table_new(g_int_hash,g_int_equal);
temp->polygons=g_hash_table_new(g_int_hash,g_int_equal);
return temp;
}
TigerMapFeature* tigermap_feature_new(void) {
TigerMapFeature* temp;
temp=(TigerMapFeature*)malloc(sizeof(TigerMapFeature));
temp->featureID=0;
temp->name=NULL;
temp->county_boundary=FALSE;
temp->begin=NULL;
temp->end=NULL;
temp->points=NULL;
return temp;
}
TigerMapLandmark* tigermap_landmark_new(void) {
TigerMapLandmark* temp;
temp=(TigerMapLandmark*)malloc(sizeof(TigerMapLandmark));
temp->landmarkID=0;
temp->name=NULL;
temp->featuretype=0;
temp->polygons=NULL;
return temp;
}
TigerMapLine* tigermap_line_new(void) {
TigerMapLine* temp;
temp=(TigerMapLine*)malloc(sizeof(TigerMapLine));
temp->feature=NULL;
temp->reversed=FALSE;
return temp;
}
TigerMapPolygon* tigermap_polygon_new(void) {
TigerMapPolygon* temp;
temp=(TigerMapPolygon*)malloc(sizeof(TigerMapPolygon));
temp->polygonID=0;
temp->not_closed=FALSE;
temp->has_hole=FALSE;
temp->featuretype=0;
temp->lines=g_hash_table_new(g_int_hash,g_int_equal);
temp->lines_sorted=NULL;
temp->cutout = NULL;
temp->large_hole=NULL;
return temp;
}
void tigermap_add_feature(TigerMap* md,TigerMapFeature* mr) {
g_hash_table_insert(md->features,&(mr->featureID),mr);
}
void tigermap_add_landmark(TigerMap* md,TigerMapLandmark* ml) {
g_hash_table_insert(md->landmarks,&(ml->landmarkID),ml);
}
void tigermap_add_polygon(TigerMap* md,TigerMapPolygon* pol) {
g_hash_table_insert(md->polygons,&(pol->polygonID),pol);
}
void tigermap_add_polygon_to_landmark(TigerMap* md,TigerMapPolygon* pol,int landmarkID) {
TigerMapLandmark* ml;
ml=g_hash_table_lookup(md->landmarks,&landmarkID);
pol->featuretype=ml->featuretype;
ml->polygons=g_list_append(ml->polygons,pol);
}
void tigermap_feature_insert_point(TigerMap* md,gint featureID,Position* p) {
TigerMapFeature* mr;
mr=g_hash_table_lookup(md->features,&featureID);
mr->points=g_list_append(mr->points,p);
}
void tigermap_feature_dump(TigerMapFeature* mr) {
GList* temp;
Position* pos;
fprintf(stderr,"%d %d ",mr->featureID,mr->featuretype);
fprintf(stderr,"'%s'\n",mr->name);
temp=mr->points;
while (temp) {
pos=(Position*)temp->data;
fprintf(stderr,"( %f , %f )\n",pos->longitude,pos->latitude);
temp=temp->next;
}
}
int tigermap_parse_int(char* buffer) {
int val=0,i;
char c;
for(i=0;i<strlen(buffer);i++) {
c=buffer[i];
if ((c>='0')&&(c<='9')) val=val*10+(c-'0');
else if (c!=' ') {
fprintf(stderr,"error while parsing value '%s', aborting program\n",buffer);
exit(1);
}
}
return val;
}
double tigermap_parse_coordinate(char* buffer,int begin,int len) {
double val=0;
int i;
char c;
char* temp;
while (buffer[begin]==' ') {
begin++;
len--;
}
temp=(char*)malloc(len+1);
bzero(temp,len+1);
strncpy(temp,&(buffer[begin]),len);
for(i=1;i<strlen(temp);i++) {
c=temp[i];
if ((c>='0')&&(c<='9')) val=val*10+(c-'0');
else if (c!=' ') {
fprintf(stderr,"error while parsing value '%s', aborting program\n",temp);
exit(1);
}
}
if (temp[0]=='-') val=-val;
val=val/1000000;
return val;
}
void tigermap_remove_blanks(char* buffer) {
int i;
for(i=strlen(buffer)-1;i>=0;i--) {
if (buffer[i]!=' ') break;
buffer[i]='\0';
}
}
void tigermap_check_coordinates(TigerMap* md,Position* pos) {
md->min->longitude=double_min(md->min->longitude,pos->longitude);
md->min->latitude=double_min(md->min->latitude,pos->latitude);
md->max->longitude=double_max(md->max->longitude,pos->longitude);
md->max->latitude=double_max(md->max->latitude,pos->latitude);
}
/*
* sizes are larger to allow for padding at end of line and
* line break characters
*/
const int RT1len=240;
const int RT2len=220;
const int RT7len=80;
const int RT8len=40;
const int RTIlen=60;
const int RTSlen=130;
void tigermap_add_first_and_last_point(gpointer key,gpointer value,gpointer userdata) {
TigerMapFeature* mr;
mr=(TigerMapFeature*)value;
mr->points=g_list_prepend(mr->points,mr->begin);
mr->points=g_list_append(mr->points,mr->end);
}
static gboolean tigermap_copy_line_to_lines_sorted(gpointer key,gpointer value,gpointer user_data) {
TigerMapPolygon* pol;
TigerMapFeature* mf;
TigerMapLine* ml;
pol=(TigerMapPolygon*)user_data;
mf=(TigerMapFeature*)value;
ml=tigermap_line_new();
ml->feature=mf;
pol->lines_sorted=g_list_append(pol->lines_sorted,ml);
/* remove the line from the hash table */
return TRUE;
}
void tigermap_show_line_info(TigerMapLine* ml) {
if (!(ml->reversed)) fprintf(stderr,"line s -> ( %f , %f ) ( %f , %f ) <- %d\n",
ml->feature->begin->longitude,
ml->feature->begin->latitude,
ml->feature->end->longitude,
ml->feature->end->latitude,
ml->feature->featureID);
else fprintf(stderr,"line r -> ( %f , %f ) ( %f , %f ) <- %d\n",
ml->feature->end->longitude,
ml->feature->end->latitude,
ml->feature->begin->longitude,
ml->feature->begin->latitude,
ml->feature->featureID);
}
void tigermap_dump_polygon (TigerMapPolygon* pol) {
GList* temp;
int i = 0;
fprintf(stderr,"polygonID : %d\nfeature type %d\n",pol->polygonID,pol->featuretype);
temp=pol->lines_sorted;
while (temp) {
tigermap_show_line_info((TigerMapLine*)temp->data);
i++;
temp=temp->next;
}
fprintf(stderr,"total : %d lines\n",i);
temp=pol->large_hole;
while (temp) {
tigermap_show_line_info((TigerMapLine*)temp->data);
i++;
temp=temp->next;
}
fprintf(stderr,"total : %d lines\n",i);
}
static void tigermap_order_lines_in_polygon(gpointer key,gpointer value,gpointer user_data) {
TigerMapPolygon* pol;
GList* sortlist;
GList* temp;
GList* polygonlist;
TigerMapLine* ml;
Position* pfirst;
Position* plast;
Position* p;
polygonlist=NULL;
pol=(TigerMapPolygon*)value;
pol->not_closed=FALSE;
/*
* first step, copying the contents of the lines hash table to lines_sorted
* that is, if the lines_sorted value is NULL (it should ;-)
*/
if (!(pol->lines_sorted))
g_hash_table_foreach_remove(pol->lines,tigermap_copy_line_to_lines_sorted,pol);
/*
show_line_info(ml);
*/
temp=pol->lines_sorted;
/*
* remove the islands and other self-enclosed areas
*/
sortlist=NULL;
while (temp) {
ml=(TigerMapLine*)temp->data;
if ((ml->feature->begin->longitude==ml->feature->end->longitude)&&
(ml->feature->begin->latitude==ml->feature->end->latitude)) {
pol->cutout=g_list_append(pol->cutout,ml);
} else sortlist=g_list_append(sortlist,ml);
temp=temp->next;
}
g_list_free(pol->lines_sorted);
pol->lines_sorted=sortlist;
sortlist=NULL;
if (!pol->lines_sorted) {
/*
* if there is no more lines to sort, the polygon contains only
* one line, thus, put the line back as the lines_sorted
*/
pol->lines_sorted=pol->cutout;
pol->cutout=NULL;
return;
}
/*
* next, sort the lines_sorted list
*/
ml=pol->lines_sorted->data;
pfirst=ml->feature->begin;
sortlist=g_list_append(NULL,ml);
pol->lines_sorted=g_list_remove(pol->li