Plot Centroid of Feature Layer Polygon - javascript

Here is the rest service I'm working from:
http://sampleserver6.arcgisonline.com/arcgis/rest/services/Census/MapServer/3
My current call for displaying the feature layer is as follows:
var recLayer = new FeatureLayer("http://sampleserver6.arcgisonline.com/arcgis/rest/services/Census/MapServer/3",{
infoTemplate: recParkTemplate,
outFields: ["STATE_NAME"]
});
map.addLayer(recLayer);
However, instead of plotting the polygon on the map as this is an esriGeometricPolygon. I would rather have it plot on the map like a esriGeometryPoint. I know this method in getting the specific polygon's centroid:
https://developers.arcgis.com/javascript/jsapi/polygon-amd.html#getcentroid
My problem is I can't figure out how to cycle among all polygons in the feature layer and then plot those polygons. I can only point and click and display similar to how this ESRI sample works: https://developers.arcgis.com/javascript/jssamples/util_label_point.html
Thank you for your assistance.
Here is the current site if you would like to take a look at it: http://joshferrell.net/ece_project/

to cycle among all geometries in your feature layer you can do something like this:
recLayer.on("update-end", function changeHandler(evt) {
require(["dojo/_base/array"], function (array) {
array.forEach(recLayer.graphics, function (entry, i) {
console.debug(entry, "at index", i);
});
});
});
inside the loop use the getCentroid and add the result to the map

Related

Drawing boundaries on a map with LeafletJS

I'm starting to play with code that can generate maps. I am now looking at OSM (OpenStreetMaps) as a great solution. Also LeafletJS makes it very easy to draw maps based on OSM. So far so good.
I would like to be able to draw an outline (boundary) of a county and am trying to understand how this process will look like. Do I first make a call to find coords and then pass them into Leaflet or is there a better way?
I can get boundaries using Nominatim API, but calling like this:
https://nominatim.openstreetmap.org/ui/search.html?state=tx&county=Lee
And I can draw area in Leaflet like this:
var polygon = L.polygon([
[51.509, -0.08],
[51.503, -0.06],
[51.51, -0.047]
]).addTo(mymap);
So, am I overthinking or this is how it works?
You can create a single function to get the county geometry and add it to map. Try the following code:
function drawCountyBoundary(county, state)
{
url = `https://nominatim.openstreetmap.org/search.php?county=${county}&state=${state}&polygon_geojson=1&format=jsonv2`
fetch(url).then(function(response) {
return response.json();
})
.then(function(json) {
geojsonFeature = json[0].geojson;
L.geoJSON(geojsonFeature).addTo(map);
});
}
drawCountyBoundary('Lee', 'Tx')

Leaflet: how to swap coordinates received from an ajax call

I am using Leaflet 1.0.3 and a few plugins including Leaflet.ajax. My L.geo.ajax call is working and returning geojson objects, however, the coordinates are reversed. I created a function to fix this:
var convertLatLng = function (latlng) {
var temp = latlng[y];
latlng[y] = latlng[x];
latlng[x] = temp;
convertedLatLng = latlng;
return convertedLatLng;
console.log('this function is running')
}
But my problem is I don't know where to put it. Do I run it inside my geoJson call? If so, where? Here is a snippet of the ajax call:
var geojson = L.geoJson.ajax('http://www.iotwf.com/deployment_map/json', {
pointToLayer: function (feature, latlng) {
convertLatLng(latlng);
...
},
onEachFeature: function(feature, layer) {
...
}
});
I am also open to other suggestions for what may fix it.
Welcome to SO!
First make sure that your coordinates are indeed reversed.
Note that the GeoJSON format expects [longitude, latitude], whereas Leaflet usually expects [latitude, longitude], EXCEPT in the case of L.geoJSON() factory (and the plugin L.geoJson.ajax()), where it automatically reads the GeoJSON order and builds the layers at the correct coordinates.
If your coordinates are still reversed, the appropriate correction would be obviously to correct the order in your data source directly (or whatever service outputs your data), so that you get actually compliant GeoJSON data. That would solve many future headaches.
If that is not possible, then indeed you could try a workaround within your script.
The most appropriate way to do so would probably be to use the coordsToLatLng option of the L.geoJSON factory.
Changing its default implementation, you would get something like:
L.geoJson.ajax(url, {
coordsToLatLng: function (coords) {
// latitude , longitude, altitude
//return new L.LatLng(coords[1], coords[0], coords[2]); //Normal behavior
return new L.LatLng(coords[0], coords[1], coords[2]);
}
});

How to modify or remove some existing data in GeoJSON Leaflet object?

