backup commit, formerly hosted on now inaccessible CVS

This commit is contained in:
Nicole Faerber 2021-05-25 00:07:57 +02:00
parent 316cc674e7
commit f15f603035
57 changed files with 6014 additions and 0 deletions

70
Makefile Normal file
View file

@ -0,0 +1,70 @@
#
# Copyright (C) 2006 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
#
# prefix for installation and search path (like icons)
PREFIX = /usr/local/
# for normal desktop GTK+
CCFLAGS = -Wall -O2 -g
GTKCFLAGS = `pkg-config --cflags gtk+-2.0`
SQLITECFLAGS = `pkg-config --cflags sqlite3`
CFLAGS = $(CCFLAGS) $(GTKCFLAGS) $(SQLITECFLAGS)
#CLDFLAGS =
GTKLDFLAGS = `pkg-config --libs gtk+-2.0`
SQLITELDFLAGS = `pkg-config --libs sqlite3`
## for Maemo/Hildon
#CCFLAGS = -Wall -Os -g -DHILDON
#GTKCFLAGS = `pkg-config --cflags gtk+-2.0` `pkg-config --cflags dbus-1`
#CFLAGS = $(CCFLAGS) $(GTKCFLAGS)
##CLDFLAGS =
#GTKLDFLAGS = `pkg-config --libs gtk+-2.0` -lhildonlgpl -losso
# no need to change anything below this line
# ------------------------------------------
.SUFFIXES: .d .c
CFLAGS += -MD -DPREFIX=\"$(PREFIX)\"
LDFLAGS = $(CLDFLAGS) $(GTKLDFLAGS) $(SQLITELDFLAGS)
MAPPIX_MEMBERS = mappix mappix-ui mappix-trackdraw mappix-gpxreader geo-dist \
mappix-trackedit mappix-trackrecord nmeap01 mappix-fileio \
mappix-waypoints
SOURCES = $(patsubst %,%.c,$(MAPPIX_MEMBERS))
OBJS = $(patsubst %,%.o,$(MAPPIX_MEMBERS))
DEPS = $(patsubst %,%.d,$(MAPPIX_MEMBERS))
all: mappix
mappix: $(OBJS)
$(CC) -o $@ $^ $(LDFLAGS)
clean:
rm -f *.o *.d mappix
-include $(DEPS)

74
NOTES Normal file
View file

@ -0,0 +1,74 @@
GIOChannel* g_io_channel_unix_new (int fd);
g_io_channel_set_encoding() function with NULL
GIOStatus g_io_channel_set_encoding (GIOChannel *channel,
const gchar *encoding,
GError **error);
guint g_io_add_watch (GIOChannel *channel,
GIOCondition condition,
GIOFunc func,
gpointer user_data);
gboolean (*GIOFunc) (GIOChannel *source,
GIOCondition condition,
gpointer data);
FALSE for end watch
Distance Point To Line:
(for Peuker)
d = |v^^.r| = (|(x_2-x_1)(y_1-y_0)-(x_1-x_0)(y_2-y_1)|)
/
(sqrt((x_2-x_1)^2+(y_2-y_1)^2))
- Ausgleichskurve
Ausgleichsrechnung
Interpolation
* Peuker line simplification
* auto-split tracks
if track has "gaps" then split track into two tracks.
A gap is when in a group of four points A, B, C, D the distance
from A to B and C to D is about the same but B to C is "a lot" more.
* spike filter
calculate mean deviation of all points of one track, then
delete all points that have deviation > delta,
recalculate mean deviation and redo
* mean of two tracks A, B
for each point of track A calculate distance to
track B and create a new point on a new track in the middle of the
distance. Next do the same process for all point of track B.
The new track lies in the middle between A and B.
Requires component-wise distance function with direction, i.e. e.g.
distance of point is x=-5 and y=3 to track.
* merge of two tracks
for each point of track A find nearest corresponding point on
track B, then calculate the average between both points and record
this as new track point
Repeat this for each point of track B.
Limit the averaging to a maximum distance.
SQLite tables
-------------
tracks track headers (streets, boundaries, rivers, ...)
idx pkey index
tid track id, id common to all data points of one track
name track-/streetname
ttype track-/streettype
latmin bbox latitude min
lonmin
latmax
lonmax
trackpts the actual track (all tracks combined in one table?)
lat
lon
ele
dtim
nrsat
hdop
vdop
pdop
points POIs
cities name, center location, "size"

39
README Normal file
View file

@ -0,0 +1,39 @@
Mappix
========
Boilerplate:
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
0. Introduction
---------------
Mappix is a to-become street map editor.
The idea is to record GPS data and edit and annotate the recorded tracks and
waypoints later. The longterm goal is to create a community of contributors.
References
----------
GPX Specification
http://www.topografix.com/GPX/1/1/

BIN
cities.db Normal file

Binary file not shown.

212
geo-dist.c Normal file
View file

@ -0,0 +1,212 @@
/*
* geo-dist
*
* Copyright (C) 2006 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
*
*/
/*
* Calculate distances on Earth surface given geogrphic locations
*/
#include <stdio.h>
#include <math.h>
#include "geo-dist.h"
// #define DEBUG
/*
* Earth models
* Remember, Earth is not a simple ball ;)
*/
struct ellipse_s {
char *name;
double a;
double invf;
};
static struct ellipse_s ellipse[] = {
{
"WGS84",
6378.137 / 1.852,
298.257223563
}, {
"NAD27",
6378.2064 / 1.852,
294.9786982138
}, {
"International",
6378.388 / 1.852,
297.0
}, {
"Krasovsky",
6378.245 / 1.852,
298.3
}, {
"Bessel",
6377.397155 / 1.852,
299.1528
}, {
"WGS72",
6378.135 / 1.852,
298.26
}, {
"WGS66",
6378.145 / 1.852,
298.25
}, {
"FAI sphere",
6371.0 / 1.852,
1000000000.
}
};
/*
* math helper
*/
#if 0
double atan2(double y, double x)
{
double out=0.;
if (x < 0) {
out = atan(y/x) + M_PI;
} else
if ((x > 0) && (y >= 0)) {
out = atan(y/x);
} else
if ((x > 0) && (y < 0)) {
out = atan(y/x) + 2. * M_PI;
} else
if ((x == 0) && (y > 0)) {
out = M_PI / 2.;
} else
if ((x == 0) && (y < 0)) {
out = 3. * M_PI / 2.;
} else
if ((x == 0) && (y == 0)) {
out= 0.;
}
return out;
}
#endif
/*
* glat1, glat2: geodetic latitude in radians, N positive
* glon1, glon2: geodetic longitude in radians E positive
* Coordinates in radians means
* 50°50.32N ^= 50 degree, 50 minutes and 32 seconds
* ^= 50 + (50 / 60) + (32 / 3600)
* ^= 50.84222
*
* returns: distance in nm (nautical miles), factor of 1.852 gives km
*/
double dist_ell(double glat1, double glon1, double glat2, double glon2, EllipsoidType e_model)
{
double a = ellipse[e_model].a; // 6378.137/1.852
double invf = ellipse[e_model].invf; // 298.257223563
double f = 1. / invf;
double r, tu1, tu2, cu1, su1, cu2, s1, b1, f1;
double x, sx, cx, sy=0, cy=0, y=0, sa, c2a=0, cz=0, e=0, c, d;
double EPS = 0.00000000005;
double s;
double l_iter=1;
double MAXITER=100;
#ifdef DEBUG
printf(" calc dist from %.04lf %.04lf to %.04lf %.04lf\n", glat1, glon1, glat2, glon2);
#endif
glat1 = (M_PI / 180.) * glat1;
glon1 = (M_PI / 180.) * -1. * glon1;
glat2 = (M_PI / 180.) * glat2;
glon2 = (M_PI / 180.) * -1. * glon2;
#ifdef DEBUG
printf("Using ellipse model %s (%.04lf %.04lf)\n", ellipse[e_model].name, a, invf);
printf(" calc dist from %.04lf %.04lf to %.04lf %.04lf\n", glat1, glon1, glat2, glon2);
#endif
if ((glat1+glat2==0.) && (fabs(glon1-glon2)==M_PI)) {
#ifdef DEBUG
printf("Warning: Course and distance between antipodal points is undefined\n");
#endif
glat1=glat1+0.00001; // allow algorithm to complete
}
if (glat1==glat2 && (glon1==glon2 || fabs(fabs(glon1-glon2)-2*M_PI) < EPS)) {
#ifdef DEBUG
printf("Points 1 and 2 are identical- course undefined\n");
#endif
return 0;
}
r = 1. - f;
tu1 = r * tan (glat1);
tu2 = r * tan (glat2);
cu1 = 1. / sqrt (1. + tu1 * tu1);
su1 = cu1 * tu1;
cu2 = 1. / sqrt (1. + tu2 * tu2);
s1 = cu1 * cu2;
b1 = s1 * tu2;
f1 = b1 * tu1;
x = glon2 - glon1;
d = x + 1.; // force one pass
while ((fabs(d - x) > EPS) && (l_iter < MAXITER)) {
l_iter = l_iter + 1;
sx = sin (x);
cx = cos (x);
tu1 = cu2 * sx;
tu2 = b1 - su1 * cu2 * cx;
sy = sqrt (tu1 * tu1 + tu2 * tu2);
cy = s1 * cx + f1;
y = atan2 (sy, cy);
sa = s1 * sx / sy;
c2a = 1. - sa * sa;
cz = f1 + f1;
if (c2a > 0.)
cz = cy - cz / c2a;
e = cz * cz * 2. - 1.;
c = ((-3. * c2a + 4.) * f + 4.) * c2a * f / 16.;
d = x;
x = ((e * cy * c + cz) * sy * c + y) * sa;
x = (1. - c) * x * f + glon2 - glon1;
}
x = sqrt ((1. / (r * r) - 1) * c2a + 1.);
x += 1.;
x = (x - 2.) / x;
c = 1. - x;
c = (x * x / 4. + 1.) / c;
d = (0.375 * x * x - 1.) * x;
x = e * cy;
s = ((((sy*sy*4.-3.)*(1.-e-e)*cz*d/6.-x)*d/4.+cz)*sy*d+y)*c*a*r;
#ifdef DEBUG
if (fabs (l_iter - MAXITER) < EPS) {
printf ("Algorithm did not converge\n");
} else
fprintf(stderr,"%s = %.4f\n", __FUNCTION__, s);
#endif
return s;
}

66
geo-dist.h Normal file
View file

@ -0,0 +1,66 @@
/*
*
* geo-dist
*
* Copyright (C) 2006 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
*
*/
#ifndef _GEO_DIST_H
#define _GEO_DIST_H
#ifdef __cplusplus
extern "C"
{
#endif
/*
* Calculate distances on Earth surface given geographic locations
*/
typedef enum {
WGS84,
NAD27,
International,
Krasovsky,
Bessel,
WGS72,
WGS66,
FAIsphere
} EllipsoidType;
/* nautical in kilometer */
#define NAUTICAL_MILE 1.852
/*
* glat1, glat2: geodetic latitude in radians, N positive
* glon1, glon2: geodetic longitude in radians E positive
* Coordinates in radians means
* 50°50.32N ^= 50 degree, 50 minutes and 32 seconds
* ^= 50 + (50 / 60) + (32 / 3600)
* ^= 50.84222
*
* returns: distance in nm (nautical miles), factor of 1.852 gives km
*/
double dist_ell(double, double, double, double, EllipsoidType);
#ifdef __cplusplus
}
#endif
#endif /* _GEO_DIST_H */

133
geo-tools.h Normal file
View file

