Skip to content

Commit

Permalink
Enable routing from providers using OSRM services
Browse files Browse the repository at this point in the history
Use json-glib to make sense of the response from OSRM services,
when requested to return 'geojson' style geometry.

Enable usage of route services of Bicycle, Driving and Foot profiles.
  • Loading branch information
rnorris committed Mar 11, 2021
1 parent 7b06434 commit 0bf136e
Show file tree
Hide file tree
Showing 19 changed files with 231 additions and 19 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ src/misc/*.o
/test/*.sh.log
/test/*.sh.trs
/test/test-suite.log
/test/geojson_osrm_to_gpx
/test/geotag_read
/test/geotag_write
/test/gpx2gpx
Expand Down
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ env:
# TRAVIS BROKEN
# - FIX_APT_CONFIG="sed -i '/^#\sdeb-src /s/^#//' /etc/apt/sources.list"
# The common extra dependencies required beyond the default distribution 'build-dep'
- COMMON_DEPS="gtk-doc-tools yelp-tools libgeoclue-2-dev nettle-dev liboauth-dev libzip-dev libgtk-3-dev"
- COMMON_DEPS="gtk-doc-tools yelp-tools libgeoclue-2-dev nettle-dev liboauth-dev libzip-dev libjson-glib-dev libgtk-3-dev"
# 'glib-compile-resources' has moved around packages libglib2.0-bin --> libglib2.0-dev-bin, so can't be in common.
#
# For available build images-> https://docs.travis-ci.com/user/reference/overview/
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ Git repository:

On Debian Sid, following packages must be installed before building:

# sudo apt install gtk-doc-tools docbook-xsl yelp-tools libpng-dev libgtk-3-dev libicu-dev
# sudo apt install gtk-doc-tools docbook-xsl yelp-tools libpng-dev libgtk-3-dev libicu-dev libjson-glib-dev

The following packages are needed (they are included by default in Debian Sid, but not in other distributions). They must be installed too:

Expand Down
3 changes: 3 additions & 0 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -98,11 +98,14 @@ dnl ------------------
dnl | Pkgconfig checks |---------------------------------------
dnl ------------------

# ATM JSON not used by much of our code, so could be made optional
# but it seems to be available on all relevant platforms
PKG_CHECK_MODULES(PACKAGE, [
glib-2.0 >= 2.44
gthread-2.0 >= 2.2
gio-2.0 >= 2.32
gdk-pixbuf-2.0 >= 2.26
json-glib-1.0 >= 0.16
])

AC_SUBST(PACKAGE_CFLAGS)
Expand Down
30 changes: 30 additions & 0 deletions data/routing.xml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,36 @@
<property name="url-via-ll"></property>
<property name="url-ll-lat-first">FALSE</property>
</object>
<object class="VikRoutingWebEngine">
<property name="id">osrmBicycle</property>
<property name="label">OSRM Bicycle</property>
<property name="format">viking-geojson-osrm</property>
<property name="url-base">https://routing.openstreetmap.de/routed-bike/route/v1/driving/</property>
<property name="url-ll-lat-first">FALSE</property>
<property name="url-start-ll">%s,%s</property>
<property name="url-stop-ll">;%s,%s?geometries=geojson&amp;overview=full</property>
<property name="url-via-ll">;%s,%s</property>
</object>
<object class="VikRoutingWebEngine">
<property name="id">osrmDriving</property>
<property name="label">OSRM Driving</property>
<property name="format">viking-geojson-osrm</property>
<property name="url-base">https://router.project-osrm.org/route/v1/driving/</property>
<property name="url-ll-lat-first">FALSE</property>
<property name="url-start-ll">%s,%s</property>
<property name="url-stop-ll">;%s,%s?geometries=geojson&amp;overview=full</property>
<property name="url-via-ll">;%s,%s</property>
</object>
<object class="VikRoutingWebEngine">
<property name="id">osrmFoot</property>
<property name="label">OSRM Foot</property>
<property name="format">viking-geojson-osrm</property>
<property name="url-base">https://routing.openstreetmap.de/routed-foot/route/v1/driving</property>
<property name="url-ll-lat-first">FALSE</property>
<property name="url-start-ll">%s,%s</property>
<property name="url-stop-ll">;%s,%s?geometries=geojson&amp;overview=full</property>
<property name="url-via-ll">;%s,%s</property>
</object>
<object class="VikRoutingWebEngine">
<property name="id">yourscar</property>
<property name="label">Yours: Car</property>
Expand Down
10 changes: 0 additions & 10 deletions doc/examples/routing.xml
Original file line number Diff line number Diff line change
@@ -1,14 +1,4 @@
<objects>
<!-- Note that OSRM no longer supports GPX output, so this example no longer works -->
<object class="VikRoutingWebEngine">
<property name="id">osrm</property>
<property name="label">OSRM</property>
<property name="format">gpx</property>
<property name="url-base">http://router.project-osrm.org/viaroute?output=gpx</property>
<property name="url-start-ll">&amp;loc=%s,%s</property>
<property name="url-stop-ll">&amp;loc=%s,%s</property>
<property name="url-via-ll">&amp;loc=%s,%s</property>
</object>
<!-- Note this no longer works as Google format has changed and GPSBabel (at time of writing) doesn't understand it -->
<object class="VikRoutingWebEngine">
<property name="id">google</property>
Expand Down
1 change: 1 addition & 0 deletions help/C/index.docbook
Original file line number Diff line number Diff line change
Expand Up @@ -4376,6 +4376,7 @@ Accept: */*
<para>The <application>GPSBabel</application> format code to interpret the service response. By default a GPX response is expected and processed internally. However if the service returns a different format then <application>GPSBabel</application> is used to transform the text into something that &appname; can understand. Only formats that <application>GPSBabel</application> supports can be used: e.g. <emphasis>gtrnctr</emphasis> (for Garmin Training Center .tcx files), etc...</para>
<para>Use <command>gpsbabel --help</command> on the command line to find out the supported file types and their codes to process them.</para>
<para>Some format codes are handled natively by &appname; such as <emphasis>gpx</emphasis> and <emphasis>kml</emphasis>.</para>
<para>A special format code of <emphasis>viking-geojson-osrm</emphasis> is available for handling responses by <ulink url="http://project-osrm.org/">OSRM</ulink> route servers.</para>
</listitem>
</varlistentry>
<varlistentry>
Expand Down
2 changes: 2 additions & 0 deletions mingw-viking.spec.in
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ BuildRequires: mingw32-gtk2-devel
# Mandatory libraries
BuildRequires: mingw32-libexpat-devel
BuildRequires: mingw32-libcurl-devel
BuildRequires: mingw32-json-glib-devel
# Optional libraries
BuildRequires: mingw32-libgexiv2-devel
BuildRequires: mingw32-libbz2-devel
Expand All @@ -51,6 +52,7 @@ BuildRequires: mingw32-liboauth-devel
Requires: mingw32-gtk2
Requires: mingw32-libexpat1
Requires: mingw32-libcurl4
Requires: mingw32-json-glib
Requires: mingw32-libgexiv2
Requires: mingw32-libstdc++6
Requires: mingw32-libsqlite3-0
Expand Down
2 changes: 2 additions & 0 deletions mingw64-viking.spec.in
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ BuildRequires: mingw64-gtk3-devel
# ATM gtk3-devel auto includes at least devel versions of glib2, gobject, zlib and more

