Leaflet and Turf.js Points within poly - javascript

I have a simple map with 17 points (GeoJSON) in leaflet, and using the draw tool, I create a polygon to use to select the points within th polygon.
map.on('draw:created', function (e) { //from draw tool
var type = e.layerType,
layer = e.layer;
editableLayers.addLayer(layer);
GetSelection(editableLayers);
});
function GetSelection(layer){
var count = allPoints.getLayers().length;
console.log(count +" Sites"); //says 17
var drawList = editableLayers.getLayers().length;
console.log(drawList +" Polys"); //Says 1
if (editableLayers.getLayers().length >0){
var fcpt = turf.featurecollection(allPoints);
console.log(fcpt); // says 17
var fcpoly = turf.featurecollection(editableLayers);
console.log(fcpoly); // fails as undefined
//var ptsWithin = turf.within(fcpt,editableLayers);
var ptsWithin = turf.within(fcpt,fcpoly);
console.log(ptsWithin); //never gets this far.
};
};
Any ideas or suggestions?

turf.featurecollection expects an array of GeoJSON Features, not a Leaflet Layer Group like your allPoints and editableLayers variables.
Similarly, turf.within expects 2 GeoJSON Feature Collections as arguments, not Leaflet Layer Groups.
So you could probably try directly:
var ptsWithin = turf.within(allPoints.toGeoJSON(), editableLayers.toGeoJSON());

#ghybs was right, it was a difference between Leaflet and turf, while the points were OK, the polygon did not come over. Passing turf the GeoJson the polygon info allowed it to work.
Working copy:
map.on('draw:created', function (e) {
featureGroup.clearLayers();
layer = e.layer;
featureGroup.addLayer(layer);
GetSelection(featureGroup);
});
function GetSelection(layer){
var shape2 = allPoints.toGeoJSON() //All facilities
var ptsWithin = turf.within(shape2, layer.toGeoJSON());
alert('Found ' + ptsWithin.features.length + ' features');
alert("results "+JSON.stringify(ptsWithin));
};

Related

Add multiple parentLines to a leaflet marker

I'm trying to create a straight line network in Leaflet, which at each junction has a marker, and on drag of each marker, update the position of the corresponding polyline which connects to it.
I've done some research (mostly this question) & reworked a fiddle to strip it down a bit to try & get it to do what I want. I am able to draw the network with individual polylines, however, I need to add multiple parentLines to the marker which is connected to two polylines. I can't find it in the Leaflet documentation, but punted with this:
marker_arr[1].parentLine = [polyline_a,polyline_b];
My issue is when I call the dragstart/drag/dragend handlers, it doesn't work with multiple polylines. (Edit) I have made some headway in capturing the parentLines as an array, but can only make it work for the first parentLine
function dragHandler(e) {
var polyline=[]
console.log("drag")
if(e.target.parentLine.length){
polyline.push(e.target.parentLine[0]);
} else {
polyline.push(e.target.parentLine);
}
if(polyline){
var latlngPoly = polyline[0].getLatLngs(), // Get the polyline's latlngs
latlngMarker = this.getLatLng(); // Get the marker's current latlng
latlngPoly.splice(this.polylineLatlng, 1, latlngMarker); // Replace the old latlng with the new
polyline[0].setLatLngs(latlngPoly); // Update the polyline with the new latlngs
}
}
Can anyone point me to either the documentation about parentLine, or how I might make this work? Using Leaflet v1.6.0 and cannot use more recent versions as this is to extend an already existing implementation of Leaflet based on 1.6.
Fiddle here
Here is a sample.
Add to the marker the parentLines always as array:
marker_arr[0].parentLine = [polyline_a];
marker_arr[1].parentLine = [polyline_a,polyline_b];
marker_arr[2].parentLine = [polyline_b];
and then loop through all parentLines in the dragstart handler:
// Now on dragstart you'll need to find the latlng from the polyline which corresponds
// with your marker's latlng and store it's key in your marker instance so you can use it later on:
function dragStartHandler(e) {
var marker = e.target;
marker.polylineLatlng = {};
e.target.parentLine.forEach((line)=>{
var latlngPoly = line.getLatLngs(), // Get the polyline's latlngs
latlngMarker = marker.getLatLng(); // Get the marker's current latlng
for (var i = 0; i < latlngPoly.length; i++) { // Iterate the polyline's latlngs
if (latlngMarker.equals(latlngPoly[i])) { // Compare marker's latlng ot the each polylines
marker.polylineLatlng[L.stamp(line)] = i; // If equals store key in marker instance
}
}
})
}
And in the drag handler:
// Now you know the key of the polyline's latlng you can change it
// when dragging the marker on the dragevent:
function dragHandler(e) {
var marker = e.target;
e.target.parentLine.forEach((line)=>{
var latlngPoly = line.getLatLngs(), // Get the polyline's latlngs
latlngMarker = marker.getLatLng(); // Get the marker's current latlng
latlngPoly.splice(marker.polylineLatlng[L.stamp(line)], 1, latlngMarker); // Replace the old latlng with the new
line.setLatLngs(latlngPoly); // Update the polyline with the new latlngs
})
}
And clean it in the dragend handler:
// Just to be clean and tidy remove the stored key on dragend:
function dragEndHandler(e) {
var marker = e.target;
delete marker.polylineLatlng;
console.log("end");
}

Mapbox LngLat object

