Leaflet plus turf.js - color of line before & after point - leaflet

I have a basic leaflet plus turf.js polyline - i'd like to be able to style the line before and after a given point. So for example - from the start to the point marker (along) (color : red). Basically, showing the portion of the route(line) that has been completed.
//path coords
var coords = [
[-3.535,55.62],
[-3.54,55.61],
[-3.547,55.6],
[-3.55,55.59],
[-3.57,55.58]
];
var features = turf.points(coords );
var center = turf.center(features);
var map = L.map('map');
L.tileLayer(
'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
attribution: '© <a href="https://openstreetmap.org" target=blank>OpenStreetMap</a> Contributors',
maxZoom: 18,
}).addTo(map);
var line = turf.lineString(coords);
var options = {units: 'miles'};
L.geoJSON(line).addTo(map);
var along = turf.along(line, 1.25, options);
L.geoJSON(along).addTo(map).bindTooltip("my tooltip text");
// get center x/y
var features = turf.points(coords);
var center = turf.center(features);
var centroid_xy = center.geometry.coordinates;
var x = centroid_xy[0];
var y = centroid_xy[1];
// get bounds
var bbox = turf.bbox(line);
var b0 = bbox[0];
var b1 = bbox[1];
var b2 = bbox[2];
var b3 = bbox[3];
L.marker([55.62, -3.535]).bindPopup("Test marker").addTo(map);
var mapMarker2 = L.icon({
iconSize: [16, 16],
iconAnchor: [8, 8],
});
map.setView([y, x], 13);
map.fitBounds([[b1, b0],[b3, b2]]);

You can use your along point to split the line with TurfJS:
split = turf.lineSplit(line, along)
This gives you a FeatureCollection of 2 features, which you can use to show the two segments on the map.
https://observablehq.com/d/f379582399e8089d

Related

Leaflet plus Turf.js - dynamically set bounds based on data points

I'm new to Turf.js but have used leaflet before. Looking to move my Google maps over to leafet/turf.js
I'm trying to dynamically set the initial map view by using getBounds as per leaflet, but when using Turf.js, I get an error 'line.getBounds' is not a function.
I've also tried using bbox, to get the bounding box of my datapoints, and whilst I can draw the box on the screen, I can't seem set the initial view to it. I can set the initial view as a static point.
//Some Points
var somePoints = [
[-3.535,55.62],
[-3.54,55.61],
[-3.547,55.6],
[-3.55,55.59],
[-3.57,55.58]
];
var features = turf.points(somePoints);
var center = turf.center(features);
var map = L.map('map').setView([55.6, -3.55], 12);
L.tileLayer(
'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
attribution: '© <a href="https://openstreetmap.org" target=blank>OpenStreetMap</a> Contributors',
maxZoom: 18,
}).addTo(map);
var line = turf.lineString(somePoints);
var options = {units: 'miles'};
L.geoJSON(line).addTo(map);
var along = turf.along(line, 1.25, options);
L.geoJSON(along).addTo(map).bindTooltip("my tooltip text");
along = turf.along(line, 2.123, options);
L.geoJSON(along).addTo(map).bindTooltip("12345");
var bbox = turf.bbox(line);
var bboxPolygon = turf.bboxPolygon(bbox);
L.geoJSON(bboxPolygon ).addTo(map)
var features = turf.points(somePoints);
var center = turf.center(features);
Updated code - I needed to find the bounds of the turf.js object
//path coords
var coords = [
[-3.535,55.62],
[-3.54,55.61],
[-3.547,55.6],
[-3.55,55.59],
[-3.57,55.58]
];
var features = turf.points(coords );
var center = turf.center(features);
var map = L.map('map');
L.tileLayer(
'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
attribution: '© <a href="https://openstreetmap.org" target=blank>OpenStreetMap</a> Contributors',
maxZoom: 18,
}).addTo(map);
var line = turf.lineString(coords);
var options = {units: 'miles'};
L.geoJSON(line).addTo(map);
var along = turf.along(line, 1.25, options);
L.geoJSON(along).addTo(map).bindTooltip("my tooltip text");
along = turf.along(line, 2.123, options);
L.geoJSON(along).addTo(map).bindTooltip("12345");
// get center x/y
var features = turf.points(coords);
var center = turf.center(features);
var centroid_xy = center.geometry.coordinates;
var x = centroid_xy[0];
var y = centroid_xy[1];
// get bounds
var bbox = turf.bbox(line);
var b0 = bbox[0];
var b1 = bbox[1];
var b2 = bbox[2];
var b3 = bbox[3];
L.marker([55.62, -3.535]).bindPopup("Test marker").addTo(map);
var mapMarker2 = L.icon({
iconSize: [16, 16],
iconAnchor: [8, 8],
});
map.setView([y, x], 13);
map.fitBounds([[b1, b0],[b3, b2]]);