@ -0,0 +1,133 @@
/*
* geo-tools.h
*
* Copyright (C) 2006,2007 Nils Faerber <nils.faerber@kernelconcepts.de>
*
* parts taken from Maemo-Mapper (GPL)
*
* 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
*
*/
#ifndef _GEO_TOOLS_H
#define _GEO_TOOLS_H
/* from GNU glibc math.h - since we do not need __USE_GNU else
* we copy it here
*/
#ifndef M_PIl
#define M_PIl 3.1415926535897932384626433832795029L
#endif
/*
* the following unit-latlpon conversions are
* shamelessly stolen^Wborrowed from Maemo-Mapper ;)
* ...and will be returned in time
* Some minor modifications have been done...
*/
#define pixel2unit(pixel) ((pixel) << _zoom)
#define unit2pixel(pixel) ((pixel) >> _zoom)
/* use 31 bits for best accuracy */
#define WORLD_SIZE_UNITS (1 << 30 /*26*/)
#define MERCATOR_SPAN (-6.28318377773622f)
#define MERCATOR_TOP (3.14159188886811f)
#define latlon2unit(lat, lon, unitx, unity) { \
gdouble tmp; \
unitx = (lon + 180.f) * (WORLD_SIZE_UNITS / 360.f) + 0.5f; \
tmp = sin(lat * (M_PIl / 180.f)); \
unity = 0.5f + (WORLD_SIZE_UNITS / MERCATOR_SPAN) \
* (log((1.f + tmp) / (1.f - tmp)) * 0.5f - MERCATOR_TOP); \
}
#define unit2latlon(unitx, unity, lat, lon) { \
(lon) = ((unitx) * (360.f / WORLD_SIZE_UNITS)) - 180.f; \
(lat) = (360.f * (atan(exp(((unity) \
* (MERCATOR_SPAN / WORLD_SIZE_UNITS)) \
+ MERCATOR_TOP)))) * (1.f / M_PIl) - 90.f; \
}
#define MACRO_RECALC_OFFSET() { \
_offsetx = grid2pixel( \
unit2grid(_center.unitx) \
- _screen_grids_halfwidth \
- tile2grid(_base_tilex)); \
_offsety = grid2pixel( \
unit2grid(_center.unity) \
- _screen_grids_halfheight \
- tile2grid(_base_tiley)); \
}
#define MACRO_RECALC_FOCUS_BASE() { \
_focus.unitx = x2unit(_screen_width_pixels * _center_ratio / 20); \
_focus.unity = y2unit(_screen_height_pixels * _center_ratio / 20); \
}
#define MACRO_RECALC_FOCUS_SIZE() { \
_focus_unitwidth = pixel2unit( \
(10 - _center_ratio) * _screen_width_pixels / 10); \
_focus_unitheight = pixel2unit( \
(10 - _center_ratio) * _screen_height_pixels / 10); \
}
#define MACRO_RECALC_CENTER_BOUNDS() { \
_min_center.unitx = pixel2unit(grid2pixel(_screen_grids_halfwidth)); \
_min_center.unity = pixel2unit(grid2pixel(_screen_grids_halfheight)); \
_max_center.unitx = WORLD_SIZE_UNITS-grid2unit(_screen_grids_halfwidth) - 1; \
_max_center.unity = WORLD_SIZE_UNITS-grid2unit(_screen_grids_halfheight)- 1; \
}
#define MACRO_INIT_TRACK(track) { \
(track).head = (track).tail = g_new(TrackPoint, ARRAY_CHUNK_SIZE); \
(track).tail->unitx = (track).tail->unity = 0; \
(track).cap = (track).head + ARRAY_CHUNK_SIZE; \
(track).whead = g_new(WayPoint, ARRAY_CHUNK_SIZE); \
(track).wtail = (track).whead - 1; \
(track).wcap = (track).whead + ARRAY_CHUNK_SIZE; \
}
#define MACRO_CLEAR_TRACK(track) if((track).head) { \
WayPoint *curr; \
g_free((track).head); \
(track).head = (track).tail = (track).cap = NULL; \
for(curr = (track).whead - 1; curr++ != (track).wtail; ) \
g_free(curr->desc); \
g_free((track).whead); \
(track).whead = (track).wtail = (track).wcap = NULL; \
}
#define DISTANCE_ROUGH(point) \
(abs((gint)((point).unitx) - _pos.unitx) \
+ abs((gint)((point).unity) - _pos.unity))
#define MACRO_QUEUE_DRAW_AREA() \
gtk_widget_queue_draw_area( \
_map_widget, \
0, 0, \
_screen_width_pixels, \
_screen_height_pixels)
#define KEEP_DISPLAY_ON() { \
/* Note that the flag means keep on ONLY when fullscreen. */ \
if(_always_keep_on || _fullscreen) \
{ \
osso_display_state_on(_osso); \
osso_display_blanking_pause(_osso); \
} \
}
#endif

134
mappix-fileio.c Normal file
View file

@ -0,0 +1,134 @@
/*
*
* mappix-fileio
*
* Copyright (C) 2006 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 <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "mappix.h"
#include "geo-tools.h"
static void
write_trackpoint(gpointer data, gpointer user_data)
{
trackdata *tdata = (trackdata *)data;
FILE *mfile = (FILE *)user_data;
gfloat llat, llong;
gchar dstr[G_ASCII_DTOSTR_BUF_SIZE];
if (tdata != NULL) {
g_fprintf(mfile, "<trkpt ");
unit2latlon(tdata->unitx, tdata->unity, llat, llong);
g_ascii_dtostr(dstr, G_ASCII_DTOSTR_BUF_SIZE, llat);
g_fprintf(mfile, "lat=\"%s\" ", dstr);
g_ascii_dtostr(dstr, G_ASCII_DTOSTR_BUF_SIZE, llong);
g_fprintf(mfile, "long=\"%s\">\n", dstr);
g_fprintf(mfile, "<ele>%.6f</ele>\n", tdata->elevation);
#if 0
// if (tdata->datetime != NULL)
// g_fprintf(mfile, "<time>%s</time>\n", tdata->datetime);
g_fprintf(mfile, "<sat>%d</sat>\n", tdata->nrsat);
g_fprintf(mfile, "<hdop>%f</hdop>\n", tdata->hdop);
g_fprintf(mfile, "<vdop>%f</vdop>\n", tdata->vdop);
g_fprintf(mfile, "<pdop>%f</pdop>\n", tdata->pdop);
#endif
g_fprintf(mfile, "</trkpt>\n");
}
}
static void
write_track(gpointer data, gpointer user_data)
{
track_head *thead = (track_head *)data;
FILE *mfile = (FILE *)user_data;
gfloat minlat, minlon, maxlat, maxlon;
if (thead != NULL) {
g_fprintf(mfile, "<trk>\n");
g_fprintf(mfile, "<name>%s</name>\n", thead->name);
g_fprintf(mfile, "<type>%d</type>\n", thead->type); /* NOT GPX CONFORMANT */
g_fprintf(mfile, "<show>%s</show>\n", thead->show ? "true" : "false"); /* NOT GPX CONFORMANT */
unit2latlon(thead->xmin, thead->ymin, minlat, minlon);
unit2latlon(thead->xmax, thead->ymax, maxlat, maxlon);
g_fprintf(mfile, "<bounds minlat=\"%f\" minlon=\"%f\" maxlat=\"%f\" maxlon=\"%f\"/>\n", minlat, minlon, maxlat, maxlon);
g_fprintf(mfile, "<trkseg>\n");
if (thead->track != NULL)
g_list_foreach(thead->track, write_trackpoint, mfile);
g_fprintf(mfile, "</trkseg>\n");
g_fprintf(mfile, "</trk>\n");
}
}
static void
write_waypoint(gpointer data, gpointer user_data)
{
waypoint *tdata = (waypoint *)data;
FILE *mfile = (FILE *)user_data;
gfloat llat, llong;
gchar dstr[G_ASCII_DTOSTR_BUF_SIZE];
if (tdata != NULL) {
g_fprintf(mfile, "<wpt ");
unit2latlon(tdata->unitx, tdata->unity, llat, llong);
g_ascii_dtostr(dstr, G_ASCII_DTOSTR_BUF_SIZE, llat);
g_fprintf(mfile, "lat=\"%s\" ", dstr);
g_ascii_dtostr(dstr, G_ASCII_DTOSTR_BUF_SIZE, llong);
g_fprintf(mfile, "long=\"%s\">\n", dstr);
g_fprintf(mfile, "<name>%s</name>\n", tdata->name);
g_fprintf(mfile, "<ele>%.6f</ele>\n", tdata->elevation);
#if 0 // not yet used
if (tdata->datetime != NULL)
g_fprintf(mfile, "<time>%s</time>\n", tdata->datetime);
g_fprintf(mfile, "<sat>%d</sat>\n", tdata->nrsat);
g_fprintf(mfile, "<hdop>%f</hdop>\n", tdata->hdop);
g_fprintf(mfile, "<vdop>%f</vdop>\n", tdata->vdop);
g_fprintf(mfile, "<pdop>%f</pdop>\n", tdata->pdop);
#endif
g_fprintf(mfile, "</wpt>\n");
}
}
gint
save_project_to_file(gchar *filename, mapwin *Mapper)
{
FILE *mfile;
mfile = g_fopen(filename, "w");
g_fprintf(mfile, "<?xml version=\"1.0\"?>\n<gpx version=\"1.0\" creator=\"Mappix\"\nxmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\nxmlns=\"http://www.topografix.com/GPX/1/0\"\nxsi:schemaLocation=\"http://www.topografix.com/GPX/1/0 http://www.topografix.com/GPX/1/0/gpx.xsd\">\n");
if (Mapper->tracklist)
g_list_foreach(Mapper->tracklist, write_track, mfile);
if (Mapper->waypoints)
g_list_foreach(Mapper->waypoints, write_waypoint, mfile);
g_fprintf(mfile, "</gpx>\n");
fclose(mfile);
return 0;
}

24
mappix-fileio.h Normal file
View file

@ -0,0 +1,24 @@
/*
*
* mappix-fileio
*
* Copyright (C) 2006 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
*
*/
gint save_project_to_file(gchar *, mapwin *);

344
mappix-gpxreader.c Normal file
View file

@ -0,0 +1,344 @@
/*
* 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;
}

37
mappix-gpxreader.h Normal file
View file

@ -0,0 +1,37 @@
/*
* mappix-gpxreader.h
*
* Copyright (C) 2006 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef _MAPPIX_GPXREADER_H
#define _MAPPIX_GPXREADER_H
#ifdef __cplusplus
extern "C"
{
#endif
gint gpxread(gchar *, mapwin *);
#ifdef __cplusplus
}
#endif
#endif /* _MAPPIX_GPXREADER_H */

744
mappix-trackdraw.c Normal file
View file

