[OpenLayers-Dev] OpenLayers.Strategy.Cluster and attributive comparisons

Marc Jansen jansen at terrestris.de
Wed Oct 6 08:11:13 EDT 2010


Hi Eric,

thanks for your feedback.

Attached is an example that shows the usage and the benefits from the 
custom classes. I would be happy if this could be included in the 
OpenLayers examples.

Cheers,
Marc and Thorsten


On 04.10.2010 19:09, Eric Lemoine wrote:
> On Monday, October 4, 2010, Marc Jansen<jansen at terrestris.de>  wrote:
>    
>> Hi list,
>>
>> the Cluster strategy decides whether two features should be grouped in a cluster and uses the relative distance of the features to do so. Nearby features are clustered, and features apart from each other are left untouched.
>>
>> In a recent project we had the need to extend this behaviour, so that the Cluster strategy should look at the attributes of the features too, when deciding on clustering: only nearby features that shared an attribute should be clustered, otherwise, they should be left alone.
>>
>> Imagine a situation where you have features with an attribute "klasse" that groups the features attributively. In the clustered map you only want Clusters of the same "klasse".
>>
>> In our case we could solve it using different layers (requested according to their "klasse") and each had their own Cluster-strategy.
>>
>> While we were refactoring that code a little bit we came up with the idea of new Cluster-subtypes: the very simple OpenLayers.Strategy.AttributeCluster and the more elaborate OpenLayers.Strategy.RuleCluster:
>>
>> OpenLayers.Strategy.AttributeCluster = OpenLayers.Class(OpenLayers.Strategy.Cluster, {
>>      /**
>>       * the attribute to use for comparison
>>       */
>>      attribute: null,
>>
>>      /**
>>       * Method: shouldCluster
>>       * Determine whether to include a feature in a given cluster.
>>       *
>>       * Parameters:
>>       * cluster - {<OpenLayers.Feature.Vector>} A cluster.
>>       * feature - {<OpenLayers.Feature.Vector>} A feature.
>>       *
>>       * Returns:
>>       * {Boolean} The feature should be included in the cluster.
>>       */
>>      shouldCluster: function(cluster, feature) {
>>          var cc = cluster.geometry.getBounds().getCenterLonLat();
>>          var fc = feature.geometry.getBounds().getCenterLonLat();
>>          var distance = (
>>              Math.sqrt(
>>                  Math.pow((cc.lon - fc.lon), 2) + Math.pow((cc.lat - fc.lat), 2)
>>              ) / this.resolution
>>          );
>>          var cc_attrval = cluster.cluster[0].attributes[this.attribute];
>>          var fc_attrval = feature.attributes[this.attribute];
>>          return (distance<= this.distance&&  cc_attrval === fc_attrval);
>>      },
>>
>>      CLASS_NAME: "OpenLayers.Strategy.AttributeCluster"
>> });
>>
>>
>>
>> OpenLayers.Strategy.RuleCluster = OpenLayers.Class(OpenLayers.Strategy.Cluster, {
>>      /**
>>       * the rule to use for comparison
>>       */
>>      rule: null,
>>
>>      /**
>>       * Method: shouldCluster
>>       * Determine whether to include a feature in a given cluster.
>>       *
>>       * Parameters:
>>       * cluster - {<OpenLayers.Feature.Vector>} A cluster.
>>       * feature - {<OpenLayers.Feature.Vector>} A feature.
>>       *
>>       * Returns:
>>       * {Boolean} The feature should be included in the cluster.
>>       */
>>      shouldCluster: function(cluster, feature) {
>>          var cc = cluster.geometry.getBounds().getCenterLonLat();
>>          var fc = feature.geometry.getBounds().getCenterLonLat();
>>          var distance = (
>>              Math.sqrt(
>>                  Math.pow((cc.lon - fc.lon), 2) + Math.pow((cc.lat - fc.lat), 2)
>>              ) / this.resolution
>>          );
>>          return (distance<= this.distance&&  this.rule.evaluate(cluster.cluster[0])&&  this.rule.evaluate(feature));
>>      },
>>
>>      CLASS_NAME: "OpenLayers.Strategy.RuleCluster"
>> });
>>
>> Usage Examples:
>>
>>          // cluster only features that have 'klasse'<  3
>>          new OpenLayers.Layer.Vector('Vektorlayer 1', {
>>              strategies: [new OpenLayers.Strategy.Fixed(), new OpenLayers.Strategy.RuleCluster({
>>                  rule: new OpenLayers.Rule({
>>                      // a rule contains an optional filter
>>                      filter: new OpenLayers.Filter.Comparison({
>>                          type: OpenLayers.Filter.Comparison.LESS_THAN,
>>                          property: "klasse",
>>                          value: 3
>>                      })
>>                  })
>>              })],
>>              protocol: new OpenLayers.Protocol.HTTP({
>>                  url: "../data/data_001.json",
>>                  format: new OpenLayers.Format.GeoJSON()
>>              })
>>          });
>>
>>          // cluster only features that are nearby and have the same "klasse"
>>          new OpenLayers.Layer.Vector('Vektorlayer 2', {
>>              strategies: [new OpenLayers.Strategy.Fixed(), new OpenLayers.Strategy.AttributeCluster({
>>                  rule: new OpenLayers.Rule({
>>                      attribute: 'klasse'
>>                  })
>>              })],
>>              protocol: new OpenLayers.Protocol.HTTP({
>>                  url: "../data/data_002.json",
>>                  format: new OpenLayers.Format.GeoJSON()
>>              })
>>          });
>>
>>
>> We are unsure whether this might be of interest to anybody. If so, we would be happy to provide patches for OpenLayers. This code currently has no tests, and there is room for optimization (the comparison of attributes is probably faster computed than the distance e.g.)
>>
>> Please share your thoughts on this and tell us of alternatives we may have missed, or drawbacks of the outlined approach.
>>      
> Your approach looks good to me, and it demonstrates well how the
> cluster strategy can be extended for specific needs. To me it'd make
> sense to have this code in a cluster-strategy-extended.html example or
> something.
>
> My 2 cents,
>
>    

-------------- next part --------------
A non-text attachment was scrubbed...
Name: cluster-strategy-extended.js
Type: application/javascript
Size: 8714 bytes
Desc: not available
Url : http://lists.osgeo.org/pipermail/openlayers-dev/attachments/20101006/3e2ad61d/cluster-strategy-extended-0001.bin
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.osgeo.org/pipermail/openlayers-dev/attachments/20101006/3e2ad61d/cluster-strategy-extended-0001.html


More information about the Dev mailing list