Ol3 unique identifier for a feature - javascript

I am trying to create some custom maps. I am using ol3 because of the drag and drop feature. The idea is to be able to style each feature on the map.
I drag and drop .gpx and .json files exported from JOSM and create a unique overlay for each feature.
I can change the stroke color etc. with a style function on that overlay. That all works great until I do the next drop.
The dropped features seem to appear in some random order getting interspersed with the ones from the previous drop. I need to have some way to tell which features are new from that drop operation so I can style those without affecting the ones I have already styled.
Is there a unique identifier of some kind that I can get from the feature?
Is there a way that I can tag a feature so with a unique id?
I tried feature.getId() but that is undefined at the time that the drag and drop event fires.

You can define your feature(s) in a json format
var geoSource = new ol.source.GeoJSON({
/* #type {olx.source.GeoJSONOptions} */
"projection": "EPSG:3857" //us
, "object": {
"type": "FeatureCollection"
, "crs": { "type": "name", "properties": { "name": "EPSG:4326" } }//'EPSG:3857'//euro 'urn:ogc:def:crs:EPSG::4326'//'urn:ogc:def:crs:OGC:1.3:CRS84'
, "features": [
{
"type": "Feature", "id": "01"
, "geometry": { "type": "Point", "coordinates": [-80.0874386, 26.7816928] }
, "properties": { "myproperty": "West Palm Beach" }
}
, {
"type": "Feature", "id": "02"
, "geometry": { "type": "Point", "coordinates": [-82.0838700, 26.9262480] }
, "properties": { "myproperty": "Punta Gonda" }
}
]
}
});
Then you access the feature by
var ff = geoSource.getFeatureById('02');
alert(ff.getProperties()['myproperty']);
or
if you need to analyse all the features, you can
geoSource.getFeatures().forEach(function (ff) {
alert(ff.getProperties()['myproperty']);
})
Does it help? Good luck.

when creating a feature, you can pass an object with custom properties to the constructor. For example:
var myFeature = new ol.Feature({
geometry: ...,
labelPoint: ..,
name:...,
customProp1: ...,
customProp2: ...,
myCustomID: myRandomIDGenerator()
})

Related

Detecting line intersections between a line string and polygon using Turf.js