@ -0,0 +1,744 @@
/*
* trackdraw
*
* Copyright (C) 2006 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 <string.h>
#include <math.h>
#include <cairo.h>
#include <sqlite3.h>
#include "mappix.h"
#include "geo-tools.h"
#include "geo-dist.h"
void
draw_waypoint_label (mapwin *Mapper, gint x, gint y, gchar *text_label)
{
PangoLayout *playout;
GdkColor fgc, bgc;
playout = gtk_widget_create_pango_layout (Mapper->drawarea, text_label);
gdk_color_parse("black", &fgc);
gdk_color_parse("yellow", &bgc);
gdk_draw_layout_with_colors(Mapper->mappix, Mapper->drawarea->style->black_gc, x+10, y-20, playout, &fgc, &bgc);
gdk_gc_set_line_attributes(Mapper->drawarea->style->black_gc, 0, GDK_LINE_SOLID, GDK_CAP_BUTT, GDK_JOIN_MITER);
gdk_draw_line(Mapper->mappix, Mapper->drawarea->style->black_gc, x+10, y-10, x, y);
gtk_widget_queue_draw(Mapper->drawarea);
}
static void
draw_city_name(mapwin *Mapper, gchar *city_name, guint x, guint y)
{
PangoLayout *playout;
GdkColor fgc;
// fprintf(stderr, "city %s\n", city_name);
playout = gtk_widget_create_pango_layout (Mapper->drawarea, city_name);
gdk_color_parse("black", &fgc);
gdk_draw_layout_with_colors(Mapper->mappix, Mapper->drawarea->style->black_gc, x, y, playout, &fgc, NULL);
gtk_widget_queue_draw(Mapper->drawarea);
}
static int
city_db_callback(void *user_data, int argc, char **argv, char **azColName)
{
mapwin *Mapper = (mapwin *)user_data;
double lat, lon;
guint unitx, unity;
// str argv[0]
lat = g_ascii_strtod(argv[1] , NULL);
lon = g_ascii_strtod(argv[2] , NULL);
latlon2unit(lat, lon, unitx, unity);
unitx = (unitx - Mapper->xoffset) * Mapper->scale;
unity = (unity - Mapper->yoffset) * Mapper->scale;
draw_city_name(Mapper, argv[0], unitx, unity);
return 0;
}
void
draw_city_names(mapwin *Mapper)
{
sqlite3 *db;
/* re-scan for cities */
if (Mapper->show_cities && !sqlite3_open("cities.db", &db)) {
char *zErrMsg = 0;
gchar sql[256];
double lat_min, lon_min;
double lat_max, lon_max;
gchar lamax[32], lamin[32], lomax[32], lomin[32];
unit2latlon(Mapper->xmin, Mapper->ymin, lat_min, lon_min);
unit2latlon(Mapper->xmax, Mapper->ymax, lat_max, lon_max);
g_ascii_dtostr(lamax, 32, lat_max);
g_ascii_dtostr(lamin, 32, lat_min);
g_ascii_dtostr(lomax, 32, lon_max);
g_ascii_dtostr(lomin, 32, lon_min);
g_sprintf(sql, "SELECT city, lat, long FROM staedte WHERE lat > %s AND lat < %s AND long > %s AND long < %s;",
lamax, lamin, lomin, lomax);
sqlite3_exec(db, sql, city_db_callback, Mapper, &zErrMsg);
// fprintf(stderr, "sql: '%s'\n", sql);
sqlite3_close(db);
}
}
void
draw_scale(mapwin *Mapper)
{
PangoLayout *playout;
GdkColor fgc;
guint x1,x2,y;
double lat1, lat2, lon1, lon2, dist;
gchar scale_text[64];
// assuming we have 50px in the lower right corner
// fprintf(stderr, "city %s\n", city_name);
x1 = Mapper->xoffset;
x2 = Mapper->xoffset + (100. / Mapper->scale);
y = Mapper->yoffset;
unit2latlon(x1, y, lat1, lon1);
unit2latlon(x2, y, lat2, lon2);
//fprintf(stderr, "x=%d x2=%d y=%d lat1=%lf lat2=%lf lon1=%lf lon2=%lf\n", x1,x2,y,lat1,lat2,lon1,lon2);
dist = dist_ell(lat1, lon1, lat2, lon2, WGS84) * NAUTICAL_MILE;
if (dist > 1.0)
g_snprintf(scale_text, 64, "%.02lfkm", dist);
else {
g_snprintf(scale_text, 64, "%.00lfm", dist*100.);
}
playout = gtk_widget_create_pango_layout (Mapper->drawarea, scale_text);
gdk_color_parse("black", &fgc);
gdk_draw_layout_with_colors(Mapper->mappix, Mapper->drawarea->style->black_gc, Mapper->canvas_x - 80, Mapper->canvas_y - 20, playout, &fgc, NULL);
gdk_gc_set_line_attributes(Mapper->drawarea->style->black_gc, 0, GDK_LINE_SOLID, GDK_CAP_BUTT, GDK_JOIN_MITER);
gdk_draw_line(Mapper->mappix, Mapper->drawarea->style->black_gc, Mapper->canvas_x-110, Mapper->canvas_y - 20, Mapper->canvas_x-10, Mapper->canvas_y - 20);
gdk_draw_line(Mapper->mappix, Mapper->drawarea->style->black_gc, Mapper->canvas_x-110, Mapper->canvas_y - 25, Mapper->canvas_x-110, Mapper->canvas_y - 15);
gdk_draw_line(Mapper->mappix, Mapper->drawarea->style->black_gc, Mapper->canvas_x-10, Mapper->canvas_y - 25, Mapper->canvas_x-10, Mapper->canvas_y - 15);
for (x1 = (Mapper->canvas_x-100); x1 < (Mapper->canvas_x-10); x1+=10)
gdk_draw_line(Mapper->mappix, Mapper->drawarea->style->black_gc, x1, Mapper->canvas_y - 25, x1, Mapper->canvas_y - 20);
gtk_widget_queue_draw(Mapper->drawarea);
}
void
do_redraw(mapwin *Mapper)
{
draw_tracks(Mapper);
if (Mapper->show_cities)
draw_city_names(Mapper);
if (Mapper->show_waypoints)
draw_waypoints(Mapper);
if (Mapper->show_scale)
draw_scale(Mapper);
gtk_widget_queue_draw(Mapper->drawarea);
}
void
change_scale(mapwin *Mapper, double new_scale)
{
Mapper->scale = new_scale;
do_redraw(Mapper);
}
void
zoom_in_cb (GtkSpinButton *widget, gpointer user_data)
{
mapwin *Mapper = (mapwin *)user_data;
gdouble scale_inc;
guint x,y;
scale_inc = Mapper->scale / 10.;
x = (Mapper->canvas_x / 2) / Mapper->scale;
y = (Mapper->canvas_y / 2) / Mapper->scale;
Mapper->scale += scale_inc;
Mapper->xoffset += x - ((Mapper->canvas_x / 2) / Mapper->scale);
Mapper->yoffset += y - ((Mapper->canvas_y / 2) / Mapper->scale);
Mapper->xmin = Mapper->xoffset;
Mapper->ymin = Mapper->yoffset;
Mapper->xmax = Mapper->xmin + (Mapper->canvas_x / Mapper->scale);
Mapper->ymax = Mapper->ymin + (Mapper->canvas_y / Mapper->scale);
change_scale(Mapper, Mapper->scale);
}
void
zoom_out_cb (GtkSpinButton *widget, gpointer user_data)
{
mapwin *Mapper = (mapwin *)user_data;
gdouble scale_inc;
guint x,y;
scale_inc = Mapper->scale / 10.;
if (scale_inc < 0)
scale_inc = 0;
x = (Mapper->canvas_x / 2) / Mapper->scale;
y = (Mapper->canvas_y / 2) / Mapper->scale;
Mapper->scale -= scale_inc;
Mapper->xoffset += x - ((Mapper->canvas_x / 2) / Mapper->scale);
Mapper->yoffset += y - ((Mapper->canvas_y / 2) / Mapper->scale);
Mapper->xmin = Mapper->xoffset;
Mapper->ymin = Mapper->yoffset;
Mapper->xmax = Mapper->xmin + (Mapper->canvas_x / Mapper->scale);
Mapper->ymax = Mapper->ymin + (Mapper->canvas_y / Mapper->scale);
change_scale(Mapper, Mapper->scale);
}
void
zoom_area_cb (GtkRadioToolButton *widget, gpointer user_data)
{
mapwin *Mapper = (mapwin *)user_data;
Mapper->toolmode = MAPPIX_TOOL_ZOOM_REGION;
}
void
move_cb (GtkRadioToolButton *widget, gpointer user_data)
{
mapwin *Mapper = (mapwin *)user_data;
Mapper->toolmode = MAPPIX_TOOL_MOVE;
}
void
auto_scale (GtkButton *widget, gpointer user_data)
{
mapwin *Mapper = (mapwin *)user_data;
change_scale(Mapper, calc_scale(Mapper));
}
void
draw_line(gint x1, gint y1, gint x2, gint y2, gint linewidth, gpointer user_data)
{
mapwin *Mapper = (mapwin *)user_data;
gdk_gc_set_line_attributes(Mapper->drawarea->style->black_gc, linewidth, GDK_LINE_SOLID, GDK_CAP_ROUND, GDK_JOIN_MITER);
gdk_draw_line(Mapper->mappix, Mapper->drawarea->style->black_gc, x1, y1, x2, y2);
}
void
draw_marker(gint x1, gint y1, gint psize, gint marker_type, gpointer user_data)
{
mapwin *Mapper = (mapwin *)user_data;
GdkGC *marker_gc;
if (!Mapper->show_marker)
return;
if (marker_type & MARKER_SELECTED) {
marker_gc = Mapper->blue_gc;
marker_type &= ~MARKER_SELECTED;
} else
marker_gc = Mapper->red_gc;
if (marker_type != MARKER_TYPE_NONE) {
if (marker_type == MARKER_TYPE_FILLED_SQUARE) {
gdk_draw_rectangle(Mapper->mappix, marker_gc, TRUE, x1 - (psize/2), y1 - (psize/2), psize, psize);
} else if (marker_type == MARKER_TYPE_SQUARE) {
gdk_draw_rectangle(Mapper->mappix, marker_gc, FALSE, x1 - (psize/2), y1 - (psize/2), psize, psize);
} else if (marker_type == MARKER_TYPE_CROSS) {
psize = psize / 2;
gdk_gc_set_line_attributes(marker_gc, 0 /*linewidth*/, GDK_LINE_SOLID, GDK_CAP_BUTT, GDK_JOIN_MITER);
gdk_draw_line(Mapper->mappix, marker_gc, x1-psize, y1-psize, x1+psize, y1+psize);
gdk_draw_line(Mapper->mappix, marker_gc, x1+psize, y1-psize, x1-psize, y1+psize);
}
}
}
void
draw_markers(track_head *trackh, double bbxmin, double bbxmax, double bbymin, double bbymax, mapwin *Mapper, cairo_t *cr)
{
GList *track = trackh->track;
trackdata *tdata;
GList *lp;
gboolean start_newline = TRUE;
if (Mapper->show_marker && Mapper->scale > 0.0009) {
double ox, oy;
double angle;
ox = 0.; oy = 0.;
cairo_set_line_width(cr, 1.5 / Mapper->scale);
for (lp = track; lp; lp=g_list_next(lp)) {
tdata = (trackdata *)lp->data;
if ((tdata->unitx < bbxmin || tdata->unitx > bbxmax) ||
(tdata->unity < bbymin || tdata->unity > bbymax)) {
start_newline = TRUE;
} else {
if (start_newline) {
ox = (double)tdata->unitx;
oy = (double)tdata->unity;
} else {
angle = -1. * atan2((double)tdata->unitx - ox,
(double)tdata->unity - oy);
cairo_move_to(cr, (double)tdata->unitx, (double)tdata->unity);
/* draw marker arrow */
cairo_save (cr);
if (tdata->selected)
cairo_set_source_rgb (cr, .0,.0,.9);
else
cairo_set_source_rgb (cr, .0,.0,.0);
// cairo_set_line_width(cr, 1.5 / Mapper->scale);
cairo_rotate(cr, angle);
cairo_rel_move_to (cr, -5./ Mapper->scale, -5./ Mapper->scale);
cairo_rel_line_to (cr, 5./ Mapper->scale,5. / Mapper->scale);
cairo_rel_line_to (cr, 5./ Mapper->scale,-5. / Mapper->scale);
cairo_stroke (cr);
cairo_restore (cr);
ox = (double)tdata->unitx;
oy = (double)tdata->unity;
}
start_newline = FALSE;
}
}
}
}
void
draw_line_with_marker(gint x1, gint y1, gint x2, gint y2, gint psize, gint linewidth, gint marker_type, gpointer user_data)
{
draw_marker(x1, y1, psize, marker_type, user_data);
draw_marker(x2, y2, psize, marker_type, user_data);
draw_line(x1, y1, x2, y2, linewidth, user_data);
}
double
do_calc_scale(mapwin *Mapper)
{
double xscale, yscale;
double scale;
/* we calculate both scales and choose the smaller scale factor so that all data will fit */
xscale = Mapper->canvas_x / (gdouble)(Mapper->xmax - Mapper->xmin);
yscale = Mapper->canvas_y / (gdouble)(Mapper->ymax - Mapper->ymin);
if (xscale < yscale)
scale = xscale;
else
scale = yscale;
/* this should bring the tracks to the lower left corner */
Mapper->xoffset = Mapper->xmin;
Mapper->yoffset = Mapper->ymin;
// g_message("xmax=%d ymax=%d xmin=%d ymax=%d xscale=%f yscale=%f scale=%f", Mapper->xmax, Mapper->ymax, Mapper->xmin, Mapper->ymin, Mapper->xscale, Mapper->yscale, Mapper->scale);
return scale;
}
double
calc_scale(mapwin *Mapper)
{
trackdata *tdata;
track_head *thead;
GList *trackh, *trackp;
// fprintf(stderr,"cs\n");
Mapper->xmin=WORLD_SIZE_UNITS;
Mapper->xmax=0;
Mapper->ymin=WORLD_SIZE_UNITS;
Mapper->ymax=0;
for (trackh=Mapper->tracklist; trackh; trackh=g_list_next(trackh)) {
// fprintf(stderr," +cs\n");
thead = (track_head *)trackh->data;
if (thead->show) {
for (trackp=thead->track; trackp; trackp=g_list_next(trackp)) {
tdata = (trackdata *)trackp->data;
// fprintf(stderr,"latmin=%lf latmax=%lf longmin=%lf longmax=%lf\n", latmin, latmax, longmin, longmax);
if (tdata->unitx < Mapper->xmin)
Mapper->xmin = tdata->unitx;
else if (tdata->unitx > Mapper->xmax)
Mapper->xmax = tdata->unitx;
if (tdata->unity < Mapper->ymin)
Mapper->ymin = tdata->unity;
else if (tdata->unity > Mapper->ymax)
Mapper->ymax = tdata->unity;
}
}
}
return do_calc_scale(Mapper);
}
void
draw_waypoints(mapwin *Mapper)
{
GList *lp;
waypoint *wpdata;
if (!Mapper->show_waypoints)
return;
for (lp = Mapper->waypoints; lp; lp=g_list_next(lp)) {
double x,y;
wpdata = (waypoint *)lp->data;
x = (wpdata->unitx - Mapper->xoffset) * Mapper->scale;
y = (wpdata->unity - Mapper->yoffset) * Mapper->scale;
// fprintf(stderr,"x=%lf y=%lf sc=%lf\n", tdata->longitude, tdata->latitude, Mapper->scale);
if (x < 0 || y < 0)
continue;
if (x > Mapper->canvas_x)
continue;
if (y > Mapper->canvas_y)
continue;
draw_waypoint_label (Mapper, x, y, wpdata->name);
}
}
#if 0
static void
print_matrix(cairo_t *cr)
{
cairo_matrix_t cmatrix;
cairo_get_matrix(cr, &cmatrix);
fprintf(stderr, "xx=%lf xy=%lf x0=%lf\n", cmatrix.xx, cmatrix.xy, cmatrix.x0);
fprintf(stderr, "yx=%lf yy=%lf y0=%lf\n", cmatrix.yx, cmatrix.yy, cmatrix.y0);
}
#endif
void
draw_track(track_head *trackh, gpointer user_data)
{
mapwin *Mapper = (mapwin *)user_data;
GList *track = trackh->track;
trackdata *tdata;
gboolean start_newline = TRUE;
GList *lp;
cairo_t *cr;
cairo_matrix_t cmatrix;
double bbxmin, bbxmax;
double bbymin, bbymax;
// double TRACK_FACTOR = (1. / (2. * Mapper->scale)) + (100000. * Mapper->scale);
double TRACK_FACTOR = (4000. * (Mapper->scale * Mapper->scale)) * (1. / Mapper->scale);
if (TRACK_FACTOR < (0.8 / Mapper->scale))
TRACK_FACTOR = 0.8 / Mapper->scale;
if (track == NULL)
return;
cr = gdk_cairo_create (GDK_DRAWABLE(Mapper->mappix));
cairo_set_line_join (cr, CAIRO_LINE_JOIN_ROUND);
cairo_set_line_cap (cr, CAIRO_LINE_CAP_ROUND);
/* first set drawing for the outline of track or for non-outlined */
if (Mapper->show_marker) {
cairo_set_source_rgb (cr, 0,0,0);
cairo_set_line_width(cr, 1.0 / Mapper->scale);
} else {
switch (trackh->type) {
case UNKNOWN:
case OUTLINE: /* always visible in 1.0pt */
cairo_set_source_rgb (cr, 0,0,0);
cairo_set_line_width(cr, 1.0 / Mapper->scale);
break;
case FOOTPATH:
cairo_set_source_rgb (cr, 0,0,0);
cairo_set_line_width(cr, 1.0 * TRACK_FACTOR);
break;
case RIVER:
cairo_set_source_rgb (cr, 0,0,.9);
cairo_set_line_width(cr, 1.3 * TRACK_FACTOR);
break;
case AGRI:
cairo_set_source_rgb (cr, 0.4,0.4,0.4);
cairo_set_line_width(cr, 1. * TRACK_FACTOR);
break;
case CITY:
cairo_set_source_rgb (cr, .5,.5,.5);
cairo_set_line_width(cr, 1. * TRACK_FACTOR);
break;
case URBAN:
cairo_set_source_rgb (cr, .3,.3,.3);
cairo_set_line_width(cr, 1.5 * TRACK_FACTOR);
break;
case MOTORWAY:
cairo_set_source_rgb (cr, .3,.3,.3);
cairo_set_line_width(cr, 3.5 * TRACK_FACTOR);
break;
case HIGHWAY:
cairo_set_source_rgb (cr, .1,.1,.1);
cairo_set_line_width(cr, 4.5 * TRACK_FACTOR);
break;
default:
cairo_set_line_width(cr, 1.0 * TRACK_FACTOR);
break;
}
}
// fprintf(stderr, "scale is: %lf\n", Mapper->scale);
cairo_matrix_init_identity(&cmatrix);
cairo_matrix_init_scale(&cmatrix, Mapper->scale, Mapper->scale);
cairo_matrix_translate(&cmatrix, -((double)Mapper->xoffset),
-((double)Mapper->yoffset));
cairo_set_matrix(cr, &cmatrix);
bbxmin = Mapper->xoffset;
bbxmax = bbxmin + ((double)Mapper->canvas_x / Mapper->scale);
bbymin = Mapper->yoffset;
bbymax = bbymin + ((double)Mapper->canvas_y / Mapper->scale);
// fprintf(stderr, "xl=%lf xh=%lf yl=%lf yh=%lf\n", bbxmin, bbxmax, bbymin, bbymax);
for (lp = track; lp; lp=g_list_next(lp)) {
tdata = (trackdata *)lp->data;
if ((tdata->unitx < bbxmin || tdata->unitx > bbxmax) ||
(tdata->unity < bbymin || tdata->unity > bbymax)) {
/* first finish this line, even if the target is outside */
if (!start_newline)
cairo_line_to (cr, (double)tdata->unitx, (double)tdata->unity);
start_newline = TRUE;
} else {
//draw_line_with_marker(x, y, x2, y2, Mapper->marker_size, Mapper->linewidth, Mapper->marker_type, Mapper);
if (start_newline) {
// fprintf(stderr, "mt\n");
cairo_move_to (cr, (double)tdata->unitx, (double)tdata->unity);
} else {
// fprintf(stderr, "lt\n");
cairo_line_to (cr, (double)tdata->unitx, (double)tdata->unity);
}
start_newline = FALSE;
}
}
// fprintf(stderr, "xl=%lf xh=%lf yl=%lf yh=%lf\n", bbxmin, bbxmax, bbymin, bbymax);
// print_matrix(cr);
cairo_stroke (cr);
if (!(Mapper->show_marker || trackh->type == UNKNOWN || trackh->type == OUTLINE
|| trackh->type == RIVER || trackh->type == FOOTPATH
|| trackh->type == AGRI)) {
cairo_set_source_rgb (cr, 0.7,0.7,0.7);
cairo_set_line_width(cr, (double)Mapper->linewidth / Mapper->scale);
/* second set drawing for the inner colored track */
switch (trackh->type) {
case CITY:
cairo_set_source_rgb (cr, 1.,1.,1.);
cairo_set_line_width(cr, .5 * TRACK_FACTOR);
break;
case URBAN:
cairo_set_source_rgb (cr, 1.,1.,.7);
cairo_set_line_width(cr, 1. * TRACK_FACTOR);
break;
case MOTORWAY:
cairo_set_source_rgb (cr, 1.,1.,.5);
cairo_set_line_width(cr, 2.5 * TRACK_FACTOR);
break;
case HIGHWAY:
cairo_set_source_rgb (cr, 9.,0.,0.);
cairo_set_line_width(cr, 3.5 * TRACK_FACTOR);
break;
default:
cairo_set_line_width(cr, 1.0 * TRACK_FACTOR);
break;
}
for (lp = track; lp; lp=g_list_next(lp)) {
tdata = (trackdata *)lp->data;
// x = (tdata->unitx - Mapper->xoffset) * Mapper->scale;
// y = (tdata->unity - Mapper->yoffset) * Mapper->scale;
// fprintf(stderr,"x=%lf y=%lf sc=%lf\n", (double)tdata->unitx, (double)tdata->unity, Mapper->scale);
// fprintf(stderr,"x=%lf y=%lf\n", x, y);
if ((tdata->unitx < bbxmin || tdata->unitx > bbxmax) ||
(tdata->unity < bbymin || tdata->unity > bbymax)) {
// fprintf(stderr, "nl\n");
/* first finish this line, even if the target is outside */
if (!start_newline)
cairo_line_to (cr, (double)tdata->unitx, (double)tdata->unity);
start_newline = TRUE;
} else {
//draw_line_with_marker(x, y, x2, y2, Mapper->marker_size, Mapper->linewidth, Mapper->marker_type, Mapper);
if (start_newline) {
// fprintf(stderr, "mt\n");
cairo_move_to (cr, (double)tdata->unitx, (double)tdata->unity);
} else {
// fprintf(stderr, "lt\n");
cairo_line_to (cr, (double)tdata->unitx, (double)tdata->unity);
}
start_newline = FALSE;
}
}
cairo_stroke (cr);
}
if (Mapper->show_marker)
draw_markers(trackh, bbxmin, bbxmax, bbymin, bbymax, Mapper, cr);
// fprintf(stderr, "xl=%lf xh=%lf yl=%lf yh=%lf\n", bbxmin, bbxmax, bbymin, bbymax);
// print_matrix(cr);
cairo_stroke (cr);
cairo_destroy (cr);
}
static gboolean
draw_idle(gpointer user_data)
{
mapwin *Mapper = (mapwin *)user_data;
static GList *track=NULL;
static track_head *trackh=NULL;
trackdata *tdata;
double x,y;
static double x2=-1,y2=-1;
static GList *lp=NULL;
if (Mapper->tracklist == NULL) {
// fprintf(stderr,"tracklist==NULL -> end\n");
/* erase drawing area */
gdk_draw_rectangle(Mapper->mappix, Mapper->drawarea->style->white_gc, 1, 0, 0, Mapper->canvas_x, Mapper->canvas_y);
gtk_widget_queue_draw(Mapper->drawarea);
Mapper->draw_idle_active = FALSE;
track = NULL;
lp = NULL;
x2 = -1;
y2 = -1;
return FALSE;
}
// start new drawing
if (!Mapper->draw_idle_active) {
// fprintf(stderr,"new drawing -> starting\n");
Mapper->draw_idle_active = TRUE;
track = Mapper->tracklist;
/* erase drawing area */
gdk_draw_rectangle(Mapper->mappix, Mapper->drawarea->style->white_gc, 1, 0, 0, Mapper->canvas_x, Mapper->canvas_y);
lp = NULL;
x2 = -1; y2 = -1;
}
trackh=(track_head *)track->data;
if (trackh->xmax < Mapper->xoffset ||
trackh->ymax < Mapper->yoffset ||
trackh->xmin > (Mapper->xoffset + (Mapper->canvas_x / Mapper->scale)) ||
trackh->ymin > (Mapper->yoffset + (Mapper->canvas_y / Mapper->scale))) {
/* fprintf(stderr, "not drawing track '%s'\n", trackh->name); */
} else if (trackh->track != NULL && trackh->show) {
if (lp == NULL)
lp = trackh->track;
tdata = (trackdata *)lp->data;
x = (tdata->unitx - Mapper->xoffset) * Mapper->scale;
y = (tdata->unity - Mapper->yoffset) * Mapper->scale;
// fprintf(stderr,"x=%lf y=%lf sc=%lf\n", tdata->longitude, tdata->latitude, Mapper->scale);
/* if the next point is the same as the previous we do not see a line so we do not paint it */
if ((guint)x != (guint)x2 || (guint)y != (guint)y2) {
if (x2 < 0 && y2 < 0) {
x2 = x; y2 = y;
draw_marker(x,y,Mapper->marker_size, Mapper->marker_type | (tdata->selected ? MARKER_SELECTED : 0), Mapper);
} else {
if ((x < 0 || x > Mapper->canvas_x) || (y < 0 || y > Mapper->canvas_y)) {
x2 = -1; y2 = -1;
} else {
draw_marker(x,y,Mapper->marker_size, Mapper->marker_type | (tdata->selected ? MARKER_SELECTED : 0), Mapper);
draw_line(x, y, x2, y2, Mapper->linewidth, Mapper);
x2 = x;
y2 = y;
}
}
}
}
// OK, done with this track
lp = g_list_next(lp);
if (lp == NULL) {
// fprintf(stderr,"track end -> next track\n");
gtk_widget_queue_draw(Mapper->drawarea);
track = g_list_next(track);
if (track != NULL) {
trackh = (track_head *)track->data;
lp = trackh->track;
x2 = -1; y2 = -1;
}
}
if (track == NULL) {
// fprintf(stderr,"end of tracks -> end\n");
draw_waypoints(Mapper);
Mapper->draw_idle_active = FALSE;
gtk_widget_queue_draw(Mapper->drawarea);
return FALSE;
}
return TRUE;
}
void
draw_tracks(mapwin *Mapper)
{
if (Mapper->use_idledraw) {
if (Mapper->draw_idle_active) {
Mapper->draw_idle_active = FALSE;
g_idle_remove_by_data(Mapper);
}
g_idle_add_full(G_PRIORITY_HIGH_IDLE + 20, draw_idle, Mapper, NULL);
} else {
GList *track;
track_head *trackh;
/* erase drawing area */
gdk_draw_rectangle(Mapper->mappix, Mapper->drawarea->style->white_gc, 1, 0, 0, Mapper->canvas_x, Mapper->canvas_y);
gtk_widget_queue_draw(Mapper->drawarea);
if (Mapper->tracklist != NULL) {
for (track=Mapper->tracklist; track; track=g_list_next(track)) {
trackh = (track_head *)track->data;
if (trackh->show) {
if (trackh->xmax < Mapper->xoffset ||
trackh->ymax < Mapper->yoffset ||
trackh->xmin > (Mapper->xoffset + (Mapper->canvas_x / Mapper->scale)) ||
trackh->ymin > (Mapper->yoffset + (Mapper->canvas_y / Mapper->scale))) {
// fprintf(stderr, "not drawing track '%s'\n", trackh->name);
} else
draw_track(trackh, Mapper);
}
}
}
}
}
void
draw_filename (gchar *fname, mapwin *Mapper)
{
if (gpxread(fname, Mapper) < 0)
return;
draw_tracks(Mapper);
draw_city_names(Mapper);
draw_waypoints(Mapper);
gtk_widget_queue_draw(Mapper->drawarea);
}

