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. "&amp;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. 
"&amp;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. "&amp;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/

Reply via email to