Recently I asked about referencing the data of an existing GeoJSON Leaflet object. My Leaflet map consists of data coming in a stream to my GeoJSON Leaflet object. User inputs can change a filter for the GeoJSON data, so to make the filter apply to both the existing and new data I am keeping track of my data in an array called myFeatures. Whenever the filters change or an item in myFeatures changes, I do the following:
myGeoJson.clearLayers();
myGeoJson.addData(myFeatures);
This is working to make my map update according to the newly updated feature data or the changes in the filter.
I am applying pop-ups to the GeoJSON object when I initialize my GeoJSON object:
var myGeoJson = L.geoJson(myFeatures, {
style: function(feature) {
...
},
pointToLayer: function(feature, latlng) {
return L.circleMarker(latlng, geojsonMarkerOptions);
},
filter: function(feature, layer) {
...
},
onEachFeature: function(feature, layer) {
if (feature.properties && feature.properties.popupContent) {
layer.bindPopup(feature.properties.popupContent);
}
}
});
When I click on an individual feature, the pop-up appears. However, the pop-up dismisses pretty quickly, thanks to clearLayers and addData being called. :(
Is there some kind of way to stop the pop-up dismissing in this situation?
Or - better question - is there a way to modifying existing data in a GeoJSON object or remove some (not all) data from a GeoJSON object?
To provide some context, my GeoJSON shows circle markers for each feature. The circle markers are colored based on a property of the feature. The property can actually change over time, so the marker's styling needs to be updated. A marker also times out after a while and needs to be removed from the map, but the other markers need to stay on the map.
There are for sure better ways to do that, but if you don't want to modify your code architecture too much, you could just create your popups in a specific layer, which you won't clear when you add your new data.
To give you an idea (markers play below the role of myGeoJson in your example):
var popup_id = {};
var popup_layer = new L.layerGroup();
var markers = new L.layerGroup();
$.each(testData, function(index, p) {
var marker = L.marker(L.latLng(p.lat, p.lon));
markers.addLayer(marker);
popup = new L.popup({offset: new L.Point(0, -30)});
popup.setLatLng(L.latLng(p.lat, p.lon));
popup.setContent(p.text);
popup_id[p.id] = popup;
marker.on('click', function() {
popup_id[p.id].openPopup();
popup_layer.addLayer(popup_id[p.id]);
markers.clearLayers();
})
});
popup_layer.addTo(map);
markers.addTo(map);
You also keep track of all your popups in a dictionary popup_id.
Since you haven't provided us with a JSfiddle it is a bit difficult to find the perfect answer for your case, but I hope that the popup layer (also here in my fiddle) gives you a good direction.

How to make Mapbox maps (with directions.js) read only? - (and prevent users from moving markers)

My maps with walking directions in Mapbox are not read only. Users can move the markers' original locations.
I referred to layer options
https://github.com/mapbox/mapbox-directions.js/blob/mb-pages/API.md#layer-options
And added:
var Layer = L.LayerGroup.extend({
options: {
readonly: true
}
});
The map remains interactive and users can move markers around.
Any suggestions?
Fiddle: https://jsfiddle.net/q9grgbt0/
You're adding the options to something called Layer, but you never use Layer. You should be adding it to directionsLayer instead. It should look something like this:
var directionsLayer = L.mapbox.directions.layer(directions, {readonly: true}).addTo(map);
I've updated your fiddle with this code fix. I also cleaned up some of the code and got rid of the unnecessary variable Layer.

How Can I animate Bing map pushpins based on a live GPS feed

I have looked over the bing maps documentation trying to find an answer to my question. I would prefer to do everything using the bing maps api and not have to add a third party library if possible.
Question: How can I animate a pushpin to make a smooth transition from one set of gps coordinate(longitude/latitude) to another in order to simulate smooth movement of a Pushpin on Bing maps?
Question: can deleting an entire object out of the map.entities array waste enough resources to cause performance issues? If so how can I change the pushpin latitude and longitude properties without deleting the entire object?
Sample code of trying to change the pushpins properties without deleting the object out of the array. This code does not work… I am unsure why it is not working?
map.entities.get(theIndexOfThePushPin)._location.latitude = newLat;
map.entities.get(theIndexOfThePushPin)._location.longitude = newLon;
I create a pushpin like so - This works fine
map.entities.push(new Microsoft.Maps.Pushpin(new Microsoft.Maps.Location(lat, lon), {
text: text,
visible: true,
textOffset: new Microsoft.Maps.Point(0, 5)
}));
Pseudo code for my recursive angular $http call
function BusMoveGPSRefresh() {
$http.get(resourceURL)
.then(function (data) {
if ('if pushpins have not been created') {
//create pushpins...
}
} else {
//delete pushpins out of the array and then recreate them
//with updated lon/lat. Or just update existing objects lon/lat properties if possible?
}
}
BusMoveGPSRefresh();//after everything is done then go get more info and start again. recursion...
}, function (reason) {// if fail than do
console.log(reason);
console.log("This Is not Working!!! Dang!!");
});
}
Any insight into the problem would be greatly appreciated! Thanks!
I could not find a simple answer for adding animation. I did find a site that gave a step by step tutorial on a more in-depth answer on how to animate pushpins.
Answer: 1 -- tutorial on how to animate bing map pushpins
https://blogs.bing.com/maps/2014/08/07/bring-your-maps-to-life-creating-animations-with-bing-maps-javascript/
Answer: 2 -- this is how to update the pushpin location without deleting the pushpin object out of the entities array.
Instead of deleting the entire pushpin object find the pushpin index and then use the property "setLocation()" and then add a new location.
//check to make sure that the lat and lon have
//changed if it is still the same location do nothing. else update
if (map.entities.get(indexOfPushpin).getLocation().latitude != lat
|| map.entities.get(indexOfPushpin).getLocation().longitude != lon) {
map.entities.get(indexOfPushpin).setLocation(new Microsoft.Maps.Location(lat, lon));
}

Categories