54
mappix-trackdraw.h Normal file
View file

@ -0,0 +1,54 @@
/*
* mappix-trackdraw.h
*
* Copyright (C) 2006 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef _MAPPIX_TRACKDRAW_H
#define _MAPPIX_TRACKDRAW_H
#ifdef __cplusplus
extern "C"
{
#endif
void draw_waypoint_label (mapwin *, gint, gint, gchar *);
void draw_pointed_line(gint, gint, gint, gint, gint, gint, gpointer);
void draw_lines_cb (GtkButton *, gpointer);
double do_calc_scale(mapwin *);
double calc_scale(mapwin *);
void do_redraw(mapwin *);
void change_scale(mapwin *, double);
void draw_marker(gint, gint, gint, gint, gpointer);
void draw_track(track_head *, gpointer);
void draw_tracks(mapwin *);
void draw_filename (gchar *, mapwin *);
void zoom_in_cb (GtkSpinButton *, gpointer);
void zoom_out_cb (GtkSpinButton *, gpointer);
void zoom_area_cb (GtkRadioToolButton *, gpointer);
void move_cb (GtkRadioToolButton *, gpointer);
void auto_scale (GtkButton *, gpointer);
void draw_waypoints(mapwin *);
void draw_city_names(mapwin *);
void draw_scale(mapwin *);
#ifdef __cplusplus
}
#endif
#endif /* _MAPPIX_TRACKDRAW_H */

