Skip to content
This repository was archived by the owner on Jun 8, 2024. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
117 changes: 117 additions & 0 deletions src/node_osrm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ class Engine final : public node::ObjectWrap {
static NAN_METHOD(nearest);
static NAN_METHOD(table);
static NAN_METHOD(match);
static NAN_METHOD(trip);

static void Run(_NAN_METHOD_ARGS, route_parameters_ptr);
static void AsyncRun(uv_work_t*);
Expand All @@ -63,6 +64,7 @@ void Engine::Initialize(Handle<Object> target) {
NODE_SET_PROTOTYPE_METHOD(lcons, "nearest", nearest);
NODE_SET_PROTOTYPE_METHOD(lcons, "table", table);
NODE_SET_PROTOTYPE_METHOD(lcons, "match", match);
NODE_SET_PROTOTYPE_METHOD(lcons, "trip", trip);
lcons->Set(NanNew("libosrm_version"), NanNew(LIBOSRM_GIT_REVISION));
target->Set(NanNew("OSRM"), lcons->GetFunction());
NanAssignPersistent(constructor, lcons);
Expand Down Expand Up @@ -377,6 +379,121 @@ NAN_METHOD(Engine::match)
NanReturnUndefined();
}

// uses the same options as viaroute
NAN_METHOD(Engine::trip)
{
NanScope();

if (args.Length() < 2) {
NanThrowTypeError("two arguments required");
NanReturnUndefined();
}

if (!args[0]->IsObject()) {
NanThrowTypeError("first arg must be an object");
NanReturnUndefined();
}

Local<Object> obj = args[0]->ToObject();

route_parameters_ptr params = make_unique<RouteParameters>();

params->zoom_level = 18; //no generalization
params->print_instructions = false; //turn by turn instructions
params->alternate_route = false; //get an alternate route, too
params->geometry = true; //retrieve geometry of route
params->compression = true; //polyline encoding
params->check_sum = 0; //see wiki
params->service = "trip"; //that's routing
params->output_format = "json";
params->jsonp_parameter = ""; //set for jsonp wrapping
params->language = ""; //unused atm

if (!obj->Has(NanNew("coordinates"))) {
NanThrowError("must provide a coordinates property");
NanReturnUndefined();
}

Local<Value> coordinates = obj->Get(NanNew("coordinates"));
if (!coordinates->IsArray()) {
NanThrowError("coordinates must be an array of (lat/long) pairs");
NanReturnUndefined();
}

Local<Array> coordinates_array = Local<Array>::Cast(coordinates);
if (coordinates_array->Length() < 2) {
NanThrowError("at least two coordinates must be provided");
NanReturnUndefined();
}

for (uint32_t i = 0; i < coordinates_array->Length(); ++i) {
Local<Value> coordinate = coordinates_array->Get(i);

if (!coordinate->IsArray()) {
NanThrowError("coordinates must be an array of (lat/long) pairs");
NanReturnUndefined();
}

Local<Array> coordinate_pair = Local<Array>::Cast(coordinate);
if (coordinate_pair->Length() != 2) {
NanThrowError("coordinates must be an array of (lat/long) pairs");
NanReturnUndefined();
}

params->coordinates.emplace_back(static_cast<int>(coordinate_pair->Get(0)->NumberValue()*COORDINATE_PRECISION),
static_cast<int>(coordinate_pair->Get(1)->NumberValue()*COORDINATE_PRECISION));
}

if (obj->Has(NanNew("alternateRoute"))) {
params->alternate_route = obj->Get(NanNew("alternateRoute"))->BooleanValue();
}

if (obj->Has(NanNew("checksum"))) {
params->check_sum = static_cast<unsigned>(obj->Get(NanNew("checksum"))->Uint32Value());
}

if (obj->Has(NanNew("zoomLevel"))) {
params->zoom_level = static_cast<short>(obj->Get(NanNew("zoomLevel"))->Int32Value());
}

if (obj->Has(NanNew("printInstructions"))) {
params->print_instructions = obj->Get(NanNew("printInstructions"))->BooleanValue();
}

if (obj->Has(NanNew("geometry"))) {
params->geometry = obj->Get(NanNew("geometry"))->BooleanValue();
}

if (obj->Has(NanNew("jsonpParameter"))) {
params->jsonp_parameter = *v8::String::Utf8Value(obj->Get(NanNew("jsonpParameter")));
}

if (obj->Has(NanNew("hints"))) {
Local<Value> hints = obj->Get(NanNew("hints"));

if (!hints->IsArray()) {
NanThrowError("hints must be an array of strings/null");
NanReturnUndefined();
}

Local<Array> hints_array = Local<Array>::Cast(hints);
for (uint32_t i = 0; i < hints_array->Length(); ++i) {
Local<Value> hint = hints_array->Get(i);
if (hint->IsString()) {
params->hints.push_back(*v8::String::Utf8Value(hint));
} else if(hint->IsNull()){
params->hints.push_back("");
}else{
NanThrowError("hint must be null or string");
NanReturnUndefined();
}
}
}

Run(args, std::move(params));
NanReturnUndefined();
}

NAN_METHOD(Engine::table)
{
NanScope();
Expand Down
163 changes: 163 additions & 0 deletions test/osrm.test.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
var OSRM = require('../');
var assert = require('assert');

///////////////////////////// CONSTRUCTOR TESTS ////////////////////////////////

it('constructor: throws if new keyword is not used', function(done) {
assert.throws(function() { OSRM(); },
/Cannot call constructor as function, you need to use 'new' keyword/);
Expand Down Expand Up @@ -49,6 +51,8 @@ it('constructor: throws if given a non-string/obj argument', function() {
/first argument must be a path string or params object/);
});

/////////////////////////////// ROUTE TESTS ////////////////////////////////////

it('route: routes Berlin', function(done) {
var osrm = new OSRM("berlin-latest.osrm");
osrm.route({coordinates: [[52.519930,13.438640], [52.513191,13.415852]]}, function(err, route) {
Expand Down Expand Up @@ -171,6 +175,159 @@ it('route: routes Berlin with null hints', function(done) {
});
});


/////////////////////////////// TRIP TESTS ////////////////////////////////////

it('trip: trip in Berlin', function(done) {
var osrm = new OSRM("berlin-latest.osrm");
osrm.trip({coordinates: [[52.519930,13.438640], [52.513191,13.415852]]}, function(err, trip) {
assert.ifError(err);
for (t = 0; t < trip.trips.length; t++) {
assert.equal(trip.trips[t].status_message, 'Found route between points');
}
done();
});
});

it('trip: trip with many locations in Berlin', function(done) {
var osrm = new OSRM("berlin-latest.osrm");
osrm.trip({coordinates: [[52.51663871100423,13.36761474609375],[52.506191342034576,13.374481201171875],[52.50535544522142,13.404693603515625],[52.50159371284434,13.388900756835938],[52.518727886767266,13.386840820312498],[52.528754547664185,13.4088134765625],[52.51705655410405,13.41156005859375],[52.512042174642346,13.420486450195312],[52.50368360390624,13.413619995117188],[52.504101570196205,13.36212158203125],[52.52248815280757,13.35113525390625],[52.53460237630516,13.36761474609375],[52.53710835019913,13.383407592773438],[52.536690697815736,13.392333984375],[52.532931647583325,13.42529296875],[52.52415927884915,13.399200439453125],[52.51956352925745,13.390960693359375],[52.533349335723294,13.375167846679688],[52.520399155853454,13.37860107421875],[52.52081696319122,13.355255126953125],[52.5143405029259,13.385467529296875],[52.513086884218325,13.398857116699219],[52.50744515744915,13.399200439453125],[52.49783165855699,13.409500122070312],[52.500339730516934,13.424949645996094],[52.50786308797268,13.440055847167969],[52.511624283857785,13.428382873535156],[52.50451953251202,13.437652587890625],[52.5199813445422,13.443145751953125],[52.52520370034151,13.431129455566406],[52.52896341209634,13.418426513671875],[52.517474393230245,13.429069519042969],[52.528127948407935,13.418083190917969],[52.52833681581998,13.405036926269531],[52.53084314728766,13.384437561035156],[52.53084314728766,13.374481201171875],[52.532305107923925,13.3978271484375],[52.526039219655445,13.418769836425781],[52.51642978796417,13.441085815429688],[52.51601193890388,13.448638916015625],[52.50535544522142,13.44623565673828],[52.502638670794546,13.430442810058594],[52.520190250694526,13.358688354492188],[52.531887409851336,13.358001708984375],[52.528545682238736,13.367271423339842],[52.52958999943304,13.387870788574219],[52.53961418106945,13.406410217285156],[52.50556442091497,13.399543762207031],[52.50389258754797,13.374824523925781],[52.51099744023003,13.386154174804688],[52.49657756892365,13.40229034423828]]}, function(err, trip) {
assert.ifError(err);
for (t = 0; t < trip.trips.length; t++) {
assert.equal(trip.trips[t].status_message, 'Found route between points');
}
done();
});
});

it('trip: throws with too few or invalid args', function(done) {
var osrm = new OSRM("berlin-latest.osrm");
assert.throws(function() { osrm.trip({coordinates: [[52.519930,13.438640], [52.513191,13.415852]]}) },
/two arguments required/);
assert.throws(function() { osrm.trip(null, function(err, trip) {}) },
/first arg must be an object/);
done();
});

it('trip: throws with bad params', function(done) {
var osrm = new OSRM("berlin-latest.osrm");
assert.throws(function () { osrm.trip({coordinates: []}, function(err) {}) });
assert.throws(function() { osrm.trip({}, function(err, trip) {}) },
/must provide a coordinates property/);
assert.throws(function() { osrm.trip({coordinates: null}, function(err, trip) {}) },
"coordinates must be an array of (lat/long) pairs");
assert.throws(function() { osrm.trip({coordinates: [52.519930, 13.438640]}, function(err, trip) {}) },
"coordinates must be an array of (lat/long) pairs");
assert.throws(function() { osrm.trip({coordinates: [[52.519930], [13.438640]]}, function(err, trip) {}) },
"coordinates must be an array of (lat/long) pairs");
assert.throws(function() { osrm.trip({coordinates: [[52.519930,13.438640], [52.513191,13.415852]], hints: null}, function(err, trip) {}) },
"hints must be an array of strings/null");
var options = {
coordinates: [[52.519930,13.438640], [52.513191,13.415852]],
alternateroute: false,
printInstructions: false,
hints: [[52.519930,13.438640]]
};
assert.throws(function() { osrm.trip(options, function(err, trip) {}) },
/hint must be null or string/);
done();
});

it('trip: takes jsonp parameter', function(done) {
var osrm = new OSRM("berlin-latest.osrm");
osrm.trip({coordinates: [[52.519930,13.438640], [52.513191,13.415852]], jsonpParameter: 'function'}, function(err, trip) {
assert.ifError(err);
for (t = 0; t < trip.trips.length; t++) {
assert.equal(trip.trips[t].status_message, 'Found route between points');
}
done();
});
});

if (process.platform === 'darwin') {
// shared memory does not work on Mac OS for now.
it.skip('trip: routes Berlin using shared memory', function(done) {});
} else {
it('trip: routes Berlin using shared memory', function(done) {
var osrm = new OSRM();
osrm.trip({coordinates: [[52.519930,13.438640], [52.513191,13.415852]]}, function(err, trip) {
assert.ifError(err);
for (t = 0; t < trip.trips.length; t++) {
assert.equal(trip.trips[t].status_message, 'Found route between points');
}
done();
});
});
}

it('trip: routes Berlin with hints', function(done) {
var osrm = new OSRM("berlin-latest.osrm");
var options = {
coordinates: [[52.519930,13.438640], [52.513191,13.415852]],
alternateroute: false,
printInstructions: false
};
osrm.trip(options, function(err, first) {
assert.ifError(err);
for (t = 0; t < first.trips.length; t++) {
assert.equal(first.trips[t].status_message, 'Found route between points');
var checksum = first.trips[t].hint_data.checksum;
options.checksum = checksum;
assert.equal("number", typeof(checksum));

options.hints = [];
options.hints.length = options.coordinates.length;

for (p = 0; p < first.trips[t].permutation.length; p++) {
options.hints[first.trips[t].permutation[p]] = first.trips[t].hint_data.locations[p];
}
}

osrm.trip(options, function(err, second) {
assert.ifError(err);
assert.deepEqual(first, second);
done();
});
});
});

it('trip: trip through Berlin with options', function(done) {
var osrm = new OSRM("berlin-latest.osrm");
var options = {
coordinates: [[52.519930,13.438640], [52.513191,13.415852]],
zoomLevel: 17,
alternateroute: false,
printInstructions: false,
geometry: false
};
osrm.trip(options, function(err, trip) {
assert.ifError(err);
for (t = 0; t < trip.trips.length; t++) {
assert.equal(trip.trips[t].status_message, 'Found route between points');
assert.equal(undefined, trip.trips[t].route_instructions);
assert.equal(undefined, trip.trips[t].alternative_geometries);
assert.equal(undefined, trip.trips[t].route_geometry);
}
done();
});
});

it('trip: routes Berlin with null hints', function(done) {
var osrm = new OSRM("berlin-latest.osrm");
var options = {
coordinates: [[52.519930,13.438640], [52.513191,13.415852]],
alternateRoute: false,
printInstructions: false,
hints: ['', '', '']
};
osrm.trip(options, function(err, second) {
assert.ifError(err);
done();
});
});

/////////////////////////////// TABLE TESTS ////////////////////////////////////

it('table: distance table in Berlin', function(done) {
var osrm = new OSRM("berlin-latest.osrm");
var options = {
Expand Down Expand Up @@ -226,6 +383,8 @@ it('table: throws on invalid arguments', function(done) {
done();
});

/////////////////////////////// MATCH TESTS ////////////////////////////////////

it('match: match in Berlin', function(done) {
var osrm = new OSRM("berlin-latest.osrm");
var options = {
Expand Down Expand Up @@ -318,6 +477,8 @@ it('match: throws on invalid timestamps param', function(done) {
done();
});

////////////////////////////// NEAREST TESTS ///////////////////////////////////

it('nearest', function(done) {
var osrm = new OSRM("berlin-latest.osrm");
osrm.nearest([52.4224, 13.333086], function(err, result) {
Expand All @@ -342,6 +503,8 @@ it('nearest: throws on invalid args', function(done) {
done();
});

////////////////////////////// LOCATE TESTS ////////////////////////////////////

it('locate', function(done) {
var osrm = new OSRM("berlin-latest.osrm");
osrm.locate([52.4224, 13.333086], function(err, result) {
Expand Down