Leaflet: impossible to remove specific image layer

Below are three functions that I use to respectively create a map, add an IMG-layer and remove an IMG-layer. Problem is that when I add an IMG-layer and then want to remove it before adding a new (different) IMG-layer......the removal is not taking place.
The IMG-layers that I use are simple URLs to png's.
So subsequently:
loadMap();
SetLayer("2018_10_13_16_15.png");
RemoveLayer("2018_10_13_16_15.png");
SetLayer("2018_10_13_16_30.png");
Then "2018_10_13_16_15.png" is not removed.
What am I doing wrong??
var map = L.map('map');
var imageBounds = [[50.520, 0.813], [54.295, 10.996]];
function loadMap(){
map.createPane('labels');
var positron = L.tileLayer('http://{s}.basemaps.cartocdn.com/light_nolabels/{z}/{x}/{y}.png', {
attribution: cartodbAttribution
}).addTo(map);
var positronLabels = L.tileLayer('http://{s}.basemaps.cartocdn.com/light_only_labels/{z}/{x}/{y}.png', {
attribution: cartodbAttribution,
pane: 'labels'
}).addTo(map);
map.setView({lat: 52.5, lng: 5.2}, 6.5);
isMap = true; //map is loaded
}
function SetLayer(url) {
IMGLayer = L.imageOverlay(url, imageBounds);
IMGLayer.addTo(map);
}
function RemoveLayer(url) {
IMGLayer = L.imageOverlay(url, imageBounds);
IMGLayer.removeFrom(map);
}

leaflet snap polyline to rout

I'm try to convert polyline to rout but I have a problem
You see in the picture below that the road is different from the polyline:
Here is my code:
var mymap = L.map('map').setView([32.661343, 51.680374], 6);
L.tileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png').addTo(mymap);
var markers = new L.MarkerClusterGroup();
var markerList = [];
var a = [];
var myTrip = [];
var myTrip2 = [];
for (var i = 1; i < locations.length ; i++) {
myTrip.push(new L.LatLng(parseFloat(locations[i]['Received']['lat']),parseFloat(locations[i]['Received']['lng'])));
a[0] = parseFloat(locations[i]['Received']['lat']);
a[1] = parseFloat(locations[i]['Received']['lng']);
var marker = new L.Marker(new L.LatLng(a[0], a[1]));
marker.bindPopup((locations[i]['Received']['id']).toString());
markerList.push(marker);
var polyline =L.polyline(myTrip, {color: 'blue'}).addTo(mymap);
}
var markerPatterns = L.polylineDecorator(myTrip, {
patterns: [
{offset: 25, repeat: 50, symbol: L.Symbol.arrowHead({pixelSize: 15, pathOptions: {fillOpacity: 1, weight: 0}})}
]
}).addTo(mymap);
var control = L.Routing.control({
waypoints: myTrip,
show: false,
waypointMode: 'snap',
showAlternatives: true,
useZoomParameter: true,
createMarker: function() {}
}).addTo(mymap);
1) So are the lines drawn using the raw coordinates? In other words, are the lines drawn like you do not use a routing service?
2) Leaflet Routing Machine is a plug-in that supports several routing engines, with OSRM as a default.
http://www.liedman.net/leaflet-routing-machine/
Have you tried inserting your DB coordinates to the OSRM-demo? Is it giving you the expected results?
http://map.project-osrm.org/
The high and low streets are routes because 1 of your waypoints are hitting that street and to get back on track again it have to turn around the block. It would have routed correcly if your waypoints where more accurate.