1124
mappix-trackedit.c Normal file

File diff suppressed because it is too large Load diff

51
mappix-trackedit.h Normal file
View file

@ -0,0 +1,51 @@
/*
* mappix-trackedit.h
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef _MAPPIX_TRACKEDIT_H
#define _MAPPIX_TRACKEDIT_H
#ifdef __cplusplus
extern "C"
{
#endif
void on_auto_split (GtkButton *, gpointer);
void on_auto_thin (GtkButton *, gpointer);
void on_properties_track (GtkButton *, gpointer);
void on_track_angle_simplify (GtkButton *, gpointer);
void on_track_delete (GtkToolButton *, gpointer);
void on_select_trackpoint_cb(GtkToolButton *, gpointer);
void on_select_region_cb(GtkToolButton *, gpointer);
void do_trackpoint_region_select(gint, gint, guint, guint, gpointer);
void on_move_trackpoint_cb(GtkToolButton *, gpointer);
void do_select_trackpoint(gint, gint, gpointer);
void do_move_trackpoint(gint, gint, gint, gint, gpointer);
void track_find_minmax(gpointer, gpointer);
void track_add_new_to_main(mapwin *, track_head *);
void on_delete_nodes_cb(GtkToolButton *, gpointer);
void on_split_track(GtkToolButton *, gpointer);
void on_track_length(GtkWidget *, gpointer);
#ifdef __cplusplus
}
#endif
#endif /* _MAPPIX_TRACKEDIT_H */

210
mappix-trackrecord.c Normal file
View file

@ -0,0 +1,210 @@
#include "mappix.h"
#include <glib.h>
#include <glib/gstdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include "nmeap.h"
#include "geo-tools.h"
#define GPS_DEVICE "/dev/rfcomm0"
struct iochandata {
track_head *track;
GtkWidget *dialog;
GtkWidget *lat_label;
GtkWidget *long_label;
GtkWidget *nrpnt_label;
gboolean end_record;
gint nrpoints;
nmeap_context_t nmeap;
nmeap_gga_t gga;
};
static gboolean
gps_ch_inev (GIOChannel *source, GIOCondition condition, gpointer data)
{
struct iochandata *iodata = (struct iochandata *)data;
GError *merr;
static gchar buf[256], label[128];
gsize rread;
gint offset, remain, status;
trackdata *trackpoint;
if (condition & (G_IO_ERR | G_IO_HUP | G_IO_NVAL)) {
/* something bad happened on the channel, close it */
g_message("error on gps_ch");
return FALSE;
}
merr = NULL;
if (g_io_channel_read_chars (source, buf, 255, &rread, &merr) != G_IO_STATUS_NORMAL)
return FALSE;
// buf[255] = 0;
if (rread == 0)
return TRUE;
// g_message("chan read %d", rread);
/* FIXME: use nmeap.sf.net instead */
remain = rread;
offset = 0;
while (remain > 0) {
status = nmeap_parseBuffer(&iodata->nmeap, &buf[offset], &remain);
offset += (rread - remain);
switch(status) {
case NMEAP_GPGGA:
g_message("found GPGGA message %.6f %.6f %.0f %lu %d %d %f %f\n", iodata->gga.latitude , iodata->gga.longitude, iodata->gga.altitude, iodata->gga.time,
iodata->gga.satellites, iodata->gga.quality, iodata->gga.hdop, iodata->gga.geoid);
if (iodata->gga.quality > 0) {
if (iodata->gga.latitude > 360 || iodata->gga.longitude > 360)
return TRUE;
iodata->nrpoints++;
//g_message("lat=%f long=%f %s, fixtype %d", iodata->nms->latitude, iodata->nms->longitude, iodata->nms->satsvalid ? "valid" : "not valid", iodata->nms->fixtype);
#if 0
for (i=0; i<12; i++) {
g_message("sat #%02d", i);
g_message("\tin use:\t%s", iodata->nms->satellites[i].used ? "yes" : "no");
g_message("\tno#:\t%d", iodata->nms->satellites[i].number);
g_message("\tele:\t%d", iodata->nms->satellites[i].elevation);
g_message("\tazim:\t%d", iodata->nms->satellites[i].azimuth);
g_message("\ts/n ratio:\t%d", iodata->nms->satellites[i].snratio);
}
#endif
g_sprintf(label, "%d", iodata->nrpoints);
gtk_label_set_text(GTK_LABEL(iodata->nrpnt_label), label);
g_sprintf(label, "%f", iodata->gga.latitude);
gtk_label_set_text(GTK_LABEL(iodata->lat_label), label);
g_sprintf(label, "%f", iodata->gga.longitude);
gtk_label_set_text(GTK_LABEL(iodata->long_label), label);
trackpoint = (trackdata *)g_malloc(sizeof(trackdata));
latlon2unit(iodata->gga.latitude, iodata->gga.longitude, trackpoint->unitx, trackpoint->unity);
trackpoint->elevation = iodata->gga.altitude;
trackpoint->selected = FALSE;
iodata->track->track = g_list_prepend(iodata->track->track, trackpoint);
}
break;
case NMEAP_GPRMC:
break;
default:
break;
}
}
if (merr != NULL)
g_error_free(merr);
if (iodata->end_record)
return FALSE;
else
return TRUE;
}
void
do_record_track (mapwin *Mapper)
{
gint fd;
GIOChannel *gps_ch;
GtkWidget *dialog;
GtkWidget *table, *w;
GtkWidget *long_label;
GtkWidget *lat_label;
GtkWidget *nrpnt_label;
gint evsrcid, res;
struct iochandata iodata;
#ifdef HILDON
gtk_infoprintf(GTK_WINDOW(gtk_widget_get_toplevel(Mapper->mainwin)),
"Connecting to GPS...");
while (gtk_events_pending())
gtk_main_iteration();
#endif
fd = g_open(GPS_DEVICE, O_RDONLY | O_NONBLOCK);
if (fd < 0) {
return;
}
gps_ch = g_io_channel_unix_new(fd);
dialog = gtk_dialog_new_with_buttons("Recording Track", GTK_WINDOW(gtk_widget_get_toplevel(Mapper->mainwin)),
GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
GTK_STOCK_ADD, 1 /* response add */,
GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE, NULL);
table = gtk_table_new (2, 3, FALSE);
gtk_table_set_row_spacings (GTK_TABLE (table), 4);
gtk_table_set_col_spacings (GTK_TABLE (table), 4);
gtk_table_set_homogeneous(GTK_TABLE (table), TRUE);
gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), table, FALSE, FALSE, 0);
w = gtk_label_new("<b>Latitude</b>");
gtk_label_set_use_markup(GTK_LABEL(w), TRUE);
lat_label = gtk_label_new("-.-X");
gtk_table_attach_defaults (GTK_TABLE (table), w, 0, 1, 0, 1);
gtk_table_attach_defaults (GTK_TABLE (table), lat_label, 1, 2, 0, 1);
w = gtk_label_new("<b>Longitude</b>");
gtk_label_set_use_markup(GTK_LABEL(w), TRUE);
long_label = gtk_label_new("-.-X");
gtk_table_attach_defaults (GTK_TABLE (table), w, 0, 1, 1, 2);
gtk_table_attach_defaults (GTK_TABLE (table), long_label, 1, 2, 1, 2);
w = gtk_label_new("<b>points #</b>");
gtk_label_set_use_markup(GTK_LABEL(w), TRUE);
nrpnt_label = gtk_label_new("0");
gtk_table_attach_defaults (GTK_TABLE (table), w, 0, 1, 2, 3);
gtk_table_attach_defaults (GTK_TABLE (table), nrpnt_label, 1, 2, 2, 3);
gtk_widget_show_all(dialog);
iodata.end_record = FALSE;
iodata.nrpoints = 0;
iodata.dialog = dialog;
iodata.lat_label = lat_label;
iodata.long_label = long_label;
iodata.nrpnt_label = nrpnt_label;
iodata.track = (track_head *)g_malloc(sizeof(track_head));
iodata.track->name = g_strdup("RecTrack");
iodata.track->show = TRUE;
//nmea_parse_line("", &nms);
if (nmeap_init(&iodata.nmeap, NULL) != 0)
return;
if (nmeap_addParser(&iodata.nmeap, "GPGGA", nmeap_gpgga, NULL, &iodata.gga) != 0)
return;
evsrcid = g_io_add_watch(gps_ch, G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL,
gps_ch_inev, &iodata);
do {
res = gtk_dialog_run(GTK_DIALOG(dialog));
if (res == 1) {
g_message("would add waypoint");
}
} while (res == 1); /* anything than 1 will leave */
iodata.end_record = TRUE;
g_io_channel_shutdown(gps_ch, FALSE, NULL);
close(fd);
track_add_new_to_main(Mapper, iodata.track);
if (iodata.dialog != NULL) {
gtk_widget_hide(iodata.dialog);
gtk_widget_destroy(iodata.dialog);
}
}
void
on_record_track (GtkButton *widget, gpointer user_data)
{
mapwin *Mapper = (mapwin *)user_data;
do_record_track(Mapper);
}

6
mappix-trackrecord.h Normal file
View file

@ -0,0 +1,6 @@
#ifndef _MAPPIX_TRACKRECORD_H
#define _MAPPIX_TRACKRECORD_H
void on_record_track (GtkButton *widget, gpointer user_data);
#endif /* _MAPPIX_TRACKRECORD_H */

1074
mappix-ui.c Normal file

File diff suppressed because it is too large Load diff

41
mappix-ui.h Normal file
View file

@ -0,0 +1,41 @@
/***************************************************************************
* mappix-ui.h
*
* Sun Jun 4 19:06:50 2006
* Copyright 2006 User
* Email
****************************************************************************/
/*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef _MAPPIX_UI_H
#define _MAPPIX_UI_H
#ifdef __cplusplus
extern "C"
{
#endif
int create_main_window(mapwin *);
gint close_application( GtkWidget *, GdkEvent *, gpointer);
#ifdef __cplusplus
}
#endif
#endif /* _MAPPIX_UI_H */

365
mappix-waypoints.c Normal file
View file

