mappix/mappix-gpxreader.c

345 lines
9.4 KiB
C
Raw Normal View History

/*
* 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;
}