Add generic reverse geocoder function to nominatim service

This commit is contained in:
Bryan Housel
2017-06-29 01:23:33 -04:00
parent 9a0deaa484
commit 1c303edf18
2 changed files with 43 additions and 28 deletions
+23 -11
View File
@@ -25,32 +25,44 @@ export default {
countryCode: function (location, callback) {
var countryCodes = nominatimCache.search(
this.reverse(location, function(err, result) {
if (err) {
return callback(err);
} else if (result.address) {
return callback(null, result.address.country_code);
} else {
return callback('Unable to geocode', null);
}
});
},
reverse: function (location, callback) {
var cached = nominatimCache.search(
{ minX: location[0], minY: location[1], maxX: location[0], maxY: location[1] }
);
if (countryCodes.length > 0) {
return callback(null, countryCodes[0].data);
if (cached.length > 0) {
return callback(null, cached[0].data);
}
var params = { format: 'json', addressdetails: 1, lat: location[1], lon: location[0] };
var params = { zoom: 13, format: 'json', addressdetails: 1, lat: location[1], lon: location[0] };
var url = apibase + 'reverse?' + utilQsString(params);
if (inflight[url]) return;
inflight[url] = d3.json(url, function(err, result) {
delete inflight[url];
if (err)
if (err) {
return callback(err);
else if (result && result.error)
} else if (result && result.error) {
return callback(result.error);
}
var extent = geoExtent(location).padByMeters(1000);
nominatimCache.insert(_.assign(extent.bbox(),
{ data: result.address.country_code }
));
var extent = geoExtent(location).padByMeters(200);
nominatimCache.insert(_.assign(extent.bbox(), {data: result}));
callback(null, result.address.country_code);
callback(null, result);
});
},
+20 -17
View File
@@ -17,7 +17,6 @@ describe('iD.serviceNominatim', function() {
describe('#countryCode', function() {
it('calls the given callback with the results of the country code query', function() {
var callback = sinon.spy();
nominatim.countryCode([16, 48], callback);
@@ -28,13 +27,15 @@ describe('iD.serviceNominatim', function() {
server.respond();
expect(query(server.requests[0].url)).to.eql(
{format: 'json', addressdetails: '1', lat: '48', lon: '16'});
{zoom: '13', format: 'json', addressdetails: '1', lat: '48', lon: '16'});
expect(callback).to.have.been.calledWithExactly(null, 'at');
});
});
it('should not cache the first country code result', function() {
describe('#reverse', function() {
it('should not cache distant result', function() {
var callback = sinon.spy();
nominatim.countryCode([16, 48], callback);
nominatim.reverse([16, 48], callback);
server.respondWith('GET', new RegExp('https://nominatim.openstreetmap.org/reverse'),
[200, { 'Content-Type': 'application/json' },
@@ -42,13 +43,14 @@ describe('iD.serviceNominatim', function() {
server.respond();
expect(query(server.requests[0].url)).to.eql(
{format: 'json', addressdetails: '1', lat: '48', lon: '16'});
expect(callback).to.have.been.calledWithExactly(null, 'at');
{zoom: '13', format: 'json', addressdetails: '1', lat: '48', lon: '16'});
expect(callback).to.have.been.calledWithExactly(null, {address: {country_code:'at'}});
server.restore();
server = sinon.fakeServer.create();
nominatim.countryCode([17, 49], callback);
callback = sinon.spy();
nominatim.reverse([17, 49], callback);
server.respondWith('GET', new RegExp('https://nominatim.openstreetmap.org/reverse'),
[200, { 'Content-Type': 'application/json' },
@@ -56,13 +58,13 @@ describe('iD.serviceNominatim', function() {
server.respond();
expect(query(server.requests[0].url)).to.eql(
{format: 'json', addressdetails: '1', lat: '49', lon: '17'});
expect(callback).to.have.been.calledWithExactly(null, 'cz');
{zoom: '13', format: 'json', addressdetails: '1', lat: '49', lon: '17'});
expect(callback).to.have.been.calledWithExactly(null, {address: {country_code:'cz'}});
});
it('should cache the first country code result', function() {
it('should cache nearby result', function() {
var callback = sinon.spy();
nominatim.countryCode([16, 48], callback);
nominatim.reverse([16, 48], callback);
server.respondWith('GET', new RegExp('https://nominatim.openstreetmap.org/reverse'),
[200, { 'Content-Type': 'application/json' },
@@ -70,24 +72,25 @@ describe('iD.serviceNominatim', function() {
server.respond();
expect(query(server.requests[0].url)).to.eql(
{format: 'json', addressdetails: '1', lat: '48', lon: '16'});
expect(callback).to.have.been.calledWithExactly(null, 'at');
{zoom: '13', format: 'json', addressdetails: '1', lat: '48', lon: '16'});
expect(callback).to.have.been.calledWithExactly(null, {address: {country_code:'at'}});
server.restore();
server = sinon.fakeServer.create();
nominatim.countryCode([16.01, 48.01], callback);
callback = sinon.spy();
nominatim.reverse([16.000001, 48.000001], callback);
server.respondWith('GET', new RegExp('https://nominatim.openstreetmap.org/reverse'),
[200, { 'Content-Type': 'application/json' },
'{"address":{"country_code":"cz"}}']);
server.respond();
expect(callback).to.have.been.calledWithExactly(null, 'at');
expect(callback).to.have.been.calledWithExactly(null, {address: {country_code:'at'}});
});
it('calls the given callback with an error', function() {
var callback = sinon.spy();
nominatim.countryCode([1000, 1000], callback);
nominatim.reverse([1000, 1000], callback);
server.respondWith('GET', new RegExp('https://nominatim.openstreetmap.org/reverse'),
[200, { 'Content-Type': 'application/json' },
@@ -95,7 +98,7 @@ describe('iD.serviceNominatim', function() {
server.respond();
expect(query(server.requests[0].url)).to.eql(
{format: 'json', addressdetails: '1', lat: '1000', lon: '1000'});
{zoom: '13', format: 'json', addressdetails: '1', lat: '1000', lon: '1000'});
expect(callback).to.have.been.calledWithExactly('Unable to geocode');
});
});