@ -0,0 +1,365 @@
/*
* mappix-waypoints
*
* 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 "mappix.h"
#include "geo-tools.h"
static void
fill_liststore(GtkListStore *store, GList *waypoints)
{
GtkTreeIter iter;
GList *lp;
waypoint *wpdata;
gdouble lat, lon;
if (waypoints == NULL)
return;
if (waypoints->data == NULL)
return;
lp = waypoints;
do {
wpdata = (waypoint *)lp->data;
unit2latlon(wpdata->unitx, wpdata->unity, lat, lon);
gtk_list_store_append(store, &iter);
gtk_list_store_set (store, &iter, 0, wpdata->name, 1, lat, 2, lon, 3, lp, -1);
} while ((lp = g_list_next(lp)));
}
static void
wp_tv_add_columns (GtkTreeView *treeview, mapwin *Mapper)
{
GtkCellRenderer *renderer;
GtkTreeViewColumn *column;
// GtkTreeModel *model;
// model = gtk_tree_view_get_model(Mapper->track_treeview);
renderer = gtk_cell_renderer_text_new ();
column = gtk_tree_view_column_new_with_attributes ("Name", renderer, "text", 0, NULL);
//gtk_tree_view_column_set_sizing (GTK_TREE_VIEW_COLUMN (column), GTK_TREE_VIEW_COLUMN_FIXED);
//gtk_tree_view_column_set_fixed_width (GTK_TREE_VIEW_COLUMN (column), 50);
gtk_tree_view_append_column (treeview, column);
renderer = gtk_cell_renderer_text_new ();
column = gtk_tree_view_column_new_with_attributes ("Latitude", renderer, "text", 1, NULL);
// gtk_tree_view_column_set_sort_column_id (column, 1);
gtk_tree_view_append_column (treeview, column);
renderer = gtk_cell_renderer_text_new ();
column = gtk_tree_view_column_new_with_attributes ("Longitude", renderer, "text", 2, NULL);
// gtk_tree_view_column_set_sort_column_id (column, 1);
gtk_tree_view_append_column (treeview, column);
gtk_tree_view_set_search_column (treeview, 0);
}
static void
delete_waypoint (GtkTreeView *treeview, GtkListStore *store, GtkWidget *parent, gpointer user_data)
{
mapwin *Mapper = (mapwin *)user_data;
waypoint *wpdata;
GtkTreeSelection *tree_selection;
GtkTreeIter iter;
GList *lp;
gint res;
GtkWidget *dialog;
tree_selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(treeview));
if (!gtk_tree_selection_get_selected(tree_selection, NULL, &iter))
return;
gtk_tree_model_get(GTK_TREE_MODEL(store), &iter, 3, &lp, -1);
wpdata = lp->data;
dialog = gtk_message_dialog_new(GTK_WINDOW(gtk_widget_get_toplevel(parent)),
GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
GTK_MESSAGE_QUESTION,
GTK_BUTTONS_YES_NO,
"Are you sure you want to delete waypoint\n%s", wpdata->name);
res = gtk_dialog_run(GTK_DIALOG(dialog));
gtk_widget_hide (dialog);
gtk_widget_destroy (dialog);
if (res != GTK_RESPONSE_YES) {
return;
}
// fprintf(stderr, "would delete %s\n", wpdata->name);
gtk_list_store_remove(GTK_LIST_STORE(store), &iter);
Mapper->waypoints = g_list_remove(lp, wpdata);
g_free(wpdata);
}
static void
edit_waypoint (GtkTreeView *treeview, GtkListStore *store, GtkWidget *parent, gpointer user_data)
{
// mapwin *Mapper = (mapwin *)user_data;
waypoint *wpdata;
GtkTreeSelection *tree_selection;
GtkTreeIter iter;
GList *lp;
gint result;
GtkWidget *dialog, *hbox, *stock, *table, *label;
GtkWidget *entry_name, *entry_lat, *entry_lon;
gdouble lat, lon;
const gchar *tmp_name;
tree_selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(treeview));
if (!gtk_tree_selection_get_selected(tree_selection, NULL, &iter))
return;
gtk_tree_model_get(GTK_TREE_MODEL(store), &iter, 3, &lp, -1);
wpdata = lp->data;
unit2latlon(wpdata->unitx, wpdata->unity, lat, lon);
dialog = gtk_dialog_new_with_buttons("Edit waypoint", GTK_WINDOW(gtk_widget_get_toplevel(parent)),
GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
GTK_STOCK_OK,
GTK_RESPONSE_ACCEPT,
GTK_STOCK_CANCEL,
GTK_RESPONSE_REJECT,
NULL);
hbox = gtk_hbox_new (FALSE, 8);
gtk_container_set_border_width (GTK_CONTAINER (hbox), 8);
gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), hbox, FALSE, FALSE, 0);
stock = gtk_image_new_from_stock (GTK_STOCK_DIALOG_QUESTION, GTK_ICON_SIZE_DIALOG);
gtk_box_pack_start (GTK_BOX (hbox), stock, FALSE, FALSE, 0);
table = gtk_table_new (3, 4, FALSE);
gtk_table_set_row_spacings (GTK_TABLE (table), 4);
gtk_table_set_col_spacings (GTK_TABLE (table), 4);
gtk_table_set_homogeneous(GTK_TABLE (table), FALSE);
gtk_box_pack_start (GTK_BOX (hbox), table, TRUE, TRUE, 0);
label = gtk_label_new ("Name");
gtk_table_attach_defaults (GTK_TABLE (table),
label,
0, 1, 0, 1);
// track_combo = gtk_combo_box_new_text();
entry_name = gtk_entry_new();
gtk_entry_set_text(GTK_ENTRY(entry_name), wpdata->name);
gtk_entry_set_editable(GTK_ENTRY(entry_name), TRUE);
gtk_table_attach_defaults (GTK_TABLE (table), entry_name, 1, 2, 0, 1);
label = gtk_label_new ("Latitude");
gtk_table_attach_defaults (GTK_TABLE (table),
label,
0, 1, 1, 2);
entry_lat = gtk_spin_button_new_with_range(0.0, 360.0, 0.00000001);
gtk_spin_button_set_digits(GTK_SPIN_BUTTON(entry_lat), 8);
gtk_spin_button_set_value(GTK_SPIN_BUTTON(entry_lat), lat);
gtk_table_attach_defaults (GTK_TABLE (table), entry_lat, 1, 2, 1, 2);
label = gtk_label_new ("Longitude");
gtk_table_attach_defaults (GTK_TABLE (table),
label,
0, 1, 2, 3);
entry_lon = gtk_spin_button_new_with_range(0.0, 360.0, 0.00000001);
gtk_spin_button_set_digits(GTK_SPIN_BUTTON(entry_lon), 8);
gtk_spin_button_set_value(GTK_SPIN_BUTTON(entry_lon), lon);
gtk_table_attach_defaults (GTK_TABLE (table), entry_lon, 1, 2, 2, 3);
gtk_widget_show_all (hbox);
result = gtk_dialog_run (GTK_DIALOG (dialog));
gtk_widget_hide (dialog);
switch (result) {
case GTK_RESPONSE_ACCEPT:
tmp_name = gtk_entry_get_text(GTK_ENTRY(entry_name));
g_free(wpdata->name);
wpdata->name = g_strdup(tmp_name);
lat = gtk_spin_button_get_value(GTK_SPIN_BUTTON(entry_lat));
lon = gtk_spin_button_get_value(GTK_SPIN_BUTTON(entry_lon));
latlon2unit(lat, lon, wpdata->unitx, wpdata->unity)
gtk_list_store_set(GTK_LIST_STORE(store), &iter, 0, wpdata->name, 1, lat, 2, lon, -1);
break;
default:
break;
}
gtk_widget_destroy (dialog);
}
static void
new_waypoint (GtkTreeView *treeview, GtkListStore *store, GtkWidget *parent, gpointer user_data)
{
mapwin *Mapper = (mapwin *)user_data;
waypoint *wpdata;
GtkTreeIter iter;
gint result;
GtkWidget *dialog, *hbox, *stock, *table, *label;
GtkWidget *entry_name, *entry_lat, *entry_lon;
gdouble lat, lon;
const gchar *tmp_name;
dialog = gtk_dialog_new_with_buttons("Edit waypoint", GTK_WINDOW(gtk_widget_get_toplevel(parent)),
GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
GTK_STOCK_OK,
GTK_RESPONSE_ACCEPT,
GTK_STOCK_CANCEL,
GTK_RESPONSE_REJECT,
NULL);
hbox = gtk_hbox_new (FALSE, 8);
gtk_container_set_border_width (GTK_CONTAINER (hbox), 8);
gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), hbox, FALSE, FALSE, 0);
stock = gtk_image_new_from_stock (GTK_STOCK_DIALOG_QUESTION, GTK_ICON_SIZE_DIALOG);
gtk_box_pack_start (GTK_BOX (hbox), stock, FALSE, FALSE, 0);
table = gtk_table_new (3, 4, FALSE);
gtk_table_set_row_spacings (GTK_TABLE (table), 4);
gtk_table_set_col_spacings (GTK_TABLE (table), 4);
gtk_table_set_homogeneous(GTK_TABLE (table), FALSE);
gtk_box_pack_start (GTK_BOX (hbox), table, TRUE, TRUE, 0);
unit2latlon(Mapper->xmin, Mapper->ymin, lat, lon);
label = gtk_label_new ("Name");
gtk_table_attach_defaults (GTK_TABLE (table),
label,
0, 1, 0, 1);
// track_combo = gtk_combo_box_new_text();
entry_name = gtk_entry_new();
gtk_entry_set_text(GTK_ENTRY(entry_name), "Label");
gtk_entry_set_editable(GTK_ENTRY(entry_name), TRUE);
gtk_table_attach_defaults (GTK_TABLE (table), entry_name, 1, 2, 0, 1);
label = gtk_label_new ("Latitude");
gtk_table_attach_defaults (GTK_TABLE (table),
label,
0, 1, 1, 2);
entry_lat = gtk_spin_button_new_with_range(0.0, 360.0, 0.00000001);
gtk_spin_button_set_digits(GTK_SPIN_BUTTON(entry_lat), 8);
gtk_spin_button_set_value(GTK_SPIN_BUTTON(entry_lat), lat);
gtk_table_attach_defaults (GTK_TABLE (table), entry_lat, 1, 2, 1, 2);
label = gtk_label_new ("Longitude");
gtk_table_attach_defaults (GTK_TABLE (table),
label,
0, 1, 2, 3);
entry_lon = gtk_spin_button_new_with_range(0.0, 360.0, 0.00000001);
gtk_spin_button_set_digits(GTK_SPIN_BUTTON(entry_lon), 8);
gtk_spin_button_set_value(GTK_SPIN_BUTTON(entry_lon), lon);
gtk_table_attach_defaults (GTK_TABLE (table), entry_lon, 1, 2, 2, 3);
gtk_widget_show_all (hbox);
result = gtk_dialog_run (GTK_DIALOG (dialog));
gtk_widget_hide (dialog);
switch (result) {
case GTK_RESPONSE_ACCEPT:
tmp_name = gtk_entry_get_text(GTK_ENTRY(entry_name));
wpdata = (waypoint *)g_malloc(sizeof(waypoint));
wpdata->name = g_strdup(tmp_name);
lat = gtk_spin_button_get_value(GTK_SPIN_BUTTON(entry_lat));
lon = gtk_spin_button_get_value(GTK_SPIN_BUTTON(entry_lon));
latlon2unit(lat, lon, wpdata->unitx, wpdata->unity)
Mapper->waypoints = g_list_prepend(Mapper->waypoints, wpdata);
gtk_list_store_append(store, &iter);
gtk_list_store_set(GTK_LIST_STORE(store), &iter, 0, wpdata->name, 1, lat, 2, lon, -1);
break;
default:
break;
}
gtk_widget_destroy (dialog);
}
void
on_editview_waypoints (GtkWidget *widget, gpointer user_data)
{
mapwin *Mapper = (mapwin *)user_data;
GtkWidget *dialog;
gint dresult;
GtkWidget *w;
GtkWidget *wp_treeview;
GtkTreeModel *tree_model;
gboolean changed=FALSE;
dialog = gtk_dialog_new_with_buttons ("My dialog", GTK_WINDOW(gtk_widget_get_toplevel(Mapper->mainwin)),
GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
"Edit", 1,
"Delete", 2,
"New", 3,
GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
NULL);
/* track list in treeview */
w = gtk_scrolled_window_new (NULL, NULL);
gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (w), GTK_SHADOW_ETCHED_IN);
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (w), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), w, TRUE, TRUE, 0);
gtk_widget_show(w);
tree_model = GTK_TREE_MODEL(gtk_list_store_new (4, G_TYPE_STRING, G_TYPE_DOUBLE, G_TYPE_DOUBLE, G_TYPE_POINTER));
wp_treeview = gtk_tree_view_new_with_model (tree_model);
#if 0
#ifdef HILDON
g_object_set(G_OBJECT(Mapper->track_treeview), "allow-checkbox-mode", FALSE, NULL);
gtk_tree_view_set_hover_selection(GTK_TREE_VIEW(Mapper->track_treeview), FALSE);
#endif
#endif
gtk_tree_view_set_rules_hint (GTK_TREE_VIEW (wp_treeview), TRUE);
g_object_unref (tree_model);
gtk_container_add (GTK_CONTAINER (w), wp_treeview);
gtk_widget_show(wp_treeview);
wp_tv_add_columns(GTK_TREE_VIEW (wp_treeview), Mapper);
fill_liststore(GTK_LIST_STORE(tree_model), Mapper->waypoints);
gtk_widget_show_all (dialog);
dresult = 0;
while (dresult >= 0) {
dresult = gtk_dialog_run(GTK_DIALOG(dialog));
switch (dresult) {
case 1:
edit_waypoint(GTK_TREE_VIEW(wp_treeview), GTK_LIST_STORE(tree_model), dialog, Mapper);
changed = TRUE;
break;
case 2:
delete_waypoint(GTK_TREE_VIEW(wp_treeview), GTK_LIST_STORE(tree_model), dialog, Mapper);
changed = TRUE;
break;
case 3:
new_waypoint(GTK_TREE_VIEW(wp_treeview), GTK_LIST_STORE(tree_model), dialog, Mapper);
changed = TRUE;
break;
default:
break;
}
}
gtk_widget_hide(dialog);
gtk_widget_destroy(dialog);
if (changed)
do_redraw(Mapper);
}

27
mappix-waypoints.h Normal file
View file

@ -0,0 +1,27 @@
/*
* mappix-waypoints.h
*
* Copyright (C) 2006 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef _MAPPIX_WAYPOINTS_H
#define _MAPPIX_WAYPOINTS_H
void on_editview_waypoints (GtkWidget *, gpointer );
#endif

53
mappix.c Normal file
View file

@ -0,0 +1,53 @@
/*
*
* mappix
*
* Copyright (C) 2006 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
*
*/
/* we don't do much here, mainly fire up the UI */
#include <stdio.h>
#include "mappix.h"
int main(int argc, char **argv)
{
mapwin Mapper;
#ifdef HILDON
osso_context_t *context;
#endif
gtk_init (&argc, &argv);
#ifdef HILDON
context = osso_initialize (OSSO_SERVICE_NAME, APP_VER, TRUE, NULL);
g_assert(context);
#endif
Mapper.tracklist = NULL;
Mapper.waypoints = NULL;
Mapper.cities = NULL;
create_main_window(&Mapper);
gtk_main();
return 0;
}

133
mappix.h Normal file
View file

