Using array of polyline objects as layer - leaflet

I have a question about why a way that I'm trying to add polylines as a layer isn't working. To be clear, I'm not trying to assert that it should be working, just that I'm curious why it works in one case but not in another. Consider the following code:
var oMbTiles = new L.tileLayer('/mbtiles/mbtiles.php?&z={z}&x={x}&y={y}', {
tms: true,
opacity: 0.7
}),
oUpIcon = new L.Icon({
iconUrl: '/custom/css/themes/app/markers/up.png',
iconSize: [24, 26]
}),
oMapTypes = {
'Yakabox': oMbTiles
},
aFirstMarkers = [],
aFirstLines = [],
aFirstLatLng,
oFirstLine,
oFirstGroup,
oLayersControl,
oOverlayMaps,
oMap,
i;
aFirstLatLng = [
[18.319026, -66.420557],
[18.180555, -66.749961],
[18.361945, -67.175597],
[18.455183, -67.119887],
[18.158345, -66.932911],
[18.295366, -67.125135],
[18.402253, -66.711397],
[18.420412, -66.671979],
[18.445147, -66.559696],
[17.991245, -67.153993],
[18.083361, -67.153897],
[18.064919, -66.716683],
[18.412600, -66.863926],
[18.190607, -66.832041],
[18.076713, -66.947389],
[18.295913, -66.515588],
[18.263085, -66.712985],
[18.433150, -66.285875],
[17.963613, -66.947127],
[18.349416, -66.578079],
[18.448452, -66.594127],
[17.985033, -66.886536],
[18.053539, -66.792931],
[18.407226, -66.808999],
[18.134695, -67.116199],
[18.468320, -67.015781],
[18.210330, -66.591616],
[18.003422, -67.035810],
[18.277102, -66.869645],
[18.240187, -66.988776],
[18.422908, -66.489337],
[18.377637, -67.079574],
[18.332568, -67.227022],
[18.434099, -66.927384],
[18.182055, -67.132502],
[18.221464, -67.156039],
[18.107800, -67.037263],
[18.332929, -66.959689]
];
for (i = 0; i < aFirstLatLng.length; i++) {
aFirstMarkers.push(L.marker(aFirstLatLng[i]).setIcon(oUpIcon).bindPopup('lat/lng : ' + aFirstLatLng[i].join(', ')))
if (i === (aFirstLatLng.length - 1)) {
aFirstLines.push(L.polyline([aFirstLatLng[i], aFirstLatLng[0]], {color: 'red', weight: 3, opacity: 0}));
} else {
aFirstLines.push(L.polyline([aFirstLatLng[i], aFirstLatLng[i + 1]], {color: 'red', weight: 3, opacity: 0}));
}
}
oFirstLine = L.polyline(aFirstLatLng, {
weight: 5,
color: 'red'
});
oFirstLine.on('click', function () {
console.log('Clicked First line', arguments);
});
oFirstGroup = L.layerGroup(aFirstMarkers, {});
// This works
oFirstGroup.addLayer(oFirstLine);
// These next two lines do not work
// Here I'm trying to just add an array of polyline objects as a layer
//oFirstGroup.addLayer(aFirstLines);
// Here I'm trying to add the array of polyline objects as a layer group
//oFirstGroup.addLayer(L.layerGroup(aFirstLines));
oOverlayMaps = {
'First Group': oFirstGroup,
};
oMap = new L.map('map', {
minZoom: 4,
maxZoom: 10,
zoom: 9,
center: aFirstLatLng[7],
layers: [oMbTiles, oFirstGroup]
});
oLayersControl = new L.Control.Layers(oMapTypes, oOverlayMaps, {
collapsed: false
}).addTo(oMap);
So here, I'm just trying to iterate through some zip codes, create markers for each location, and connect the markers using polylines. If I instantiate the polyline object using only the array of lat/lng, that works when I add that polyline to the markers layer group (oFirstGroup). But if I pass in an array of polyline objects (which were passed in the start/end lat/lng coordinates), that doesn't work. The lines do not show up on the map. This is because I get an error saying "The provided object is not a layer". Ok, so I try to explicitly create a layer group using that array of polyline objects and while the error goes away, the lines are still not added to the map.
So I'm curious, should that be working? Or is it the case that the only way to properly create a polyline connecting markers is by passing the lat/lng coordinates as an array when instantiating a single polyline object for adding to the layer? Why is it that I can pass in an array of marker objects (when instantiating oFirstGroup) and add that layer to the map but I can't do the same thing when passing in an array of polyline objects?
thnx,
Christoph

Ok, I'm not ashamed to admit it -- I'm a moron. The problem was opacity: 0. I copied the code from elsewhere (to try to understand what was going on) and I didn't remove that. As soon as I did, voila!
I iz be dumm.
thnx,
Christoph

Related

Leaflet current position multiple markers

