Reverse-geocode when clicking on map or searching for coords

pull/54/merge
Candid Dauth 2016-10-18 16:26:04 +03:00
rodzic 065c8340c4
commit f31ef6ea22
3 zmienionych plików z 88 dodań i 45 usunięć

Wyświetl plik

@ -132,7 +132,7 @@
map.map.on("click", function(e) {
map.mapEvents.$emit("click", e.latlng);
});
}.fpWrapApply($rootScope));
map.map.on("layeradd", function() {
map.mapEvents.$emit("layerchange");

Wyświetl plik

@ -42,12 +42,12 @@
result.marker ? result.marker.openPopup() : result.layer.openPopup();
} else {
clearRenders();
renderResult(result, true);
renderResult(result, true, layerGroup);
if(result.boundingbox)
_flyToBounds(L.latLngBounds([ [ result.boundingbox[0], result.boundingbox[3 ] ], [ result.boundingbox[1], result.boundingbox[2] ] ]));
else if(result.lat && result.lon && result.zoom)
if(result.lat && result.lon && result.zoom)
map.map.flyTo([ result.lat, result.lon ], result.zoom);
else if(result.boundingbox)
_flyToBounds(L.latLngBounds([ [ result.boundingbox[0], result.boundingbox[3 ] ], [ result.boundingbox[1], result.boundingbox[2] ] ]));
else if(result.layer)
_flyToBounds(result.layer.getBounds());
}
@ -57,7 +57,7 @@
clearRenders();
for(var i=0; i<scope.searchResults.length; i++)
renderResult(scope.searchResults[i], false);
renderResult(scope.searchResults[i], false, layerGroup);
_flyToBounds(layerGroup.getBounds());
};
@ -82,6 +82,28 @@
$compile(el)(scope);
scope.$evalAsync(); // $compile only replaces variables on next digest
var clickMarker = L.featureGroup([]).addTo(map.map);
clickMarker.on("popupclose", function() {
clickMarker.clearLayers();
});
map.mapEvents.$on("click", function(e, latlng) {
clickMarker.clearLayers();
map.loadStart();
map.socket.emit("find", { query: "geo:" + latlng.lat + "," + latlng.lng + "?z=" + map.map.getZoom(), loadUrls: false }, function(err, results) {
map.loadEnd();
if(err)
return map.messages.showMessage("danger", err);
clickMarker.clearLayers();
if(results.length > 0)
renderResult(results[0], true, clickMarker);
});
});
var layerGroup = L.featureGroup([]).addTo(map.map);
function _flyToBounds(bounds) {
@ -119,8 +141,6 @@
return geojson = content;
}
console.log(geojson);
if(geojson == null)
return errors = true;
@ -189,7 +209,7 @@
return ret;
}
function renderResult(result, showPopup) {
function renderResult(result, showPopup, layerGroup) {
if(!result.lat || !result.lon || (result.geojson && result.geojson.type != "Point")) { // If the geojson is just a point, we already render our own marker
result.layer = L.geoJson(result.geojson, {
pointToLayer: function(geoJsonPoint, latlng) {
@ -233,8 +253,12 @@
layerGroup.addLayer(result.marker);
}
if(showPopup)
result.marker ? result.marker.openPopup() : result.layer.openPopup();
if(showPopup) {
if(result.marker)
result.marker.openPopup();
else if(result.layer)
result.layer.openPopup();
}
}
function clearRenders() {

Wyświetl plik

@ -13,7 +13,7 @@ request = request.defaults({
});
var shortLinkCharArray = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_@";
var nameFinderUrl = "https://nominatim.openstreetmap.org/search";
var nameFinderUrl = "https://nominatim.openstreetmap.org";
var limit = 25;
var stateAbbr = {
"us" : {
@ -57,7 +57,7 @@ function find(query, loadUrls) {
return Promise.resolve().then(function() {
query = query.replace(/^\s+/, "").replace(/\s+$/, "");
var lonlat = isLonLatQuery(query);
var lonlat = decodeLonLatUrl(query);
if(lonlat) {
return [ {
lat: lonlat.lat,
@ -83,36 +83,65 @@ function find(query, loadUrls) {
return loadUrl(query);
}
var lonlat_match = query.match(/^(geo\s*:\s*)?(-?\s*\d+([.,]\d+)?)\s*[,;]\s*(-?\s*\d+([.,]\d+)?)(\s*\?z\s*=\s*(\d+))?$/)
if(lonlat_match)
{ // Coordinates
lonlat = {
lat: 1*lonlat_match[2].replace(",", ".").replace(/\s+/, ""),
lon : 1*lonlat_match[4].replace(",", ".").replace(/\s+/, ""),
zoom : lonlat_match[7] != null ? 1*lonlat_match[7] : null
};
return request({
url: nameFinderUrl + "/reverse?format=json&addressdetails=1&polygon_geojson=1&extratags=1&namedetails=1"
+ "&lat=" + lonlat.lat
+ "&lon=" + lonlat.lon
+ "&zoom=" + (lonlat.zoom != null ? lonlat.zoom : 17),
json: true
}).then(function(body) {
if(!body)
throw "Invalid response from name finder.";
body.lat = lonlat.lat;
body.lon = lonlat.lon;
if(lonlat.zoom != null)
body.zoom = lonlat.zoom;
return [ prepareSearchResult(body) ];
});
}
return request({
url: nameFinderUrl + "?format=jsonv2&polygon_geojson=1&addressdetails=1&namedetails=1&limit=" + encodeURIComponent(limit) + "&extratags=1&q=" + encodeURIComponent(query),
url: nameFinderUrl + "/search?format=jsonv2&polygon_geojson=1&addressdetails=1&namedetails=1&limit=" + encodeURIComponent(limit) + "&extratags=1&q=" + encodeURIComponent(query),
json: true
}).then(function(body) {
if(!body)
throw "Invalid response from name finder.";
var results = [ ];
body.forEach(function(result) {
var displayName = makeDisplayName(result);
results.push({
short_name: displayName.split(',')[0],
display_name: displayName,
boundingbox: result.boundingbox,
lat: result.lat,
lon: result.lon,
extratags: result.extratags,
geojson: result.geojson,
icon: result.icon || "https://nominatim.openstreetmap.org/images/mapicons/poi_place_city.p.20.png",
type: result.type == "yes" ? result.category : result.type,
osm_id: result.osm_id,
osm_type: result.osm_type
});
});
return results;
return body.map(prepareSearchResult);
});
});
}
function prepareSearchResult(result) {
var displayName = makeDisplayName(result);
return {
short_name: result.namedetails.name || displayName.split(',')[0],
display_name: displayName,
boundingbox: result.boundingbox,
lat: result.lat,
lon: result.lon,
zoom: result.zoom,
extratags: result.extratags,
geojson: result.geojson,
icon: result.icon || "https://nominatim.openstreetmap.org/images/mapicons/poi_place_city.p.20.png",
type: result.type == "yes" ? result.category : result.type,
osm_id: result.osm_id,
osm_type: result.osm_type
};
}
/**
* Tries to format a search result in a readable way according to the address notation habits in
* the appropriate country.
@ -351,12 +380,11 @@ function makeDisplayName(result) {
}
/**
* Checks whether the given query string is a representation of coordinates, such as
* 48.123,5.123 or an OSM permalink.
* Checks whether the given query string is a representation of coordinates, such an OSM permalink.
* @param query {String}
* @return {Object} An object with the properties lonlat and zoom or null
*/
function isLonLatQuery(query) {
function decodeLonLatUrl(query) {
var query = query.replace(/^\s+/, "").replace(/\s+$/, "");
var query_match,query_match2;
if(query_match = query.match(/^http:\/\/(www\.)?osm\.org\/go\/([-A-Za-z0-9_@]+)/))
@ -364,15 +392,6 @@ function isLonLatQuery(query) {
return decodeShortLink(query_match[2]);
}
if(query_match = query.match(/^(geo\s*:\s*)?(-?\s*\d+([.,]\d+)?)\s*[,;]\s*(-?\s*\d+([.,]\d+)?)(\s*\?z\s*=\s*(\d+))?$/))
{ // Coordinates
return {
lat: 1*query_match[2].replace(",", ".").replace(/\s+/, ""),
lon : 1*query_match[4].replace(",", ".").replace(/\s+/, ""),
zoom : query_match[7] != null ? 1*query_match[7] : 15
};
}
function decodeQueryString(str) {
var lonMatch,latMatch,leafletMatch;