@ -0,0 +1,133 @@
/*
* mappix
*
* Copyright (C) 2006 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
*
*/
#ifndef _MAPPIX_H
#define _MAPPIX_H
#ifdef __cplusplus
extern "C"
{
#endif
#include <glib.h>
#include <glib/gstdio.h>
#include <gtk/gtk.h>
#include <libintl.h>
#include <locale.h>
#include <math.h>
#ifdef HILDON
#include <hildon-widgets/hildon-app.h>
#include <hildon-widgets/hildon-appview.h>
#include <hildon-widgets/gtk-infoprint.h>
#include <libosso.h>
#define APP_NAME "mappix"
#define APP_VER "0.1-1"
#define OSSO_SERVICE_NAME "mappix"
#endif
#include "trackdata.h"
/* what are we doing right now? */
typedef enum {
MAPPIX_TOOL_NONE,
MAPPIX_TOOL_ZOOM_REGION,
MAPPIX_TOOL_SELECT_REGION,
MAPPIX_TOOL_MOVE,
MAPPIX_TOOL_SELECT_TRACKPOINT,
MAPPIX_TOOL_MOVE_TRACKPOINT
} MappixToolmode;
typedef enum {
MARKER_TYPE_NONE,
MARKER_TYPE_FILLED_SQUARE,
MARKER_TYPE_SQUARE,
MARKER_TYPE_CROSS,
MARKER_SELECTED = 0x80
} MappixMarkerType;
// to avoid globals we pass around a monster-struct
typedef struct {
GtkWidget *mainwin;
#ifdef HILDON
HildonApp *hildon_app;
HildonAppView *hildon_mainview;
#endif
GdkCursor *cursor_normal, *cursor_mover, *cursor_crosshair, *cursor_hand, *cursor_select;
GtkWidget *track_treeview;
GtkWidget *drawarea;
GdkGC *red_gc;
GdkGC *blue_gc;
GdkGC *select_gc;
GdkPixmap *mappix;
GdkPixmap *mappix_blank;
GtkWidget *statbar;
GtkRadioToolButton *zoom_area_toggle_button, *move_toggle_button;
gint linewidth;
MappixMarkerType marker_type; // 0=no marker, 1=filled square, 2=non-filled square, 3=cross
gint marker_size;
gboolean show_marker;
guint lstatid; // ID of last statusbar message
gint canvas_x;
gint canvas_y;
double xscale;
double yscale;
double scale;
gint xoffset;
gint yoffset;
guint pointer_x, pointer_y; // scaled coordinates
guint mouse_x, mouse_y; // unscaled coordinates
guint mouse_px, mouse_py; // unscaled coordinates of last mouse button press
gint xmin, xmax;
gint ymin, ymax;
MappixToolmode toolmode;
gboolean modified;
gboolean use_idledraw;
gboolean draw_idle_active; // we redraw the tracks in idle loop
// gboolean use_ellipse_projection;
gboolean draw_selection;
gboolean move_selection;
GList *tracklist;
GList *waypoints;
GList *cities;
gboolean show_waypoints;
gboolean show_cities;
gboolean show_scale;
} mapwin;
#include "mappix-ui.h"
#include "mappix-trackdraw.h"
#include "mappix-trackedit.h"
#include "mappix-gpxreader.h"
#include "mappix-trackrecord.h"
#include "mappix-fileio.h"
#include "mappix-waypoints.h"
#ifdef __cplusplus
}
#endif
#endif /* _MAPPIX_H */

218
nmeap.h Normal file
View file

@ -0,0 +1,218 @@
/*
Copyright (c) 2005, David M Howard (daveh at dmh2000.com)
All rights reserved.
This product is licensed for use and distribution under the BSD Open Source License.
see the file COPYING for more details.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __NMEAP_H__
#define __NMEAP_H__
#ifdef __cplusplus
extern "C" {
#endif
#define NDEBUG 1
/*
============================================
COMPILE TIME CONFIGURATION CONSTANTS
============================================
*/
/* these constants affect the size of the context object. tweak them as desired but know what you are doing */
/** maximum number of sentence parsers supported */
#define NMEAP_MAX_SENTENCES 8
/** length of sentence name. leave this at 5 unless you really know what you are doing */
#define NMEAP_MAX_SENTENCE_NAME_LENGTH 5
/** max length of a complete sentence. the standard says 82 bytes, but its probably better to go at least 128 since
* some units don't adhere to the 82 bytes especially for proprietary sentences */
#define NMEAP_MAX_SENTENCE_LENGTH 255
/** max tokens in one sentence. 24 is enough for any standard sentence */
#define NMEAP_MAX_TOKENS 24
/* predefined message ID's */
/* GGA MESSAGE ID */
#define NMEAP_GPGGA 1
/* RMC MESSAGE ID */
#define NMEAP_GPRMC 2
/** user defined parsers should make ID numbers using NMEAP_USER as the base value, plus some increment */
#define NMEAP_USER 100
/* forward references */
struct nmeap_context;
struct nmeap_sentence;
/*
============================================
CALLOUTS
============================================
*/
/**
* sentence callout function type
* a callout is fired for each registered sentence type
* the callout gets the object context and a pointer to sentence specific data.
* the callout must cast the 'sentence_data' to the appropriate type for that callout
* @param context nmea object context
* @param sentence_data sentence specific data
*/
typedef void (*nmeap_callout_t)(struct nmeap_context *context,void *sentence_data,void *user_data);
/**
* sentence parser function type
* stored in the object context and called internally when the sentence name matches
* the specified value
* the callout gets the object context and a pointer to sentence specific data.
* the callout must cast the 'sentence_data' to the appropriate type for that callout
* @param context nmea object context
* @param sentence_data sentence specific data
* @return id of sentence (each sentence parser knows its own ID)
*/
typedef int (*nmeap_sentence_parser_t)(struct nmeap_context *context,struct nmeap_sentence *sentence);
/* ==== opaque types === */
#include "nmeap_def.h"
/*
============================================
STANDARD SENTENCE DATA STRUCTURES
============================================
*/
/** extracted data from a GGA message */
struct nmeap_gga {
double latitude;
double longitude;
double altitude;
unsigned long time;
int satellites;
int quality;
double hdop;
double geoid;
};
typedef struct nmeap_gga nmeap_gga_t;
/** extracted data from an RMC message */
struct nmeap_rmc {
unsigned long time;
char warn;
double latitude;
double longitude;
double speed;
double course;
unsigned long date;
double magvar;
};
typedef struct nmeap_rmc nmeap_rmc_t;
/*
============================================
METHODS
============================================
*/
/**
* initialize an NMEA parser. call this function to initialize a user allocated context object
* @param context nmea object context. allocated by user statically or dynamically.
* @param user_data pointer to user defined data
* @return 0 if ok, -1 if initialization failed
*/
int nmeap_init(nmeap_context_t *context,void *user_data);
/**
* register an NMEA sentence parser
* @param context nmea object context
* @param sentence_name string matching the sentence name for this parser. e.g. "GPGGA". not including the '$'
* @param sentence_parser parser function for this sentence
* @param sentence_callout callout triggered when this sentence is received and parsed.
* if null, no callout is triggered for this sentence
* @param sentence_data user allocated sentence specific data defined by the application. the parser uses
this data item to store the extracted data. This data object needs to persist over the life
of the parser, so be careful if allocated on the stack.
* @return 0 if registered ok, -1 if registration failed
*/
int nmeap_addParser(nmeap_context_t *context,
const char *sentence_name,
nmeap_sentence_parser_t sentence_parser,
nmeap_callout_t sentence_callout,
void *sentence_data
);
/**
* parse a buffer of nmea data.
* @param context nmea object context
* @param buffer buffer of input characters
* @param length [in,out] pointer to length of buffer. on return, contains number of characters not used for
* the current sentence
* @return -1 if error, 0 if the data did not complete a sentence, sentence code if a sentence was found in the stream
*/
int nmeap_parseBuffer(nmeap_context_t *context,const char *buffer,int *length);
/**
* parse one character of nmea data.
* @param context nmea object context
* @param ch input character
* @return -1 if error, 0 if the data did not complete a sentence, sentence code if a sentence was found in the stream
*/
int nmeap_parse(nmeap_context_t *context,char ch);
/**
* built-in parser for GGA sentences.
* @param context nmea object context
* @param sentence sentence object for this parser
*/
int nmeap_gpgga(nmeap_context_t *context,nmeap_sentence_t *sentence);
/**
* built-in parser for RMC sentences.
* @param context nmea object context
* @param sentence sentence object for this parser
*/
int nmeap_gprmc(nmeap_context_t *context,nmeap_sentence_t *sentence);
/**
* extract latitude from 2 tokens in ddmm.mmmm,h format.
* @param plat pointer to token with numerical latitude
* @param phem pointer to token with hemisphere
* @return latitude in degrees and fractional degrees
*/
double nmeap_latitude(const char *plat,const char *phem);
/**
* extract longitude from 2 tokens in ddmm.mmmm,h format.
* @param plat pointer to token with numerical longitude
* @param phem pointer to token with hemisphere
* @return longitude in degrees and fractional degrees
*/
double nmeap_longitude(const char *plat,const char *phem);
#ifdef __cplusplus
} // extern C
#endif
#endif

621
nmeap01.c Normal file
View file

