2 * This file is part of mapper
4 * Copyright (C) 2008 Kaj-Michael Lang
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24 #include "mapper-types.h"
35 struct sql_select_stmt {
36 sqlite3_stmt *select_path;
37 sqlite3_stmt *select_path_nodes;
38 sqlite3_stmt *insert_path;
39 sqlite3_stmt *insert_path_node;
40 sqlite3_stmt *delete_path_nodes;
41 sqlite3_stmt *delete_path;
43 static struct sql_select_stmt sql;
45 /* Path point add sensitivity */
46 static gint sensitivity=3;
63 g_slice_free(Path, p);
71 p->length=p->avgspeed=0.0;
76 path_resize(Path *path, guint size)
78 if (path->head + size != path->cap) {
79 Point *old_head = path->head;
81 path->head = g_renew(Point, old_head, size);
82 path->cap = path->head + size;
83 if (path->head != old_head) {
84 path->tail = path->head + (path->tail - old_head);
86 /* Adjust all of the waypoints. */
87 for (curr = path->whead - 1; curr++ != path->wtail;)
88 curr->point = path->head + (curr->point - old_head);
96 path_wresize(Path *path, guint wsize)
98 if (path->whead + wsize != path->wcap) {
99 WayPoint *old_whead = path->whead;
100 path->whead = g_renew(WayPoint, old_whead, wsize);
101 path->wtail = path->whead + (path->wtail - old_whead);
102 path->wcap = path->whead + wsize;
109 path_add_point(Path *path, GpsData *gps)
112 MACRO_PATH_INCREMENT_TAIL(*path);
113 *path->tail=_point_null;
117 if (abs((gint)gps->unitx-path->tail->unitx) > sensitivity || abs((gint)gps->unity-path->tail->unity) > sensitivity) {
118 if (path->tail->unity && path->tail->unitx) {
121 unit2latlon(path->tail->unitx, path->tail->unity, lat, lon);
122 path->length+=calculate_distance(lat, lon, gps->lat, gps->lon);
124 MACRO_PATH_INCREMENT_TAIL(*path);
125 path->tail->unitx=gps->unitx;
126 path->tail->unity=gps->unity;
127 path->tail->time=gps->time;
128 path->tail->altitude=gps->altitude;
129 path->maxspeed=gps->maxspeed;
130 path->tspeed+=gps->speed;
131 path->avgspeed=(path->points>0) ? path->tspeed/path->points : 0.0;
133 g_debug("TRACK: %f %f (%d)", path->length, path->avgspeed, path->points);
140 path_insert_break(Path *path)
148 if (path->tail->unity) {
151 /* To mark a "waypoint" in a track, we'll add a (0, 0) point and then
152 * another instance of the most recent track point. */
153 MACRO_PATH_INCREMENT_TAIL(*path);
154 *path->tail=_point_null;
155 MACRO_PATH_INCREMENT_TAIL(*path);
156 *path->tail=path->tail[-2];
159 /* Instead of calling map_render_paths(), we'll just draw the waypoint ourselves. */
160 x1 = unit2bufx(path->tail->unitx);
161 y1 = unit2bufy(path->tail->unity);
162 map_render_waypoint(x1, y1, _gc[COLORABLE_TRACK_BREAK]);
170 path_find_last_point(Path *path)
174 if (path->head == path->tail)
177 for (p=path->tail; !p->unity; p--) {
183 path_get_distance_to(Path *path, Point *point, gdouble lat, gdouble lon)
185 gdouble lat1, lon1, lat2, lon2;
188 /* If point is NULL, use the next waypoint. */
189 if (point == NULL && path->next_way)
190 point = path->next_way->point;
192 /* If point is still NULL, return an error. */
199 if (point > path->near_point) {
201 /* Skip _near_point in case we have already passed it. */
202 for (curr = path->near_point + 1; curr <= point; ++curr) {
204 unit2latlon(curr->unitx, curr->unity, lat2, lon2);
205 sum += calculate_distance(lat1, lon1, lat2, lon2);
210 } else if (point < path->near_point) {
212 /* Skip near_point in case we have already passed it. */
213 for (curr = path->near_point - 1; curr >= point; --curr) {
215 unit2latlon(curr->unitx, curr->unity, lat2, lon2);
216 sum += calculate_distance(lat1, lon1, lat2, lon2);
222 /* Waypoint _is_ the nearest point. */
223 unit2latlon(path->near_point->unitx, path->near_point->unity, lat2, lon2);
224 sum += calculate_distance(lat1, lon1, lat2, lon2);
230 path_load(Path *path, const gchar *config_dir, const gchar *file)
236 pfile = gnome_vfs_uri_make_full_from_relative(config_dir, file);
237 if (gnome_vfs_read_entire_file(pfile, &size, &bytes)==GNOME_VFS_OK)
238 gpx_parse(path, bytes, size, GPX_PATH_NEW);
244 path_save(Path *path, const gchar *config_dir, const gchar *file)
246 GnomeVFSHandle *handle;
248 tfile=gnome_vfs_uri_make_full_from_relative(config_dir, file);
249 if (gnome_vfs_create(&handle, tfile, GNOME_VFS_OPEN_WRITE, FALSE, 0600)==GNOME_VFS_OK) {
250 gpx_write(path, handle);
251 gnome_vfs_close(handle);
258 * Add a text description at current point
262 path_insert_mark_text(Path *path, gchar *text)
265 MACRO_PATH_INCREMENT_WTAIL(*path);
266 path->wtail->point=path->tail;
268 path->wtail->desc=text;
271 path->wtail->desc=g_strdup_printf("WP: %u", path->wpcnt);
276 path_generate_store(Path *path)
283 gchar tmp1[16], tmp2[16];
284 gdouble lat1, lon1, lat2, lon2;
287 if (path->whead==path->wtail)
298 unit2latlon(wcurr->point->unitx, wcurr->point->unity, lat1, lon1);
300 store=gtk_list_store_new(ROUTE_NUM_COLUMNS, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_DOUBLE, G_TYPE_DOUBLE);
302 while (wcurr!=path->wtail) {
308 g_debug("No point for waypoint (%s) skipping", wcurr->desc);
313 unit2latlon(wcurr->point->unitx, wcurr->point->unity, lat2, lon2);
314 lat_format(_degformat, lat2, tmp1);
315 lon_format(_degformat, lon2, tmp2);
317 g_snprintf(buffer1, sizeof(buffer1), "%s,%s", tmp1, tmp2);
318 sum += calculate_distance(lat1, lon1, lat2, lon2);
319 g_snprintf(buffer2, sizeof(buffer2), "%.02f %s", sum * UNITS_CONVERT[_units], UNITS_TEXT[_units]);
321 gtk_list_store_append(store, &iter);
322 gtk_list_store_set(store, &iter,
323 ROUTE_LATLON, buffer1,
324 ROUTE_DISTANCE, buffer2,
325 ROUTE_WAYPOINT, wcurr->desc,
340 position_set(Position *pos, gboolean valid, gdouble lat, gdouble lon)
343 pos->lat=valid ? lat : NAN;
344 pos->lon=valid ? lon : NAN;
348 position_update(Position *pos, GpsData *data)