This patch add a menu entry for track/route in order to request a refined version of the track/route.
The user is now able to plan a journey by creating a simple track/route and then request a routing engine to refine this track/route. This is a simple solution to extend route finder tool, adding 'via' points in the journey. Signed-off-by: Guilhem Bonnefille <guilhem.bonnefi...@gmail.com> --- help/C/viking.xml | 4 ++ src/vikroutingengine.c | 48 ++++++++++++++++++++ src/vikroutingengine.h | 8 +++- src/vikroutingwebengine.c | 106 +++++++++++++++++++++++++++++++++++++++++++++ src/viktrwlayer.c | 69 +++++++++++++++++++++++++++++ 5 files changed, 233 insertions(+), 2 deletions(-) diff --git a/help/C/viking.xml b/help/C/viking.xml index f07a11d..e434db0 100644 --- a/help/C/viking.xml +++ b/help/C/viking.xml @@ -2485,6 +2485,10 @@ Accept: */* <listitem><para>the part of the URL setting the end point location, parametrized in the spirit of C printf format, with 2 "%s" for coordinates (eg. "&stop=%s,%s")</para></listitem> </varlistentry> <varlistentry> + <term>url-via-ll</term> + <listitem><para>the part of the URL setting via point location, parametrized in the spirit of C printf format, with 2 "%s" for coordinates (eg. "&via=%s,%s")</para></listitem> + </varlistentry> + <varlistentry> <term>url-start-dir</term> <listitem><para>the part of the URL setting the starting point location for direction based routing, parametrized in the spirit of C printf format, with one "%s" for direction (eg. "&start=%s")</para> <para>(Optional)</para></listitem> diff --git a/src/vikroutingengine.c b/src/vikroutingengine.c index 5e20b4a..8da3af7 100644 --- a/src/vikroutingengine.c +++ b/src/vikroutingengine.c @@ -141,9 +141,13 @@ vik_routing_engine_class_init ( VikRoutingEngineClass *klass ) routing_class = VIK_ROUTING_ENGINE_CLASS ( klass ); routing_class->find = NULL; + routing_class->supports_direction = NULL; routing_class->get_cmd_from_directions = NULL; + routing_class->refine = NULL; + routing_class->supports_refine = NULL; + pspec = g_param_spec_string ("id", "Identifier", "The identifier of the routing engine", @@ -297,3 +301,47 @@ vik_routing_engine_get_cmd_from_directions ( VikRoutingEngine *self, const gchar return klass->get_cmd_from_directions( self, start, end ); } + +/** + * vik_routing_engine_refine: + * @self: self object + * @vtl: layer where to create new track + * @vt: the simple route to refine + * + * Retrieve a route refining the @vt track/route. + * + * A refined route is computed from @vt. + * The route is compute from first trackpoint to last trackpoint, + * and going via all intermediate trackpoints. + * + * Returns: indicates success or not. + */ +int +vik_routing_engine_refine ( VikRoutingEngine *self, VikTrwLayer *vtl, VikTrack *vt ) +{ + VikRoutingEngineClass *klass; + + g_return_val_if_fail ( VIK_IS_ROUTING_ENGINE (self), 0 ); + klass = VIK_ROUTING_ENGINE_GET_CLASS ( self ); + g_return_val_if_fail ( klass->refine != NULL, 0 ); + + return klass->refine ( self, vtl, vt ); +} + +/** + * vik_routing_engine_supports_refine: + * @self: routing engine + * + * Returns: %TRUE if this engine supports the refine of track + */ +gboolean +vik_routing_engine_supports_refine ( VikRoutingEngine *self ) +{ + VikRoutingEngineClass *klass; + + g_return_val_if_fail ( VIK_IS_ROUTING_ENGINE (self), FALSE ); + klass = VIK_ROUTING_ENGINE_GET_CLASS ( self ); + g_return_val_if_fail ( klass->supports_refine != NULL, FALSE ); + + return klass->supports_refine ( self ); +} diff --git a/src/vikroutingengine.h b/src/vikroutingengine.h index a5da970..7762c73 100644 --- a/src/vikroutingengine.h +++ b/src/vikroutingengine.h @@ -45,9 +45,11 @@ typedef struct _VikRoutingEngineClass VikRoutingEngineClass; struct _VikRoutingEngineClass { GObjectClass object_class; - int (*find)(VikRoutingEngine *self, VikTrwLayer *vt, struct LatLon start, struct LatLon end); + int (*find)(VikRoutingEngine *self, VikTrwLayer *vtl, struct LatLon start, struct LatLon end); gchar *(*get_cmd_from_directions)(VikRoutingEngine *self, const gchar *start, const gchar *end); gboolean (*supports_direction)(VikRoutingEngine *self); + int (*refine)(VikRoutingEngine *self, VikTrwLayer *vtl, VikTrack *vt); + gboolean (*supports_refine)(VikRoutingEngine *self); }; GType vik_routing_engine_get_type (); @@ -56,7 +58,8 @@ struct _VikRoutingEngine { GObject obj; }; -int vik_routing_engine_find ( VikRoutingEngine *self, VikTrwLayer *vt, struct LatLon start, struct LatLon end ); +int vik_routing_engine_find ( VikRoutingEngine *self, VikTrwLayer *vtl, struct LatLon start, struct LatLon end ); +int vik_routing_engine_refine ( VikRoutingEngine *self, VikTrwLayer *vtl, VikTrack *vt ); gchar *vik_routing_engine_get_cmd_from_directions ( VikRoutingEngine *self, const gchar *start, const gchar *end ); /* Acessors */ @@ -65,6 +68,7 @@ gchar *vik_routing_engine_get_label ( VikRoutingEngine *self ); gchar *vik_routing_engine_get_format ( VikRoutingEngine *self ); gboolean vik_routing_engine_supports_direction ( VikRoutingEngine *self ); +gboolean vik_routing_engine_supports_refine ( VikRoutingEngine *self ); G_END_DECLS diff --git a/src/vikroutingwebengine.c b/src/vikroutingwebengine.c index 4377a22..71eae71 100644 --- a/src/vikroutingwebengine.c +++ b/src/vikroutingwebengine.c @@ -45,6 +45,8 @@ static void vik_routing_web_engine_finalize ( GObject *gob ); static int vik_routing_web_engine_find ( VikRoutingEngine *self, VikTrwLayer *vtl, struct LatLon start, struct LatLon end ); static gchar *vik_routing_web_engine_get_cmd_from_directions(VikRoutingEngine *self, const gchar *start, const gchar *end); static gboolean vik_routing_web_engine_supports_direction(VikRoutingEngine *self); +static int vik_routing_web_engine_refine ( VikRoutingEngine *self, VikTrwLayer *vtl, VikTrack *vt ); +static gboolean vik_routing_web_engine_supports_refine ( VikRoutingEngine *self ); typedef struct _VikRoutingWebEnginePrivate VikRoutingWebEnginePrivate; struct _VikRoutingWebEnginePrivate @@ -209,6 +211,8 @@ static void vik_routing_web_engine_class_init ( VikRoutingWebEngineClass *klass parent_class->find = vik_routing_web_engine_find; parent_class->supports_direction = vik_routing_web_engine_supports_direction; parent_class->get_cmd_from_directions = vik_routing_web_engine_get_cmd_from_directions; + parent_class->refine = vik_routing_web_engine_refine; + parent_class->supports_refine = vik_routing_web_engine_supports_refine; /** * VikRoutingWebEngine:url-base: @@ -475,3 +479,105 @@ vik_routing_web_engine_supports_direction ( VikRoutingEngine *self ) return (priv->url_start_dir_fmt) != NULL; } + +struct _append_ctx { + VikRoutingWebEnginePrivate *priv; + gchar **urlParts; + int nb; +}; + +static void +_append_stringified_coords ( gpointer data, gpointer user_data ) +{ + VikTrackpoint *vtp = (VikTrackpoint*)data; + struct _append_ctx *ctx = (struct _append_ctx*)user_data; + + /* Stringify coordinate */ + struct LatLon position; + vik_coord_to_latlon ( &(vtp->coord), &position ); + gchar *string = substitute_latlon ( ctx->priv->url_via_ll_fmt, position ); + + /* Append */ + ctx->urlParts[ctx->nb] = string; + ctx->nb++; +} + +static gchar * +vik_routing_web_engine_get_url_for_track ( VikRoutingEngine *self, VikTrack *vt ) +{ + gchar **urlParts; + gchar *url; + + VikRoutingWebEnginePrivate *priv = VIK_ROUTING_WEB_ENGINE_PRIVATE ( self ); + + g_return_val_if_fail ( priv->url_base != NULL, NULL ); + g_return_val_if_fail ( priv->url_start_ll_fmt != NULL, NULL ); + g_return_val_if_fail ( priv->url_stop_ll_fmt != NULL, NULL ); + g_return_val_if_fail ( priv->url_via_ll_fmt != NULL, NULL ); + + /* Init temporary storage */ + gsize len = 1 + g_list_length ( vt->trackpoints ) + 1; /* base + trackpoints + NULL */ + urlParts = g_malloc ( sizeof(gchar*)*len ); + urlParts[0] = g_strdup ( priv->url_base ); + urlParts[len-1] = NULL; + + struct _append_ctx ctx; + ctx.priv = priv; + ctx.urlParts = urlParts; + ctx.nb = 1; /* First cell available, previous used for base URL */ + + /* Append all trackpoints to URL */ + g_list_foreach ( vt->trackpoints, _append_stringified_coords, &ctx ); + + /* Override first and last positions with associated formats */ + struct LatLon position; + VikTrackpoint *vtp; + g_free ( urlParts[1] ); + vtp = g_list_first ( vt->trackpoints )->data; + vik_coord_to_latlon ( &(vtp->coord ), &position ); + urlParts[1] = substitute_latlon ( priv->url_start_ll_fmt, position ); + g_free ( urlParts[len-2] ); + vtp = g_list_last ( vt->trackpoints )->data; + vik_coord_to_latlon ( &(vtp->coord), &position ); + urlParts[len-2] = substitute_latlon ( priv->url_stop_ll_fmt, position ); + + /* Concat */ + url = g_strjoinv ( NULL, urlParts ); + g_debug ( "%s: %s", __FUNCTION__, url ); + + /* Free */ + g_strfreev ( urlParts ); + + return url; +} + +static int +vik_routing_web_engine_refine ( VikRoutingEngine *self, VikTrwLayer *vtl, VikTrack *vt ) +{ + gchar *uri; + int ret = 0; /* OK */ + + /* Compute URL */ + uri = vik_routing_web_engine_get_url_for_track ( self, vt ); + + /* Download data */ + DownloadMapOptions *options = vik_routing_web_engine_get_download_options ( self ); + + /* Convert and insert data in model */ + gchar *format = vik_routing_engine_get_format ( self ); + a_babel_convert_from_url ( vtl, uri, format, NULL, NULL, options ); + + g_free(uri); + + return ret; +} + +static gboolean +vik_routing_web_engine_supports_refine ( VikRoutingEngine *self ) +{ + g_return_val_if_fail ( VIK_IS_ROUTING_WEB_ENGINE (self), FALSE); + + VikRoutingWebEnginePrivate *priv = VIK_ROUTING_WEB_ENGINE_PRIVATE ( self ); + + return priv->url_via_ll_fmt != NULL; +} diff --git a/src/viktrwlayer.c b/src/viktrwlayer.c index 02a157f..2e1632b 100644 --- a/src/viktrwlayer.c +++ b/src/viktrwlayer.c @@ -4675,6 +4675,66 @@ static void trw_layer_auto_track_view ( gpointer pass_along[6] ) } } +/* + * Refine the selected track/route with a routing engine. + * The routing engine is selected by the user, when requestiong the job. + */ +static void trw_layer_track_refine ( gpointer pass_along[6] ) +{ + static gint last_engine = 0; + VikTrwLayer *vtl = VIK_TRW_LAYER(pass_along[0]); + VikTrack *trk; + + if ( GPOINTER_TO_INT (pass_along[2]) == VIK_TRW_LAYER_SUBLAYER_ROUTE ) + trk = (VikTrack *) g_hash_table_lookup ( vtl->routes, pass_along[3] ); + else + trk = (VikTrack *) g_hash_table_lookup ( vtl->tracks, pass_along[3] ); + + if ( trk && trk->trackpoints ) + { + /* Select engine from dialog */ + GtkWidget *dialog = gtk_dialog_new_with_buttons (_("Routing Engine..."), + VIK_GTK_WINDOW_FROM_LAYER (vtl), + GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT, + GTK_STOCK_CANCEL, + GTK_RESPONSE_REJECT, + GTK_STOCK_OK, + GTK_RESPONSE_ACCEPT, + NULL); + GtkWidget * combo = vik_routing_ui_selector_new ( (Predicate)vik_routing_engine_supports_refine, NULL ); + gtk_combo_box_set_active (GTK_COMBO_BOX (combo), last_engine); + gtk_widget_show_all(combo); + + gtk_box_pack_start ( GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(dialog))), combo, TRUE, TRUE, 0 ); + + gtk_dialog_set_default_response ( GTK_DIALOG(dialog), GTK_RESPONSE_ACCEPT ); + + if ( gtk_dialog_run ( GTK_DIALOG(dialog) ) == GTK_RESPONSE_ACCEPT ) + { + /* Dialog validated: retrieve selected engine and do the job */ + last_engine = gtk_combo_box_get_active ( GTK_COMBO_BOX(combo) ); + VikRoutingEngine *routing = vik_routing_ui_selector_get_nth (combo, last_engine); + + /* Force saving track */ + /* FIXME: remove or rename this hack */ + vtl->route_finder_check_added_track = TRUE; + + /* the job */ + vik_routing_engine_refine (routing, vtl, trk); + + /* FIXME: remove or rename this hack */ + if ( vtl->route_finder_added_track ) + vik_track_calculate_bounds ( vtl->route_finder_added_track ); + + vtl->route_finder_added_track = NULL; + vtl->route_finder_check_added_track = FALSE; + + vik_layer_emit_update ( VIK_LAYER(vtl) ); + } + gtk_widget_destroy ( dialog ); + } +} + static void trw_layer_edit_trackpoint ( gpointer pass_along[6] ) { VikTrwLayer *vtl = VIK_TRW_LAYER(pass_along[0]); @@ -6850,6 +6910,15 @@ static gboolean trw_layer_sublayer_add_menu_items ( VikTrwLayer *l, GtkMenu *men gtk_menu_shell_append ( GTK_MENU_SHELL(menu), item ); gtk_widget_show ( item ); + if ( subtype == VIK_TRW_LAYER_SUBLAYER_TRACK ) + item = gtk_image_menu_item_new_with_mnemonic ( _("Refine Track...") ); + else + item = gtk_image_menu_item_new_with_mnemonic ( _("Refine Route...") ); + gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_FIND, GTK_ICON_SIZE_MENU) ); + g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_track_refine), pass_along ); + gtk_menu_shell_append ( GTK_MENU_SHELL(menu), item ); + gtk_widget_show ( item ); + /* ATM This function is only available via the layers panel, due to the method in finding out the maps in use */ if ( vlp ) { if ( subtype == VIK_TRW_LAYER_SUBLAYER_TRACK ) -- tg: (661703c..) t/routing/refine-route (depends on: master) ------------------------------------------------------------------------------ This SF.net email is sponsored by Windows: Build for Windows Store. http://p.sf.net/sfu/windows-dev2dev _______________________________________________ Viking-devel mailing list Viking-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/viking-devel Viking home page: http://viking.sf.net/