Hello everyone I have some problems its about the current positionmarker in my leaflet its supposed to update every 3 second and it does but it everytime it puts a new "position" marker on the map and the old one stays how can i fix this?
L.tileLayer('https://api.mapbox.com/styles/v1/{id}/tiles/{z}/{x}/{y}?access_token={accessToken}', {
attribution: '© Leaflet 2021',
tileSize: 512,
zoomOffset: -1,
id: 'mapbox/streets-v11',
accessToken: '######'
}).addTo(map);
var greenIcon = L.icon({
iconUrl: 'person.png',
iconSize: [35, 35], // size of the icon // the same for the shadow
popupAnchor: [0, -20] // point from which the popup should open relative to the iconAnchor
});
// placeholders for the L.marker and L.circle representing user's current position and accuracy
var current_position, current_accuracy;
function onLocationFound(e) {
var radius = e.accuracy / 2;
var marker;
L.marker(e.latlng, {icon: greenIcon}).addTo(map)
}
// wrap map.locate in a function
function locate() {
map.locate({setView: true, maxZoom: 15});
}
map.on('locationfound', onLocationFound);
// call locate every 3 seconds... forever
setInterval(locate, 3000);
An efficient way to fix this is to keep a reference to the marker you create, so that you can update its position rather than creating a new marker each time you get a location update. The reference needs to be held in a variable that is outside your callback function, but in scope when the callback is created.
For instance, your callback can check whether the marker already exists, and either create it and attach it to the map object for easy re-use, or just update its coordinates if it is already there:
function onLocationFound(e) {
var radius = e.accuracy / 2;
if (map._here_marker) {
// Update the marker if it already exists.
map._here_marker.setLatLng(e.latlng);
} else {
// Create a new marker and add it to the map
map._here_marker = L.marker(e.latlng, {icon: greenIcon}).addTo(map);
}
}
Having this reference will also let you edit the marker from other functions, e.g. to change the icon or popup, hide it from view, etc.
You can do it, for example, in the following way.
Add an ID (customId) to the marker:
const marker = L.marker([lng, lat], {
id: customId
});
And when you add a new marker remove the existing one with the code below:
map.eachLayer(function(layer) {
if (layer.options && layer.options.pane === "markerPane") {
if (layer.options.id !== customId) {
map.removeLayer(layer);
}
}
});

Finding Leaflet Layer Dasharray

I am creating a document from a leaflet map. The legend from the map features will not be part of the map but a separate area on the document. I am trying to get the Layer information such as color and dasharray(solid, dashed....) information from each layer.
I have used feature.option.style, but I get function style(feature) {return....}. I want to get the actual values.
var lyrs = map._layers;
for (var f in map._layers) {
var feature = map._layers[f];
alert(feature.options.style);
return false;
}
I get this:
function style(feature) {
return {
weight: 1,
opacity: 1,
color: 'black',
dashArray: '3',
fillOpacity: 0.7,
fillColor: getColor(feature.properties.Rights, "geojson", "parcel")
};
}
I want to be able to get:
fillColor:black;
dashArray: '3'
Instead of using the style call the code should read as follows
var lyrs = map._layers;
for (var f in lyrs) {
var feature = map._layers[f];
var properties = feature.options.dashArray;
alert(properties);
return false;
}
This returns the value of 3. Exactly what was desired. The same call could be used to find the weight, opacity, color, fillOpacity or fillColor

Polygon on Bing Map using Local GeoJSON Object results in wrong location

Im using Bing Map v8 to draw a polygon on a map.
for some reason, two different methods for doing so results in different results even though im using the same coordinates.
This method
as shown here
works well:
map = new Microsoft.Maps.Map(document.getElementById("map"), {
credentials: '',
mapTypeId: Microsoft.Maps.MapTypeId.aerial,
});
var polygon = new Microsoft.Maps.Polygon([
new Microsoft.Maps.Location(32.57922,34.91395),
new Microsoft.Maps.Location(32.53799,34.9021),
new Microsoft.Maps.Location(32.53264,34.91292),
new Microsoft.Maps.Location(32.55398,34.92339),
new Microsoft.Maps.Location(32.57156,34.93489),
new Microsoft.Maps.Location(32.57503,34.92614)],
{ fillColor: 'rgba(241, 227, 100, 0.3)', strokeColor: 'rgba(241, 227, 100, 0.8)', strokeThickness: 1 });
map.entities.push(polygon);
When using this Microsoft.Maps.GeoJson.read method as shown here to read a GeoJson object with the same polygon coordinates, the polygon is being drawn in an area hundreds of miles north-west from the original location. why is that ?
map = new Microsoft.Maps.Map(document.getElementById("map"), {
credentials: '',
mapTypeId: Microsoft.Maps.MapTypeId.aerial,
});
//define polygon using GeoJson Object
var GeoJson = {
"type": "Polygon",
"coordinates": [[
[32.57922,34.91395],
[32.53799,34.9021],
[32.53264,34.91292],
[32.55398,34.92339],
[32.57156,34.93489],
[32.57503,34.92614]
]]
};
//Load the GeoJson Module.
Microsoft.Maps.loadModule('Microsoft.Maps.GeoJson', function () {
//Parse the GeoJson object into a Bing Maps shape.
var shape = Microsoft.Maps.GeoJson.read(GeoJson, {
polygonOptions: {
fillColor: 'rgba(255,0,0,0.5)',
strokeColor: 'rgba(241, 227, 100, 0.8)',
strokeThickness: 1
}
});
//Add the shape to the map.
//results in wrong location !
map.entities.push(shapeA);
});
Bing Maps Locations take in latitude,longitude, while GeoJSON positions/coordinates are longitude/latitude. Reverse the numbers in your GeoJSON coordinates.