i have a little problem, need seperates two values from a LngLat Mapbox object. Im creating a marker on double click in the map. Works fine. The problem is that i need to store the value of longtitude and latitude in my database. And i have a problem with getting this values from lnglat object. I was looking in mapbox doc, but there is no any method for that object that could help. Is there any solution for this?
map.on('dblclick', (e) => {
const popupForm = document.querySelector('#marker-popup-form');
const popupText = popupForm['marker-infoo'].value;
// create the popup
var popup = new mapboxgl.Popup().setText(popupText);
popupForm.reset();
// create DOM element for the marker
var el = document.createElement('div');
el.id = 'marker';
// create the marker
new mapboxgl.Marker(el)
.setLngLat(e.lngLat)
.setPopup(popup)
.addTo(map);});
Ok, i found a solution by making and array and then extract the value
// Here array.values() function is called.
var iterator = el.values();
// All the elements of the array the array
// is being printed.
var myLng = iterator.next().value;
var myLat = iterator.next().value;
console.log('Lng = ' + myLng);
console.log('Lat = ' + myLat);
});
Console looks like this:
Lng = 18.263916015625682
Lat = 50.436719121999545

amcharts - how to set lat/lon in mappolygon?

Basically, I just want to plot a circle, at a user defined lat/lon with a radius of X km.
So I realize looking through documentation, I can't change the lat/lons of the mappolygons that are already loaded through the geodata, but I guess I'm not quite sure how to create a new map polygon with a specified lat/lon or if I can even do that!
My code is set up so that everytime the user clicks somewhere a marker is plotted or replotted accordingly, the location of the marker is where I would like to plot the center of the circle. I get that using the getCircle function I need to do the whole km2deg for the third variable, but I'm more concerned with the location right now. Any help would be great!
https://codepen.io/kbreezy/pen/wLRrPq
below is my onclick method of the code.
chart.seriesContainer.events.on("hit", function(ev) {
var lp = $("#chartdiv").data("point");
var coords = chart.svgPointToGeo(ev.svgPoint);
if (lp) {
lp.latitude = coords.latitude;
lp.longitude = coords.longitude;
} else {
var marker = imageSeries.mapImages.create();
marker.latitude = coords.latitude;
marker.longitude = coords.longitude;
}
$("#chartdiv").data("point", marker);
var circleSeries = chart.series.push(new am4maps.MapPolygonSeries())
var circleTemplate = circleSeries.mapPolygons.template;
circleTemplate.fill = am4core.color("#bf7569");
circleTemplate.strokeOpacity = 1;
circleTemplate.fillOpacity = 0.75;
var polygon = circleSeries.mapPolygons.create();
var mapPolygon = polygonSeries.getPolygonById("DE");
mapPolygon.setPropertyValue('latitude', coords.latitude);
mapPolygon.setPropertyValue('longitude', coords.longitude);
polygon.latitude = coords.latitude;
polygon.longitude = coords.longitude;
polygon.multiPolygon = am4maps.getCircle(mapPolygon.visualLongitude, mapPolygon.visualLatitude, 5);
//polygon.multiPolygon = am4maps.getCircle(coords.latitude, coords.longitude, 5);
});
MapPolygon does not have some latitude/longitude where you could "move" it. It's multipolygon must contain coordinates of the area you want to show. So when you pass longitude/latitude to the getCircle method, it returns multiPolygon around that point.
I modified your pen where to show the concept: https://codepen.io/team/amcharts/pen/ydrLZw
polygon.multiPolygon = am4maps.getCircle(coords.longitude, coords.latitude, 5);

How to get map.getBounds() as a list of 4 floats?

I'd like to get the coordinates of map bounds as a list of 4 floats (i.e. two points in latitude/longitude coordinates).
This (Google maps undocumented feature) used to work until a few days ago:
var b = map.getBounds();
var bounds = [b.H.H, b.H.j, b.j.j, b.j.H];
It doesn't work anymore. How to get these 4 floats ?
function getRectFromBounds(bounds) {
var ne = bounds.getNorthEast();
var sw = bounds.getSouthWest();
return [ne.lat(), ne.lng(), sw.lat(), sw.lng()];
};
var rect = getRectFromBounds(map.getBounds());
you can extend LatLngBounds and create a utility function to return this array, something like map.getBounds().toRect()

Drop Marker with 3857 projection in leafletjs

Is it possible in leaflet to drop marker with 3857 projection on map?
I fond a solution where first translate point to 4326 using proj4js and than drop it on map.
var source = new Proj4js.Proj('EPSG:3857');
var dest = new Proj4js.Proj('EPSG:4326');
var p = new Proj4js.Point(-12307.601047734, 6711475.1283642);
Proj4js.transform(source, dest, p);
new L.Marker([p.y, p.x], {bounceOnAdd: true}).addTo(map);
is there any other way in core leaflet or leaflet plugin to drop marker without using proj4js library.
Thanks.
After spending good time on internet.i'm finally done it.
var point = new L.Point(-12307.601047734, 6711475.1283642);
var earthRadius = 6378137;
var latlng = L.Projection.SphericalMercator.unproject(
point.divideBy(earthRadius));
new L.Marker([latlng.lat, latlng.lng], {bounceOnAdd: true}).addTo(map);
Same code into a reusable function:
L.CRS.EPSG3857.unproject = function (point) { // (Point) -> LatLng
var earthRadius = 6378137,
normalizedPoint = point.divideBy(earthRadius);
return this.projection.unproject(normalizedPoint);
}
Use it like:
var latlng = L.CRS.EPSG3857.unproject(point);
Example:
var point = new L.Point(-12307.601047734, 6711475.1283642);
L.marker(L.CRS.EPSG3857.unproject(point), {bounceOnAdd: true}).addTo(map);

Categories