/* * gpxreader * read GPX files * * Copyright (C) 2006, 2007 Nils Faerber * * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * */ #include #include #include #include #include #include "mappix.h" #include "geo-tools.h" #define BUFFSIZE 8192 /* oh well ... we have to remember in which tag we are... */ #define CurrentIsTrackMask (guint)0x000000ff #define CurrentIsTrack (guint)1 << 0 #define CurrentIsTrackName (guint)1 << 1 #define CurrentIsTrackType (guint)1 << 2 #define CurrentIsTrackShow (guint)1 << 3 #define CurrentIsTrackpointMask (guint)0x0000ff00 #define CurrentIsTrackpoint (guint)1 << 8 #define CurrentIsTrackpointEle (guint)1 << 9 #define CurrentIsTrackpointNRSAT (guint)1 << 10 #define CurrentIsTrackpointHDOP (guint)1 << 11 #define CurrentIsTrackpointPDOP (guint)1 << 12 #define CurrentIsWaypointMask (guint)0x00ff0000 #define CurrentIsWaypoint (guint)1 << 16 #define CurrentIsWaypointEle (guint)1 << 17 #define CurrentIsWaypointName (guint)1 << 18 /* for passing data around the callbacks */ typedef struct { mapwin *Mapper; guint current; GList *track; GList *waypoints; trackdata *tdata; waypoint *wpt; gchar *fname; gchar *tname; gboolean show; tracktype type; } udt; void finish_track(udt *ltdata) { track_head *new_track; if (ltdata->track != NULL) { /* done reading the track */ new_track = (track_head *)malloc(sizeof(track_head)); new_track->xmax = -1; new_track->ymax = -1; new_track->xmin = WORLD_SIZE_UNITS; new_track->ymin = WORLD_SIZE_UNITS; new_track->track = g_list_reverse(ltdata->track); new_track->show = ltdata->show; new_track->type = ltdata->type; if (ltdata->tname != NULL) new_track->name = g_strdup(ltdata->tname); else new_track->name = g_path_get_basename(ltdata->fname); // fprintf(stderr,"track '%s' has bbox latmin=%lf longmin=%lf latmax=%lf longmax=%lf\n", new_track->name, new_track->latmin, new_track->longmin, new_track->latmax, new_track->longmax); track_add_new_to_main(ltdata->Mapper, new_track); } } static void XMLCALL startElement(void *userData, const char *name, const char **atts) { udt *ud = (udt *)userData; gdouble rlat, rlong; if (strncmp(name, "trkpt", 5) == 0) { ud->tdata = (trackdata *)malloc(sizeof(trackdata)); memset(ud->tdata, 0, sizeof(trackdata)); if (ud->tdata != NULL) { ud->current |= CurrentIsTrackpoint; rlat = g_ascii_strtod (atts[1], NULL); rlong = g_ascii_strtod (atts[3], NULL); latlon2unit(rlat, rlong, ud->tdata->unitx, ud->tdata->unity); ud->tdata->selected = FALSE; } //fprintf(stderr,"lat=%lf long=%lf\n", tdata->latitude, tdata->longitude); } else if (strncmp(name, "trkseg", 6) == 0) { /* not yet supported */ } else if (strncmp(name, "trk", 3) == 0) { // g_message("new track"); ud->current |= CurrentIsTrack; if (ud->tname != NULL) { g_free(ud->tname); ud->tname = NULL; }; ud->type = UNKNOWN; ud->show = FALSE; } else if (strncmp(name, "wpt", 3) == 0) { ud->wpt = (waypoint *)malloc(sizeof(waypoint)); memset(ud->wpt, 0, sizeof(waypoint)); if (ud->wpt != NULL) { ud->current |= CurrentIsWaypoint; rlat = g_ascii_strtod (atts[1], NULL); rlong = g_ascii_strtod (atts[3], NULL); latlon2unit(rlat, rlong, ud->wpt->unitx, ud->wpt->unity); ud->wpt->name = NULL; } } else { // fprintf(stderr,"xml unkn: '%s'\n", name); if (ud->current & CurrentIsTrackpoint) { //fprintf(stderr, "is trackpoint\n"); if (strncmp(name, "ele", 3) == 0) ud->current |= CurrentIsTrackpointEle; if (strncmp(name, "sat", 3) == 0) ud->current |= CurrentIsTrackpointNRSAT; if (strncmp(name, "hdop", 4) == 0) ud->current |= CurrentIsTrackpointHDOP; if (strncmp(name, "pdop", 4) == 0) ud->current |= CurrentIsTrackpointPDOP; } else if (ud->current & CurrentIsWaypoint) { //fprintf(stderr, "is waypoint\n"); if (strncmp(name, "name", 4) == 0) ud->current |= CurrentIsWaypointName; if (strncmp(name, "ele", 3) == 0) ud->current |= CurrentIsWaypointEle; } else if (ud->current & CurrentIsTrack) { //fprintf(stderr, "is track\n"); if (strncmp(name, "name", 4) == 0) { ud->current |= CurrentIsTrackName; //fprintf(stderr,"name start\n"); } if (strncmp(name, "type", 4) == 0) { ud->current |= CurrentIsTrackType; //fprintf(stderr,"type start\n"); } if (strncmp(name, "show", 4) == 0) { ud->current |= CurrentIsTrackShow; //fprintf(stderr,"show start\n"); } } } } static void XMLCALL endElement(void *userData, const char *name) { udt *ud = (udt *)userData; //mapwin *Mapper = (mapwin *)userData; //fprintf(stderr,"xml endelem: '%s'\n", name); /* trackpoints */ if (strncmp(name, "trkpt", 5) == 0) { ud->current &= ~CurrentIsTrackpointMask; ud->track = g_list_prepend(ud->track, ud->tdata); } else if (strncmp(name, "trkseg", 6) == 0) { } else if (strncmp(name, "trk", 3) == 0) { finish_track(ud); ud->current = 0; ud->track = NULL; ud->current &= ~CurrentIsTrackMask; } if (ud->current & CurrentIsTrackName) { if (strncmp(name, "name", 4) == 0) { //fprintf(stderr, "bnamee 0x%04x ", ud->current); ud->current ^= CurrentIsTrackName; //fprintf(stderr, "anamee 0x%04x\n", ud->current); } } if (ud->current & CurrentIsTrackpoint) { if (strncmp(name, "ele", 3) == 0) ud->current ^= CurrentIsTrackpointEle; } /* waypoints */ if (strncmp(name, "wpt", 3) == 0) { ud->current &= ~CurrentIsWaypointMask; //ud->Mapper->waypoints = g_list_prepend(ud->Mapper->waypoints, ud->wpt); ud->waypoints = g_list_prepend(ud->waypoints, ud->wpt); } if (ud->current & CurrentIsWaypoint) { if (strncmp(name, "name", 4) == 0) ud->current ^= CurrentIsWaypointName; } if (ud->current & CurrentIsTrack) { if (CurrentIsTrackType && strncmp(name, "type", 4) == 0) ud->current ^= CurrentIsTrackType; if (CurrentIsTrackShow && strncmp(name, "show", 4) == 0) ud->current ^= CurrentIsTrackShow; } } static void XMLCALL CharData (void *userData, const XML_Char *s, int len) { udt *ud = (udt *)userData; gchar *tmp; /* string is not null terminated */ tmp = (gchar *)malloc(2+len*sizeof(gchar)); memcpy(tmp,s,len); tmp[len] = 0; // fprintf(stderr,"char-data: '%s'\n", tmp); /* track head */ if (ud->current & CurrentIsTrackName) { if (ud->tname == NULL) ud->tname = g_strdup(tmp); else ud->tname = g_strconcat(ud->tname, tmp, NULL); } if (ud->current & CurrentIsTrackType) { //fprintf(stderr, "type = '%s'\n", tmp); gint val; sscanf(tmp, "%d", &val); ud->type = val; } if (ud->current & CurrentIsTrackShow) { //fprintf(stderr, "show = '%s'\n", tmp); if (len > 0 && g_ascii_strncasecmp("true", tmp, 4)==0 ) ud->show = TRUE; else ud->show = FALSE; } /* trackpoints */ if (ud->current & CurrentIsTrackpointEle) { sscanf(tmp, "%f", &ud->tdata->elevation); } if (ud->current & CurrentIsTrackpointNRSAT) { gint val; sscanf(tmp, "%d", &val); ud->tdata->nrsat = val; } if (ud->current & CurrentIsTrackpointHDOP) { sscanf(tmp, "%f", &ud->tdata->hdop); } if (ud->current & CurrentIsTrackpointPDOP) { sscanf(tmp, "%f", &ud->tdata->pdop); } /* waypoints */ if (ud->current & CurrentIsWaypointName) { if (ud->wpt->name == NULL) ud->wpt->name = g_strdup(tmp); else ud->wpt->name = g_strconcat(ud->wpt->name, tmp, NULL); } if (ud->current & CurrentIsWaypointEle) { sscanf(tmp, "%f", &ud->wpt->elevation); } free(tmp); } #ifdef DEBUG_WP void print_waypoints(gpointer data, gpointer user_data) { waypoint *wpnt = (waypoint *)data; if (data != NULL) { fprintf(stderr,"wpt: lat=%lf long=%lf name='%s'\n", wpnt->unitx, wpnt->unity, wpnt->name); } } #endif gint gpxread(gchar *fname, mapwin *Mapper) { char buf[BUFFSIZE]; XML_Parser parser = XML_ParserCreate(NULL); int done; FILE *inpfile; udt ldata; // track_head *new_track; inpfile=fopen(fname, "r"); if (inpfile == NULL) return -1; ldata.fname = fname; ldata.current = 0; ldata.Mapper = Mapper; ldata.track = NULL; ldata.tname = NULL; ldata.waypoints = NULL; XML_SetUserData(parser, &ldata); XML_SetElementHandler(parser, startElement, endElement); XML_SetCharacterDataHandler(parser, CharData); do { size_t len = fread(buf, 1, sizeof(buf), inpfile); done = len < sizeof(buf); if (XML_Parse(parser, buf, len, done) == XML_STATUS_ERROR) { fprintf(stderr, "%s at line %d\n", XML_ErrorString(XML_GetErrorCode(parser)), XML_GetCurrentLineNumber(parser)); return -1; } } while (!done); XML_ParserFree (parser); fclose (inpfile); if (ldata.waypoints) { ldata.waypoints = g_list_reverse(ldata.waypoints); Mapper->waypoints = g_list_concat(Mapper->waypoints, ldata.waypoints); } #ifdef DEBUG_WP if (Mapper->waypoints != NULL) { g_list_foreach(Mapper->waypoints, print_waypoints, NULL); } #endif return 0; }