diff options
Diffstat (limited to 'misc/openlayers/examples/strategy-cluster-extended.js')
-rw-r--r-- | misc/openlayers/examples/strategy-cluster-extended.js | 247 |
1 files changed, 247 insertions, 0 deletions
diff --git a/misc/openlayers/examples/strategy-cluster-extended.js b/misc/openlayers/examples/strategy-cluster-extended.js new file mode 100644 index 0000000..163cbf4 --- /dev/null +++ b/misc/openlayers/examples/strategy-cluster-extended.js @@ -0,0 +1,247 @@ +/** + * Class: OpenLayers.Strategy.AttributeCluster + * Strategy for vector feature clustering based on feature attributes. + * + * Inherits from: + * - <OpenLayers.Strategy.Cluster> + */ +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_attrval = cluster.cluster[0].attributes[this.attribute]; + var fc_attrval = feature.attributes[this.attribute]; + var superProto = OpenLayers.Strategy.Cluster.prototype; + return cc_attrval === fc_attrval && + superProto.shouldCluster.apply(this, arguments); + }, + CLASS_NAME: "OpenLayers.Strategy.AttributeCluster" +}); + +/** + * Class: OpenLayers.Strategy.RuleCluster + * Strategy for vector feature clustering according to a given rule. + * + * Inherits from: + * - <OpenLayers.Strategy.Cluster> + */ +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 superProto = OpenLayers.Strategy.Cluster.prototype; + return this.rule.evaluate(cluster.cluster[0]) && + this.rule.evaluate(feature) && + superProto.shouldCluster.apply(this, arguments); + }, + CLASS_NAME: "OpenLayers.Strategy.RuleCluster" +}); + + +// global variables +var map, vectorlayer, features, stylemap, select; + +// wrap the instanciation code in an anonymous function that gets executed +// immeadeately +(function(){ + + // The function that gets called on feature selection: shows information + // about the feature/cluser in a div on the page + var showInformation = function(evt){ + var feature = evt.feature; + var info = 'Last hovered feature:<br>'; + if (feature.cluster) { + info += ' Cluster of ' + feature.attributes.count + ' features:'; + var clazzes = { + '1': 0, + '2': 0, + '3': 0, + '4': 0 + }; + for (var i = 0; i < feature.attributes.count; i++) { + var feat = feature.cluster[i]; + clazzes[feat.attributes.clazz]++; + } + for (var j=1; j<=4; j++) { + var plural_s = (clazzes[j] !== 1) ? 's' : ''; + info += '<br> • clazz ' + j + ': ' + clazzes[j] + ' feature' + plural_s; + } + } else { + info += ' Single feature of clazz = ' + feature.attributes.clazz; + } + document.getElementById('info').innerHTML = info; + }; + + // The function that gets called on feature selection. Shows information + // about the number of "points" on the map. + var updateGeneralInformation = function() { + var info = 'Currently ' + vectorlayer.features.length + ' points are shown on the map.'; + document.getElementById('generalinfo').innerHTML = info; + }; + + // instanciate the map + map = new OpenLayers.Map("map"); + + // background WMS + var ol_wms = new OpenLayers.Layer.WMS("OpenLayers WMS", "http://vmap0.tiles.osgeo.org/wms/vmap0", { + layers: "basic" + }); + + // context to style the vectorlayer + var context = { + getColor: function(feature){ + var color = '#aaaaaa'; + if (feature.attributes.clazz && feature.attributes.clazz === 4) { + color = '#ee0000'; + } else if(feature.cluster) { + var onlyFour = true; + for (var i = 0; i < feature.cluster.length; i++) { + if (onlyFour && feature.cluster[i].attributes.clazz !== 4) { + onlyFour = false; + } + } + if (onlyFour === true) { + color = '#ee0000'; + } + } + return color; + } + }; + + // style the vectorlayer + stylemap = new OpenLayers.StyleMap({ + 'default': new OpenLayers.Style({ + pointRadius: 5, + fillColor: "${getColor}", + fillOpacity: 0.7, + strokeColor: "#666666", + strokeWidth: 1, + strokeOpacity: 1, + graphicZIndex: 1 + }, { + context: context + }), + 'select' : new OpenLayers.Style({ + pointRadius: 5, + fillColor: "#ffff00", + fillOpacity: 1, + strokeColor: "#666666", + strokeWidth: 1, + strokeOpacity: 1, + graphicZIndex: 2 + }) + }); + + // the vectorlayer + vectorlayer = new OpenLayers.Layer.Vector('Vectorlayer', {styleMap: stylemap, strategies: []}); + + // the select control + select = new OpenLayers.Control.SelectFeature( + vectorlayer, {hover: true} + ); + map.addControl(select); + select.activate(); + vectorlayer.events.on({"featureselected": showInformation}); + + map.addLayers([ol_wms, vectorlayer]); + map.addControl(new OpenLayers.Control.LayerSwitcher()); + map.zoomToMaxExtent(); + + features = []; + // adding lots of features: + for (var i = 0; i < 700; i++) { + var r1 = Math.random(); + var r2 = Math.random(); + var r3 = Math.random(); + var r4 = Math.random(); + var px = r1 * 180 * ((r2 < 0.5) ? -1 : 1); + var py = r3 * 90 * ((r4 < 0.5) ? -1 : 1); + var p = new OpenLayers.Geometry.Point(px, py); + var clazz = (i % 10 === 0) ? 4 : Math.ceil(r4 * 3); + var f = new OpenLayers.Feature.Vector(p, {clazz: clazz}); + features.push(f); + } + vectorlayer.addFeatures(features); + updateGeneralInformation(); + + // the behaviour and methods for the radioboxes + var changeStrategy = function() { + var strategies = []; + // this is the checkbox + switch(this.value) { + case 'cluster': + // standard clustering + strategies.push(new OpenLayers.Strategy.Cluster()); + break; + case 'attribute-cluster': + // use the custom class: only cluster features of the same clazz + strategies.push(new OpenLayers.Strategy.AttributeCluster({ + attribute:'clazz' + })); + break; + case 'rule-cluster': + // use the custom class: only cluster features that have a + // clazz smaller than 4 + strategies.push(new OpenLayers.Strategy.RuleCluster({ + rule: new OpenLayers.Rule({ + filter: new OpenLayers.Filter.Comparison({ + type: OpenLayers.Filter.Comparison.LESS_THAN, + property: "clazz", + value: 4 + }) + }) + })); + break; + } + // remove layer and control + map.removeLayer(vectorlayer); + map.removeControl(select); + // rebuild layer + vectorlayer = new OpenLayers.Layer.Vector('Vectorlayer', {styleMap: stylemap, strategies: strategies}); + map.addLayer( vectorlayer ); + vectorlayer.addFeatures(features); + // rebuild select control + select = new OpenLayers.Control.SelectFeature( + vectorlayer, {hover: true} + ); + map.addControl(select); + select.activate(); + vectorlayer.events.on({"featureselected": showInformation}); + // update meta information + updateGeneralInformation(); + }; + // bind the behviour to the radios + var inputs = document.getElementsByTagName('input'); + for( var cnt = 0; cnt < inputs.length; cnt++) { + var input = inputs[cnt]; + if (input.name === 'strategy') { + input.onclick = changeStrategy; + } + } +})(); |