Trying to show an OSM/Nominatim relation on an OpenLayers 3 map

I am trying to show the boundary of relation 4569(Brugge, West Flanders, Flanders, Knokke-Heist) on an OpenLayers 3 type map, like http://nominatim.openstreetmap.org . But I don't know how to proceed.
These are the things I am doing:
I am querying Overpass API with the following parameters:
data=[output:json];relation(4569); out geom; out center;
This query gives me back the information about the relation with the id of 4569 from OpenStreetMaps.
The result set from this query is multiple ways, which have their role set as outer. I am combinining these ways to create a polygon, and storing them in an array.
foreach ($geom['members'] as $_poly) {
if ($_poly['role'] != 'outer' && $_poly['role'] != 'inner') continue;
if ($_poly['role'] == 'outer') {
foreach ($_poly['geometry'] as $latlon) $poly['outer'][]=array($latlon['lon'], $latlon['lat']);
} else {
$poly['inner'][]=array();
foreach ($_poly['geometry'] as $latlon) $poly['inner'][count($poly['inner'])-1][]=array($latlon['lon'], $latlon['lat']);
}
}
if ($poly['outer'][0] != $poly['outer'][count($poly['outer'])-1]) $poly['outer'][]=$poly['outer'][0];
$out['polygons']=$poly;
Afterwards, this array is sent to javascript, where I process it, and try to add a Polygon object to an OpenLayers 3 map. This is the javascript code I use. (It is wrapped in a JS prototype made by me)
Map.prototype.addPolygon = function(name, data) {
var _coordinates=[], i;
for (i=0; i<data.outer.length; i++ ) {
console.log(data.outer[i]);
_coordinates.push(ol.proj.transform(data.outer[i], 'EPSG:4326', 'EPSG:3857'));
}
console.log("Creating polygon", _coordinates);
var Polygon = new ol.geom.Polygon([_coordinates]);
var feature = new ol.Feature({
name: name+"-outer",
geometry: Polygon
});
this.polygons[name]=Polygon;
var polyStyle = new ol.style.Style({
fill: new ol.style.Fill({
color: [121, 115, 251, .2]
}),
stroke: new ol.style.Stroke({
color: '#051165',
width: 2
})
});
this.vectorSource.addFeature(feature);
feature.setStyle(polyStyle);
this.map.getView().fit(Polygon, this.map.getSize());
}
Below you will find two images, the first is the end result which I get, and the second is the end result which Nominatim gets(my desired result). If you observe, you will see that the borders of my polygon are all messy, and there are additional lines in my polygon.
My end result
Nominatim result - the desired result
What am I doing wrong? If I am doing the same thing with boundaries which are represented by a single WAY, everyting works as expected.

Start-Marker from geojson polyline

i have a map with some walking- and bike-routes and popups with a few details an a pic. Now i want to set a marker on the first vertex of a geojson polyline, but i cant find out how. Btw. i´m new to leaflet/mapbox, and i put my map togehter from code snippets.
Here is the map now:
This is how i create the polylines now. I call them via layercontrol.
var mtb = L.geoJson(radjs, {
filter: function (feature, layer) {
if (feature.properties) {
// If the property "underConstruction" exists and is true, return false (don't render features under construction)
return feature.properties.typ === 'mtb';
}
return true;
},
style: {
"color": '#6699cc',
dashArray: '',
"weight": 4,
"opacity": 0.6
}, onEachFeature: onEachFeature2}).addTo(rad);
Thank you for your help,
Marc
You could just add a Feature to your geojson with the latitude and longitude like the do it in the Leaflet GeoJSON Example.
Probably it will be more convenient to read the geometry.coordinates from geojson features and define a new marker.
Beside you have an error on line 569. You should change:
var map = L.mapbox.map('map','',{
to:
var map = L.mapbox.map('map',null,{
Create a simple marker object and add it to the map.
marker = L.marker([0, 0], {
icon: L.mapbox.marker.icon()
}).addTo(map)
Then set the latitude and longitude to the first coordinates of your geoJSON. Assuming your geoJSON is set to the var geojson, you can access the coordinates by indexing into the array.
marker.setLatLng(L.latLng(
geojson.coordinates[0][1],
geojson.coordinates[0][0]))