Skip to content
Snippets Groups Projects
Commit 05e7a741 authored by xaralis's avatar xaralis Committed by jan.bednarik
Browse files

feat(maps_utils): support more GeoJSON feature types: MultiPoint, MultiLineString, MultiPolygon

parent 95982558
No related branches found
No related tags found
2 merge requests!505Release,!502Support more GeoJSON feature types on a map
......@@ -9,4 +9,11 @@ MAP_STYLES = (
DEFAULT_MAP_STYLE = "osm-mapnik"
SUPPORTED_FEATURE_TYPES = ("Point", "Polygon", "LineString")
SUPPORTED_FEATURE_TYPES = (
"Point",
"MultiPoint",
"Polygon",
"MultiPolygon",
"LineString",
"MultiLineString",
)
......@@ -253,16 +253,7 @@ const GeoFeatureCollection = Vue.component("GeoFeatureCollection", {
)
: buildMarkerIcon("000000", number);
/**
* Process Point type GeoJSON features.
* Called for each such feature when building the map.
*/
const pointToLayer = (feature, latlng) => {
const markerPosLatLng = L.latLng(
feature.geometry.coordinates[1],
feature.geometry.coordinates[0]
);
const addMarker = (feature, markerPosLatLng, onClick) => {
// add marker
const featureMarker = new L.marker(markerPosLatLng, {
icon: feature.properties.color
......@@ -274,72 +265,83 @@ const GeoFeatureCollection = Vue.component("GeoFeatureCollection", {
feature.properties.category,
feature.properties.index
),
}).on("click", (evt) => {
this.zoomToPoint(evt.latlng, feature);
});
}).on("click", onClick);
// Add item marker to the cluster.
markers.addLayer(featureMarker);
return false;
return featureMarker;
}
/**
* Process Point/MultiPoint type GeoJSON features.
* Called for each such feature when building the map.
*/
const pointToLayer = (feature, latlng) => {
const onClick = (evt) => {
this.zoomToPoint(evt.latlng, feature);
};
return addMarker(feature, latlng, onClick);
};
/**
* Process Polygon/LineString type GeoJSON features.
* Process Polygon/MultiPolygon/LineString/MultiLineString type GeoJSON features.
* Called for each such feature when building the map.
*/
const onEachFeature = (feature, layer) => {
let markerPosLatLng;
const markerPosLatLng = [];
const onClick = (evt) => this.zoomToLayer(layer);
/**
* Supported GeoJSON features: Polygon, LineString.
* Point features are better handled by pointToLayer function.
* It's better idea to convert Points to small Polygons (ask marek.forster@pirati.cz for conversion tool)
**/
// Polygons and LineString features are supported, try to get rid of Points (bounds and zoom methods not supported)
if (feature.geometry.type == "Polygon") {
const markerForPolyCoords = (coords) => {
// Find pole of inaccessibility (not centroid) for the polygon
// @see: https://github.com/mapbox/polylabel
const markerPos = polylabel(
feature.geometry.coordinates,
1
);
markerPosLatLng = L.latLng(markerPos[1], markerPos[0]);
} else if (feature.geometry.type == "LineString") {
const markerPos = polylabel(coords, 1);
markerPosLatLng.push(L.latLng(markerPos[1], markerPos[0]));
};
const markerForLineStringCoords = (coords) => {
// Find a middle sector of LineString and set position to middle of it
const sectorCount = feature.geometry.coordinates.length;
const sectorCount = coords.length;
const sectorIndex = Math.floor((sectorCount - 1) / 2);
markerPosLatLng = L.latLng(
(feature.geometry.coordinates[sectorIndex][1] +
feature.geometry.coordinates[sectorIndex + 1][1]) /
markerPosLatLng.push(L.latLng(
(coords[sectorIndex][1] +
coords[sectorIndex + 1][1]) /
2,
(feature.geometry.coordinates[sectorIndex][0] +
feature.geometry.coordinates[sectorIndex + 1][0]) /
(coords[sectorIndex][0] +
coords[sectorIndex + 1][0]) /
2
);
));
}
/**
* Supported GeoJSON features: Polygon, MultiPolygon, LineString, MultiLineString.
* Point/MultiPoint features are better handled by pointToLayer function.
* It's better idea to convert Points to small Polygons (ask marek.forster@pirati.cz for conversion tool) as
* bounds and zoom methods are not supported for those.
**/
if (feature.geometry.type == "Polygon") {
markerForPolyCoords(feature.geometry.coordinates);
} else if (feature.geometry.type == "MultiPolygon") {
feature.geometry.coordinates.forEach(markerForPolyCoords);
} else if (feature.geometry.type == "LineString") {
markerForLineStringCoords(feature.geometry.coordinates);
} else if (feature.geometry.type == "MultiLineString") {
feature.geometry.coordinates.forEach(markerForLineStringCoords);
} else if (feature.geometry.type == "MultiPoint") {
// Supported via `pointToLayer`, noop here.
} else {
console.warn(
`GeoJSON feature type unsupported: ${feature.geometry.type}`
);
}
if (markerPosLatLng) {
// add marker
const featureMarker = new L.marker(markerPosLatLng, {
icon: feature.properties.color
? buildMarkerIcon(
feature.properties.color,
feature.properties.index
)
: markerIconForCategory(
feature.properties.category,
feature.properties.index
),
}).on("click", (evt) => this.zoomToLayer(layer));
// Add item marker to the cluster.
markers.addLayer(featureMarker);
if (markerPosLatLng.length) {
markerPosLatLng.forEach(pos => {
addMarker(feature, pos, onClick);
// Bind click event on the layer.
layer.on({ click: (evt) => this.zoomToLayer(evt.target) });
})
}
};
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment