Merge pull request #362 from nrenner/ringgo-patch
Use boundaries to determine country rules on click
This commit is contained in:
commit
d33413d00e
10 changed files with 220 additions and 104 deletions
|
|
@ -79,7 +79,7 @@ var paths = {
|
||||||
'layers/config/geometry.js',
|
'layers/config/geometry.js',
|
||||||
],
|
],
|
||||||
layersConfigDestName: 'layersConf.js',
|
layersConfigDestName: 'layersConf.js',
|
||||||
boundaries: 'resources/boundaries/*.geojson',
|
boundaries: ['resources/boundaries/*.geojson', 'resources/boundaries/*.topo.json'],
|
||||||
zip: ['dist/**', 'index.html', 'config.template.js', 'keys.template.js'],
|
zip: ['dist/**', 'index.html', 'config.template.js', 'keys.template.js'],
|
||||||
dest: 'dist',
|
dest: 'dist',
|
||||||
destName: 'brouter-web',
|
destName: 'brouter-web',
|
||||||
|
|
|
||||||
36
js/Util.js
36
js/Util.js
|
|
@ -30,6 +30,38 @@ BR.Util = {
|
||||||
return new Error(msg);
|
return new Error(msg);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
getJson: function (url, context, cb) {
|
||||||
|
BR.Util.get(url, function (err, data) {
|
||||||
|
if (err) {
|
||||||
|
BR.message.showError('Error getting ' + context + ': ' + err);
|
||||||
|
return cb(err);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
var json = JSON.parse(data);
|
||||||
|
cb(null, json);
|
||||||
|
} catch (err) {
|
||||||
|
BR.message.showError('Error parsing ' + context + ': ' + err);
|
||||||
|
console.error(err);
|
||||||
|
cb(err);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
getGeoJson: function (url, context, cb) {
|
||||||
|
BR.Util.getJson(url, context, function (err, data) {
|
||||||
|
if (err) return cb(err);
|
||||||
|
|
||||||
|
var geoJson = data;
|
||||||
|
if (data && data.type && data.type === 'Topology') {
|
||||||
|
var key = Object.keys(data.objects)[0];
|
||||||
|
geoJson = topojson.feature(data, data.objects[key]);
|
||||||
|
}
|
||||||
|
|
||||||
|
cb(null, geoJson);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
// check if localStorage is available, especially for catching SecurityError
|
// check if localStorage is available, especially for catching SecurityError
|
||||||
// when cookie settings are blocking access (Chrome, Pale Moon, older Firefox)
|
// when cookie settings are blocking access (Chrome, Pale Moon, older Firefox)
|
||||||
//
|
//
|
||||||
|
|
@ -118,6 +150,10 @@ BR.Util = {
|
||||||
}
|
}
|
||||||
|
|
||||||
// fallback when country not available
|
// fallback when country not available
|
||||||
|
if (language) {
|
||||||
return lang[0] === language;
|
return lang[0] === language;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,16 @@
|
||||||
BR.CircleGoArea = L.Control.extend({
|
BR.CircleGoArea = L.Control.extend({
|
||||||
circleLayer: null,
|
circleLayer: null,
|
||||||
boundaryLayer: null,
|
boundaryLayer: null,
|
||||||
outsideAreaRenderer: L.svg({ padding: 1 }),
|
maskRenderer: L.svg({ padding: 2 }),
|
||||||
|
countries: null,
|
||||||
|
countriesMask: null,
|
||||||
states: null,
|
states: null,
|
||||||
|
statesLoading: false,
|
||||||
|
|
||||||
options: {
|
options: {
|
||||||
radius: 1000, // in meters
|
radius: 1000, // in meters
|
||||||
stateRules: false,
|
countriesUrl: BR.conf.countriesUrl || 'dist/boundaries/countries.topo.json',
|
||||||
statesUrl: BR.conf.statesUrl || 'dist/boundaries/germany-states.geojson',
|
statesUrl: BR.conf.statesUrl || 'dist/boundaries/germany-states.topo.json',
|
||||||
overpassBaseUrl: BR.conf.overpassBaseUrl || 'https://overpass-api.de/api/interpreter?data=',
|
overpassBaseUrl: BR.conf.overpassBaseUrl || 'https://overpass-api.de/api/interpreter?data=',
|
||||||
shortcut: {
|
shortcut: {
|
||||||
draw: {
|
draw: {
|
||||||
|
|
@ -58,16 +61,22 @@ BR.CircleGoArea = L.Control.extend({
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
|
|
||||||
if (this.options.stateRules) {
|
|
||||||
this.drawButton.disable();
|
this.drawButton.disable();
|
||||||
this._loadStates(
|
this.once(
|
||||||
L.bind(function () {
|
'countries:loaded',
|
||||||
|
function () {
|
||||||
this.drawButton.enable();
|
this.drawButton.enable();
|
||||||
if (this.marker && !this.marker.dragging.enabled()) {
|
if (this.marker && !this.marker.dragging.enabled()) {
|
||||||
this.marker.dragging.enable();
|
this.marker.dragging.enable();
|
||||||
}
|
}
|
||||||
}, this)
|
},
|
||||||
|
this
|
||||||
);
|
);
|
||||||
|
this._loadCountries();
|
||||||
|
|
||||||
|
// preload states in parallel, before clicked country is known, using browser language as indicator
|
||||||
|
if (BR.Util.isCountry('DE')) {
|
||||||
|
this._loadStates();
|
||||||
}
|
}
|
||||||
|
|
||||||
map.on('routing:draw-start', function () {
|
map.on('routing:draw-start', function () {
|
||||||
|
|
@ -86,10 +95,12 @@ BR.CircleGoArea = L.Control.extend({
|
||||||
this.routing.draw(false);
|
this.routing.draw(false);
|
||||||
this.pois.draw(false);
|
this.pois.draw(false);
|
||||||
this.map.on('click', this.onMapClick, this);
|
this.map.on('click', this.onMapClick, this);
|
||||||
|
this.map.addLayer(this.countriesMask);
|
||||||
this._unlockOutsideArea();
|
this._unlockOutsideArea();
|
||||||
L.DomUtil.addClass(this.map.getContainer(), 'circlego-draw-enabled');
|
L.DomUtil.addClass(this.map.getContainer(), 'circlego-draw-enabled');
|
||||||
} else {
|
} else {
|
||||||
this.map.off('click', this.onMapClick, this);
|
this.map.off('click', this.onMapClick, this);
|
||||||
|
this.map.removeLayer(this.countriesMask);
|
||||||
this._lockOutsideArea();
|
this._lockOutsideArea();
|
||||||
L.DomUtil.removeClass(this.map.getContainer(), 'circlego-draw-enabled');
|
L.DomUtil.removeClass(this.map.getContainer(), 'circlego-draw-enabled');
|
||||||
}
|
}
|
||||||
|
|
@ -126,17 +137,11 @@ BR.CircleGoArea = L.Control.extend({
|
||||||
var url = this.options.overpassBaseUrl + encodeURIComponent(query);
|
var url = this.options.overpassBaseUrl + encodeURIComponent(query);
|
||||||
|
|
||||||
this.marker.setIcon(this.iconSpinner);
|
this.marker.setIcon(this.iconSpinner);
|
||||||
BR.Util.get(
|
BR.Util.getJson(
|
||||||
url,
|
url,
|
||||||
L.bind(function (err, data) {
|
'boundary for coordinate "' + center + '"',
|
||||||
if (err) {
|
L.bind(function (err, osmJson) {
|
||||||
BR.message.showError('Error getting boundary for coordinate "' + center + '": ' + err);
|
if (!err) {
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
var osmJson = JSON.parse(data);
|
|
||||||
|
|
||||||
if (osmJson.elements.length === 0) {
|
if (osmJson.elements.length === 0) {
|
||||||
if (adminLevel === 8 || adminLevel === 7) {
|
if (adminLevel === 8 || adminLevel === 7) {
|
||||||
// admin_level 6 (kreisfreie Stadt)
|
// admin_level 6 (kreisfreie Stadt)
|
||||||
|
|
@ -150,14 +155,9 @@ BR.CircleGoArea = L.Control.extend({
|
||||||
var geoJson = osmtogeojson(osmJson);
|
var geoJson = osmtogeojson(osmJson);
|
||||||
|
|
||||||
this._setBoundary(geoJson);
|
this._setBoundary(geoJson);
|
||||||
|
}
|
||||||
|
|
||||||
this.marker.setIcon(this.icon);
|
this.marker.setIcon(this.icon);
|
||||||
} catch (err) {
|
|
||||||
BR.message.showError('Error parsing boundary: ' + err);
|
|
||||||
console.error(err);
|
|
||||||
} finally {
|
|
||||||
this.marker.setIcon(this.icon);
|
|
||||||
}
|
|
||||||
}, this)
|
}, this)
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|
@ -196,21 +196,29 @@ BR.CircleGoArea = L.Control.extend({
|
||||||
this.setOutsideArea(ring);
|
this.setOutsideArea(ring);
|
||||||
},
|
},
|
||||||
|
|
||||||
_getState: function (center) {
|
_getPolygonForPoint: function (center, featureCollection) {
|
||||||
var state = null;
|
var polygon = null;
|
||||||
var point = turf.point(center);
|
var point = turf.point(center);
|
||||||
|
|
||||||
var features = this.states.features;
|
var features = featureCollection.features;
|
||||||
for (var i = 0; i < features.length; i++) {
|
for (var i = 0; i < features.length; i++) {
|
||||||
var feature = features[i];
|
var feature = features[i];
|
||||||
var inside = turf.booleanPointInPolygon(point, feature);
|
var inside = turf.booleanPointInPolygon(point, feature);
|
||||||
if (inside) {
|
if (inside) {
|
||||||
state = feature;
|
polygon = feature;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return state;
|
return polygon;
|
||||||
|
},
|
||||||
|
|
||||||
|
_getState: function (center) {
|
||||||
|
return this._getPolygonForPoint(center, this.states);
|
||||||
|
},
|
||||||
|
|
||||||
|
_getCountry: function (center) {
|
||||||
|
return this._getPolygonForPoint(center, this.countries);
|
||||||
},
|
},
|
||||||
|
|
||||||
_applyStateRules: function (center) {
|
_applyStateRules: function (center) {
|
||||||
|
|
@ -244,6 +252,42 @@ BR.CircleGoArea = L.Control.extend({
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
_applyCountryRules: function (center) {
|
||||||
|
var country = this._getCountry(center);
|
||||||
|
|
||||||
|
if (country) {
|
||||||
|
var name = country.properties.name;
|
||||||
|
|
||||||
|
if (name === 'Germany') {
|
||||||
|
this.options.radius = 15000;
|
||||||
|
|
||||||
|
if (!this.states) {
|
||||||
|
this.marker.setIcon(this.iconSpinner);
|
||||||
|
this.once(
|
||||||
|
'states:loaded',
|
||||||
|
function () {
|
||||||
|
this.marker.setIcon(this.icon);
|
||||||
|
if (this.states) {
|
||||||
|
this._applyStateRules(center);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
this
|
||||||
|
);
|
||||||
|
this._loadStates();
|
||||||
|
} else {
|
||||||
|
this._applyStateRules(center);
|
||||||
|
}
|
||||||
|
} else if (name === 'Metropolitan France') {
|
||||||
|
this.options.radius = 20000;
|
||||||
|
this._setNogoCircle(center);
|
||||||
|
} else {
|
||||||
|
console.error('unhandled country: ' + name);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// NOOP, no rules implemented for this location
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
// debugging
|
// debugging
|
||||||
_logStates: function (states) {
|
_logStates: function (states) {
|
||||||
for (var i = 0; i < states.features.length; i++) {
|
for (var i = 0; i < states.features.length; i++) {
|
||||||
|
|
@ -255,19 +299,22 @@ BR.CircleGoArea = L.Control.extend({
|
||||||
},
|
},
|
||||||
|
|
||||||
// debugging
|
// debugging
|
||||||
_addStatesLayer: function (states) {
|
_addGeoJsonLayer: function (states, options) {
|
||||||
// delay, otherwise triggers premature hash update through mapmove
|
// delay, otherwise triggers premature hash update through mapmove
|
||||||
setTimeout(
|
setTimeout(
|
||||||
L.bind(function () {
|
L.bind(function () {
|
||||||
L.geoJson(states, {
|
L.geoJson(states, {
|
||||||
style: function (feature) {
|
style: function (feature) {
|
||||||
return {
|
return L.extend(
|
||||||
|
{
|
||||||
weight: 1,
|
weight: 1,
|
||||||
color: 'navy',
|
color: 'navy',
|
||||||
opacity: 0.8,
|
opacity: 0.8,
|
||||||
fill: false,
|
fill: false,
|
||||||
interactive: false,
|
interactive: false,
|
||||||
};
|
},
|
||||||
|
options
|
||||||
|
);
|
||||||
},
|
},
|
||||||
}).addTo(this.map);
|
}).addTo(this.map);
|
||||||
}, this),
|
}, this),
|
||||||
|
|
@ -275,29 +322,63 @@ BR.CircleGoArea = L.Control.extend({
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|
||||||
_loadStates: function (cb) {
|
_loadStates: function () {
|
||||||
BR.Util.get(
|
if (this.statesLoading) return;
|
||||||
this.options.statesUrl,
|
|
||||||
L.bind(function (err, data) {
|
|
||||||
if (err) {
|
|
||||||
BR.message.showError('Error getting states: ' + err);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
this.statesLoading = true;
|
||||||
this.states = JSON.parse(data);
|
BR.Util.getGeoJson(
|
||||||
|
this.options.statesUrl,
|
||||||
|
'states',
|
||||||
|
L.bind(function (err, data) {
|
||||||
|
if (!err) {
|
||||||
|
this.states = data;
|
||||||
|
|
||||||
// debugging
|
// debugging
|
||||||
//this._logStates(this.states);
|
//this._logStates(this.states);
|
||||||
//this._addStatesLayer(this.states);
|
//this._addGeoJsonLayer(this.states);
|
||||||
|
|
||||||
this.fire('states:loaded');
|
|
||||||
|
|
||||||
cb();
|
|
||||||
} catch (err) {
|
|
||||||
BR.message.showError('Error parsing states: ' + err);
|
|
||||||
console.error(err);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.statesLoading = false;
|
||||||
|
this.fire('states:loaded');
|
||||||
|
}, this)
|
||||||
|
);
|
||||||
|
},
|
||||||
|
|
||||||
|
_loadCountries: function () {
|
||||||
|
BR.Util.getJson(
|
||||||
|
this.options.countriesUrl,
|
||||||
|
'countries',
|
||||||
|
L.bind(function (err, data) {
|
||||||
|
if (err) return;
|
||||||
|
|
||||||
|
var key = Object.keys(data.objects)[0];
|
||||||
|
this.countries = topojson.feature(data, data.objects[key]);
|
||||||
|
|
||||||
|
var union = topojson.merge(data, [data.objects[key]]);
|
||||||
|
this.countriesMask = L.geoJson(union, {
|
||||||
|
renderer: this.maskRenderer,
|
||||||
|
// use Leaflet.snogylop plugin here, turf.mask too slow (~4s) for some reason
|
||||||
|
invert: true,
|
||||||
|
style: function (feature) {
|
||||||
|
return {
|
||||||
|
weight: 1,
|
||||||
|
color: 'darkgreen',
|
||||||
|
opacity: 0.8,
|
||||||
|
fillColor: '#020',
|
||||||
|
fillOpacity: 0.2,
|
||||||
|
className: 'circlego-outside',
|
||||||
|
};
|
||||||
|
},
|
||||||
|
});
|
||||||
|
this.countriesMask.on('click', L.DomEvent.stop);
|
||||||
|
this.countriesMask.bindTooltip(i18next.t('map.not-applicable-here'), {
|
||||||
|
sticky: true,
|
||||||
|
offset: [10, 0],
|
||||||
|
direction: 'right',
|
||||||
|
opacity: 0.8,
|
||||||
|
});
|
||||||
|
|
||||||
|
this.fire('countries:loaded');
|
||||||
}, this)
|
}, this)
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|
@ -325,23 +406,19 @@ BR.CircleGoArea = L.Control.extend({
|
||||||
this._removeNogo();
|
this._removeNogo();
|
||||||
|
|
||||||
if (center) {
|
if (center) {
|
||||||
if (this.options.stateRules) {
|
if (!this.countries) {
|
||||||
if (!this.states) {
|
// wait for countries to be loaded (when circlego hash parameter without polylines)
|
||||||
// wait for states to be loaded (when circlego hash parameter without polylines)
|
|
||||||
this.marker.setIcon(this.iconSpinner);
|
this.marker.setIcon(this.iconSpinner);
|
||||||
this.once(
|
this.once(
|
||||||
'states:loaded',
|
'countries:loaded',
|
||||||
function () {
|
function () {
|
||||||
this._applyStateRules(center);
|
|
||||||
this.marker.setIcon(this.icon);
|
this.marker.setIcon(this.icon);
|
||||||
|
this._applyCountryRules(center);
|
||||||
},
|
},
|
||||||
this
|
this
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
this._applyStateRules(center);
|
this._applyCountryRules(center);
|
||||||
}
|
|
||||||
} else {
|
|
||||||
this._setNogoCircle(center);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
@ -368,7 +445,7 @@ BR.CircleGoArea = L.Control.extend({
|
||||||
var mask = turf.mask(turf.polygonize(ring));
|
var mask = turf.mask(turf.polygonize(ring));
|
||||||
|
|
||||||
this.outsideArea = L.geoJson(mask, {
|
this.outsideArea = L.geoJson(mask, {
|
||||||
renderer: this.outsideAreaRenderer,
|
renderer: this.maskRenderer,
|
||||||
style: function (feature) {
|
style: function (feature) {
|
||||||
return {
|
return {
|
||||||
weight: 4,
|
weight: 4,
|
||||||
|
|
@ -427,8 +504,8 @@ BR.CircleGoArea = L.Control.extend({
|
||||||
this.clear();
|
this.clear();
|
||||||
marker.addTo(this.circleLayer);
|
marker.addTo(this.circleLayer);
|
||||||
|
|
||||||
if (this.options.stateRules && !this.states) {
|
// prevent editing (when called by hash) until countries are loaded, see _loadCountries call in onAdd
|
||||||
// prevent editing (when called by hash) until states are loaded, see _loadStates call in onAdd
|
if (!this.countries) {
|
||||||
marker.dragging.disable();
|
marker.dragging.disable();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -538,19 +615,5 @@ BR.CircleGoArea = L.Control.extend({
|
||||||
BR.CircleGoArea.include(L.Evented.prototype);
|
BR.CircleGoArea.include(L.Evented.prototype);
|
||||||
|
|
||||||
BR.circleGoArea = function (routing, nogos, pois) {
|
BR.circleGoArea = function (routing, nogos, pois) {
|
||||||
var circleGo = null;
|
return new BR.CircleGoArea(routing, nogos, pois);
|
||||||
var options = {};
|
|
||||||
|
|
||||||
if (BR.Util.isCountry('FR', 'fr')) {
|
|
||||||
options.radius = 20000;
|
|
||||||
} else if (BR.Util.isCountry('DE', 'de')) {
|
|
||||||
options.radius = 15000;
|
|
||||||
options.stateRules = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (options) {
|
|
||||||
circleGo = new BR.CircleGoArea(routing, nogos, pois, options);
|
|
||||||
}
|
|
||||||
|
|
||||||
return circleGo;
|
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -96,8 +96,8 @@
|
||||||
"delete-nogo-areas": "Delete all no-go areas",
|
"delete-nogo-areas": "Delete all no-go areas",
|
||||||
"delete-pois": "Delete all points of interest",
|
"delete-pois": "Delete all points of interest",
|
||||||
"delete-route": "Delete route",
|
"delete-route": "Delete route",
|
||||||
"draw-circlego-start": "Draw limited {{radius}}km go-to zone",
|
"draw-circlego-start": "Draw limited go-to zone",
|
||||||
"draw-circlego-stop": "Stop drawing limited {{radius}}km go-to zone",
|
"draw-circlego-stop": "Stop drawing limited go-to zone",
|
||||||
"draw-poi-start": "Draw points of interest",
|
"draw-poi-start": "Draw points of interest",
|
||||||
"draw-poi-stop": "Stop drawing points of interest",
|
"draw-poi-stop": "Stop drawing points of interest",
|
||||||
"draw-route-start": "Draw route",
|
"draw-route-start": "Draw route",
|
||||||
|
|
@ -132,6 +132,7 @@
|
||||||
"edit": "Click to edit",
|
"edit": "Click to edit",
|
||||||
"help": "□ = move / resize, <span class=\"fa fa-trash-o\"></span> = delete,<br>click circle to quit editing"
|
"help": "□ = move / resize, <span class=\"fa fa-trash-o\"></span> = delete,<br>click circle to quit editing"
|
||||||
},
|
},
|
||||||
|
"not-applicable-here": "not applicable here",
|
||||||
"opacity-slider": "Set transparency of route track and markers",
|
"opacity-slider": "Set transparency of route track and markers",
|
||||||
"opacity-slider-shortcut": "{{action}}\n(Hold {{key}} key to mute temporarily)",
|
"opacity-slider-shortcut": "{{action}}\n(Hold {{key}} key to mute temporarily)",
|
||||||
"preview": "Preview",
|
"preview": "Preview",
|
||||||
|
|
|
||||||
|
|
@ -74,6 +74,7 @@
|
||||||
"mapbbcode": "MapBBCode/mapbbcode#v1.2.0",
|
"mapbbcode": "MapBBCode/mapbbcode#v1.2.0",
|
||||||
"osmtogeojson": "^3.0.0-beta.4",
|
"osmtogeojson": "^3.0.0-beta.4",
|
||||||
"promise-polyfill": "^8.2.0",
|
"promise-polyfill": "^8.2.0",
|
||||||
|
"topojson-client": "^3.1.0",
|
||||||
"url-search-params": "~0.5.0",
|
"url-search-params": "~0.5.0",
|
||||||
"whatwg-fetch": "^3.5.0"
|
"whatwg-fetch": "^3.5.0"
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,25 @@
|
||||||
# boundaries
|
# boundaries
|
||||||
|
|
||||||
## germany-states.geojson
|
Downloaded from https://osm-boundaries.com.
|
||||||
|
|
||||||
|
TopoJSON (https://github.com/topojson/topojson) used to convert to topology, simplify and reduce precision:
|
||||||
|
`npm install -g topojson`
|
||||||
|
|
||||||
|
## germany-states
|
||||||
|
|
||||||
Currently only containing states that do not use the municipality boundary for the Corona 15 km allowed zone rule.
|
Currently only containing states that do not use the municipality boundary for the Corona 15 km allowed zone rule.
|
||||||
|
|
||||||
Downloaded from https://osm-boundaries.com with:
|
|
||||||
|
|
||||||
```
|
```
|
||||||
curl --remote-name --remote-header-name --location --max-redirs -1 "https://osm-boundaries.com/Download/Submit?apiKey=YOUR_API_KEY&db=osm20201109&osmIds=-28322,-62771,-62372,-62467,-62607,-62422,-62782,-62504&includeAllTags&simplify=0.0001"
|
curl --remote-name --remote-header-name --location --max-redirs -1 "https://osm-boundaries.com/Download/Submit?apiKey=YOUR_API_KEY&db=osm20201109&osmIds=-28322,-62771,-62372,-62467,-62607,-62422,-62782,-62504&includeAllTags"
|
||||||
|
|
||||||
|
geo2topo germany-states.geojson | toposimplify -s 3e-12 | topoquantize 1e6 > germany-states.topo.json
|
||||||
|
```
|
||||||
|
|
||||||
|
## countries
|
||||||
|
|
||||||
|
```
|
||||||
|
curl --remote-name --remote-header-name --location --max-redirs -1 "https://osm-boundaries.com/Download/Submit?apiKey=YOUR_API_KEY&db=osm20201109&osmIds=-51477,-1403916"
|
||||||
|
|
||||||
|
geo2topo countries.geojson | toposimplify -s 3e-12 | topoquantize 1e6 > countries.topo.json
|
||||||
```
|
```
|
||||||
|
|
|
||||||
1
resources/boundaries/countries.topo.json
Normal file
1
resources/boundaries/countries.topo.json
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
1
resources/boundaries/germany-states.topo.json
Normal file
1
resources/boundaries/germany-states.topo.json
Normal file
File diff suppressed because one or more lines are too long
|
|
@ -8173,7 +8173,7 @@ toidentifier@1.0.0:
|
||||||
resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.0.tgz#7e1be3470f1e77948bc43d94a3c8f4d7752ba553"
|
resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.0.tgz#7e1be3470f1e77948bc43d94a3c8f4d7752ba553"
|
||||||
integrity sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==
|
integrity sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==
|
||||||
|
|
||||||
topojson-client@3:
|
topojson-client@3, topojson-client@^3.1.0:
|
||||||
version "3.1.0"
|
version "3.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/topojson-client/-/topojson-client-3.1.0.tgz#22e8b1ed08a2b922feeb4af6f53b6ef09a467b99"
|
resolved "https://registry.yarnpkg.com/topojson-client/-/topojson-client-3.1.0.tgz#22e8b1ed08a2b922feeb4af6f53b6ef09a467b99"
|
||||||
integrity sha512-605uxS6bcYxGXw9qi62XyrV6Q3xwbndjachmNxu8HWTtVPxZfEJN9fd/SZS1Q54Sn2y0TMyMxFj/cJINqGHrKw==
|
integrity sha512-605uxS6bcYxGXw9qi62XyrV6Q3xwbndjachmNxu8HWTtVPxZfEJN9fd/SZS1Q54Sn2y0TMyMxFj/cJINqGHrKw==
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue