I have a .geojson file. Inside the file there is one Feature and that feature has this property:
"geometry": { "type": "LineString", "coordinates": [ [ 103.766547, 1.377559, 0.0 ], [ 103.771405, 1.374479, 0.0 ] ] }
What I am trying to do now is something like this: when I mouse over a feature, I want to get two separate latlng objects from within the coordinates array. Using my code below:
map.data.addListener("mouseover", function(event) {
var coordinates = event.feature.getGeometry("coordinates");
console.log(coordinates);
});
Below is what is shown inside the console:
so the coordinates variable contains one 'i' property. 'i' is an array with two objects inside it.
Is it possible to get two separate latlng object from this array ?
I want to achieve this because I hope that later I can get the distance between these two latlng objects.
LineString has a .getArray() method which returns the array of LatLng objects:
map.data.addListener("mouseover", function(event) {
var coordinates = event.feature.getGeometry("coordinates").getArray();
for (var i=0; i<coordinates.length; i++) {
console.log(coordinates[i].toUrlValue(6));
}
});
proof of concept fiddle
Related
Salutations all and happy holidays.
I Noticed an interesting behavioral quirk while trying to draw polygon layers with L.geoJson(). consider the following code:
var polygonCoords = [
{"type": "Feature",
"properties": {"group": "Violations"},
"geometry": {
"type" : "Polygon",
"coordinates": [[
[-107.69348, 43.22519],
[-105.48523, 42.99259],
[-107.7594, 42.26105]
]]
}
}];
and
var polygons = L.polygon([
[43.22519, -107.69348],
[42.99259, -105.48523],
[42.26105, -107.7594]
]);
Now, both work in their respective contexts. I was just wondering why the coordinate matrix within L.polygon() has to be reflected in order to show up where one expects it to be when passed into L.goeJson() like so:
var jsonPoly = L.geoJson(polygonCoords, {
style: function(feature) {
if (feature.properties.group == "Violations") {
return {color: "#ff0000"};
}
}
});
Or is this an oversight within leaflet? Also, is there a way to automate this reflection with say toGeoJson(polygons)?
Thanks so much all.
When creating a geoJson layer the coordinates are expected to match the GeoJSON standard (x,y,z or lng, lat, altitude) (GeoJSON position specs)
If you have string of GeoJSON where your coordinates are not in this format, you can create your GeoJSON layer with a custom coordsToLatLng function that will handle this conversion to the standard's format (Leaflet Doc)
If you have a polygon layer and want to add it to an existing GeoJSON feature group you can do something like:
var polygons = L.polygon([
[43.22519, -107.69348],
[42.99259, -105.48523],
[42.26105, -107.7594]
]);
var gg = polygons.toGeoJSON();
var jsonFeatureGroup = L.geoJson().addTo(map);
jsonFeatureGroup.addData(gg);
map.fitBounds(jsonFeatureGroup.getBounds());
I'm having some troubles when it comes to using the draw control given by leaflet-geoman:
What I'm trying to achieve:
Draw Polygon(s) --> ✅
Get geojson from layer(s) --> ✅
Store in database --> ✅
Retrieve from database --> ✅
Load in leaflet map and be able to edit, crop it and remove it. --> ✅ ?
Get new geojson from modified layer(s) or if I had 2 layers and removed one, get only one. --> X
I haven't been able to get the new geojson from the modifications I did through the geoman draw control. No matter what I do, I always get the same result I had in the beginning when I loaded the data to the map.
Fiddle: https://jsfiddle.net/pjkLr41q/34/
const shapes = [{
"type": "Feature",
"properties": {},
"geometry": {
"type": "Polygon",
"coordinates": [
[
[-3.701856, 40.422481],
[-3.707092, 40.418593],
[-3.70177, 40.417809],
[-3.701899, 40.422873],
[-3.701856, 40.422481]
]
]
}
}];
const geojson = L.geoJSON(shapes).addTo(map);
map.eachLayer((layer) => {
if (layer.pm) {
const geojson = layer.toGeoJSON();
if (layer instanceof L.Circle) {
geojson.properties.radius = 10;
}
shapes.push(geojson);
}});
I ain't sure if its because the way I load the data, straight with the L.geoJSON(data) or maybe going through the eachLayer function isn't what I need in this case, but I'm kinda lost right now. Help really appreciated.
You can get all Geoman layers with: L.PM.Utils.findLayers(map).
In the next Version 2.7.0 there will be the functions map.pm.getGeomanLayers() and map.pm.getGeomanDrawLayers()
So you can get the new geojson with:
var layers = L.PM.Utils.findLayers(map);
var group = L.featureGroup();
layers.forEach((layer)=>{
group.addLayer(layer);
});
shapes = group.toGeoJSON();
I'm trying to figure out how to pass in coordinates to the L.LatLng function in leaflet so that it can map the coordinates.
I can successfully load in the data, and it looks like this:
//This is the structure of the geojson data, as an example
var SanFranciscoData = {"type":"FeatureCollection", "features": [
{"type":"Feature","geometry":{"type":"Point","coordinates":[-96.97593699999999,32.889954000000046]}
//Load in the geojson
d3.json("data/dataPoints.json", function(SFData) {
var SFData = SanFranciscoData.features
})
//pass in coordinates to the L.LatLng leaflet function
SFData.forEach(function(d) {
d.latLong = new L.LatLng(d.features.geometry.coordinates[1],
d.features.geometry.coordinates[0]);
})
I've also tried, as I've seen done in examples:
var coords = SFData.feature.geometry.coordinates;
Both methods above give the same result: the coordinates are undefined. What am I doing wrong? I'm not sure how to access the coordinates array using object notation in order to access the lat / longs.
Ok.. this worked:
SFData.forEach(function(d) {
var coords = d.geometry.coordinates
console.log(coords)
d.latLong = new L.LatLng(coords[1],
coords[0]);
})
Seems as if coordinates needed to be defined withing the .forEach function!
Is there any way I can specify/set the DOM Id of an OpenLayers Geometry Point object i.e. call it "myID" instead of "OpenLayers_Geometry_Point_nnn"?
As far as I can tell, in Openlayers 2.13, creating a OpenLayers.Geometry.Point object does not accept any form of DOM id attribute, and creates its own unique ID through `OpenLayers.Util.createUniqueID. The OpenLayers.Geometry.Point.initialize 'constructor' only accepts X and Y values, not additional info.
I'd really like to use Selenium to verify/manipulate certain objects are on a map, and having predictable DOM Ids seems the be best way to do this.
One "solution" I have implemented is to replace OpenLayers.Util.createUniqueID whilst I am creating the objects I wish to test.
// replace OpenLayer Dom ID generation for this layer
var olPrefix = "MyPrefix";
var olCount = 0;
var old = OpenLayers.Util.createUniqueID;
OpenLayers.Util.createUniqueID = function(prefix) {
if (prefix.search( '^OpenLayers.Geometry') >= 0) {
// special Dom IDs for Geometry nodes only...
olCount++;
return olPrefix + "_" + olCount;
}
// default to using the previous ID generator...
return( old( prefix));
}
var geoJSON = {
"type": "FeatureCollection",
"features": [
{
"type":"Feature",
"geometry": { "type":"Point","coordinates":[ 1.0, 52.0]},
"properties":{ "myProperty":"myValue" }
},
// more features here
]
};
var geoformat = new OpenLayers.Format.GeoJSON();
var features = geoformat.read( geoJSON);
// finished creating your features, so put the "old" ID routine back...
OpenLayers.Util.createUniqueID = old;
Another possibility is to replace OpenLayers.Geometry.initialize in some way
Given the following code for Mapbox, whereby I am plotting points and polylines between a number of points. User will choose a different selection and the results of that will replace the pins on the map. These pins will then be drawn together in the correct order using polylines.
$.post('_posts/get-pins.php', {traveller: $(this).val()}, function(data){
var featureLayer = L.mapbox.featureLayer().addTo(map);
var featureCollection = {
"type": "FeatureCollection",
"features": []
};
var lineArray = [];
$.each(data, function (k, item) {
featureCollection.features.push({
"type": "Feature",
"properties": {
"id": item.id,
"title": item.title,
"description": item.description,
"image": item.image,
"marker-symbol": "star",
"marker-color": "#ff8888",
"marker-size": "large"
},
"geometry": {
"type": "Point",
"coordinates": [
item.long,
item.lat
]
}
});
lineArray[item.id] = [item.lat, item.long];
});
featureLayer.setGeoJSON(featureCollection);
lineArray = lineArray.filter(function(){return true});
var polyline = L.polyline(lineArray).addTo(map);
},'json');
So I need to remove the polylines and the markers before plotting the new ones. I have tried numerous combinations of map.removeLayer(xxx) replacing xxx with many of the variables that are being created but all I have managed to do is remove the markers. It just leaves the polylines intact and just stacks the polyline layers.
Declare your variables for the featureLayer and polyline outside of the method/function you are using to update them:
var featureLayer, polyline;
In the function, check if the variable featureLayer already is an instance of FeatureLayer then clear it's layers, if it's not create the new layer:
if (featureLayer instanceof L.mapbox.FeatureLayer) {
featureLayer.clearLayers();
} else {
featureLayer = L.mapbox.featureLayer().addTo(map);
}
With the polyline you got to do it differently because it hasn't got a function to clear al the added points, just check if it's an instance of L.Polyline, if so remove it from the map using L.Map's removeLayer method and afterwards just define a new polyline:
if (polyline instanceof L.Polyline) {
map.removeLayer(polyline);
}
polyline = L.polyline([]).addTo(map);
Working example on Plunker: http://plnkr.co/edit/7nlgiA50NuPGsQOF0Fv4?p=preview