Changing Leaflet ImageLayer With File Input

I'm working on a dynamic image mapper that will users can load their floor plan of apartment then put markers on parts of floor. So I wan't to change url of image layer of Leaflet map dynamically.
I'm loading map with ChangeMap function for the first time. It loads my image correctly.
function ChangeMap(_url)
{
var map = L.map('map', {
minZoom: 1,
maxZoom: 5,
center: [0, 0],
zoom: 3,
crs: L.CRS.Simple
}).setView([50.4333, 30.5167], 3);
// dimensions of the image
var w = 1526,
h = 626,
url = _url;
// calculate the edges of the image, in coordinate space
var southWest = map.unproject([0, h], map.getMaxZoom() - 1);
var northEast = map.unproject([w, 0], map.getMaxZoom() - 1);
var bounds = new L.LatLngBounds(southWest, northEast);
// add the image overlay,
// so that it covers the entire map
var overlay = L.imageOverlay(url, bounds);
overlay.addTo(map);
}
But if I try another time without refresh the page I'm getting an error "map container is alreay initialized". After that error I thought I can add div with id='map' dynamically like this.
var mapContainer = $("#mapContainer");
mapContainer.append("<div id='map' width='100%' height='400px'></div>");
I added that append function at the beginning of my ChangeMap() function. But this time there was no map on page. How can I do this ?
Only initialize the map once...So take var map = L.map('map', {... out of ChangeMap and only run it once before.I'd also recommend only initializing the L.imageOverlay once...and using setUrl to dynamically swap when needed inside ChangeMap.

Leaflet Circle radius changing dependant on y/lng coords

I am using mapbox/leaflet to display a picture of a human body rather than a regular map.
I am using leaflet draw and I need to be able to create a circle and move it around while maintaining its radius. However, when I move it towards the bottom of the map/screen, the size increases exponentialy. I want it to stay the same size.
I assume it's something to do with projection or CRS but I'm not sure what to do to stop it.
My code is :
var mapMinZoom = 0;
var mapMaxZoom = 4;
var map = L.map('map', {
maxZoom: mapMaxZoom,
minZoom: mapMinZoom,
crs: L.CRS.Simple,
noWrap: true,
continuousWorld: true
}).setView([0, 0], mapMaxZoom);
var mapBounds = new L.LatLngBounds(
map.unproject([0, 3840], mapMaxZoom),
map.unproject([4096, 0], mapMaxZoom));
map.fitBounds(mapBounds);
L.tileLayer('/tiles/{z}/{x}/{y}.png', {
minZoom: mapMinZoom, maxZoom: mapMaxZoom,
bounds: mapBounds,
attribution: 'Rendered with MapTiler',
noWrap: true,
continuousWorld: true
}).addTo(map);
var touches;
var featureGroup = L.featureGroup().addTo(map);
var drawControl = new L.Control.Draw({
edit: {
featureGroup: featureGroup
}
}).addTo(map);
map.on('draw:created', function (e) {
featureGroup.addLayer(e.layer);
});
Any ideas? I don't need to use leaflet draw, just the L.circle would do, but it has the same issue.
Gif of issue here :
Turns out there are a load of todos in the leaflet 0.7 code... including this little gem :
// TODO Earth hardcoded, move into projection code!
_getLatRadius: function () {
return (this._mRadius / 40075017) * 360;
},
_getLngRadius: function () {
return this._getLatRadius() / Math.cos(L.LatLng.DEG_TO_RAD * this._latlng.lat);
},
Updated to 0.8Dev and it has all been fixed!