From: Kaj-Michael Lang Date: Fri, 18 Apr 2008 15:07:14 +0000 (+0300) Subject: More Path/Route/Track cleanups: X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=75e019b4cb78f21a12118b2bebbda0ec565f5316;p=mapper More Path/Route/Track cleanups: - Convert more track/route specific functions to generic path functions. - Prepare for multiple tracks/routes, don't use global track/route variables in track/route functions. - Adjust common code for above changes - Still much todo... --- diff --git a/src/cb.c b/src/cb.c index 7677474..1efbbc5 100644 --- a/src/cb.c +++ b/src/cb.c @@ -77,7 +77,7 @@ store=path_generate_store(path); if (!store) return FALSE; -gtk_tree_view_set_model(tree_view, store); +gtk_tree_view_set_model(GTK_TREE_VIEW(tree_view), store); g_object_unref(G_OBJECT(store)); return TRUE; } @@ -88,7 +88,7 @@ return TRUE; gboolean menu_cb_route_download(GtkAction * action) { -route_download(NULL); +route_download(_route, NULL); route_menu_set_sensitive(path_tree_view_update_store(route_tree_view, _route)); return TRUE; } @@ -96,7 +96,7 @@ return TRUE; gboolean menu_cb_route_open(GtkAction *action) { -route_open_file(); +route_open_file(_route); route_menu_set_sensitive(path_tree_view_update_store(route_tree_view, _route)); return TRUE; } @@ -104,28 +104,28 @@ return TRUE; gboolean menu_cb_route_save(GtkAction * action) { -route_save(); +route_save(_route); return TRUE; } gboolean menu_cb_route_distnext(GtkAction * action) { -route_show_distance_to_next(); +route_show_distance_to_next(_route); return TRUE; } gboolean menu_cb_route_distlast(GtkAction * action) { -route_show_distance_to_last(); +route_show_distance_to_last(_route); return TRUE; } gboolean menu_cb_route_reset(GtkAction * action) { -route_find_nearest_point(); +route_find_nearest_point(_route); map_render_data(); MACRO_QUEUE_DRAW_AREA(); return TRUE; @@ -134,9 +134,10 @@ return TRUE; gboolean menu_cb_route_clear(GtkAction * action) { -route_clear(); -gtk_tree_view_set_model(route_tree_view, NULL); -route_menu_set_sensitive(FALSE); +if (route_clear(_route)) { + gtk_tree_view_set_model(route_tree_view, NULL); + route_menu_set_sensitive(FALSE); +} return TRUE; } @@ -146,7 +147,7 @@ return TRUE; gboolean menu_cb_track_open(GtkAction * action) { -track_open(); +track_open(_track); path_tree_view_update_store(track_tree_view, _track); return TRUE; } @@ -154,7 +155,7 @@ return TRUE; gboolean menu_cb_track_save(GtkAction * action) { -track_save(); +track_save(_track); path_tree_view_update_store(track_tree_view, _track); return TRUE; } @@ -162,7 +163,7 @@ return TRUE; gboolean menu_cb_track_insert_break(GtkAction * action) { -track_insert_break(); +path_insert_break(_track); path_tree_view_update_store(track_tree_view, _track); return TRUE; } @@ -170,7 +171,7 @@ return TRUE; gboolean menu_cb_track_insert_mark(GtkAction * action) { -if (track_insert_mark()) { +if (track_insert_mark(_track)) { map_render_paths(); MACRO_QUEUE_DRAW_AREA(); path_tree_view_update_store(track_tree_view, _track); @@ -181,21 +182,21 @@ return TRUE; gboolean menu_cb_track_distlast(GtkAction * action) { -track_show_distance_from_last(); +track_show_distance_from_last(_track); return TRUE; } gboolean menu_cb_track_distfirst(GtkAction * action) { -track_show_distance_from_first(); +track_show_distance_from_first(_track); return TRUE; } gboolean menu_cb_track_clear(GtkAction * action) { -track_clear(); +track_clear(_track); path_tree_view_update_store(track_tree_view, _track); return TRUE; } @@ -484,7 +485,7 @@ if ((_enable_gps = gtk_toggle_action_get_active(GTK_TOGGLE_ACTION(action)))) { if (_gps->io.conn > RCVR_OFF) gps_conn_set_state(_gps, RCVR_OFF); gps_disconnect(_gps); - track_add(NULL); + track_add(_track, NULL); _speed_excess=FALSE; } if (_enable_gps==FALSE) @@ -722,19 +723,19 @@ switch (event->keyval) { } break; case CUSTOM_ACTION_ROUTE_DISTNEXT: - route_show_distance_to_next(); + route_show_distance_to_next(_route); break; case CUSTOM_ACTION_ROUTE_DISTLAST: - route_show_distance_to_last(); + route_show_distance_to_last(_route); break; case CUSTOM_ACTION_TRACK_BREAK: - track_insert_break(); + path_insert_break(_track); break; case CUSTOM_ACTION_TRACK_DISTLAST: - track_show_distance_from_last(); + track_show_distance_from_last(_track); break; case CUSTOM_ACTION_TRACK_DISTFIRST: - track_show_distance_from_first(); + track_show_distance_from_first(_track); break; case CUSTOM_ACTION_TOGGLE_GPS: set_action_activate("gps_enable", !_enable_gps); @@ -812,7 +813,7 @@ g_ascii_formatd(strlat, 32, "%.06f", lat); g_ascii_formatd(strlon, 32, "%.06f", lon); g_snprintf(buffer, sizeof(buffer), "%s, %s", strlat, strlon); -route_download(buffer); +route_download(_route, buffer); } void @@ -834,7 +835,7 @@ cmenu_add_route(guint unitx, guint unity) MACRO_PATH_INCREMENT_TAIL(*_route); _route->tail->unitx = x2unit(_cmenu_position_x); _route->tail->unity = y2unit(_cmenu_position_y); -route_find_nearest_point(); +route_find_nearest_point(_route); map_force_redraw(); } @@ -855,105 +856,92 @@ dialog = gtk_dialog_new_with_buttons(_("Add Waypoint"), GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT, NULL); - gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), - table = gtk_table_new(2, 2, FALSE), TRUE, TRUE, 0); - - gtk_table_attach(GTK_TABLE(table), - label = gtk_label_new(_("Lat, Lon")), - 0, 1, 0, 1, GTK_FILL, 0, 2, 4); - gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f); - - unit2latlon(unitx, unity, lat, lon); - lat_format(_degformat, lat, tmp1); - lon_format(_degformat, lon, tmp2); - p_latlon = g_strdup_printf("%s, %s", tmp1, tmp2); - gtk_table_attach(GTK_TABLE(table), - label = gtk_label_new(p_latlon), - 1, 2, 0, 1, GTK_FILL, 0, 2, 4); - gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f); - g_free(p_latlon); - - gtk_table_attach(GTK_TABLE(table), - label = gtk_label_new(_("Description")), - 0, 1, 1, 2, GTK_FILL, 0, 2, 4); - gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f); - - txt_scroll = gtk_scrolled_window_new(NULL, NULL); - gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(txt_scroll), - GTK_SHADOW_IN); - gtk_table_attach(GTK_TABLE(table), - txt_scroll, - 1, 2, 1, 2, GTK_EXPAND | GTK_FILL, 0, 2, 4); - - gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(txt_scroll), - GTK_POLICY_AUTOMATIC, - GTK_POLICY_AUTOMATIC); - - txt_desc = gtk_text_view_new(); - gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(txt_desc), GTK_WRAP_WORD); - - gtk_container_add(GTK_CONTAINER(txt_scroll), txt_desc); - gtk_widget_set_size_request(GTK_WIDGET(txt_scroll), 400, 60); - - gtk_widget_show_all(dialog); - - while (GTK_RESPONSE_ACCEPT == gtk_dialog_run(GTK_DIALOG(dialog))) { - GtkTextBuffer *tbuf; - GtkTextIter ti1, ti2; - gchar *desc; - - tbuf = gtk_text_view_get_buffer(GTK_TEXT_VIEW(txt_desc)); - gtk_text_buffer_get_iter_at_offset(tbuf, &ti1, 0); - gtk_text_buffer_get_end_iter(tbuf, &ti2); - desc = gtk_text_buffer_get_text(tbuf, &ti1, &ti2, TRUE); - - if (*desc) { - /* There's a description. Add a waypoint. */ - MACRO_PATH_INCREMENT_TAIL(*_route); - _route->tail->unitx = unitx; - _route->tail->unity = unity; - _route->tail->time = 0; - _route->tail->altitude = NAN; +gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), table = gtk_table_new(2, 2, FALSE), TRUE, TRUE, 0); - MACRO_PATH_INCREMENT_WTAIL(*_route); - _route->wtail->point = _route->tail; - _route->wtail->desc - = gtk_text_buffer_get_text(tbuf, &ti1, &ti2, TRUE); - } else { - GtkWidget *confirm; +gtk_table_attach(GTK_TABLE(table), label = gtk_label_new(_("Lat, Lon")), 0, 1, 0, 1, GTK_FILL, 0, 2, 4); +gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f); - g_free(desc); +unit2latlon(unitx, unity, lat, lon); +lat_format(_degformat, lat, tmp1); +lon_format(_degformat, lon, tmp2); +p_latlon = g_strdup_printf("%s, %s", tmp1, tmp2); +gtk_table_attach(GTK_TABLE(table), label = gtk_label_new(p_latlon), 1, 2, 0, 1, GTK_FILL, 0, 2, 4); +gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f); +g_free(p_latlon); - confirm = hildon_note_new_confirmation(GTK_WINDOW(dialog), - _("Creating a \"waypoint\" with no description actually " - "adds a break point. Is that what you want?")); +gtk_table_attach(GTK_TABLE(table), label = gtk_label_new(_("Description")), 0, 1, 1, 2, GTK_FILL, 0, 2, 4); +gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f); - if (GTK_RESPONSE_OK == gtk_dialog_run(GTK_DIALOG(confirm))) { - /* There's no description. Add a break by adding a (0, 0) - * point (if necessary), and then the ordinary route point. */ - if (_route->tail->unity) { - MACRO_PATH_INCREMENT_TAIL(*_route); - *_route->tail = _point_null; - } +txt_scroll = gtk_scrolled_window_new(NULL, NULL); +gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(txt_scroll), GTK_SHADOW_IN); +gtk_table_attach(GTK_TABLE(table), txt_scroll, 1, 2, 1, 2, GTK_EXPAND | GTK_FILL, 0, 2, 4); - MACRO_PATH_INCREMENT_TAIL(*_route); - _route->tail->unitx = unitx; - _route->tail->unity = unity; - _route->tail->time = 0; - _route->tail->altitude = NAN; +gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(txt_scroll), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); - gtk_widget_destroy(confirm); - } else { - gtk_widget_destroy(confirm); - continue; +txt_desc = gtk_text_view_new(); +gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(txt_desc), GTK_WRAP_WORD); + +gtk_container_add(GTK_CONTAINER(txt_scroll), txt_desc); +gtk_widget_set_size_request(GTK_WIDGET(txt_scroll), 400, 60); + +gtk_widget_show_all(dialog); + +while (GTK_RESPONSE_ACCEPT == gtk_dialog_run(GTK_DIALOG(dialog))) { + GtkTextBuffer *tbuf; + GtkTextIter ti1, ti2; + gchar *desc; + + tbuf = gtk_text_view_get_buffer(GTK_TEXT_VIEW(txt_desc)); + gtk_text_buffer_get_iter_at_offset(tbuf, &ti1, 0); + gtk_text_buffer_get_end_iter(tbuf, &ti2); + desc = gtk_text_buffer_get_text(tbuf, &ti1, &ti2, TRUE); + + if (*desc) { + /* There's a description. Add a waypoint. */ + MACRO_PATH_INCREMENT_TAIL(*_route); + _route->tail->unitx = unitx; + _route->tail->unity = unity; + _route->tail->time = 0; + _route->tail->altitude = NAN; + + MACRO_PATH_INCREMENT_WTAIL(*_route); + _route->wtail->point = _route->tail; + _route->wtail->desc = gtk_text_buffer_get_text(tbuf, &ti1, &ti2, TRUE); + } else { + GtkWidget *confirm; + + g_free(desc); + + confirm = hildon_note_new_confirmation(GTK_WINDOW(dialog), + _("Creating a \"waypoint\" with no description actually " + "adds a break point. Is that what you want?")); + + if (GTK_RESPONSE_OK == gtk_dialog_run(GTK_DIALOG(confirm))) { + /* There's no description. Add a break by adding a (0, 0) + * point (if necessary), and then the ordinary route point. */ + if (_route->tail->unity) { + MACRO_PATH_INCREMENT_TAIL(*_route); + *_route->tail = _point_null; } - } - route_find_nearest_point(); - map_render_paths(); - MACRO_QUEUE_DRAW_AREA(); - break; + MACRO_PATH_INCREMENT_TAIL(*_route); + _route->tail->unitx = unitx; + _route->tail->unity = unity; + _route->tail->time = 0; + _route->tail->altitude = NAN; + + gtk_widget_destroy(confirm); + } else { + gtk_widget_destroy(confirm); + continue; + } } + + route_find_nearest_point(_route); + map_render_paths(); + MACRO_QUEUE_DRAW_AREA(); + break; +} gtk_widget_destroy(dialog); } @@ -1116,7 +1104,7 @@ unit2latlon(_gps->data.unitx, _gps->data.unity, _gps->data.lat, _gps->data.lon); /* Move mark to new location. */ _gps->data.time=time(NULL); -track_add(&_gps->data); +track_add(_track, &_gps->data); map_refresh_mark(); return TRUE; @@ -1127,7 +1115,7 @@ cmenu_cb_way_show_latlon(GtkAction * action) { WayPoint *way; -if ((way = find_nearest_waypoint(x2unit(_cmenu_position_x), y2unit(_cmenu_position_y)))) +if ((way = route_find_nearest_waypoint(_route, x2unit(_cmenu_position_x), y2unit(_cmenu_position_y)))) cmenu_show_latlon(way->point->unitx, way->point->unity); return TRUE; @@ -1138,7 +1126,7 @@ cmenu_cb_way_show_desc(GtkAction * action) { WayPoint *way; -if ((way = find_nearest_waypoint(x2unit(_cmenu_position_x), y2unit(_cmenu_position_y)))) { +if ((way = route_find_nearest_waypoint(_route, x2unit(_cmenu_position_x), y2unit(_cmenu_position_y)))) { MACRO_BANNER_SHOW_INFO(_window, way->desc); } @@ -1150,7 +1138,7 @@ cmenu_cb_way_clip_latlon(GtkAction * action) { WayPoint *way; -if ((way = find_nearest_waypoint(x2unit(_cmenu_position_x), y2unit(_cmenu_position_y)))) +if ((way = route_find_nearest_waypoint(_route, x2unit(_cmenu_position_x), y2unit(_cmenu_position_y)))) cmenu_clip_latlon(way->point->unitx, way->point->unity); return TRUE; } @@ -1160,7 +1148,7 @@ cmenu_cb_way_clip_desc(GtkAction * action) { WayPoint *way; -if ((way = find_nearest_waypoint(x2unit(_cmenu_position_x), y2unit(_cmenu_position_y)))) +if ((way = route_find_nearest_waypoint(_route, x2unit(_cmenu_position_x), y2unit(_cmenu_position_y)))) gtk_clipboard_set_text(gtk_clipboard_get(GDK_SELECTION_CLIPBOARD), way->desc, -1); return TRUE; @@ -1171,7 +1159,7 @@ cmenu_cb_way_route_to(GtkAction * action) { WayPoint *way; -if ((way = find_nearest_waypoint(x2unit(_cmenu_position_x), y2unit(_cmenu_position_y)))) +if ((way = route_find_nearest_waypoint(_route, x2unit(_cmenu_position_x), y2unit(_cmenu_position_y)))) cmenu_route_to(way->point->unitx, way->point->unity); return TRUE; @@ -1182,8 +1170,8 @@ cmenu_cb_way_distance_to(GtkAction * action) { WayPoint *way; -if ((way = find_nearest_waypoint(x2unit(_cmenu_position_x), y2unit(_cmenu_position_y)))) - route_show_distance_to(way->point); +if ((way = route_find_nearest_waypoint(_route, x2unit(_cmenu_position_x), y2unit(_cmenu_position_y)))) + route_show_distance_to(_route, way->point); return TRUE; } @@ -1193,7 +1181,7 @@ cmenu_cb_way_delete(GtkAction * action) { WayPoint *way; -if ((way = find_nearest_waypoint(x2unit(_cmenu_position_x), y2unit(_cmenu_position_y)))) { +if ((way = route_find_nearest_waypoint(_route, x2unit(_cmenu_position_x), y2unit(_cmenu_position_y)))) { gchar buffer[BUFFER_SIZE]; GtkWidget *confirm; @@ -1246,7 +1234,7 @@ if ((way = find_nearest_waypoint(x2unit(_cmenu_position_x), y2unit(_cmenu_positi } _route->wtail--; - route_find_nearest_point(); + route_find_nearest_point(_route); map_force_redraw(); } gtk_widget_destroy(confirm); @@ -1269,12 +1257,13 @@ cmenu_cb_way_add_poi(GtkAction * action) { WayPoint *way; -if ((way = find_nearest_waypoint(x2unit(_cmenu_position_x), y2unit(_cmenu_position_y)))) { +if ((way = route_find_nearest_waypoint(_route, x2unit(_cmenu_position_x), y2unit(_cmenu_position_y)))) { poi_info *p; p=poi_new(); unit2latlon(way->point->unitx, way->point->unity, p->lat, p->lon); poi_edit_dialog(ACTION_ADD_POI, p); + /* XXX: free it ? */ } return TRUE; } diff --git a/src/map-download.c b/src/map-download.c index 60913f5..5311ac4 100644 --- a/src/map-download.c +++ b/src/map-download.c @@ -133,10 +133,10 @@ while (_curl_multi && (msg = curl_multi_info_read(_curl_multi, &num_msgs))) { /* Now, parse the autoroute and update the display. */ if (_autoroute_data.enabled && gpx_parse(&_route, _autoroute_data.rdl_data.bytes, _autoroute_data.rdl_data.bytes_read, 0)) { /* Find the nearest route point, if we're connected. */ - route_find_nearest_point(); + route_find_nearest_point(_route); map_force_redraw(); } - route_cancel_autoroute(TRUE); /* We're done. Clean up. */ + route_cancel_autoroute(_route, TRUE); /* We're done. Clean up. */ } else { ProgressUpdateInfo *pui = g_hash_table_lookup(pui_by_easy, msg->easy_handle); g_queue_push_head(curl_easy_queue, msg->easy_handle); diff --git a/src/map.c b/src/map.c index 7bfdc97..48f41f0 100644 --- a/src/map.c +++ b/src/map.c @@ -1252,7 +1252,7 @@ unit2latlon(_gps->data.unitx, _gps->data.unity, _gps->data.lat, _gps->data.lon); _gps->data.speed=20.f; gps_data_integerize(&_gps->data); _gps->data.time=time(NULL); -track_add(&_gps->data); +track_add(_track, &_gps->data); map_refresh_mark(); } diff --git a/src/path.c b/src/path.c index 197daac..a1c8c48 100644 --- a/src/path.c +++ b/src/path.c @@ -8,10 +8,25 @@ #include "map.h" #include "track.h" #include "route.h" +#include "gps.h" #include "settings.h" #include "latlon.h" #include "gpx.h" +struct sql_select_stmt { + sqlite3_stmt *select_path; + sqlite3_stmt *select_path_nodes; + sqlite3_stmt *insert_path; + sqlite3_stmt *insert_path_node; + sqlite3_stmt *delete_path_nodes; + sqlite3_stmt *delete_path; +}; +static struct sql_select_stmt sql; + + +/* Path point add sensitivity */ +static gint sensitivity=3; + Path * path_new(void) { @@ -30,7 +45,16 @@ MACRO_PATH_FREE(*p); g_slice_free(Path, p); } -void +void +path_clear(Path *p) +{ +g_return_if_fail(p); +MACRO_PATH_FREE(*p); +p->length=p->avgspeed=0.0; +p->points=0; +} + +gboolean path_resize(Path *path, guint size) { if (path->head + size != path->cap) { @@ -45,10 +69,12 @@ if (path->head + size != path->cap) { for (curr = path->whead - 1; curr++ != path->wtail;) curr->point = path->head + (curr->point - old_head); } + return TRUE; } +return FALSE; } -void +gboolean path_wresize(Path *path, guint wsize) { if (path->whead + wsize != path->wcap) { @@ -56,7 +82,40 @@ if (path->whead + wsize != path->wcap) { path->whead = g_renew(WayPoint, old_whead, wsize); path->wtail = path->whead + (path->wtail - old_whead); path->wcap = path->whead + wsize; + return TRUE; +} +return FALSE; +} + +gboolean +path_add_point(Path *path, GpsData *gps) +{ +if (!gps) { + MACRO_PATH_INCREMENT_TAIL(*path); + *path->tail=_point_null; + return FALSE; +} + +if (abs((gint)gps->unitx-path->tail->unitx) > sensitivity || abs((gint)gps->unity-path->tail->unity) > sensitivity) { + if (path->tail->unity && path->tail->unitx) { + gdouble lat, lon; + + unit2latlon(path->tail->unitx, path->tail->unity, lat, lon); + path->length+=calculate_distance(lat, lon, gps->lat, gps->lon); + } + MACRO_PATH_INCREMENT_TAIL(*path); + path->tail->unitx=gps->unitx; + path->tail->unity=gps->unity; + path->tail->time=gps->time; + path->tail->altitude=gps->altitude; + path->maxspeed=gps->maxspeed; + path->tspeed+=gps->speed; + path->avgspeed=(path->points>0) ? path->tspeed/path->points : 0.0; + path->points++; + g_debug("TRACK: %f %f (%d)", path->length, path->avgspeed, path->points); } + +return TRUE; } gboolean @@ -84,10 +143,71 @@ if (path->tail->unity) { y1 = unit2bufy(path->tail->unity); map_render_waypoint(x1, y1, _gc[COLORABLE_TRACK_BREAK]); #endif + return TRUE; } return FALSE; } +Point * +path_find_last_point(Path *path) +{ +Point *p=NULL; + +if (path->head == path->tail) + return p; + +for (p=path->tail; !p->unity; p--) { +} +return p; +} + +gdouble +path_get_distance_to(Path *path, Point *point, gdouble lat, gdouble lon) +{ +gdouble lat1, lon1, lat2, lon2; +gdouble sum=0.0; + +/* If point is NULL, use the next waypoint. */ +if (point == NULL && path->next_way) + point = path->next_way->point; + +/* If point is still NULL, return an error. */ +if (point==NULL) + return FALSE; + +lat1=lat; +lon1=lon; + +if (point > path->near_point) { + Point *curr; + /* Skip _near_point in case we have already passed it. */ + for (curr = path->near_point + 1; curr <= point; ++curr) { + if (curr->unity) { + unit2latlon(curr->unitx, curr->unity, lat2, lon2); + sum += calculate_distance(lat1, lon1, lat2, lon2); + lat1 = lat2; + lon1 = lon2; + } + } +} else if (point < path->near_point) { + Point *curr; + /* Skip near_point in case we have already passed it. */ + for (curr = path->near_point - 1; curr >= point; --curr) { + if (curr->unity) { + unit2latlon(curr->unitx, curr->unity, lat2, lon2); + sum += calculate_distance(lat1, lon1, lat2, lon2); + lat1 = lat2; + lon1 = lon2; + } + } +} else { + /* Waypoint _is_ the nearest point. */ + unit2latlon(path->near_point->unitx, path->near_point->unity, lat2, lon2); + sum += calculate_distance(lat1, lon1, lat2, lon2); +} +return sum; +} + gboolean path_load(Path *path, const gchar *config_dir, const gchar *file) { @@ -125,8 +245,13 @@ path_insert_mark_text(Path *path, gchar *text) { g_assert(path); MACRO_PATH_INCREMENT_WTAIL(*path); -path->wtail->point = path->tail; -path->wtail->desc = text; +path->wtail->point=path->tail; +if (text) { + path->wtail->desc=text; +} else { + path->wpcnt++; + path->wtail->desc=g_strdup_printf("WP: %u", path->wpcnt); +} } GtkListStore * @@ -197,17 +322,13 @@ void position_set(Position *pos, gboolean valid, gdouble lat, gdouble lon) { pos->valid=valid; -if (valid) { - pos->lat=lat; - pos->lon=lon; -} else { - pos->lat=NAN; - pos->lon=NAN; -} +pos->lat=valid ? lat : NAN; +pos->lon=valid ? lon : NAN; } void position_update(Position *pos, GpsData *data) { - +if (!pos->valid) + return; } diff --git a/src/path.h b/src/path.h index fcacf89..6879e71 100644 --- a/src/path.h +++ b/src/path.h @@ -4,46 +4,17 @@ #include #include -#define MACRO_PATH_INIT(path) { \ - (path).head = (path).tail = g_new0(Point, ARRAY_CHUNK_SIZE); \ - *((path).tail) = _point_null; \ - (path).cap = (path).head + ARRAY_CHUNK_SIZE; \ - (path).whead = g_new0(WayPoint, ARRAY_CHUNK_SIZE); \ - (path).wtail = (path).whead - 1; \ - (path).wcap = (path).whead + ARRAY_CHUNK_SIZE; \ -} - -#define MACRO_PATH_FREE(path) if((path).head) { \ - WayPoint *curr; \ - g_free((path).head); \ - (path).head = (path).tail = (path).cap = NULL; \ - for(curr = (path).whead - 1; curr++ != (path).wtail; ) \ - g_free(curr->desc); \ - g_free((path).whead); \ - (path).whead = (path).wtail = (path).wcap = NULL; \ -} - -#define MACRO_PATH_INCREMENT_TAIL(route) { \ - if(++(route).tail == (route).cap) \ - path_resize(&(route), (route).cap - (route).head + ARRAY_CHUNK_SIZE);\ -} - -#define MACRO_PATH_INCREMENT_WTAIL(route) { \ - if(++(route).wtail == (route).wcap) \ - path_wresize(&(route), (route).wcap - (route).whead + ARRAY_CHUNK_SIZE); \ -} - /** A lat/lon/alt position */ typedef struct _Position Position; struct _Position { - gchar *desc; + gchar *name; gboolean valid; gdouble lat; gdouble lon; gfloat altitude; gfloat angle; /* Course from current position to this one */ time_t time; - guint type; /* Type of position */ + guint type; /* Type of position (Home, Destination, Waypoint, etc) */ }; /** A general definition of a point in the Mapper unit system. */ @@ -75,8 +46,21 @@ struct _Path { WayPoint *wtail; /* points to last element in array. */ WayPoint *wcap; /* points after last slot in array. */ + /* Internal waypoint data */ + Point *near_point; + guint64 near_point_dist_squared; + + /* next_way is what we currently interpret to be the next waypoint. */ + WayPoint *next_way; + guint64 next_way_dist_squared; + + /* next_wpt is the route point immediately following next_way. */ + Point *next_wpt; + guint64 next_wpt_dist_squared; + /* Path statistics */ - guint32 points; + guint32 points; + guint32 wpcnt; /* Auto waypoint number counter */ gdouble length; gdouble tspeed; gdouble avgspeed; @@ -87,9 +71,9 @@ struct _Path { gchar *desc; gchar *author; gchar *keywords; - time_t time; gchar *copyright; gchar *src; + time_t time; }; /* Null point */ @@ -101,12 +85,49 @@ Position _dest; Path *path_new(void); void path_free(Path *p); +void path_clear(Path *p); -void path_insert_mark_text(Path *path, gchar *text); +Point *path_find_last_point(Path *path); + +gboolean path_resize(Path *path, guint size); +gboolean path_wresize(Path *path, guint wsize); -void path_resize(Path *path, guint size); -void path_wresize(Path *path, guint wsize); +gdouble path_get_distance_to(Path *path, Point *point, gdouble lat, gdouble lon); + +gboolean path_insert_break(Path *path); +void path_insert_mark_text(Path *path, gchar *text); +void path_insert_mark_autonumber(Path *path); +void path_insert_mark_audio(Path *path, gchar *audio); GtkListStore *path_generate_store(Path *path); +#define MACRO_PATH_INIT(path) { \ + (path).head = (path).tail = g_new0(Point, ARRAY_CHUNK_SIZE); \ + *((path).tail) = _point_null; \ + (path).cap = (path).head + ARRAY_CHUNK_SIZE; \ + (path).whead = g_new0(WayPoint, ARRAY_CHUNK_SIZE); \ + (path).wtail = (path).whead - 1; \ + (path).wcap = (path).whead + ARRAY_CHUNK_SIZE; \ +} + +#define MACRO_PATH_FREE(path) if((path).head) { \ + WayPoint *curr; \ + g_free((path).head); \ + (path).head = (path).tail = (path).cap = NULL; \ + for(curr = (path).whead - 1; curr++ != (path).wtail; ) \ + g_free(curr->desc); \ + g_free((path).whead); \ + (path).whead = (path).wtail = (path).wcap = NULL; \ +} + +#define MACRO_PATH_INCREMENT_TAIL(route) { \ + if(++(route).tail == (route).cap) \ + path_resize(&(route), (route).cap - (route).head + ARRAY_CHUNK_SIZE);\ +} + +#define MACRO_PATH_INCREMENT_WTAIL(route) { \ + if(++(route).wtail == (route).wcap) \ + path_wresize(&(route), (route).wcap - (route).whead + ARRAY_CHUNK_SIZE); \ +} + #endif diff --git a/src/route.c b/src/route.c index 4058ca0..67966d8 100644 --- a/src/route.c +++ b/src/route.c @@ -47,37 +47,34 @@ struct _OriginToggleInfo { GtkWidget *chk_auto; GtkWidget *txt_from; GtkWidget *txt_to; + Path *path; }; -void route_find_nearest_point(void); -void route_cancel_autoroute(gboolean temporary); -void route_show_distance_to_last(void); -void route_set_destination_from_last(void); - -void -route_clear(void) +gboolean +route_clear(Path *route) { GtkWidget *confirm; +gboolean r=FALSE; -confirm = hildon_note_new_confirmation(GTK_WINDOW(_window), _("Really clear the route?")); +confirm=hildon_note_new_confirmation(GTK_WINDOW(_window), _("Really clear the route?")); if (GTK_RESPONSE_OK == gtk_dialog_run(GTK_DIALOG(confirm))) { - route_cancel_autoroute(FALSE); + route_cancel_autoroute(route, FALSE); announced_waypoint=NULL; - path_free(_route); - _route=path_new(); - route_find_nearest_point(); - map_force_redraw(); + path_clear(route); + route_find_nearest_point(route); + r=TRUE; } gtk_widget_destroy(confirm); +return r; } /** * Check if we should announce upcoming waypoints. */ void -route_check_waypoint_announce(GpsData *gps) +route_check_waypoint_announce(Path *route, GpsData *gps) { guint announce_thres_unsquared; @@ -103,32 +100,31 @@ if (_next_way_dist_squared<(announce_thres_unsquared * announce_thres_unsquared) * Check if we should re-calculate route */ void -route_autoroute_check(void) +route_autoroute_check(Path *route) { if (_autoroute_data.enabled && !_autoroute_data.in_progress && _near_point_dist_squared > 400) { MACRO_BANNER_SHOW_INFO(_window, _("Recalculating directions...")); _autoroute_data.in_progress = TRUE; show_directions = FALSE; - g_idle_add((GSourceFunc)auto_route_dl_idle, NULL); + g_idle_add((GSourceFunc)route_auto_route_dl_idle_cb, NULL); } } gboolean -route_open_file(void) +route_open_file(Path *route) { gchar *buffer; gint size; if (file_open_get_contents(&_route_dir_uri, &buffer, &size)) { /* If auto is enabled, append the route, otherwise replace it. */ - if (gpx_parse(_route, buffer, size, _autoroute_data.enabled ? GPX_PATH_APPEND : GPX_PATH_NEW)) { - route_cancel_autoroute(FALSE); + if (gpx_parse(route, buffer, size, _autoroute_data.enabled ? GPX_PATH_APPEND : GPX_PATH_NEW)) { + route_cancel_autoroute(route, FALSE); MACRO_BANNER_SHOW_INFO(_window, _("Route Opened")); /* Find the nearest route point, if we're connected. */ - route_find_nearest_point(); - map_force_redraw(); - route_set_destination_from_last(); + route_find_nearest_point(route); + route_set_destination_from_last(route); return TRUE; } else { popup_error(_window, _("Error parsing GPX file.")); @@ -143,17 +139,17 @@ return FALSE; * Ask user to save route */ gboolean -route_save(void) +route_save(Path *route) { GnomeVFSHandle *handle; -if (_route->head==_route->tail) { +if (route->head==route->tail) { MACRO_BANNER_SHOW_INFO(_window, _("No route exist.")); return FALSE; } if (file_save(&_route_dir_uri, &_route_dir_uri, &handle)) { - if (gpx_write(_route, handle)) { + if (gpx_write(route, handle)) { MACRO_BANNER_SHOW_INFO(_window, _("Route Saved")); } else { popup_error(_window, _("Error writing GPX file.")); @@ -168,7 +164,7 @@ return FALSE; * */ static gboolean -origin_type_selected_cb(GtkWidget * toggle, OriginToggleInfo * oti) +route_origin_type_selected_cb(GtkWidget *toggle, OriginToggleInfo *oti) { if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(toggle))) { if (toggle == oti->rad_use_gps) { @@ -183,18 +179,17 @@ if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(toggle))) { gchar buffer[80]; gchar strlat[32]; gchar strlon[32]; - Point *p; gdouble lat, lon; + Point *p; - /* Use last non-zero route point. */ - for (p = _route->tail; !p->unity; p--) { + p=path_find_last_point(oti->path); + if (p) { + unit2latlon(p->unitx, p->unity, lat, lon); + g_ascii_formatd(strlat, 32, "%.06f", lat); + g_ascii_formatd(strlon, 32, "%.06f", lon); + g_snprintf(buffer, sizeof(buffer), "%s, %s", strlat, strlon); + gtk_entry_set_text(GTK_ENTRY(oti->txt_from), buffer); } - - unit2latlon(p->unitx, p->unity, lat, lon); - g_ascii_formatd(strlat, 32, "%.06f", lat); - g_ascii_formatd(strlon, 32, "%.06f", lon); - g_snprintf(buffer, sizeof(buffer), "%s, %s", strlat, strlon); - gtk_entry_set_text(GTK_ENTRY(oti->txt_from), buffer); } gtk_widget_set_sensitive(oti->txt_from, toggle == oti->rad_use_text); gtk_widget_set_sensitive(oti->chk_auto, toggle == oti->rad_use_gps); @@ -206,7 +201,7 @@ return TRUE; * Cancel the current auto-route. */ void -route_cancel_autoroute(gboolean temporary) +route_cancel_autoroute(Path *route, gboolean temporary) { if (_autoroute_data.enabled) { if (!temporary) { @@ -251,7 +246,7 @@ return (size * nmemb); } gboolean -auto_route_dl_idle() +route_auto_route_dl_idle_cb() { gchar latstr[32], lonstr[32], *latlonstr; @@ -268,7 +263,7 @@ curl_easy_setopt(_autoroute_data.curl_easy, CURLOPT_WRITEDATA, &_autoroute_data. curl_multi_add_handle(_curl_multi, _autoroute_data.curl_easy); if (iap_is_connected() && !_curl_sid) - _curl_sid = g_timeout_add(100, (GSourceFunc) map_download_timeout, NULL); + _curl_sid = g_timeout_add(100, (GSourceFunc)map_download_timeout, NULL); _autoroute_data.in_progress = TRUE; @@ -286,7 +281,7 @@ return FALSE; * safe to free either string as soon as this function returns. */ gboolean -route_download(gchar * to) +route_download(Path *route, gchar *to) { GtkWidget *dialog; GtkWidget *table; @@ -296,8 +291,9 @@ GtkWidget *hbox; OriginToggleInfo oti; GtkEntryCompletion *from_comp; GtkEntryCompletion *to_comp; +gboolean r=FALSE; -iap_connect(); +oti.path=route; dialog = gtk_dialog_new_with_buttons(_("Download Route"), GTK_WINDOW(_window), @@ -307,9 +303,7 @@ dialog = gtk_dialog_new_with_buttons(_("Download Route"), GTK_RESPONSE_REJECT, NULL); help_dialog_help_enable(GTK_DIALOG(dialog), HELP_ID_DOWNROUTE); - -gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), - table = gtk_table_new(2, 5, FALSE), TRUE, TRUE, 0); +gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), table = gtk_table_new(2, 5, FALSE), TRUE, TRUE, 0); from_comp = gtk_entry_completion_new(); gtk_entry_completion_set_model(from_comp, GTK_TREE_MODEL(_loc_model)); @@ -325,53 +319,34 @@ gtk_table_attach(GTK_TABLE(table), txt_source_url = gtk_entry_new(), 1, 2, 0, 1, gtk_entry_set_width_chars(GTK_ENTRY(txt_source_url), 25); /* Auto. */ -gtk_table_attach(GTK_TABLE(table), - hbox = gtk_hbox_new(FALSE, 6), - 0, 2, 1, 2, GTK_FILL, 0, 2, 4); -gtk_box_pack_start(GTK_BOX(hbox), - oti.rad_use_gps = gtk_radio_button_new_with_label(NULL, _("Use GPS Location")), - TRUE, TRUE, 0); -gtk_box_pack_start(GTK_BOX(hbox), oti.chk_auto = - gtk_check_button_new_with_label(_("Auto-Update")), - TRUE, TRUE, 0); +gtk_table_attach(GTK_TABLE(table), hbox = gtk_hbox_new(FALSE, 6), 0, 2, 1, 2, GTK_FILL, 0, 2, 4); +gtk_box_pack_start(GTK_BOX(hbox), oti.rad_use_gps = gtk_radio_button_new_with_label(NULL, _("Use GPS Location")), TRUE, TRUE, 0); +gtk_box_pack_start(GTK_BOX(hbox), oti.chk_auto = gtk_check_button_new_with_label(_("Auto-Update")), TRUE, TRUE, 0); gtk_widget_set_sensitive(oti.chk_auto, FALSE); /* Use End of Route. */ -gtk_table_attach(GTK_TABLE(table), - hbox = gtk_hbox_new(FALSE, 6), - 0, 2, 2, 3, GTK_FILL, 0, 2, 4); -gtk_box_pack_start(GTK_BOX(hbox), - oti.rad_use_route = - gtk_radio_button_new_with_label_from_widget - (GTK_RADIO_BUTTON(oti.rad_use_gps), - _("Use End of Route")), TRUE, TRUE, 0); -gtk_widget_set_sensitive(oti.rad_use_route, _route->head != _route->tail); +gtk_table_attach(GTK_TABLE(table), hbox = gtk_hbox_new(FALSE, 6), 0, 2, 2, 3, GTK_FILL, 0, 2, 4); +gtk_box_pack_start(GTK_BOX(hbox), oti.rad_use_route = gtk_radio_button_new_with_label_from_widget + (GTK_RADIO_BUTTON(oti.rad_use_gps), _("Use End of Route")), TRUE, TRUE, 0); +gtk_widget_set_sensitive(oti.rad_use_route, route->head != route->tail); /* Origin. */ -gtk_table_attach(GTK_TABLE(table), - oti.rad_use_text = - gtk_radio_button_new_with_label_from_widget - (GTK_RADIO_BUTTON(oti.rad_use_gps), _("Origin")), 0, 1, - 3, 4, GTK_FILL, 0, 2, 4); -gtk_table_attach(GTK_TABLE(table), oti.txt_from = - gtk_entry_new(), 1, 2, 3, 4, GTK_EXPAND | GTK_FILL, 0, - 2, 4); +gtk_table_attach(GTK_TABLE(table), oti.rad_use_text = gtk_radio_button_new_with_label_from_widget + (GTK_RADIO_BUTTON(oti.rad_use_gps), _("Origin")), 0, 1, 3, 4, GTK_FILL, 0, 2, 4); +gtk_table_attach(GTK_TABLE(table), oti.txt_from = gtk_entry_new(), 1, 2, 3, 4, GTK_EXPAND | GTK_FILL, 0, 2, 4); gtk_entry_set_completion(GTK_ENTRY(oti.txt_from), from_comp); gtk_entry_set_width_chars(GTK_ENTRY(oti.txt_from), 25); /* Destination. */ -gtk_table_attach(GTK_TABLE(table), - label = gtk_label_new(_("Destination")), - 0, 1, 4, 5, GTK_FILL, 0, 2, 4); +gtk_table_attach(GTK_TABLE(table), label = gtk_label_new(_("Destination")), 0, 1, 4, 5, GTK_FILL, 0, 2, 4); gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f); -gtk_table_attach(GTK_TABLE(table), - oti.txt_to = gtk_entry_new(), 1, 2, 4, 5, GTK_EXPAND | GTK_FILL, 0, 2, 4); +gtk_table_attach(GTK_TABLE(table), oti.txt_to = gtk_entry_new(), 1, 2, 4, 5, GTK_EXPAND | GTK_FILL, 0, 2, 4); gtk_entry_set_completion(GTK_ENTRY(oti.txt_to), to_comp); gtk_entry_set_width_chars(GTK_ENTRY(oti.txt_to), 25); -g_signal_connect(G_OBJECT(oti.rad_use_gps), "toggled", G_CALLBACK(origin_type_selected_cb), &oti); -g_signal_connect(G_OBJECT(oti.rad_use_route), "toggled", G_CALLBACK(origin_type_selected_cb), &oti); -g_signal_connect(G_OBJECT(oti.rad_use_text), "toggled", G_CALLBACK(origin_type_selected_cb), &oti); +g_signal_connect(G_OBJECT(oti.rad_use_gps), "toggled", G_CALLBACK(route_origin_type_selected_cb), &oti); +g_signal_connect(G_OBJECT(oti.rad_use_route), "toggled", G_CALLBACK(route_origin_type_selected_cb), &oti); +g_signal_connect(G_OBJECT(oti.rad_use_text), "toggled", G_CALLBACK(route_origin_type_selected_cb), &oti); #if defined (WITH_HILDON) && defined (HILDON_AUTOCAP) g_object_set(G_OBJECT(oti.txt_from), HILDON_AUTOCAP, FALSE, NULL); @@ -384,18 +359,16 @@ gtk_entry_set_text(GTK_ENTRY(oti.txt_to), (to ? to : "")); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(oti.rad_use_text), TRUE); -/* Use "End of Route" by default if they have a route. */ -if (_route->head != _route->tail) { +if (route->head != route->tail) { + /* Use "End of Route" by default if they have a route. */ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(oti.rad_use_route), TRUE); gtk_widget_grab_focus(oti.rad_use_route); -} -/* Else use "GPS Location" if they have GPS enabled. */ -else if (_enable_gps) { +} else if (_enable_gps) { + /* Else use "GPS Location" if they have GPS enabled. */ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(oti.rad_use_gps), TRUE); gtk_widget_grab_focus(oti.rad_use_gps); -} -/* Else use text. */ -else { +} else { + /* Else use text. */ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(oti.rad_use_text), TRUE); gtk_widget_grab_focus(oti.txt_from); } @@ -436,6 +409,8 @@ while (GTK_RESPONSE_ACCEPT == gtk_dialog_run(GTK_DIALOG(dialog))) { g_free(from_escaped); g_free(to_escaped); + iap_connect(); + /* Attempt to download the route from the server. */ MACRO_CURL_EASY_INIT(curl_easy); curl_easy_setopt(curl_easy, CURLOPT_URL, buffer); @@ -457,17 +432,15 @@ while (GTK_RESPONSE_ACCEPT == gtk_dialog_run(GTK_DIALOG(dialog))) { /* Let them try again. */ } /* Else, if GPS is enabled, replace the route, otherwise append it. */ - else if (gpx_parse(_route, rdl_data.bytes, rdl_data.bytes_read, + else if (gpx_parse(route, rdl_data.bytes, rdl_data.bytes_read, (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(oti.rad_use_gps)) ? GPX_PATH_NEW : GPX_PATH_APPEND))) { GtkTreeIter iter; /* Find the nearest route point, if we're connected. */ - route_find_nearest_point(); + route_find_nearest_point(route); /* Cancel any autoroute that might be occurring. */ - route_cancel_autoroute(FALSE); - - map_force_redraw(); + route_cancel_autoroute(route, FALSE); if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(oti.chk_auto))) { /* Kick off a timeout to start the first update. */ @@ -476,8 +449,7 @@ while (GTK_RESPONSE_ACCEPT == gtk_dialog_run(GTK_DIALOG(dialog))) { } /* Save Origin in Route Locations list if not from GPS. */ - if (!gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(oti.rad_use_gps)) - && !g_slist_find_custom(_loc_list, from, (GCompareFunc) strcmp)) { + if (!gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(oti.rad_use_gps)) && !g_slist_find_custom(_loc_list, from, (GCompareFunc) strcmp)) { _loc_list = g_slist_prepend(_loc_list, g_strdup(from)); gtk_list_store_insert_with_values(_loc_model, &iter, INT_MAX, 0, from, -1); } @@ -488,14 +460,17 @@ while (GTK_RESPONSE_ACCEPT == gtk_dialog_run(GTK_DIALOG(dialog))) { gtk_list_store_insert_with_values(_loc_model, &iter, INT_MAX, 0, to, -1); } + map_force_redraw(); + MACRO_BANNER_SHOW_INFO(_window, _("Route Downloaded")); g_free(rdl_data.bytes); - route_set_destination_from_last(); + route_set_destination_from_last(route); /* Success! Get out of the while loop. */ + r=TRUE; break; } else { - popup_error(dialog, _("Error parsing GPX file.")); + popup_error(dialog, _("Error parsing route GPX data.")); g_free(rdl_data.bytes); /* Let them try again. */ } @@ -503,22 +478,22 @@ while (GTK_RESPONSE_ACCEPT == gtk_dialog_run(GTK_DIALOG(dialog))) { gtk_widget_hide(dialog); /* Destroying causes a crash (!?!?!??!) */ -return TRUE; +return r; } WayPoint * -find_nearest_waypoint(guint unitx, guint unity) +route_find_nearest_waypoint(Path *route, guint unitx, guint unity) { WayPoint *wcurr; WayPoint *wnear; guint64 nearest_squared; Point pos = { unitx, unity, 0, NAN }; -wcurr = wnear = _route->whead; -if (wcurr && wcurr->point && wcurr != _route->wtail) { +wcurr = wnear = route->whead; +if (wcurr && wcurr->point && wcurr != route->wtail) { nearest_squared = DISTANCE_SQUARED(pos, *(wcurr->point)); - while (wcurr++ != _route->wtail) { + while (wcurr++ != route->wtail) { guint64 test_squared = DISTANCE_SQUARED(pos, *(wcurr->point)); if (test_squared < nearest_squared) { wnear = wcurr; @@ -530,8 +505,7 @@ if (wcurr && wcurr->point && wcurr != _route->wtail) { if (wnear && wnear->point) { /* Only use the waypoint if it is within a 6*_draw_width square drawn * around the position. This is consistent with select_poi(). */ - if (abs(unitx - wnear->point->unitx) < pixel2unit(3 * _draw_width) && - abs(unity - wnear->point->unity) < pixel2unit(3 * _draw_width)) + if (abs(unitx - wnear->point->unitx) < pixel2unit(3 * _draw_width) && abs(unity - wnear->point->unity) < pixel2unit(3 * _draw_width)) return wnear; } @@ -547,7 +521,7 @@ return NULL; * stop searching when we find a point that is farther away. */ gboolean -route_update_nears(gboolean quick) +route_update_nears(Path *route, gboolean quick) { gboolean ret = FALSE; Point *curr, *near; @@ -564,10 +538,10 @@ if (_next_way) { near = _near_point; near_dist_squared = DISTANCE_SQUARED(_gps->data, *near); - /* Now, search _route for a closer point. If quick is TRUE, then we'll + /* Now, search route for a closer point. If quick is TRUE, then we'll * only search forward, only as long as we keep finding closer points. */ - for (curr = _near_point; curr++ != _route->tail;) { + for (curr = _near_point; curr++ != route->tail;) { if (curr->unity) { guint dist_squared = DISTANCE_SQUARED(_gps->data, *curr); if (dist_squared <= near_dist_squared) { @@ -582,7 +556,7 @@ if (_next_way) { _near_point = near; _near_point_dist_squared = near_dist_squared; - for (wnext = wcurr = _next_way; wcurr != _route->wtail; wcurr++) { + for (wnext = wcurr = _next_way; wcurr != route->wtail; wcurr++) { if (wcurr->point < near || (wcurr->point == near && quick && (_next_wpt && (DISTANCE_SQUARED(_gps->data, *near) > _next_way_dist_squared && DISTANCE_SQUARED(_gps->data, *_next_wpt) < _next_wpt_dist_squared)))) @@ -599,7 +573,7 @@ if (_next_way) { break; } - if (wnext == _route->wtail && (wnext->point < near || (wnext->point == near && quick + if (wnext == route->wtail && (wnext->point < near || (wnext->point == near && quick && (_next_wpt && (DISTANCE_SQUARED (_gps->data, *near) > _next_way_dist_squared && DISTANCE_SQUARED(_gps->data, *_next_wpt) < _next_wpt_dist_squared))))) { @@ -615,11 +589,11 @@ if (_next_way) { if (!quick || _next_way != wnext) { _next_way = wnext; _next_wpt = wnext->point; - if (_next_wpt == _route->tail) + if (_next_wpt == route->tail) _next_wpt = NULL; else { while (!(++_next_wpt)->unity) { - if (_next_wpt == _route->tail) { + if (_next_wpt == route->tail) { _next_wpt = NULL; break; } @@ -640,19 +614,19 @@ return ret; * route point and waypoint. */ void -route_find_nearest_point() +route_find_nearest_point(Path *route) { /* Initialize _near_point to first non-zero point. */ -_near_point = _route->head; -while (!_near_point->unity && _near_point != _route->tail) +_near_point = route->head; +while (!_near_point->unity && _near_point != route->tail) _near_point++; /* Initialize _next_way. */ -if (_route->wtail == _route->whead - 1 || (_autoroute_data.enabled && _route->wtail == _route->whead)) +if (route->wtail == route->whead - 1 || (_autoroute_data.enabled && route->wtail == route->whead)) _next_way = NULL; else /* We have at least one waypoint. */ - _next_way = (_autoroute_data.enabled ? _route->whead + 1 : _route->whead); + _next_way = (_autoroute_data.enabled ? route->whead + 1 : route->whead); _next_way_dist_squared = -1; @@ -660,58 +634,23 @@ _next_way_dist_squared = -1; _next_wpt = NULL; _next_wpt_dist_squared = -1; -route_update_nears(FALSE); +route_update_nears(route, FALSE); } /** * Show the distance from the current GPS location to the given point, - * following the route. If point is NULL, then the distance is shown to the + * following the route. If point is NULL, then the distance is shown to the * next waypoint. */ gboolean -route_show_distance_to(Point *point) +route_show_distance_to(Path *route, Point *point) { gchar buffer[80]; -gdouble lat1, lon1, lat2, lon2; -gdouble sum = 0.0; - -/* If point is NULL, use the next waypoint. */ -if (point == NULL && _next_way) - point = _next_way->point; - -/* If point is still NULL, return an error. */ -if (point == NULL) - return FALSE; - -unit2latlon(_gps->data.unitx, _gps->data.unity, lat1, lon1); -if (point > _near_point) { - Point *curr; - /* Skip _near_point in case we have already passed it. */ - for (curr = _near_point + 1; curr <= point; ++curr) { - if (curr->unity) { - unit2latlon(curr->unitx, curr->unity, lat2, lon2); - sum += calculate_distance(lat1, lon1, lat2, lon2); - lat1 = lat2; - lon1 = lon2; - } - } -} else if (point < _near_point) { - Point *curr; - /* Skip _near_point in case we have already passed it. */ - for (curr = _near_point - 1; curr >= point; --curr) { - if (curr->unity) { - unit2latlon(curr->unitx, curr->unity, lat2, lon2); - sum += calculate_distance(lat1, lon1, lat2, lon2); - lat1 = lat2; - lon1 = lon2; - } - } -} else { - /* Waypoint _is_ the nearest point. */ - unit2latlon(_near_point->unitx, _near_point->unity, lat2, lon2); - sum += calculate_distance(lat1, lon1, lat2, lon2); -} +gdouble lat, lon; +gdouble sum; +unit2latlon(_gps->data.unitx, _gps->data.unity, lat, lon); +sum=path_get_distance_to(route, point, lat, lon); g_snprintf(buffer, sizeof(buffer), "%s: %.02f %s", _("Distance"), sum * UNITS_CONVERT[_units], UNITS_TEXT[_units]); MACRO_BANNER_SHOW_INFO(_window, buffer); @@ -719,44 +658,37 @@ return TRUE; } void -route_show_distance_to_next() +route_show_distance_to_next(Path *route) { -if (!route_show_distance_to(NULL)) { +if (!route_show_distance_to(route, NULL)) MACRO_BANNER_SHOW_INFO(_window, _("There is no next waypoint.")); } -} -void -route_set_destination_from_last(void) +gboolean +route_set_destination_from_last(Path *route, Position *pos) { Point *p; gdouble lat,lon; -if (_route->head == _route->tail) - return; -/* Find last non-zero point. */ -for (p = _route->tail; !p->unity; p--) { +if (route->head==route->tail) { + position_set(pos, FALSE, NAN, NAN); + return FALSE; +} + +p=path_find_last_point(route); +if (p) { + unit2latlon(p->unitx, p->unity, lat, lon); + position_set(pos, TRUE, lat, lon); } -unit2latlon(p->unitx, p->unity, lat, lon); -_dest.valid=TRUE; -_dest.lat=lat; -_dest.lon=lon; +return TRUE; } void -route_show_distance_to_last(void) +route_show_distance_to_last(Path *route) { -Point *p; - -if (_route->head != _route->tail) { - /* Find last non-zero point. */ - for (p = _route->tail; !p->unity; p--) { - } - route_show_distance_to(p); +if (route->head != route->tail) { + route_show_distance_to(route, path_find_last_point(route)); } else { MACRO_BANNER_SHOW_INFO(_window, _("The current route is empty.")); - } } - -/***/ - +} diff --git a/src/route.h b/src/route.h index 6650258..f1200ff 100644 --- a/src/route.h +++ b/src/route.h @@ -40,25 +40,24 @@ guint64 _next_wpt_dist_squared; /** The singleton auto-route-download data. */ AutoRouteDownloadData _autoroute_data; -void route_init(void); -void route_deinit(void); +gboolean route_open_file(Path *route); +gboolean route_save(Path *route); +gboolean route_download(Path *route, gchar *to); +gboolean route_clear(Path *route); -gboolean route_open_file(void); -gboolean route_save(void); -gboolean route_download(gchar * to); -void route_clear(void); +void route_check_waypoint_announce(Path *route, GpsData *gps); +void route_autoroute_check(Path *route); -void route_check_waypoint_announce(GpsData *gps); -void route_autoroute_check(void); +gboolean route_auto_route_dl_idle_cb(); +void route_cancel_autoroute(Path *route, gboolean temporary); -gboolean auto_route_dl_idle(); +void route_find_nearest_point(Path *route); +WayPoint *route_find_nearest_waypoint(Path *route, guint unitx, guint unity); -WayPoint *find_nearest_waypoint(guint unitx, guint unity); +gboolean route_update_nears(Path *route, gboolean quick); -gboolean route_update_nears(gboolean quick); - -gboolean route_show_distance_to(Point * point); -void route_show_distance_to_last(); -void route_show_distance_to_next(); +gboolean route_show_distance_to(Path *route, Point *point); +void route_show_distance_to_last(Path *route); +void route_show_distance_to_next(Path *route); #endif diff --git a/src/track.c b/src/track.c index d59aeed..c473aed 100644 --- a/src/track.c +++ b/src/track.c @@ -10,36 +10,25 @@ #include "settings.h" #include "mapper-types.h" #include "ui-common.h" +#include "dialogs.h" #include "file.h" #include "track.h" #include "latlon.h" #include "path.h" #include "gpx.h" -struct sql_select_stmt { - sqlite3_stmt *select_track; - sqlite3_stmt *select_track_nodes; - sqlite3_stmt *insert_track; - sqlite3_stmt *insert_track_node; - sqlite3_stmt *delete_track_nodes; - sqlite3_stmt *delete_track; -}; -static struct sql_select_stmt sql; - /* Add sensitivity */ static gint sensitivity=3; void -track_clear(void) +track_clear(Path *track) { GtkWidget *confirm; confirm = hildon_note_new_confirmation(GTK_WINDOW(_window), _("Clear the track?")); if (GTK_RESPONSE_OK == gtk_dialog_run(GTK_DIALOG(confirm))) { - _track->tail = _track->head; - _track->length=_track->avgspeed=0.0; - _track->points=0; + path_clear(track); map_force_redraw(); } gtk_widget_destroy(confirm); @@ -48,9 +37,10 @@ gtk_widget_destroy(confirm); gdouble track_calculate_distance_from(Point *point) { +Point *curr; gdouble lat1, lon1, lat2, lon2; gdouble sum = 0.0; -Point *curr; + unit2latlon(_gps->data.unitx, _gps->data.unity, lat1, lon1); /* Skip _track->tail because that should be _gps. */ @@ -66,15 +56,13 @@ return sum; } void -track_show_distance_from(Point * point) +track_show_distance_from(Point *point) { gchar buffer[80]; gdouble sum; sum = track_calculate_distance_from(point); - -g_snprintf(buffer, sizeof(buffer), "%s: %.02f %s", _("Distance"), - sum * UNITS_CONVERT[_units], UNITS_TEXT[_units]); +g_snprintf(buffer, sizeof(buffer), "%s: %.02f %s", _("Distance"), sum * UNITS_CONVERT[_units], UNITS_TEXT[_units]); MACRO_BANNER_SHOW_INFO(_window, buffer); } @@ -111,18 +99,19 @@ if (_track->head != _track->tail) { * appended to _track with time zero (this produces a "break" in the track). */ gboolean -track_add(GpsData *gps) +track_add(Path *track, GpsData *gps) { if (!gps) { - MACRO_PATH_INCREMENT_TAIL(*_track); - *_track->tail=_point_null; + MACRO_PATH_INCREMENT_TAIL(*track); + *track->tail=_point_null; return FALSE; } -if (abs((gint)gps->unitx-_track->tail->unitx) > sensitivity || abs((gint)gps->unity-_track->tail->unity) > sensitivity) { +if (abs((gint)gps->unitx-track->tail->unitx) > sensitivity || abs((gint)gps->unity-track->tail->unity) > sensitivity) { /* If gps is available, update the nearest-waypoint data. */ - if (gps && _route->head != _route->tail && (gps->newly_fixed ? (route_find_nearest_point(), TRUE) : route_update_nears(TRUE))) { + /* XXX: MOVE THIS */ + if (gps && _route->head != _route->tail && (gps->newly_fixed ? (route_find_nearest_point(_route), TRUE) : route_update_nears(_route, TRUE))) { /* Nearest waypoint has changed - re-render paths. */ map_render_paths(); MACRO_QUEUE_DRAW_AREA(); @@ -134,11 +123,11 @@ if (abs((gint)gps->unitx-_track->tail->unitx) > sensitivity || abs((gint)gps->un /* Instead of calling map_render_paths(), we'll draw the new line * ourselves and call gtk_widget_queue_draw_area(). */ map_render_segment(_gc[COLORABLE_TRACK], _gc[COLORABLE_TRACK_BREAK], - _track->tail->unitx, _track->tail->unity, gps->unitx, gps->unity); + track->tail->unitx, track->tail->unity, gps->unitx, gps->unity); - if (_track->tail->unity && _track->tail->unitx) { - tx1 = unit2x(_track->tail->unitx); - ty1 = unit2y(_track->tail->unity); + if (track->tail->unity && track->tail->unitx) { + tx1 = unit2x(track->tail->unitx); + ty1 = unit2y(track->tail->unity); tx2 = unit2x(gps->unitx); ty2 = unit2y(gps->unity); @@ -151,63 +140,40 @@ if (abs((gint)gps->unitx-_track->tail->unitx) > sensitivity || abs((gint)gps->un } } - if (_track->tail->unity && _track->tail->unitx) { + if (track->tail->unity && track->tail->unitx) { gdouble lat, lon; - unit2latlon(_track->tail->unitx, _track->tail->unity, lat, lon); - _track->length += calculate_distance(lat, lon, gps->lat, gps->lon); - _track->tspeed+=gps->speed; - if (_track->points>0) - _track->avgspeed=_track->tspeed/_track->points; + unit2latlon(track->tail->unitx, track->tail->unity, lat, lon); + track->length += calculate_distance(lat, lon, gps->lat, gps->lon); + track->tspeed+=gps->speed; + if (track->points>0) + track->avgspeed=track->tspeed/track->points; else - _track->avgspeed=0.0; - g_debug("TRACK: %f %f (%d)", _track->length, _track->avgspeed, _track->points); + track->avgspeed=0.0; + g_debug("TRACK: %f %f (%d)", track->length, track->avgspeed, track->points); } - MACRO_PATH_INCREMENT_TAIL(*_track); - _track->tail->unitx=gps->unitx; - _track->tail->unity=gps->unity; - _track->tail->time=gps->time; - _track->tail->altitude=gps->altitude; - _track->maxspeed=gps->maxspeed; - _track->points++; + MACRO_PATH_INCREMENT_TAIL(*track); + track->tail->unitx=gps->unitx; + track->tail->unity=gps->unity; + track->tail->time=gps->time; + track->tail->altitude=gps->altitude; + track->maxspeed=gps->maxspeed; + track->points++; } -/* Keep the display on if we are moving. */ -KEEP_DISPLAY_ON(); return TRUE; } -gboolean -track_insert_break(void) -{ -if (_track->tail->unity) { - guint x1, y1; - - /* To mark a "waypoint" in a track, we'll add a (0, 0) point and then - * another instance of the most recent track point. */ - MACRO_PATH_INCREMENT_TAIL(*_track); - *_track->tail=_point_null; - MACRO_PATH_INCREMENT_TAIL(*_track); - *_track->tail=_track->tail[-2]; - - /* Instead of calling map_render_paths(), we'll just draw the waypoint ourselves. */ - x1 = unit2bufx(_track->tail->unitx); - y1 = unit2bufy(_track->tail->unity); - map_render_waypoint(x1, y1, _gc[COLORABLE_TRACK_BREAK]); -} -return FALSE; -} - gboolean -track_open(void) +track_open(Path *track) { gchar *buffer; gint size; gboolean r = FALSE; if (file_open_get_contents(&_track_file_uri, &buffer, &size)) { - if (gpx_parse(_track, buffer, size, GPX_PATH_NEW)) { + if (gpx_parse(track, buffer, size, GPX_PATH_NEW)) { map_force_redraw(); MACRO_BANNER_SHOW_INFO(_window, _("Track Opened")); r = TRUE; @@ -220,16 +186,16 @@ return r; } gboolean -track_save(void) +track_save(Path *track) { GnomeVFSHandle *handle; gboolean r = FALSE; if (file_save(&_track_file_uri, &_track_file_uri, &handle)) { - if (gpx_write(_track, handle)) { + if (gpx_write(track, handle)) { MACRO_BANNER_SHOW_INFO(_window, _("Track Saved")); r = TRUE; - track_clear(); + track_clear(track); } else { popup_error(_window, _("Error writing GPX file.")); } @@ -243,7 +209,7 @@ return r; * */ gboolean -track_insert_mark(void) +track_insert_mark(Path *track) { gdouble lat, lon; gchar tmp1[16], tmp2[16], *p_latlon; @@ -255,10 +221,10 @@ GtkWidget *txt_desc; gboolean ret; dialog = gtk_dialog_new_with_buttons(_("Insert Mark"), - GTK_WINDOW(_window), GTK_DIALOG_MODAL, - GTK_STOCK_OK, GTK_RESPONSE_ACCEPT, - GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT, - NULL); + GTK_WINDOW(_window), GTK_DIALOG_MODAL, + GTK_STOCK_OK, GTK_RESPONSE_ACCEPT, + GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT, + NULL); gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), table = gtk_table_new(2, 2, FALSE), TRUE, TRUE, 0); @@ -300,7 +266,7 @@ while (GTK_RESPONSE_ACCEPT == gtk_dialog_run(GTK_DIALOG(dialog))) { gtk_text_buffer_get_end_iter(tbuf, &ti2); if (gtk_text_buffer_get_char_count(tbuf)>0) { - path_insert_mark_text(_track, gtk_text_buffer_get_text(tbuf, &ti1, &ti2, TRUE)); + path_insert_mark_text(track, gtk_text_buffer_get_text(tbuf, &ti1, &ti2, TRUE)); } else { popup_error(dialog, _("Please provide a description for the mark.")); continue; diff --git a/src/track.h b/src/track.h index 43370d9..beb0dfc 100644 --- a/src/track.h +++ b/src/track.h @@ -26,15 +26,14 @@ struct { void track_init(void); void track_deinit(void); -gboolean track_add(GpsData *gps); -gboolean track_insert_break(void); -gboolean track_insert_mark(void); -gboolean track_save(void); -gboolean track_open(void); -void track_clear(void); +gboolean track_add(Path *track, GpsData *gps); +gboolean track_insert_mark(Path *track); +gboolean track_save(Path *track); +gboolean track_open(Path *track); +void track_clear(Path *track); void track_show_distance_from_first(); void track_show_distance_from_last(); -void track_show_distance_from(Point * point); +void track_show_distance_from(Point *point); #endif diff --git a/src/ui-common.c b/src/ui-common.c index 594087c..5a5fc61 100644 --- a/src/ui-common.c +++ b/src/ui-common.c @@ -796,6 +796,8 @@ g_signal_connect(G_OBJECT(_window), "key_release_event", G_CALLBACK(window_cb_ke gtk_idle_add((GSourceFunc)window_present, NULL); } +/******* XXX: Move these !! *******/ + gboolean gps_info_update(Gps *gps) { @@ -824,8 +826,9 @@ gps_location_update(Gps *gps) g_assert(gps); if (filter_check(&filter, &gps->data, &map_loc)==TRUE) { if (track_add(&_gps->data)) { - route_check_waypoint_announce(&_gps->data); - route_autoroute_check(); + KEEP_DISPLAY_ON(); + route_check_waypoint_announce(_route, &_gps->data); + route_autoroute_check(_route); } map_refresh_mark(); }