From 9f30939ade46329639cb8586a6cc1e29a9a495b1 Mon Sep 17 00:00:00 2001 From: Guilhem Bonnefille Date: Thu, 16 May 2013 23:36:09 +0200 Subject: [PATCH] Generalize route finder This patch generalize the route finder feature. The goal is to allow the use of different services to compute a route from two clics. To achieve this I introduced: - vik_routing_engine as base class for engines - vik_routing module for registering engines and providing "default" features And I rewrote the Google related feature. The new design seems quite overkill, but many more feature will be add in the future. One of them is to rewrite the Acquire -> Google Direction. An other is to add a "filter" on a route/track in order to allow a finer route computation, based on more than 2 points. Signed-off-by: Guilhem Bonnefille --- help/C/viking.xml | 14 +- src/Makefile.am | 3 + src/google.c | 7 + src/googlerouting.c | 118 +++++++++++++++++ src/googlerouting.h | 56 ++++++++ src/main.c | 3 + src/vikrouting.c | 189 +++++++++++++++++++++++++++ src/vikrouting.h | 41 ++++++ src/vikroutingengine.c | 286 +++++++++++++++++++++++++++++++++++++++++ src/vikroutingengine.h | 68 ++++++++++ src/viktrwlayer.c | 31 +---- 11 files changed, 785 insertions(+), 31 deletions(-) create mode 100644 src/googlerouting.c create mode 100644 src/googlerouting.h create mode 100644 src/vikrouting.c create mode 100644 src/vikrouting.h create mode 100644 src/vikroutingengine.c create mode 100644 src/vikroutingengine.h diff --git a/help/C/viking.xml b/help/C/viking.xml index 2aa1d871..61db5191 100644 --- a/help/C/viking.xml +++ b/help/C/viking.xml @@ -669,7 +669,7 @@ By default routes are coloured red. Tracks are automatically assigned a spread o -Most operations are available on tracks are available on routes, except for functionality that relies on having timestamps - since routes by definition have no timing information. Thus for example, uploading a route to OpenStreetMap Traces is not available nor is Geotagging on a route. +Most operations available on tracks are available on routes, except for functionality that relies on having timestamps - since routes by definition have no timing information. Thus for example, uploading a route to OpenStreetMap Traces is not available nor is Geotagging on a route. It is possible to convert between Tracks and Routes, although converting from a Track to a Route may involve a loss of information (hence you are required to confirm this operation before it happens). @@ -1053,7 +1053,7 @@ Changes the current tool to add trackpoints to the end of the track.
Extend Using Route Finder -Enables the Route Finder tool. Thus on a subsequent left click in the viewport, a route is calculated from the end of track to that point using Google's route service and applied to the track. +Enables the Route Finder tool. Thus on a subsequent left click in the viewport, a route is calculated from the end of track to that point using the default route service and applied to the track.
@@ -1539,11 +1539,11 @@ For Linux you can override this with the setting in the Route Finder Enable this tool by clicking on the toolbar icon: -Creates a track using Google maps routing between two points. +Creates a track using default routing engine between two points. Requires an internet connection. Click one point, then click another to create a track. @@ -1735,6 +1735,12 @@ Your OSM password will be stored in plain text. +
Routing +
Routing engine +You can select the routing engine used by default, ie by features that do not propose a live selection, like . +
+
+ diff --git a/src/Makefile.am b/src/Makefile.am index 5ed5ea6e..e8397d5d 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -85,6 +85,8 @@ libviking_a_SOURCES = \ vikgoto.c vikgoto.h \ viktrwlayer_tpwin.c viktrwlayer_tpwin.h \ viktrwlayer_propwin.c viktrwlayer_propwin.h \ + vikrouting.c vikrouting.h \ + vikroutingengine.c vikroutingengine.h \ thumbnails.c thumbnails.h \ background.c background.h \ vikradiogroup.c vikradiogroup.h \ @@ -137,6 +139,7 @@ endif if GOOGLE libviking_a_SOURCES += \ + googlerouting.c googlerouting.h \ google.c google.h endif diff --git a/src/google.c b/src/google.c index de20d08e..eea0c4e2 100644 --- a/src/google.c +++ b/src/google.c @@ -30,6 +30,8 @@ #include "vikwebtoolcenter.h" #include "vikgoto.h" #include "googlesearch.h" +#include "vikrouting.h" +#include "googlerouting.h" void google_init () { // Webtools @@ -41,4 +43,9 @@ void google_init () { GoogleGotoTool *gototool = google_goto_tool_new ( ); vik_goto_register ( VIK_GOTO_TOOL ( gototool ) ); g_object_unref ( gototool ); + + // Routing + GoogleRouting *routing = google_routing_new ( ); + vik_routing_register ( VIK_ROUTING_ENGINE ( routing ) ); + g_object_unref ( routing ); } diff --git a/src/googlerouting.c b/src/googlerouting.c new file mode 100644 index 00000000..97df9099 --- /dev/null +++ b/src/googlerouting.c @@ -0,0 +1,118 @@ +/* + * viking -- GPS Data and Topo Analyzer, Explorer, and Manager + * + * Copyright (C) 2005-2008, Alex Foobarian + * Copyright (C) 2012-2013, Guilhem Bonnefille + * + * 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 + * + */ + +/** + * SECTION:googlerouting + * @short_description: the class for Google Directions + * + * The #GoogleRouting class handles Google Directions + * service as routing engine. + * + * Technical details are available here: + * https://developers.google.com/maps/documentation/directions/#DirectionsResponses + * + * gpsbabel supports this format. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +#include +#include + +#include "googlerouting.h" + +#define GOOGLE_DIRECTIONS_STRING "maps.google.com/maps?q=from:%s,%s+to:%s,%s&output=js" + +static DownloadMapOptions googles_routing_options = { FALSE, FALSE, "http://maps.google.com/", 0, NULL }; + +static void google_routing_finalize ( GObject *gob ); + +static gchar *google_routing_get_url_for_coords ( VikRoutingEngine *self, struct LatLon start, struct LatLon end ); +static DownloadMapOptions *google_routing_get_download_options ( VikRoutingEngine *self ); + +G_DEFINE_TYPE (GoogleRouting, google_routing, VIK_ROUTING_ENGINE_TYPE) + +static void google_routing_class_init ( GoogleRoutingClass *klass ) +{ + GObjectClass *object_class; + VikRoutingEngineClass *parent_class; + + object_class = G_OBJECT_CLASS (klass); + + object_class->finalize = google_routing_finalize; + + parent_class = VIK_ROUTING_ENGINE_CLASS (klass); + + parent_class->get_url_for_coords = google_routing_get_url_for_coords; + parent_class->get_download_options = google_routing_get_download_options; +} + +/** + * google_routing_new: + * + * Create a new instance of GoogleRouting routing engine. + */ +GoogleRouting *google_routing_new () +{ + return GOOGLE_ROUTING ( g_object_new ( GOOGLE_ROUTING_TYPE, + "id", "google", + "label", "Google", + "format", "google", + NULL ) ); +} + +static void google_routing_init ( GoogleRouting *vlp ) +{ +} + +static void google_routing_finalize ( GObject *gob ) +{ + G_OBJECT_GET_CLASS(gob)->finalize(gob); +} + +static DownloadMapOptions * +google_routing_get_download_options ( VikRoutingEngine *self ) +{ + return &googles_routing_options; +} + +/* + * Override VikRoutingEngine:get_download_options() + */ +gchar * +google_routing_get_url_for_coords ( VikRoutingEngine *self, struct LatLon start, struct LatLon end ) +{ + gchar startlat[G_ASCII_DTOSTR_BUF_SIZE], startlon[G_ASCII_DTOSTR_BUF_SIZE]; + gchar endlat[G_ASCII_DTOSTR_BUF_SIZE], endlon[G_ASCII_DTOSTR_BUF_SIZE]; + gchar *url; + url = g_strdup_printf(GOOGLE_DIRECTIONS_STRING, + g_ascii_dtostr (startlat, G_ASCII_DTOSTR_BUF_SIZE, (gdouble) start.lat), + g_ascii_dtostr (startlon, G_ASCII_DTOSTR_BUF_SIZE, (gdouble) start.lon), + g_ascii_dtostr (endlat, G_ASCII_DTOSTR_BUF_SIZE, (gdouble) end.lat), + g_ascii_dtostr (endlon, G_ASCII_DTOSTR_BUF_SIZE, (gdouble) end.lon)); + + return url; +} diff --git a/src/googlerouting.h b/src/googlerouting.h new file mode 100644 index 00000000..a67ba7bc --- /dev/null +++ b/src/googlerouting.h @@ -0,0 +1,56 @@ +/* + * viking -- GPS Data and Topo Analyzer, Explorer, and Manager + * + * Copyright (C) 2012-2013, Guilhem Bonnefille + * + * 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 _GOOGLE_ROUTING_H +#define _GOOGLE_ROUTING_H + +#include + +#include "vikroutingengine.h" + +G_BEGIN_DECLS + +#define GOOGLE_ROUTING_TYPE (google_routing_get_type ()) +#define GOOGLE_ROUTING(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GOOGLE_ROUTING_TYPE, GoogleRouting)) +#define GOOGLE_ROUTING_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GOOGLE_ROUTING_TYPE, GoogleRoutingClass)) +#define GOOGLE_IS_ROUTING(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GOOGLE_ROUTING_TYPE)) +#define GOOGLE_IS_ROUTING_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GOOGLE_ROUTING_TYPE)) +#define GOOGLE_ROUTING_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GOOGLE_ROUTING_TYPE, GoogleRoutingClass)) + + +typedef struct _GoogleRouting GoogleRouting; +typedef struct _GoogleRoutingClass GoogleRoutingClass; + +struct _GoogleRoutingClass +{ + VikRoutingEngineClass object_class; +}; + +GType google_routing_get_type (); + +struct _GoogleRouting { + VikRoutingEngine obj; +}; + +GoogleRouting *google_routing_new (); + +G_END_DECLS + +#endif diff --git a/src/main.c b/src/main.c index ab353b57..31861a62 100644 --- a/src/main.c +++ b/src/main.c @@ -34,6 +34,7 @@ #include "viklayer_defaults.h" #include "globals.h" #include "vikmapslayer.h" +#include "vikrouting.h" #ifdef VIK_CONFIG_GEOCACHES void a_datasource_gc_init(); @@ -182,6 +183,8 @@ int main( int argc, char *argv[] ) a_datasource_gc_init(); #endif + vik_routing_prefs_init(); + /* Set the icon */ main_icon = gdk_pixbuf_from_pixdata(&viking_pixbuf, FALSE, NULL); gtk_window_set_default_icon(main_icon); diff --git a/src/vikrouting.c b/src/vikrouting.c new file mode 100644 index 00000000..6a4fd477 --- /dev/null +++ b/src/vikrouting.c @@ -0,0 +1,189 @@ +/* + * viking -- GPS Data and Topo Analyzer, Explorer, and Manager + * + * Copyright (C) 2012-2013, Guilhem Bonnefille + * + * 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 + */ + +/** + * SECTION:vikrouting + * @short_description: the routing framework + * + * This module handles the list of #VikRoutingEngine. + * It also handles the "default" functions. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include + +#include "curl_download.h" +#include "babel.h" + +#include "preferences.h" + +#include "vikrouting.h" +#include "vikroutingengine.h" + +/* params will be routing.default */ +/* we have to make sure these don't collide. */ +#define VIKING_ROUTING_PARAMS_GROUP_KEY "routing" +#define VIKING_ROUTING_PARAMS_NAMESPACE "routing." + +/* List to register all routing engines */ +static GList *routing_engine_list = NULL; + +static VikLayerParam prefs[] = { + { VIK_LAYER_NUM_TYPES, VIKING_ROUTING_PARAMS_NAMESPACE "default", VIK_LAYER_PARAM_STRING, VIK_LAYER_GROUP_NONE, N_("Default engine:"), VIK_LAYER_WIDGET_COMBOBOX, NULL, NULL, NULL }, +}; + +gchar **routing_engine_labels = NULL; +gchar **routing_engine_ids = NULL; + +/** + * vik_routing_prefs_init: + * + * Initialize the preferences of the routing feature. + */ +void +vik_routing_prefs_init() +{ + a_preferences_register_group ( VIKING_ROUTING_PARAMS_GROUP_KEY, "Routing" ); + + VikLayerParamData tmp; + tmp.s = NULL; + a_preferences_register(prefs, tmp, VIKING_ROUTING_PARAMS_GROUP_KEY); +} + +static gint +search_by_id (gconstpointer a, + gconstpointer b) +{ + const gchar *id = b; + VikRoutingEngine *engine = a; + gchar *engineId = vik_routing_engine_get_id (engine); + if (id && engine) + return strcmp(id, engineId); + else + return -1; +} + +/** + * vik_routing_find_engine: + * @id: the id of the engine we are looking for + * + * Returns: the found engine or %NULL + */ +VikRoutingEngine * +vik_routing_find_engine ( const gchar *id ) +{ + VikRoutingEngine *engine = NULL; + GList *elem = g_list_find_custom (routing_engine_list, id, search_by_id); + if (elem) + engine = elem->data; + return engine; +} + +/** + * vik_routing_default: + * + * Retrieve the default engine, based on user's preferences. + * + * Returns: the default engine + */ +static VikRoutingEngine * +vik_routing_default( void ) +{ + gchar *id = a_preferences_get ( VIKING_ROUTING_PARAMS_NAMESPACE "default")->s; + VikRoutingEngine *engine = vik_routing_find_engine(id); + if (engine == NULL && routing_engine_list != NULL && g_list_first (routing_engine_list) != NULL) + /* Fallback to first element */ + engine = g_list_first (routing_engine_list)->data; + + return engine; +} + +/** + * vik_routing_default_find: + * + * Route computation with default engine. + */ +void +vik_routing_default_find(VikTrwLayer *vt, struct LatLon start, struct LatLon end) +{ + /* The engine */ + VikRoutingEngine *engine = vik_routing_default ( ); + /* The route computation */ + vik_routing_engine_find ( engine, vt, start, end ); +} + +/** + * vik_routing_register: + * @engine: new routing engine to register + * + * Register a new routing engine. + */ +void +vik_routing_register( VikRoutingEngine *engine ) +{ + if ( VIK_IS_ROUTING_ENGINE ( engine ) ) + routing_engine_list = g_list_append ( routing_engine_list, g_object_ref ( engine ) ); + + gsize len = 0; + if (routing_engine_labels) + len = g_strv_length (routing_engine_labels); + + gchar *label = vik_routing_engine_get_label ( engine ); + gchar *id = vik_routing_engine_get_id ( engine ); + + /* Add the label */ + routing_engine_labels = g_realloc (routing_engine_labels, (len+2)*sizeof(gchar*)); + routing_engine_labels[len] = g_strdup (label); + routing_engine_labels[len+1] = NULL; + + /* Add the id */ + routing_engine_ids = g_realloc (routing_engine_ids, (len+2)*sizeof(gchar*)); + routing_engine_ids[len] = g_strdup (id); + routing_engine_ids[len+1] = NULL; + + /* Hack + We have to ensure the mode LayerParam references the up-to-date + GLists. + */ + /* + memcpy(&maps_layer_params[0].widget_data, ¶ms_maptypes, sizeof(gpointer)); + memcpy(&maps_layer_params[0].extra_widget_data, ¶ms_maptypes_ids, sizeof(gpointer)); + */ + prefs[0].widget_data = routing_engine_labels; + prefs[0].extra_widget_data = routing_engine_ids; +} + +/** + * vik_routing_unregister_all: + * + * Unregister all registered routing engines. + */ +void +vik_routing_unregister_all () +{ + g_list_foreach ( routing_engine_list, (GFunc) g_object_unref, NULL ); + g_strfreev ( routing_engine_labels ); + g_strfreev ( routing_engine_ids ); +} diff --git a/src/vikrouting.h b/src/vikrouting.h new file mode 100644 index 00000000..1a986363 --- /dev/null +++ b/src/vikrouting.h @@ -0,0 +1,41 @@ +/* + * viking -- GPS Data and Topo Analyzer, Explorer, and Manager + * + * Copyright (C) 2012-2013, Guilhem Bonnefille + * + * 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 _VIKING_ROUTING_H +#define _VIKING_ROUTING_H + +#include + +#include "vikroutingengine.h" + +G_BEGIN_DECLS + + +/* Default */ +void vik_routing_default_find ( VikTrwLayer *vt, struct LatLon start, struct LatLon end ); + +/* Routing engines management */ +void vik_routing_prefs_init(); +void vik_routing_register( VikRoutingEngine *engine ); +void vik_routing_unregister_all (); + +G_END_DECLS + +#endif diff --git a/src/vikroutingengine.c b/src/vikroutingengine.c new file mode 100644 index 00000000..34fa34ae --- /dev/null +++ b/src/vikroutingengine.c @@ -0,0 +1,286 @@ +/* + * viking -- GPS Data and Topo Analyzer, Explorer, and Manager + * + * Copyright (C) 2012-2013, Guilhem Bonnefille + * + * 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 + */ + +/** + * SECTION:vikroutingengine + * @short_description: the base class to describe routing engine + * + * The #VikRoutingEngine class is both the interface and the base class + * for the hierarchie of routing engines. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include + +#include "curl_download.h" +#include "babel.h" + +#include "vikroutingengine.h" + +static void vik_routing_engine_finalize ( GObject *gob ); +static DownloadMapOptions *vik_routing_engine_get_download_options_default ( VikRoutingEngine *self ); +static GObjectClass *parent_class; + +typedef struct _VikRoutingPrivate VikRoutingPrivate; +struct _VikRoutingPrivate +{ + gchar *id; + gchar *label; + gchar *format; +}; + +#define VIK_ROUTING_ENGINE_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), VIK_ROUTING_ENGINE_TYPE, VikRoutingPrivate)) + +/* properties */ +enum +{ + PROP_0, + + PROP_ID, + PROP_LABEL, + PROP_FORMAT, +}; + +G_DEFINE_ABSTRACT_TYPE (VikRoutingEngine, vik_routing_engine, G_TYPE_OBJECT) + +static void +vik_routing_engine_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + VikRoutingPrivate *priv = VIK_ROUTING_ENGINE_PRIVATE ( object ); + + switch (property_id) + { + case PROP_ID: + g_free (priv->id); + priv->id = g_strdup(g_value_get_string (value)); + break; + + case PROP_LABEL: + g_free (priv->label); + priv->label = g_strdup(g_value_get_string (value)); + break; + + case PROP_FORMAT: + g_free (priv->format); + priv->format = g_strdup(g_value_get_string (value)); + break; + + default: + /* We don't have any other property... */ + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +static void +vik_routing_engine_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + VikRoutingPrivate *priv = VIK_ROUTING_ENGINE_PRIVATE ( object ); + + switch (property_id) + { + case PROP_ID: + g_value_set_string (value, priv->id); + break; + + case PROP_LABEL: + g_value_set_string (value, priv->label); + break; + + case PROP_FORMAT: + g_value_set_string (value, priv->format); + break; + + default: + /* We don't have any other property... */ + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +static void +vik_routing_engine_class_init ( VikRoutingEngineClass *klass ) +{ + GObjectClass *object_class; + VikRoutingEngineClass *routing_class; + GParamSpec *pspec = NULL; + + object_class = G_OBJECT_CLASS (klass); + + object_class->set_property = vik_routing_engine_set_property; + object_class->get_property = vik_routing_engine_get_property; + object_class->finalize = vik_routing_engine_finalize; + + parent_class = g_type_class_peek_parent (klass); + + routing_class = VIK_ROUTING_ENGINE_CLASS ( klass ); + routing_class->find = NULL; + routing_class->get_download_options = vik_routing_engine_get_download_options_default; + routing_class->get_url_for_coords = NULL; + + + pspec = g_param_spec_string ("id", + "Identifier", + "The identifier of the routing engine", + "" /* default value */, + G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE); + g_object_class_install_property (object_class, PROP_ID, pspec); + + pspec = g_param_spec_string ("label", + "Label", + "The label of the routing engine", + "" /* default value */, + G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE); + g_object_class_install_property (object_class, PROP_LABEL, pspec); + + pspec = g_param_spec_string ("format", + "Format", + "The format of the output (see gpsbabel)", + "" /* default value */, + G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE); + g_object_class_install_property (object_class, PROP_FORMAT, pspec); + + g_type_class_add_private (klass, sizeof (VikRoutingPrivate)); +} + +static void +vik_routing_engine_init ( VikRoutingEngine *self ) +{ + VikRoutingPrivate *priv = VIK_ROUTING_ENGINE_PRIVATE (self); + + priv->id = NULL; + priv->label = NULL; + priv->format = NULL; +} + +static void +vik_routing_engine_finalize ( GObject *self ) +{ + VikRoutingPrivate *priv = VIK_ROUTING_ENGINE_PRIVATE (self); + + g_free (priv->id); + priv->id = NULL; + + g_free (priv->label); + priv->label = NULL; + + g_free (priv->format); + priv->format = NULL; + + G_OBJECT_CLASS(parent_class)->finalize(self); +} + +static DownloadMapOptions * +vik_routing_engine_get_download_options_default ( VikRoutingEngine *self ) +{ + // Default: return NULL + return NULL; +} + +static gchar * +vik_routing_engine_get_url_for_coords ( VikRoutingEngine *self, struct LatLon start, struct LatLon end ) +{ + VikRoutingEngineClass *klass; + + g_return_val_if_fail ( VIK_IS_ROUTING_ENGINE (self), NULL ); + klass = VIK_ROUTING_ENGINE_GET_CLASS( self ); + g_return_val_if_fail ( klass->get_url_for_coords != NULL, NULL ); + + return klass->get_url_for_coords( self, start, end ); +} + +static DownloadMapOptions * +vik_routing_engine_get_download_options ( VikRoutingEngine *self ) +{ + VikRoutingEngineClass *klass; + + g_return_val_if_fail ( VIK_IS_ROUTING_ENGINE (self), NULL ); + klass = VIK_ROUTING_ENGINE_GET_CLASS( self ); + g_return_val_if_fail ( klass->get_download_options != NULL, NULL ); + + return klass->get_download_options( self ); +} + +int +vik_routing_engine_find ( VikRoutingEngine *self, VikTrwLayer *vtl, struct LatLon start, struct LatLon end ) +{ + gchar *uri; + int ret = 0; /* OK */ + + uri = vik_routing_engine_get_url_for_coords(self, start, end); + + DownloadMapOptions *options = vik_routing_engine_get_download_options(self); + + gchar *format = vik_routing_engine_get_format ( self ); + a_babel_convert_from_url ( vtl, uri, format, NULL, NULL, options ); + + g_free(uri); + return ret; +} + +/** + * vik_routing_engine_get_id: + * + * Returns: the id of self + */ +gchar * +vik_routing_engine_get_id ( VikRoutingEngine *self ) +{ + VikRoutingPrivate *priv = VIK_ROUTING_ENGINE_PRIVATE (self); + + return priv->id; +} + +/** + * vik_routing_engine_get_label: + * + * Returns: the label of self + */ +gchar * +vik_routing_engine_get_label ( VikRoutingEngine *self ) +{ + VikRoutingPrivate *priv = VIK_ROUTING_ENGINE_PRIVATE (self); + + return priv->label; +} + +/** + * vik_routing_engine_get_format: + * + * Returns: the format of self + */ +gchar * +vik_routing_engine_get_format ( VikRoutingEngine *self ) +{ + VikRoutingPrivate *priv = VIK_ROUTING_ENGINE_PRIVATE (self); + + return priv->format; +} diff --git a/src/vikroutingengine.h b/src/vikroutingengine.h new file mode 100644 index 00000000..c90d4e69 --- /dev/null +++ b/src/vikroutingengine.h @@ -0,0 +1,68 @@ +/* + * viking -- GPS Data and Topo Analyzer, Explorer, and Manager + * + * Copyright (C) 2012-2013, Guilhem Bonnefille + * + * 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 _VIKING_ROUTING_ENGINE_H +#define _VIKING_ROUTING_ENGINE_H + +#include + +#include "viktrwlayer.h" +#include "coords.h" +#include "download.h" + +#include "vikwindow.h" + +G_BEGIN_DECLS + +#define VIK_ROUTING_ENGINE_TYPE (vik_routing_engine_get_type ()) +#define VIK_ROUTING_ENGINE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), VIK_ROUTING_ENGINE_TYPE, VikRoutingEngine)) +#define VIK_ROUTING_ENGINE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), VIK_ROUTING_ENGINE_TYPE, VikRoutingEngineClass)) +#define VIK_IS_ROUTING_ENGINE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), VIK_ROUTING_ENGINE_TYPE)) +#define VIK_IS_ROUTING_ENGINE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), VIK_ROUTING_ENGINE_TYPE)) +#define VIK_ROUTING_ENGINE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), VIK_ROUTING_ENGINE_TYPE, VikRoutingEngineClass)) + + +typedef struct _VikRoutingEngine VikRoutingEngine; +typedef struct _VikRoutingEngineClass VikRoutingEngineClass; + +struct _VikRoutingEngineClass +{ + GObjectClass object_class; + void (*find)(VikTrwLayer *vt, struct LatLon start, struct LatLon end); + gchar *(*get_url_for_coords)(VikRoutingEngine *self, struct LatLon start, struct LatLon end); + DownloadMapOptions *(*get_download_options) ( VikRoutingEngine *self ); +}; + +GType vik_routing_engine_get_type (); + +struct _VikRoutingEngine { + GObject obj; +}; + +int vik_routing_engine_find ( VikRoutingEngine *self, VikTrwLayer *vt, struct LatLon start, struct LatLon end ); + +/* Acessors */ +gchar *vik_routing_engine_get_id ( VikRoutingEngine *self ); +gchar *vik_routing_engine_get_label ( VikRoutingEngine *self ); +gchar *vik_routing_engine_get_format ( VikRoutingEngine *self ); + +G_END_DECLS + +#endif diff --git a/src/viktrwlayer.c b/src/viktrwlayer.c index 8c4455b9..bf09976f 100644 --- a/src/viktrwlayer.c +++ b/src/viktrwlayer.c @@ -6,6 +6,7 @@ * Copyright (C) 2007, Quy Tonthat * Copyright (C) 2009, Hein Ragas * Copyright (c) 2012, Rob Norris + * Copyright (c) 2012-2013, Guilhem Bonnefille * * 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 @@ -55,6 +56,8 @@ #include "vikexttool_datasources.h" #include "util.h" +#include "vikrouting.h" + #include "icons/icons.h" #ifdef HAVE_MATH_H @@ -74,10 +77,6 @@ #include #include -#ifdef VIK_CONFIG_GOOGLE -#define GOOGLE_DIRECTIONS_STRING "maps.google.com/maps?q=from:%s,%s+to:%s,%s&output=js" -#endif - #define VIK_TRW_LAYER_TRACK_GC 6 #define VIK_TRW_LAYER_TRACK_GCS 10 #define VIK_TRW_LAYER_TRACK_GC_BLACK 0 @@ -356,10 +355,8 @@ static void tool_new_track_release ( VikTrwLayer *vtl, GdkEventButton *event, Vi static gboolean tool_new_track_key_press ( VikTrwLayer *vtl, GdkEventKey *event, VikViewport *vvp ); static gpointer tool_new_waypoint_create ( VikWindow *vw, VikViewport *vvp); static gboolean tool_new_waypoint_click ( VikTrwLayer *vtl, GdkEventButton *event, VikViewport *vvp ); -#ifdef VIK_CONFIG_GOOGLE static gpointer tool_route_finder_create ( VikWindow *vw, VikViewport *vvp); static gboolean tool_route_finder_click ( VikTrwLayer *vtl, GdkEventButton *event, VikViewport *vvp ); -#endif static void cached_pixbuf_free ( CachedPixbuf *cp ); static gint cached_pixbuf_cmp ( CachedPixbuf *cp, const gchar *name ); @@ -428,13 +425,11 @@ static VikToolInterface trw_layer_tools[] = { FALSE, GDK_CURSOR_IS_PIXMAP, &cursor_showpic_pixbuf }, -#ifdef VIK_CONFIG_GOOGLE { { "RouteFinder", "vik-icon-Route Finder", N_("Route _Finder"), "F", N_("Route Finder"), 0 }, (VikToolConstructorFunc) tool_route_finder_create, NULL, NULL, NULL, (VikToolMouseFunc) tool_route_finder_click, NULL, NULL, (VikToolKeyFunc) NULL, FALSE, GDK_CURSOR_IS_PIXMAP, &cursor_route_finder_pixbuf }, -#endif }; enum { @@ -444,9 +439,7 @@ enum { TOOL_EDIT_WAYPOINT, TOOL_EDIT_TRACKPOINT, TOOL_SHOW_PICTURE, -#ifdef VIK_CONFIG_GOOGLE TOOL_ROUTE_FINDER, -#endif NUM_TOOLS }; @@ -4552,7 +4545,6 @@ static void trw_layer_extend_track_end ( gpointer pass_along[6] ) goto_coord ( pass_along[1], pass_along[0], pass_along[5], &(((VikTrackpoint *)g_list_last(track->trackpoints)->data)->coord) ); } -#ifdef VIK_CONFIG_GOOGLE /** * extend a track using route finder */ @@ -4573,7 +4565,6 @@ static void trw_layer_extend_track_end_route_finder ( gpointer pass_along[6] ) goto_coord ( pass_along[1], pass_along[0], pass_along[5], &last_coord) ; } -#endif static void trw_layer_apply_dem_data ( gpointer pass_along[6] ) { @@ -6668,7 +6659,6 @@ 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 ); -#ifdef VIK_CONFIG_GOOGLE if ( subtype == VIK_TRW_LAYER_SUBLAYER_ROUTE ) { item = gtk_image_menu_item_new_with_mnemonic ( _("Extend _Using Route Finder") ); gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock ("Route Finder", GTK_ICON_SIZE_MENU) ); // Own icon - see stock_icons in vikwindow.c @@ -6676,7 +6666,6 @@ 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 ); } -#endif // ATM can't upload a single waypoint but can do waypoints to a GPS if ( subtype != VIK_TRW_LAYER_SUBLAYER_WAYPOINT ) { @@ -8275,7 +8264,6 @@ static gboolean tool_edit_trackpoint_release ( VikTrwLayer *vtl, GdkEventButton } -#ifdef VIK_CONFIG_GOOGLE /*** Route Finder ***/ static gpointer tool_route_finder_create ( VikWindow *vw, VikViewport *vvp) { @@ -8307,9 +8295,6 @@ static gboolean tool_route_finder_click ( VikTrwLayer *vtl, GdkEventButton *even } else if ( vtl->route_finder_started || (event->state & GDK_CONTROL_MASK && vtl->route_finder_current_track) ) { struct LatLon start, end; - gchar startlat[G_ASCII_DTOSTR_BUF_SIZE], startlon[G_ASCII_DTOSTR_BUF_SIZE]; - gchar endlat[G_ASCII_DTOSTR_BUF_SIZE], endlon[G_ASCII_DTOSTR_BUF_SIZE]; - gchar *url; vik_coord_to_latlon ( &(vtl->route_finder_coord), &start ); vik_coord_to_latlon ( &(tmp), &end ); @@ -8323,14 +8308,7 @@ static gboolean tool_route_finder_click ( VikTrwLayer *vtl, GdkEventButton *even vtl->route_finder_started = FALSE; } - url = g_strdup_printf(GOOGLE_DIRECTIONS_STRING, - g_ascii_dtostr (startlat, G_ASCII_DTOSTR_BUF_SIZE, (gdouble) start.lat), - g_ascii_dtostr (startlon, G_ASCII_DTOSTR_BUF_SIZE, (gdouble) start.lon), - g_ascii_dtostr (endlat, G_ASCII_DTOSTR_BUF_SIZE, (gdouble) end.lat), - g_ascii_dtostr (endlon, G_ASCII_DTOSTR_BUF_SIZE, (gdouble) end.lon)); - // NB normally this returns a GPX Route - so subsequent usage of it must lookup via the routes hash - a_babel_convert_from_url ( vtl, url, "google", NULL, NULL, NULL ); - g_free ( url ); + vik_routing_default_find ( vtl, start, end); /* see if anything was done -- a track was added or appended to */ if ( vtl->route_finder_check_added_track && vtl->route_finder_added_track ) { @@ -8356,7 +8334,6 @@ static gboolean tool_route_finder_click ( VikTrwLayer *vtl, GdkEventButton *even } return TRUE; } -#endif /*** Show picture ****/ -- 2.39.5