Reputation: 55
I am loading multiple points from a geojson file and want to delete duplicates which exist in the data (For some features the properties are equal despite the ID). To reach this goal I want to find out if ol.Feature
objects are equal to other ol.Feature
objects.
Is equality somehow defined on ol.Feature objects or do I have to define it by myself?
Upvotes: 4
Views: 2418
Reputation: 2485
I think it depends a lot on the perspective and use case to say when features are equal which is why it is left to the user to define equality. Some might say that features are equal if they share the (exact) same geometry (1). Others might say that features need to have the same properties (2) or even both (3).
To check properties equality I would recommend to define the attributes that matter for your definition of equality. Then you can use code similar to this to check if 2 ol.Feature
objects are equal:
// Define your important properties
var mySelectedProperties = ["importantProperty", "anotherImportantProperty", "propertyX"];
// Check for property equality between two ol.Feature objects
function areEqual(featureA, featureB){
var equal = true;
for(let property of mySelectedProperties){
if(featureA.get(property) != featureB.get(property)){
equal = false;
return equal ;
}
}
return equal;
}
For geometry equality you might want to check if the (x & y) coordinates are the same. Here some more considerations:
E.g.: lineA: pointA-pointB and lineB: pointB-pointA
or even this: polygonA: pointA-pointB-pointC-pointA and polygonB: pointB-pointC-pointA-pointB
Upvotes: 0
Reputation: 1647
You should loop through every feature and get its properties. The ID will always be different, and that's why it is not possible to use the method getFeatureById
(from the layer or the source) or the method getId
(from a single feature).
I have created a living example which is working and removing the duplicated features when you press the button.
Notice that we are getting the properties name and tag and we convert them into a JSON variable to compare them easily, but you can select the properties that fit your needs.
var features = [];
var point1 = ol.proj.transform([-50, 4.678], 'EPSG:4326', 'EPSG:3857');
var point2 = ol.proj.transform([20, 4.678], 'EPSG:4326', 'EPSG:3857');
var feature1 = new ol.Feature({
geometry: new ol.geom.Point(point1),
name: "First",
tag: "TAG"
});
var feature2 = new ol.Feature({
geometry: new ol.geom.Point(point2),
name: "Second",
tag: "TAG"
});
features.push(feature1);
features.push(feature2);
features.push(new ol.Feature({
geometry: new ol.geom.Point(point1),
name: "First",
tag: "TAG"
}));
var vectorSource = new ol.source.Vector({
features: features
});
var vectorLayer = new ol.layer.Vector({
source: vectorSource
});
var map = new ol.Map({
layers: [
new ol.layer.Tile({
source: new ol.source.OSM()
}),
vectorLayer
],
target: 'map',
view: new ol.View({
center: [0, 0],
zoom: 2
})
});
document.getElementById("btn").onclick = function(){
var totalProperties = [];
vectorSource.getFeatures().forEach(function(feature){
var propertiesThis = {},
p = feature.getProperties();
for (var i in p) {
if (i === 'name' || i === 'tag') {
propertiesThis[i] = p[i];
}
}
var jsonProperties = JSON.stringify(propertiesThis);
if (totalProperties.indexOf(jsonProperties) === -1) {
totalProperties.push(jsonProperties);
} else {
vectorSource.removeFeature(feature);
console.log(propertiesThis['name'] + " feature removed")
}
});
};
<link href="https://openlayers.org/en/v3.20.1/css/ol.css" rel="stylesheet"/>
<script src="https://openlayers.org/en/v3.20.1/build/ol.js"></script>
<div id="map" class="map" tabindex="0"></div>
<button id="btn">Remove duplicates</button>
Upvotes: 4
Reputation: 2829
Two ol.Feature
object with the exact same properties will not be equal one an other.
So yes, you need to clear the duplicates manually. You say that the ids are always unique, but the rest can sometime be the same. In that case, you could loop in your features. For each one, get a JSON string of all properties (with the exception of the id and geometry) and compare that a new collection of features.
Here's how you could do this (untested, but this could give you an idea):
var uniqueFeatures = [];
var feature;
var properties;
var json;
var jsons = [];
for (var i = 0, ii = features.length; i < ii; i++) {
feature = features[0];
// Stringify the properties of the feature
properties = feature.getProperties();
var props4json;
for (var key in properties) {
if (key !== 'id' && key !== 'geometry') {
props4json[key] = properties[key];
}
}
json = JSON.stringify(props4json);
// Check if the stringified properties exist...
// if not, we have a new unique feature.
if (jsons.indexOf(json) === -1) {
jsons.push(json);
uniqueFeatures(feature);
}
}
Upvotes: 0