I am trying to write a section of JavaScript code that allows a user to analyse a route they have plotted on a map. After the user has finished plotting their route, I want to determine if the route they have plotted crosses over any areas of interest.
To do this I am using the lineIntersect method in Turf.js which should allow me to pass a LineString and MultiPolygon.
I have created a Turf.js MultiPolygon:
{
"type": "Feature",
"properties": {},
"geometry": {
"type": "MultiPolygon",
"coordinates": [
[
[
51.50836874890726,
-0.091989636996398
],
[
51.50797826040486,
-0.088994163337176
],
[
51.507701047593805,
-0.085230241948645
],
(the full object had too many characters to post here so I pasted the full output to CodePen)
and converted the user's route to a Turf.js LineString:
{
"type": "Feature",
"properties": {},
"geometry": {
"type": "LineString",
"coordinates": [
[
51.50350693825546,
-0.027165818854444357
],
[
51.50115610069437,
-0.041240038776924066
]
]
}
}
However when I pass these two objects to the lineIntersect method:
turf.lineIntersect(myLineString, myMultiPolygon);
I am getting the following error:
Uncaught Error: coordinates must contain numbers
com turf/turf/turf.min.js:1
There is an extra number 4 at line 8782 in the feature data.
(Line 8782)
[4
51.49960254940379,
-0.093191432240797
],
Once it is eliminated you can use it.
...
var feat1 = ... //that corrected code
var turf_pgon1 = turf.polygon(feat1.geometry.coordinates);
var line1 = {
"type": "Feature",
"properties": {},
"geometry": {
"type": "LineString",
"coordinates": [
[
51.50350693825546,
-0.027165818854444357
],
[
51.50115610069437,
-0.041240038776924066
]
]
}
}
// turf-intersection
var ans = turf.lineIntersect(line1, turf_pgon1);
To get the coordinates of the intersection points.
var xy1 = ans.features[0].geometry.coordinates; //[ 51.503118870662334, -0.02948913916413884 ]
var xy2 = ans.features[1].geometry.coordinates; //[ 51.50157899855393, -0.038708193285440035 ]

How to pass custom fields into mapbox-gl js to create points on map?

I've created a map using mapbox and plotted multiple custom points that you can interact with. I am also using Wordpress and want to use advanced custom fields to create each point so they can easily be managed from a non-technical person. The fields are all setup, but I am having trouble passing them into the javascript in my php template.
I've tried using a loop but I can't use the loop inside javascript. Here is my Mapbox code that I am using to plot the points and want to use advanced custom fields with:
var map = new mapboxgl.Map({
container: 'map',
style: 'mapbox://styles/coptmarketing/cjvi7hc4602dk1cpgqul6mz0b',
center: [-76.615573, 39.285685],
zoom: 16 // starting zoom
});
var geojson = {
"type": "FeatureCollection",
"features": [{
"type": "Feature",
"properties": {
"title": "Shake Shack",
"id": "shake-shack"
},
"geometry": {
"type": "Point",
"coordinates": [-76.609844, 39.286894]
}
},
{
"type": "Feature",
"properties": {
"title": "Starbucks",
"id": "starbucks"
},
"geometry": {
"type": "Point",
"coordinates": [-76.619071, 39.286649]
}
}
]
};
I've stored the data in a JSON array:
[{"title":"Shake Shack","slug":"shake-shack","latitude":"-76.609844","longitude":"39.286894"},{"title":"Starbucks","slug":"starbucks","latitude":"-76.619071","longitude":"39.286649"}]
How do I insert this into the geoJSON?
Figured it out:
First I created a plugin that stored the custom post data in a JSON array and stored it on the server. This also updated every time I updated, saved or deleted a post. Here is the example JSON:
data = {"placeList": [{"title":"Shake Shack","slug":"shake-shack","latitude":"-76.609844","longitude":"39.286894"},{"title":"Starbucks","slug":"starbucks","latitude":"-76.619071","longitude":"39.286649"}]}
Then in the php file, I called the .json file and in my javascript, inserted the array into the GeoJSON:
var placeJson = data;
var geojson = {
type: "FeatureCollection",
features: [],
};
for (i = 0; i < placeJson.placeList.length; i++) {
geojson.features.push({
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [placeJson.placeList[i].latitude, placeJson.placeList[i].longitude]
},
"properties": {
"id": placeJson.placeList[i].slug,
"title": placeJson.placeList[i].title
}
});
}

GUIDE4YOU - how to add a dynamic layer?

The guys from guide4you did a great job making this lib opensource!!
I've succeeded in having a working demo guide4you sample.
How adjustable is the lib?
For instance how can I add layers with GeoJSON instead of KML.
Can the layers be added dynamically (with own javascript) instead of predefined?
Take this as example: https://openlayers.org/en/latest/examples/geojson.html
To be more specific: how can that example work together with guide4you ?
Kind regards,
Sam
To use a GeoJSON layer in guide4you you can just specify the type "GeoJSON" in the layerconfig.
{
"id": "3",
"type": "GeoJSON",
"source": {
"url": "path/to/geojson"
}
}
See also https://github.com/KlausBenndorf/guide4you/blob/master/conf/full/layers.commented.json for some examples
If you like to add a layer on the fly with javascript you can use this api function:
map.get('api').addFeatureLayer({
"id": "3",
"type": "GeoJSON",
"source": {
"url": "path/to/geojson"
},
"visible": true
})
the possible options are the same as in the layer config.
If you like to add only new features you can create a layer with type "Intern" and add the features with openlayers functionalities. The source of a feature layer is a subclass of ol.source.Vector.
In the example below I am assuming that geojsonObject is of the same kind as in the geojson example of openlayers.
var layer = map.get('api').addFeatureLayer({
"id": "3",
"type": "Intern",
"source": {
"features": []
},
"visible": true
});
layer.getSource().addFeatures((new ol.format.GeoJSON()).readFeatures(geojsonObject));
And last but not least you can use a simplified api to define features inside a layerConfig object like this:
{
"id": "3",
"type": "Intern",
"source": {
"features": [{
"id": 6,
"name": "Some feature",
"description: "Some description",
"style": "#defaultStyle",
"geometryWKT": "... any wkt string here ..."
},{
"geometryWKT": "... any wkt string here ..."
}]
}
}
this can be used either in a layerConfig file or in the addFeatureLayer api method.

Mapbox GL js available icons

I am rewriting a web application from Mapbox.js to Mapbox GL js.
Using the standard 'mapbox://styles/mapbox/streets-v8' style, where can I find a list of all working marker icons?
Here is my code:
m.map.addSource("markers", {
"type": "geojson",
"data": {
"type": "FeatureCollection",
"features": {
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": ["-75.532965", "35.248018"]
},
"properties": {
"title": "Start",
"marker-symbol": "entrance",
"marker-size": "small",
"marker-color": "#D90008"
}
}
}
});
m.map.addLayer({
"id": "markers",
"type": "symbol",
"source": "markers",
"layout": {
"icon-image": "{marker-symbol}-15", //but monument-15 works
"text-field": "{title}",
"text-font": ["Open Sans Semibold", "Arial Unicode MS Bold"],
"text-offset": [0, -1.6],
"text-anchor": "top"
}
});
I read that all Maki icons should be made available for styles that don't have icons as a default:
https://github.com/mapbox/mapbox-gl-styles/issues/241
But most of them don't work.
Also there is the problem with the sizes - for Maki they were -small, -medium and -large, and now I see -11 and -15.
I just need to use some basic marker icons.
We're still sorting out the final implementation details for the default icon set and will document that set thoroughly once it has been decided upon.
Until then, you can see exactly what icons are available for a given style by peeking at the mapbox-gl-styles repo in the sprites folder.
Since that issue was closed, all maki icons are now natively available in mapbox-gl.js. You can see all available at https://www.mapbox.com/maki-icons/. You can also multiply their size using the icon-size paint property, though this may result in pixelation. There are still some hitches, like the icon-color property not yet working, so you'll need to edit, recolor, and republish icons for now. (issue #3605).

TimeSlider Plugin and Leaflet - Markers not appearing in order

Updated with a JSFIDDLE link
I am using LeafletJS to build a web map with a timeline slider. I am using the LeafletSlider plugin to show a group of markers based on a GEOJSON property named DATE_START. Here's an example of what my data object looks like:
var camps = {
"type": "FeatureCollection",
"features": [{
"type": "Feature",
"properties": {
"STATUS": "UNOCCUPIED",
"DATE_START": "2015-06-23",
"DATE_CLOSED": "2016-01-23"
},
"geometry": {
"type": "Point",
"coordinates": [64.6875, 34.97600151317591]
}
}, {
"type": "Feature",
"properties": {
"STATUS": "OCCUPIED",
"DATE_START": "2014-01-21",
"DATE_CLOSED": "2015-05-25"
},
"geometry": {
"type": "Point",
"coordinates": [65.335693359375, 36.26199220445664]
}
}, {
"type": "Feature",
"properties": {
"STATUS": "UNOCCUPIED",
"DATE_START": "2015-09-13",
"DATE_CLOSED": ""
},
"geometry": {
"type": "Point",
"coordinates": [67.587890625, 35.969115075774845]
}
}]
};
An example of my code:
//Create a marker layer (in the example done via a GeoJSON FeatureCollection)
var testlayer = L.geoJson(camps, {
onEachFeature: function(feature, layer) {
layer.bindPopup(feature.properties.DATE_START);
}
});
var sliderControl = L.control.sliderControl({
position: "topright",
layer: testlayer,
timeAttribute: 'DATE_START'
});
//Make sure to add the slider to the map ;-)
map.addControl(sliderControl);
//And initialize the slider
sliderControl.startSlider();
I've added the timeslider plugin to my map, and although it's functioning, I can't seem to get the slider to show the markers in a temporal order. For example, the marker with the DATE_START value of 2014-01-21 is shown second when in fact it should be shown first because it's the marker with the earliest date.
How can I get my timeslider/markers to appear in the correct order from earliest to latest? Thanks.
EDIT:
As ghybs mentions below (and shows in an example), the proper way to ensure that the slider returns data in the correct order is to sort the options.markers array of the sliderControl:
sliderControl.options.markers.sort(function(a, b) {
return (a.feature.properties.DATE_START > b.feature.properties.DATE_START);
});
My original answer (below) sorts the features of the GeoJSON, but this does not guarantee that Leaflet will return them in the correct order.
Original answer:
You can use the array.sort method to sort the features array in place:
camps.features.sort(function(a, b) {
return (a.properties.DATE_START > b.properties.DATE_START);
});
http://jsfiddle.net/nathansnider/ngeLm8c0/4/

Categories