345 lines
9.4 KiB
C
345 lines
9.4 KiB
C
![]() |
/*
|
||
|
* gpxreader
|
||
|
* read GPX files
|
||
|
*
|
||
|
* Copyright (C) 2006, 2007 Nils Faerber <nils.faerber@kernelconcepts.de>
|
||
|
*
|
||
|
*
|
||
|
* 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 <stdio.h>
|
||
|
#include <expat.h>
|
||
|
#include <string.h>
|
||
|
|
||
|
#include <glib.h>
|
||
|
#include <math.h>
|
||
|
|
||
|
#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;
|
||
|
}
|