@ -0,0 +1,621 @@
/*
Copyright (c) 2005, David M Howard (daveh at dmh2000.com)
All rights reserved.
This product is licensed for use and distribution under the BSD Open Source License.
see the file COPYING for more details.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/**
* nmeap01.c
* nmeap gps data parser
*
* see the file COPYING for terms of the licnese
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <ctype.h>
#include "nmeap.h"
/* this only works if you are sure you have an upper case hex digit */
#define HEXTOBIN(ch) ((ch <= '9') ? ch - '0' : ch - ('A' - 10))
/* forward references */
int nmeap_init(nmeap_context_t *context,void *user_data);
int nmeap_addParser(nmeap_context_t *context,
const char *sentence_name,
nmeap_sentence_parser_t sentence_parser,
nmeap_callout_t sentence_callout,
void *sentence_data
);
int nmeap_tokenize(nmeap_context_t *context);
int nmeap_process(nmeap_context_t *context);
int nmeap_parse(nmeap_context_t *context,char ch);
int nmeap_parseBuffer(nmeap_context_t *context,const char *buffer,int *length);
/**
* get a latitude out of a pair of nmea tokens
*/
double nmeap_latitude(const char *plat,const char *phem)
{
double lat;
int deg;
double min;
int ns;
assert(plat != 0);
assert(phem != 0);
if (*plat == 0) {
return 0.0;
}
if (*phem == 0) {
return 0.0;
}
/* north lat is +, south lat is - */
if (*phem == 'N') {
ns = 1;
}
else {
ns = -1;
}
/* latitude is degrees, minutes, fractional minutes */
/* no validation is performed on the token. it better be good.*/
/* if it comes back 0.0 then probably the token was bad */
lat = atof(plat);
/* extract the degree part */
deg = (int)(lat / 100.0);
/* mask out the degrees */
min = lat - (deg * 100.0);
/* compute the actual latitude in degrees.decimal-degrees */
lat = (deg + (min / 60.0)) * ns;
return lat;
}
/**
* get a longitude out of a pair of nmea tokens
*/
double nmeap_longitude(const char *plon,const char *phem)
{
double lon;
int deg;
double min;
int ew;
assert(plon != 0);
assert(phem != 0);
if (*plon == 0) {
return 0.0;
}
if (*phem == 0) {
return 0.0;
}
/* west long is negative, east long is positive */
if (*phem == 'E') {
ew = 1;
}
else {
ew = -1;
}
/* longitude is degrees, minutes, fractional minutes */
/* no validation is performed on the token. it better be good.*/
/* if it comes back 0.0 then probably the token was bad */
lon = atof(plon);
/* extract the degree part */
deg = (int)(lon / 100.0);
/* mask out the degrees */
min = lon - (deg * 100.0);
/* compute the actual lonitude in degrees.decimal-degrees */
lon = (deg + (min / 60.0)) * ew;
return lon;
}
/**
* get an altitude longitude out of a pair of nmea tokens
* ALTITUDE is returned in METERS
*/
double nmeap_altitude(const char *palt,const char *punits)
{
double alt;
if (*palt == 0) {
return 0.0;
}
/* convert with no error checking */
alt = atof(palt);
if (*punits == 'M') {
/* already in meters */
}
else if (*punits == 'F') {
/* convert to feet */
alt = alt * 3.2808399;
}
return alt;
}
/**
* initialize an NMEA parser
*/
int nmeap_init(nmeap_context_t *context,void *user_data)
{
assert(context != 0);
memset(context,0,sizeof(*context));
context->user_data = user_data;
return 0;
}
/**
* register an NMEA sentence parser
*/
int nmeap_addParser(nmeap_context_t *context,
const char *sentence_name,
nmeap_sentence_parser_t sentence_parser,
nmeap_callout_t sentence_callout,
void *sentence_data
)
{
nmeap_sentence_t *s = 0;
/* runtime error */
assert(context != 0);
/* sentence capacity overflow */
if (context->sentence_count >= NMEAP_MAX_SENTENCES) {
return -1;
}
/* point at next empty sentence buffer */
s = &context->sentence[context->sentence_count];
/* advance sentence data count */
context->sentence_count++;
/* clear the sentence data */
memset(s,0,sizeof(*s));
/* name */
strncpy(s->name,sentence_name,NMEAP_MAX_SENTENCE_NAME_LENGTH);
/* parser */
s->parser = sentence_parser;
/* callout */
s->callout = sentence_callout;
/* data */
s->data = sentence_data;
return 0;
}
/**
* tokenize a buffer
*/
int nmeap_tokenize(nmeap_context_t *context)
{
char *s;
int tokens;
int state;
/* first token is header. assume it is there */
tokens = 0;
s = context->input;
context->token[tokens] = s;
/* get rest of tokens */
tokens = 1;
state = 0;
while((*s != 0)&&(tokens < NMEAP_MAX_TOKENS)) {
switch(state) {
case 0:
/* looking for end of a token */
if (*s == ',') {
/* delimit at the comma */
*s = 0;
/* new token */
state = 1;
}
break;
case 1:
/* start of next token, might be another comma */
context->token[tokens++] = s;
if (*s == ',') {
/* delimit at the comma */
*s = 0;
}
else {
/* not a comma */
state = 0;
}
break;
default:
state = 0;
break;
}
// next character
s++;
}
return tokens;
}
/**
* process a sentence
*/
int nmeap_process(nmeap_context_t *context)
{
int id=0;
int i;
nmeap_sentence_t *s;
/* copy the input to a debug buffer */
/* remove debug_input when everything is working. */
strncpy(context->debug_input,context->input,sizeof(context->debug_input));
/* tokenize the input */
context->tokens = nmeap_tokenize(context);
/* try to find a matching sentence parser */
/* this search is O(n). it has a lot of potential for optimization, at the expense of complexity, if you have a lot of sentences */
/* binary search instead of linear (have to keep sentences in sorted order) O(NlogN) */
/* OR, when sentences are added, create a TRIE structure to find the names with a constant time search O(5) */
for(i=0;i<context->sentence_count;i++) {
s = &context->sentence[i];
assert(s != 0);
if (strncmp(context->input_name,s->name,5) == 0) {
/* found a match, call its parser */
id = (*context->sentence[i].parser)(context,s);
if (id > 0) {
break;
}
}
}
return id;
}
/**
+-5-+ +---+
v | v |
+------+ +------+ +------+ +------+ +------+
| 0 |--$--> |1-hdr |--alnum--> |2-data|----\r-->| 6-LF |---\n--->| done |--> 0
+------+ +------+ +------+ +------+ +------+
| ^
* +--------\r-------+
V |
+------+ +------+ +------+
|3-cks |--xdigit-->|4-cks |-xdigit->| 5-CR |
+------+ +------+ +------+
return to start conditions:
1. buffer overflow
2. invalid character for state
checksum calculation
two hex digits represent the XOR of all characters between, but not
including, the "$" and "*". A checksum is required on some
sentences.
*/
int nmeap_parse(nmeap_context_t *context,char ch)
{
int status = 0;
/* check for input buffer overrun first to avoid duplicating code in the
individual states
*/
if (context->input_count >= (sizeof(context->input)-1)) {
/* input buffer overrun, restart state machine */
context->input_state = 0;
/* reset input count */
context->input_count = 0;
}
/* store the byte */
context->input[context->input_count] = ch;
/* next buffer position */
context->input_count++;
/* run it through the lexical scanner */
switch(context->input_state) {
/* LOOKING FOR $ */
case 0:
if (ch == '$') {
/*look for id */
context->input_state = 1;
context->ccks = 0;
context->icks = 0;
}
else {
/* header error, start over */
context->err_hdr++;
context->input_state = 0;
context->input_count = 0;
}
break;
/* LOOKING FOR 5 CHARACTER SENTENCE ID */
case 1:
/* allow numbers even though it isn't usually done */
/* a proprietary id might have a numeral */
if (isalnum(ch)) {
/* store name separately */
context->input_name[context->input_count - 2] = ch;
/* checksum */
context->ccks ^= ch;
/* end of header? */
if (context->input_count >= 6) {
/* yes, get body */
context->input_state = 2;
}
}
else {
/* bad character, start over */
context->err_id++;
context->input_state = 0;
context->input_count = 0;
}
break;
/* LOOKING FOR CR OR CHECKSUM INDICATOR */
case 2:
if (ch == '*') {
/* this sentence has a checksum */
context->input_state = 3;
}
else if (ch == '\r') {
/* carriage return, no checksum, force a match */
context->icks = 0;
context->ccks = 0;
context->input_state = 6;
}
else {
/* continue accumulating data */
/* checksum */
context->ccks ^= ch;
}
break;
/* LOOKING FOR FIRST CHECKSUM CHARACTER */
case 3:
/* must be upper case hex digit */
if (isxdigit(ch) && (ch <= 'F')) {
/* got first checksum byte */
context->input_state = 4;
context->icks = HEXTOBIN(ch) << 4;
}
else {
/* input error, restart */
context->err_cks++;
context->input_state = 0;
context->input_count = 0;
}
break;
/* LOOKING FOR SECOND CHECKSUM CHARACTER */
case 4:
/* must be upper case hex digit */
if (isxdigit(ch) && (ch <= 'F')) {
/* got second checksum byte */
context->input_state = 5;
context->icks += HEXTOBIN(ch);
}
else {
/* input error, restart */
context->err_cks++;
context->input_state = 0;
context->input_count = 0;
}
break;
/* LOOKING FOR CR */
case 5:
if (ch == '\r') {
/* carriage return */
context->input_state = 6;
}
else {
/* input error, restart */
context->err_crl++;
context->input_state = 0;
context->input_count = 0;
}
break;
/* LOOKING FOR LINE FEED */
case 6:
if (ch == '\n') {
/* linefeed, line complete */
/* delimit buffer */
context->input[context->input_count] = 0;
/* if the checksums match, process the sentence */
if (context->ccks == context->icks) {
/* process */
status = nmeap_process(context);
/* count good messages */
context->msgs++;
}
else {
/* count checksum errors */
context->err_cks++;
}
/* restart next time */
context->input_state = 0;
context->input_count = 0;
}
else {
/* input error, restart */
context->err_crl++;
context->input_state = 0;
context->input_count = 0;
}
break;
default:
context->err_unk++;
context->input_state = 0;
break;
}
return status;
}
/**
* parse a buffer of nmea data
*/
int nmeap_parseBuffer(nmeap_context_t *context,const char *buffer,int *length)
{
int i;
int status;
int rem;
int tlen;
tlen = *length;
rem = *length;
status = 0;
/* for each byte in the buffer */
for(i=0;i<tlen;i++) {
/* decrement remaining byte count */
rem--;
/* parse the byte */
status = nmeap_parse(context,buffer[i]);
if (status != 0) {
/* message found or error */
break;
}
}
/* return remaining byte count */
*length = rem;
return status;
}
/**
* standard GPGGA sentence parser
*/
int nmeap_gpgga(nmeap_context_t *context,nmeap_sentence_t *sentence)
{
#ifndef NDEBUG
int i;
#endif
/* get pointer to sentence data */
nmeap_gga_t *gga = (nmeap_gga_t *)sentence->data;
/* if there is a data element, extract data from the tokens */
if (gga != 0) {
gga->latitude = nmeap_latitude(context->token[2],context->token[3]);
gga->longitude = nmeap_longitude(context->token[4],context->token[5]);
gga->altitude = nmeap_altitude(context->token[9],context->token[10]);
gga->time = atoi(context->token[1]);
gga->satellites = atoi(context->token[7]);
gga->quality = atoi(context->token[6]);
gga->hdop = atof(context->token[8]);
gga->geoid = nmeap_altitude(context->token[11],context->token[12]);
}
#ifndef NDEBUG
/* print raw input string */
printf("%s",context->debug_input);
/* print some validation data */
printf("%s==%s %02x==%02x\n",context->input_name,sentence->name,context->icks,context->ccks);
/* print the tokens */
for(i=0;i<context->tokens;i++) {
printf("%d:%s\n",i,context->token[i]);
}
#endif
/* if the sentence has a callout, call it */
if (sentence->callout != 0) {
(*sentence->callout)(context,gga,context->user_data);
}
return NMEAP_GPGGA;
}
/**
* standard GPRMCntence parser
*/
int nmeap_gprmc(nmeap_context_t *context,nmeap_sentence_t *sentence)
{
#ifndef NDEBUG
int i;
#endif
/* get pointer to sentence data */
nmeap_rmc_t *rmc = (nmeap_rmc_t *)sentence->data;
/* if there is a data element, use it */
if (rmc != 0) {
/* extract data from the tokens */
rmc->time = atoi(context->token[1]);
rmc->warn = *context->token[2];
rmc->latitude = nmeap_latitude(context->token[3],context->token[4]);
rmc->longitude = nmeap_longitude(context->token[5],context->token[6]);
rmc->speed = atof(context->token[7]);
rmc->course = atof(context->token[8]);
rmc->date = atoi(context->token[9]);
rmc->magvar = atof(context->token[10]);
}
#ifndef NDEBUG
/* print raw input string */
printf("%s",context->debug_input);
/* print some validation data */
printf("%s==%s %02x==%02x\n",context->input_name,sentence->name,context->icks,context->ccks);
/* print the tokens */
for(i=0;i<context->tokens;i++) {
printf("%d:%s\n",i,context->token[i]);
}
#endif
/* if the sentence has a callout, call it */
if (sentence->callout != 0) {
(*sentence->callout)(context,rmc,context->user_data);
}
return NMEAP_GPRMC;
}

72
nmeap_def.h Normal file
View file

@ -0,0 +1,72 @@
/*
Copyright (c) 2005, David M Howard (daveh at dmh2000.com)
All rights reserved.
This product is licensed for use and distribution under the BSD Open Source License.
see the file COPYING for more details.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __NMEAP_DEF_H__
#define __NMEAP_DEF_H__
/**
* context for a single sentence
*/
typedef struct nmeap_sentence {
char name[NMEAP_MAX_SENTENCE_NAME_LENGTH + 1];
int id;
nmeap_sentence_parser_t parser;
nmeap_callout_t callout;
void *data;
} nmeap_sentence_t;
/**
* parser context
*/
struct nmeap_context {
/** support up to 8 sentences */
nmeap_sentence_t sentence[NMEAP_MAX_SENTENCES]; /* sentence descriptors */
int sentence_count; /* number of initialized descriptors */
/** sentence input buffer */
char input[NMEAP_MAX_SENTENCE_LENGTH + 1]; /* input line buffer */
int input_count; /* index into 'input */
int input_state; /* current lexical scanner state */
char input_name[6]; /* sentence name */
char icks; /* input checksum */
char ccks; /* computed checksum */
/* tokenization */
char *token[NMEAP_MAX_TOKENS]; /* list of delimited tokens */
int tokens; /* list of tokens */
/** errors and debug. optimize these as desired */
unsigned long msgs; /* count of good messages */
unsigned long err_hdr; /* header error */
unsigned long err_ovr; /* overrun error */
unsigned long err_unk; /* unknown error */
unsigned long err_id; /* bad character in id */
unsigned long err_cks; /* bad checksum */
unsigned long err_crl; /* expecting cr or lf, got something else */
char debug_input[NMEAP_MAX_SENTENCE_LENGTH + 1]; /* input line buffer for debug */
/** opaque user data */
void *user_data;
};
typedef struct nmeap_context nmeap_context_t;
#endif /* __NMEAP_DEF_H__ */

Binary file not shown.

After

Width:  |  Height:  |  Size: 454 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 412 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 202 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 790 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 605 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 510 B

BIN
pixmaps/stock_delete.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 552 B

BIN
pixmaps/stock_frame.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 267 B

BIN
pixmaps/stock_node-add.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 443 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 466 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 630 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 434 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 427 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 741 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 670 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 764 B

BIN
pixmaps/stock_node-move.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 678 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 407 B

BIN
pixmaps/stock_zoom-1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

BIN
pixmaps/stock_zoom-in.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

BIN
pixmaps/stock_zoom-next.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

BIN
pixmaps/stock_zoom-out.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

BIN
pixmaps/stock_zoom-page.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

BIN
pixmaps/stock_zoom.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 997 B

88
trackdata.h Normal file
View file

@ -0,0 +1,88 @@
/*
* trackdata
*
* 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
*
*/
#ifndef _TRACKDATA_H_
#define _TRACKDATA_H_
/* track element */
typedef struct {
// data
gint unitx;
gint unity;
gfloat elevation;
gchar *datetime;
gchar nrsat; // number of satellites in view
gfloat hdop; // horizontal delution
gfloat vdop; // vertital delution
gfloat pdop; // ??? other dilution
// attributes for UI
gboolean selected;
} trackdata;
/* track types, LANEs are no. of lanes per direction */
typedef enum {
UNKNOWN,
OUTLINE, // like borders
RIVER,
FOOTPATH,
AGRI,
CITY,
URBAN,
MOTORWAY,
HIGHWAY,
} tracktype;
/* tracklist element */
typedef struct {
GList *track; // list of trackdata trackpoints
gboolean show; // if this track is to be drawn
gchar *name; // visible name of this track
gint xmax, ymax; // bounding box of this track
gint xmin, ymin;
tracktype type;
} track_head;
/* waypoint / POI */
typedef struct {
gint unitx;
gint unity;
gfloat elevation;
gchar *name;
} waypoint;
/*
* cities
* Cities are stored in database, internal GList if cities only stores
* the cities inside the current view
*/
typedef struct {
gint unitx;
gint unity;
gchar *name;
guint population;
} city;
#endif