Skip to content

Commit

Permalink
Add support for Duration & Distance in Table API.
Browse files Browse the repository at this point in the history
Add the ability to specify whether the table should be annotated with
distance and/or duration, as well as a new API for returning the
distance. This is done in a way that allows us to return errors for
unrouteable routes (where `null` is returned in the JSON), as in #7.

I'm not 100% sure of the use of `stdbool` in a FFI interface - it's been
a while since I had to write C!
  • Loading branch information
mjkillough authored and daniel-j-h committed Mar 17, 2019
1 parent 802ec5a commit 38e6af2
Show file tree
Hide file tree
Showing 2 changed files with 84 additions and 1 deletion.
71 changes: 70 additions & 1 deletion libosrmc/osrmc.cc
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,31 @@ float osrmc_route_response_duration(osrmc_route_response_t response, osrmc_error
return INFINITY;
}

osrmc_table_annotations_t osrmc_table_annotations_construct(osrmc_error_t* error) try {
auto* out = new osrm::TableParameters::AnnotationsType{osrm::TableParameters::AnnotationsType::Duration};
return reinterpret_cast<osrmc_table_annotations_t>(out);
} catch (const std::exception& e) {
osrmc_error_from_exception(e, error);
return nullptr;
}

void osrmc_table_annotations_destruct(osrmc_table_annotations_t annotations) {
delete reinterpret_cast<osrm::TableParameters::AnnotationsType*>(annotations);
}

void osrmc_table_annotations_enable_distance(osrmc_table_annotations_t annotations, bool enable, osrmc_error_t* error) try {
using AnnotationsType = osrm::TableParameters::AnnotationsType;
auto* annotations_typed = reinterpret_cast<AnnotationsType*>(annotations);

if (enable) {
*annotations_typed |= AnnotationsType::Distance;
} else {
*annotations_typed = static_cast<AnnotationsType>(static_cast<int>(*annotations_typed) ^ static_cast<int>(AnnotationsType::Distance));
}
} catch (const std::exception& e) {
osrmc_error_from_exception(e, error);
}

