Make ol.source.Cluster more flexible by adding a geometryFunction option

This commit is contained in:
Andreas Hocevar
2016-02-25 14:58:09 +01:00
parent fa180cfa13
commit 0407e779f9
3 changed files with 108 additions and 29 deletions

View File

@@ -14,7 +14,9 @@ goog.require('ol.source.Vector');
/**
* @classdesc
* Layer source to cluster vector data.
* Layer source to cluster vector data. Works out of the box with point
* geometries. For other geometry types, or if not all geometries should be
* considered for clustering, a custom `geometryFunction` can be defined.
*
* @constructor
* @param {olx.source.ClusterOptions} options Constructor options.
@@ -48,6 +50,17 @@ ol.source.Cluster = function(options) {
*/
this.features_ = [];
/**
* @param {ol.Feature} feature Feature.
* @return {ol.geom.Point} Cluster calculation point.
*/
this.geometryFunction_ = options.geometryFunction || function(feature) {
var geometry = feature.getGeometry();
goog.asserts.assert(geometry instanceof ol.geom.Point,
'feature geometry is a ol.geom.Point instance');
return geometry;
};
/**
* @type {ol.source.Vector}
* @private
@@ -117,25 +130,25 @@ ol.source.Cluster.prototype.cluster_ = function() {
for (var i = 0, ii = features.length; i < ii; i++) {
var feature = features[i];
if (!(goog.getUid(feature).toString() in clustered)) {
var geometry = feature.getGeometry();
goog.asserts.assert(geometry instanceof ol.geom.Point,
'feature geometry is a ol.geom.Point instance');
var coordinates = geometry.getCoordinates();
ol.extent.createOrUpdateFromCoordinate(coordinates, extent);
ol.extent.buffer(extent, mapDistance, extent);
var geometry = this.geometryFunction_(feature);
if (geometry) {
var coordinates = geometry.getCoordinates();
ol.extent.createOrUpdateFromCoordinate(coordinates, extent);
ol.extent.buffer(extent, mapDistance, extent);
var neighbors = this.source_.getFeaturesInExtent(extent);
goog.asserts.assert(neighbors.length >= 1, 'at least one neighbor found');
neighbors = neighbors.filter(function(neighbor) {
var uid = goog.getUid(neighbor).toString();
if (!(uid in clustered)) {
clustered[uid] = true;
return true;
} else {
return false;
}
});
this.features_.push(this.createCluster_(neighbors));
var neighbors = this.source_.getFeaturesInExtent(extent);
goog.asserts.assert(neighbors.length >= 1, 'at least one neighbor found');
neighbors = neighbors.filter(function(neighbor) {
var uid = goog.getUid(neighbor).toString();
if (!(uid in clustered)) {
clustered[uid] = true;
return true;
} else {
return false;
}
});
this.features_.push(this.createCluster_(neighbors));
}
}
}
goog.asserts.assert(
@@ -150,16 +163,16 @@ ol.source.Cluster.prototype.cluster_ = function() {
* @private
*/
ol.source.Cluster.prototype.createCluster_ = function(features) {
var length = features.length;
var centroid = [0, 0];
for (var i = 0; i < length; i++) {
var geometry = features[i].getGeometry();
goog.asserts.assert(geometry instanceof ol.geom.Point,
'feature geometry is a ol.geom.Point instance');
var coordinates = geometry.getCoordinates();
ol.coordinate.add(centroid, coordinates);
for (var i = features.length - 1; i >= 0; --i) {
var geometry = this.geometryFunction_(features[i]);
if (geometry) {
ol.coordinate.add(centroid, geometry.getCoordinates());
} else {
features.splice(i, 1);
}
}
ol.coordinate.scale(centroid, 1 / length);
ol.coordinate.scale(centroid, 1 / features.length);
var cluster = new ol.Feature(new ol.geom.Point(centroid));
cluster.set('features', features);