We're looking for a way to get our data points that are inside a polygon using JavaScript HereMaps API
We're adding 4 datapoints to a ClusterLayer / ClusterProvider and a polygon to the map. 3 of the 4 points are within the drawn Polygon (data of the points: a, b, d). Point with data = c is not within the polygon (see jsfiddle)
We tried to use map.getObjectsWithin
but this functions only returns the polygon. We assume that this is caused by the different layers.
What's the best way to get the datapoints which are in the bounds of the polygon? We try to avoid additional dependencies to solve this issue.
quick demo: http://jsfiddle.net/4dno0gu2/59/
We found this question, but there wasn't any example, no activity for a long time and no solution. HereMap getObjectsWithin does not show objects in LocalObjectProvider
Yeah the method getObjectsWithin doesn't work for ObjectProvider although this implemented in JS API but simple this functionality is not a public method, apologies for it.
Short description of workaround:
Code:
/**
* Adds a polygon to the map
*
* @param {H.Map} map A HERE Map instance within the application
*/
function addPolygonToMap(map) {
var geoStrip = new H.geo.LineString(
[48.8, 13.5, 100, 48.4, 13.0, 100, 48.4, 13.5, 100]
);
var polygon = new H.map.Polygon(geoStrip, {
style: {
strokeColor: '#829',
lineWidth: 8
},
data: 'polygon'
});
//map.addObject(polygon);
return polygon;
}
function logObjectsInPolygon(map, polygon){
var geoPolygon = polygon.getGeometry();
map.getObjectsWithin(geoPolygon, (o) => {
console.log('found mapObjects: '+ o.length);
o.forEach(x=>{
if(typeof x.getData === 'function'){
console.log(x.getData());
}
});
});
}
function isPointInPolygon(testPoint, polygPoints) {
let result = false;
let j = polygPoints.length - 1;
for(i=0,len=j+1; i<len; i++){
let p = polygPoints[i];
let lP = polygPoints[j];
if(p.y < testPoint.y && lP.y >= testPoint.y || lP.y < testPoint.y && p.y >= testPoint.y){
if((p.x + (testPoint.y - p.y) / (lP.y - p.y) * (lP.x - p.x)) < testPoint.x){
result = !result;
}
}
j = i;
}
return result;
}
/**
* Boilerplate map initialization code starts below:
*/
//Step 1: initialize communication with the platform
var platform = new H.service.Platform({
apikey: 'H6XyiCT0w1t9GgTjqhRXxDMrVj9h78ya3NuxlwM7XUs',
useCIT: true,
useHTTPS: true
});
var defaultLayers = platform.createDefaultLayers();
//Step 2: initialize a map - this map is centered over Europe
var map = new H.Map(document.getElementById('map'),
defaultLayers.raster.normal.map,{
center: {lat:48.5, lng:13.45},
zoom: 10
});
//Step 3: make the map interactive
// MapEvents enables the event system
// Behavior implements default interactions for pan/zoom (also on mobile touch environments)
var behavior = new H.mapevents.Behavior(new H.mapevents.MapEvents(map));
// Create the default UI components
var ui = H.ui.UI.createDefault(map, defaultLayers);
//this marker should go to clusters if there is more data points
var dataPoints = [];
dataPoints.push(new H.clustering.DataPoint(48.5, 13.45,{}, 'a'));
dataPoints.push(new H.clustering.DataPoint(48.5001, 13.45,{}, 'b'));
dataPoints.push(new H.clustering.DataPoint(48.5002, 13.51,{}, 'c')); // not in Polygon
dataPoints.push(new H.clustering.DataPoint(48.53, 13.45,{}, 'd'));
var clusteredDataProvider = new H.clustering.Provider(dataPoints);
var layer = new H.map.layer.ObjectLayer(clusteredDataProvider);
map.addLayer(layer);
// createPolygon to select clustered (noise) points
var polygon = addPolygonToMap(map);
let extPoly = polygon.getGeometry().getExterior();
let seqPointsPoly = [];
extPoly.eachLatLngAlt((lat, lng, alt, idy) => {
seqPointsPoly.push( {y: lat, x: lng});
});
console.log("seqPointsPoly:", seqPointsPoly);
map.addEventListener("tap", (e) => {
let pBbox = polygon.getBoundingBox();
let arrPnts = clusteredDataProvider.requestMarkers(pBbox);
for(let i=0,len=arrPnts.length; i<len; i++){
let m = arrPnts[i];
let p = {y: m.getGeometry().lat, x: m.getGeometry().lng};
let clustData = m.getData();
if(!clustData.getData){
console.log("cluster: is in polygon:", isPointInPolygon(p, seqPointsPoly));
} else if(clustData.getData){
console.log("nois: is in polygon:", clustData.getData(), m.getGeometry(), isPointInPolygon(p, seqPointsPoly));
}else{
console.log("unknown type");
}
}
console.log("clusteredDataProvider:", pBbox, clusteredDataProvider.requestMarkers(pBbox));
// Our expected logging is: points a, b, d
//logObjectsInPolygon(map, polygon);
});
Worked example (tap on map to start processing): http://jsfiddle.net/m1ey7p2h/1/