# Mandatory libraries
BuildRequires: mingw64-json-glib-devel
BuildRequires: mingw64-libexpat-devel
BuildRequires: mingw64-libcurl-devel
# Optional libraries
Expand All @@ -49,6 +50,7 @@ BuildRequires: mingw64-liboauth-devel

# Libs for runtime (and thus also available for the NSIS installer to include the dependencies)
Requires: mingw64-gtk3
Requires: mingw64-json-glib
Requires: mingw64-libexpat1
Requires: mingw64-libcurl4
Requires: mingw64-libgexiv2
Expand Down
23 changes: 17 additions & 6 deletions src/babel.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
#include "viking.h"
#include "gpx.h"
#include "kml.h"
#include "geojson.h"
#include "babel.h"
#ifdef HAVE_UNISTD_H
#include <unistd.h>
Expand Down Expand Up @@ -385,7 +386,7 @@ gboolean a_babel_convert_from_shellcommand ( VikTrwLayer *vt, const char *input_
*
* Download the file pointed by the URL and optionally uses GPSBabel to convert from input_type.
* If input_type and babelfilters are %NULL, gpsbabel is not used.
* If input_type is 'gpx' of 'kml' then we will use our own native parsers.
* If input_type is 'gpx' or 'kml' or 'geojson-osrm' then we will use our own native parsers.
* NB TCX and indeed Vikings own files aren't available via this method since they can only be
* loaded into an aggregate layer (i.e. not into a %VikTrwLayer which is all that is available here)
*
Expand Down Expand Up @@ -415,31 +416,41 @@ gboolean a_babel_convert_from_url_filter ( VikTrwLayer *vt, const char *url, con
if (fetch_ret == DOWNLOAD_SUCCESS) {
gboolean do_gpx = FALSE;
gboolean do_kml = FALSE;
gboolean do_gjo = FALSE;
if ( g_strcmp0(input_type, "gpx") == 0 )
do_gpx = TRUE;
if ( g_strcmp0(input_type, "kml") == 0 )
do_kml = TRUE;
if ( g_strcmp0(input_type, "viking-geojson-osrm") == 0 )
do_gjo = TRUE;

if ( !do_gpx && !do_kml ) {
if ( !do_gpx && !do_kml && !do_gjo ) {
if (input_type != NULL || babelfilters != NULL) {
babelargs = (input_type) ? g_strdup_printf(" -i %s", input_type) : g_strdup("");
ret = a_babel_convert_from_filter( vt, babelargs, name_src, babelfilters, NULL, NULL, NULL );
} else
// No input_type specified - resort to GPX
do_gpx = TRUE;
}
if ( do_gpx || do_kml ) {
if ( do_gpx || do_kml || do_gjo ) {
/* Process directly the retrieved file */
g_debug ( "%s: directly read file %s", __FUNCTION__, name_src );
FILE *f = g_fopen(name_src, "r");
if (f) {
gchar *dirpath = g_path_get_dirname ( name_src );
if ( do_kml )
if ( do_kml ) {
ret = a_kml_read_file ( vt, f );
else
fclose(f);
}
else if ( do_gjo ) {
fclose(f);
ret = a_geojson_read_file_OSRM ( vt, name_src );
}
else {
ret = a_gpx_read_file ( vt, f, dirpath, FALSE );
fclose(f);
}
g_free ( dirpath );
fclose(f);
}
// Try to avoid adding the description if URL is OAuth signed
if ( !g_ascii_strncasecmp(url, "?oauth_consumer_key=", 20) ) {
Expand Down
4 changes: 4 additions & 0 deletions src/dialog.c
Original file line number Diff line number Diff line change
Expand Up @@ -990,6 +990,7 @@ void a_dialog_license ( GtkWindow *parent, const gchar *map, const gchar *licens
#ifdef HAVE_OAUTH_H
#include <oauth.h>
#endif
#include <json-glib/json-glib.h>

void a_dialog_build_info ( GtkWindow *parent )
{
Expand Down Expand Up @@ -1042,6 +1043,9 @@ void a_dialog_build_info ( GtkWindow *parent )
#ifdef LIBOAUTH_VERSION
g_string_append_printf ( msg, "liboauth version: %s\n", LIBOAUTH_VERSION );
#endif
#endif
#ifdef JSON_VERSION_S
g_string_append_printf ( msg, "json-glib version: %s\n", JSON_VERSION_S );
#endif

// https://docs.flatpak.org/en/latest/flatpak-command-reference.html#flatpak-metadata
Expand Down
89 changes: 89 additions & 0 deletions src/geojson.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
#include <glib.h>
#include <glib/gstdio.h>
#include <glib/gi18n.h>
#include <json-glib/json-glib.h>

/**
* Perform any cleanup actions once program has completed running
Expand Down Expand Up @@ -186,3 +187,91 @@ gchar* a_geojson_import_to_gpx ( const gchar *filename )

return gpx_filename;
}

/**
* Handle response from
* http://project-osrm.org/docs/v5.23.0/api/#route-service
* ATM only try to get the geometry out of the response
* i.e. no handling of 'code' response or 'message'
*/
gboolean a_geojson_read_file_OSRM ( VikTrwLayer *vtl, const gchar *filename )
{
JsonParser *jp = json_parser_new();
GError *error = NULL;
gboolean ans = json_parser_load_from_file ( jp, filename, &error );
if ( error ) {
g_warning ( "%s: parse load failed: %s", __FUNCTION__, error->message );
g_error_free ( error );
return FALSE;
}

JsonNode *result;
JsonPath *path = json_path_new ();
json_path_compile ( path, "$.routes..geometry..coordinates", NULL );
result = json_path_match ( path, json_parser_get_root(jp) );

JsonGenerator *generator = json_generator_new ();
json_generator_set_root ( generator, result );

// Not sure of a good way to use native glib types (or GObjects etc...)
// so simply hack apart this returned string
gchar *str = json_generator_to_data ( generator, NULL );
//g_debug ( "%s result: %s\n", __FUNCTION__, str );

if ( strlen(str) > 8 ) {
// Not sure how efficient this is; but should suffice for our use cases
gchar *ptr = GINT_TO_POINTER(1);
while ( ptr ) {
// Remove the inbetween brackets
ptr = g_strrstr ( str, "],[" );
if ( ptr )
// NB using memcpy() as compiler moans about not nul-terminated for strncpy(),
// but here we definitely want just a direct substitution
//strncpy ( ptr, " ", 3 );
memcpy ( ptr, " ", 3 );
}

// Tidy up beginning and ending brackets
ptr = g_strrstr ( str, "]]]" );
if ( ptr )
memcpy ( ptr, " ", 3 ); // as above
ptr = g_strrstr ( str, "[[[" );
if ( ptr )
memcpy ( ptr, " ", 3 ); // as above

gchar **coords = g_strsplit ( str, " ", -1 );

gint gi = 0;
gchar *coord = coords[0];
if ( coord ) {
ans = TRUE;
VikCoordMode coord_mode = vik_trw_layer_get_coord_mode ( vtl );
VikTrack *trk = vik_track_new ();
trk->is_route = TRUE;
VikTrackpoint *tp;
struct LatLon ll;
while ( coord ) {
gchar **vals = g_strsplit ( coord, ",", -1 );
guint nn = g_strv_length ( vals );
if ( nn == 2 ) {
tp = vik_trackpoint_new ();
// Remember geojson coordinates are in the 'lon,lat' order
ll.lat = g_ascii_strtod ( vals[1], NULL );
ll.lon = g_ascii_strtod ( vals[0], NULL );
vik_coord_load_from_latlon ( &tp->coord, coord_mode, &ll );
trk->trackpoints = g_list_prepend ( trk->trackpoints, tp );
}
g_strfreev ( vals );
//gi++;
coord = coords[gi++];
}
trk->trackpoints = g_list_reverse ( trk->trackpoints );
// Potentially could try to be more clever with the name...
vik_trw_layer_filein_add_track ( vtl, N_("OSRM Route"), trk );
}
g_strfreev ( coords );
}
g_object_unref ( jp );

return ans;
}
3 changes: 3 additions & 0 deletions src/geojson.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
* viking -- GPS Data and Topo Analyzer, Explorer, and Manager
*
* Copyright (c) 2014, Rob Norris <rw_norris@hotmail.com>
* Copyright (c) 2021, Rob Norris <rw_norris@hotmail.com>
*
* 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
Expand Down Expand Up @@ -33,6 +34,8 @@ const gchar* a_geojson_program_import ( void );

gchar* a_geojson_import_to_gpx ( const gchar *filename );

gboolean a_geojson_read_file_OSRM ( VikTrwLayer *vtl, const gchar *filename );

G_END_DECLS

#endif
10 changes: 10 additions & 0 deletions test/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ TESTS = check_degrees_conversions.sh \
check_babel.sh \
check_vik2vik.sh \
check_gpx.sh \
check_geojson_osrm.sh \
check_help_xml.sh \
check_metatile.sh
if GEOTAG
Expand All @@ -29,6 +30,7 @@ TESTS += check_md5_hash.sh
endif

check_PROGRAMS = degrees_converter \
geojson_osrm_to_gpx \
gpx2gpx \
vik2vik \
test_vikgotoxmltool \
Expand All @@ -49,6 +51,7 @@ check_SCRIPTS = check_degrees_conversions.sh \
check_parse_latlon.sh \
check_vik2vik.sh \
check_gpx.sh \
check_geojson_osrm.sh \
check_help_xml.sh \
check_metatile.sh
if GEOTAG
Expand All @@ -71,6 +74,8 @@ EXTRA_DIST = check_degrees_conversions.sh \
check_md5_hash.sh \
check_metatile.sh \
metatile_example/13/0/0/250/220/0.meta \
check_geojson_osrm.sh \
OSRM_sample_response.txt \
check_geotag.sh \
Stonehenge.jpg \
ViewFromCribyn-Wales-GPS.jpg
Expand Down Expand Up @@ -122,6 +127,11 @@ test_coord_conversion_LDADD = \
$(top_builddir)/src/libviking.a \
$(LDADD)

geojson_osrm_to_gpx_SOURCES = geojson_osrm_to_gpx.c
geojson_osrm_to_gpx_LDADD = \
$(top_builddir)/src/libviking.a \
$(LDADD)

test_parse_latlon_SOURCES = test_parse_latlon.c
test_parse_latlon_LDADD = \
$(top_builddir)/src/libviking.a \
Expand Down
Loading

0 comments on commit 0bf136e

Please sign in to comment.