osrmc_table_params_t osrmc_table_params_construct(osrmc_error_t* error) try {
auto* out = new osrm::TableParameters;
return reinterpret_cast<osrmc_table_params_t>(out);
Expand All @@ -237,6 +262,14 @@ void osrmc_table_params_add_destination(osrmc_table_params_t params, size_t inde
osrmc_error_from_exception(e, error);
}

void osrmc_table_params_set_annotations(osrmc_table_params_t params, osrmc_table_annotations_t annotations, osrmc_error_t* error) try {
auto* params_typed = reinterpret_cast<osrm::TableParameters*>(params);
auto* annotations_typed = reinterpret_cast<osrm::TableParameters::AnnotationsType*>(annotations);
params_typed->annotations = *annotations_typed;
} catch (const std::exception& e) {
osrmc_error_from_exception(e, error);
}

osrmc_table_response_t osrmc_table(osrmc_osrm_t osrm, osrmc_table_params_t params, osrmc_error_t* error) try {
auto* osrm_typed = reinterpret_cast<osrm::OSRM*>(osrm);
auto* params_typed = reinterpret_cast<osrm::TableParameters*>(params);
Expand All @@ -262,16 +295,52 @@ float osrmc_table_response_duration(osrmc_table_response_t response, unsigned lo
osrmc_error_t* error) try {
auto* response_typed = reinterpret_cast<osrm::json::Object*>(response);

if (response_typed->values.find("durations") == response_typed->values.end()) {
*error = new osrmc_error{"NoTable", "Table request not configured to return durations"};
return INFINITY;
}

auto& durations = response_typed->values["durations"].get<osrm::json::Array>();
auto& durations_from_to_all = durations.values.at(from).get<osrm::json::Array>();
auto duration = durations_from_to_all.values.at(to).get<osrm::json::Number>().value;
auto nullable = durations_from_to_all.values.at(to);

if (nullable.is<osrm::json::Null>()) {
*error = new osrmc_error{"NoRoute", "Impossible route between points"};
return INFINITY;
}
auto duration = nullable.get<osrm::json::Number>().value;

return duration;
} catch (const std::exception& e) {
osrmc_error_from_exception(e, error);
return INFINITY;
}

float osrmc_table_response_distance(osrmc_table_response_t response, unsigned long from, unsigned long to,
osrmc_error_t* error) try {
auto* response_typed = reinterpret_cast<osrm::json::Object*>(response);

if (response_typed->values.find("distances") == response_typed->values.end()) {
*error = new osrmc_error{"NoTable", "Table request not configured to return distances"};
return INFINITY;
}

auto& distances = response_typed->values["distances"].get<osrm::json::Array>();
auto& distances_from_to_all = distances.values.at(from).get<osrm::json::Array>();
auto nullable = distances_from_to_all.values.at(to);

if (nullable.is<osrm::json::Null>()) {
*error = new osrmc_error{"NoRoute", "Impossible route between points"};
return INFINITY;
}
auto distance = nullable.get<osrm::json::Number>().value;

return distance;
} catch (const std::exception& e) {
*error = new osrmc_error{e.what()};
return INFINITY;
}

osrmc_nearest_params_t osrmc_nearest_params_construct(osrmc_error_t* error) try {
auto* out = new osrm::NearestParameters;
return reinterpret_cast<osrmc_nearest_params_t>(out);
Expand Down
14 changes: 14 additions & 0 deletions libosrmc/osrmc.h
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
#include <stdbool.h>

#ifndef OSRMC_H_
#define OSRMC_H_

Expand Down Expand Up @@ -144,6 +146,7 @@ typedef struct osrmc_params* osrmc_params_t;

typedef struct osrmc_route_params* osrmc_route_params_t;
typedef struct osrmc_table_params* osrmc_table_params_t;
typedef struct osrmc_table_annotations* osrmc_table_annotations_t;
typedef struct osrmc_nearest_params* osrmc_nearest_params_t;
typedef struct osrmc_match_params* osrmc_match_params_t;

Expand Down Expand Up @@ -194,15 +197,26 @@ OSRMC_API float osrmc_route_response_duration(osrmc_route_response_t response, o

/* Table service */

OSRMC_API osrmc_table_annotations_t osrmc_table_annotations_construct(osrmc_error_t* error);
OSRMC_API void osrmc_table_annotations_destruct(osrmc_table_annotations_t annotations);
OSRMC_API void osrmc_table_annotations_enable_distance(osrmc_table_annotations_t annotations, bool enable, osrmc_error_t* error);

OSRMC_API osrmc_table_params_t osrmc_table_params_construct(osrmc_error_t* error);
OSRMC_API void osrmc_table_params_destruct(osrmc_table_params_t params);
OSRMC_API void osrmc_table_params_set_annotations(osrmc_table_params_t params, osrmc_table_annotations_t annotations, osrmc_error_t* error);
OSRMC_API void osrmc_table_params_add_source(osrmc_table_params_t params, size_t index, osrmc_error_t* error);
OSRMC_API void osrmc_table_params_add_destination(osrmc_table_params_t params, size_t index, osrmc_error_t* error);

OSRMC_API osrmc_table_response_t osrmc_table(osrmc_osrm_t osrm, osrmc_table_params_t params, osrmc_error_t* error);
OSRMC_API void osrmc_table_response_destruct(osrmc_table_response_t response);

// INFINITY will be returned if there is no route between the from/to.
// An error will also be returned with a code of 'NoRoute'.
OSRMC_API float osrmc_table_response_duration(osrmc_table_response_t response, unsigned long from, unsigned long to,
osrmc_error_t* error);
OSRMC_API float osrmc_table_response_distance(osrmc_table_response_t response, unsigned long from, unsigned long to,
osrmc_error_t* error);

/* Nearest service */

OSRMC_API osrmc_nearest_params_t osrmc_nearest_params_construct(osrmc_error_t* error);
Expand Down

0 comments on commit 38e6af2

Please sign in to comment.