Cluster de OpenLayers multicapa y dinámico

Antes que nada para explicar qué es un Cluster de OpenLayers será más fácil comprenderlo con una imagen.

Como se puede apreciar en la primera imagen se pueden ver muchas marcas azules en el mapa, mientras que en la segunda con un zoom menor se aprecian menos, esto es porque todas las marcas que se ven en la primera se van agrupando para mejor visibilidad y nulo solapamiento, de forma que conforme se haga zoom irán apareciendo cada una de ellas.

¿Qué funcionalidad extra hemos añadido?

Problema con la versión de OpenLayers: El cluster de OpenLayers no funciona para marcas que estén en distintas capas, además no permite ni añadir ni eliminar elementos al conjunto de marcas que se muestran en el mapa ya que sólo actúa con un array inicial de marcas sin poder ser modificado.

Solución multicapa dinámica: Hacer que la estrategia de OpenLayers sea multicapa, es decir, que actúe sobre un array de capas, en vez de una única capa, y además hacer que sea dinámico, es decir, que podamos añadir y eliminar elementos a esas capas sin perder el resto de features del cluster.

¿Cómo funciona un Cluster de OpenLayers?

El cluster básicamente es una capa que contiene un array de features, en las que cada una de esas features a su vez contiene un array cluster en el que se localizan cada una de las features que se van a agrupar.

Para solucionar el problema de añadir/eliminar features del cluster y que actúe sobre cualquier capa, lo que hacemos es, cuando añadimos una marca a una capa, capturamos el evento “beforefeaturesadded” de OpenLayers y hacemos que sea cual sea la capa, dicha feature se añada al array de features del cluster, así como a la capa propia del cluster, evitando así que dicha feature se añada a su capa y haciendo que todas las marcas independientemente de la capa de la que provengan se añadan a la misma. Al igual hacemos a la hora de eliminar una marca con el evento “befoefeaturesremoved”.

Para ello nos definimos dos funciones en el ‘activate’ del cluster:

activate: function(evt){

   evt.layer.events.on({

“beforefeaturesadded”: this.cacheFeatures,

           “beforefeaturesremoved”: this.cacheRemoveFeatures,

           “moveend”: this.cluster,

           scope: this

    });

},

La primera función básicamente lo que hace es añadir una feature al array de features del cluster, así como a la capa del mismo. Posteriormente se llama al método que es capaz de agrupar cada una de las features en otras features para que se vea el efecto anterior mencionado, este método se llama ‘cluster’.

cacheFeatures: function(evt) {

  var propagate = true;

      if(evt.features[0].geometry instanceof OpenLayers.Geometry.Point){

if(!this.clustering) {

               if(this.features == null){

this.features = [];

               }

               for(var i=0; i<evt.features.length; i++){

                this.features.push(evt.features[i]);

               }

               this.layer.addFeatures(evt.features);

               this.cluster();

               propagate = false;

           }

    }

       return propagate;

   },

La segunda función es simétrica a la anterior, pero eliminando las features en vez de añadirlas.

cacheRemoveFeatures: function(evt){

    var propagate = true;

       if(!this.clustering) {

           if(this.features != null){

            for(var i=0; i<evt.features.length; i++){

            OpenLayers.Util.removeItem(this.features, evt.features[i]);

               }

               this.layer.removeFeatures(evt.features);

               this.cluster();

               propagate = false;

           }

       }

       return propagate;

   },

La función cluster es la original de OpenLayers pero con un pequeño cambio:

cluster: function(evt) {

       if((!evt || evt.zoomChanged || (evt && evt.recluster)) && this.features) {

           var resolution = this.layer.map.getResolution();

           if(resolution != this.resolution || !this.clustersExist() || (evt && evt.recluster)) {

               this.resolution = resolution;

},

Este cambio tiene que realizarse ya que queremos que cuando añadamos/eliminemos una feature de la capa, activemos el reagrupamiento de las features en los cluster.

Además hay que crear otro método para que cuando se cree una capa de features a las que le queramos aplicar el cluster, se recorran todas sus features y se añadan a la capa del cluster.

addLayerToCluster: function(layer){

    if(OpenLayers.Util.indexOf(this.layers, layer) == -1){

    // Register the events

    layer.events.on({

               “added”: this.activate,

               “removed”: this.removeAllFromCluster,

               scope: this

           });

    this.layers.push(layer);

    }

   },

¿Cómo se usa?

Lo primero nos definimos una MultiLayerCluster Strategy de OpenLayers (nombre que le hemos puesto a la extensión del Cluster propio de OpenLayers), poniéndole una distancia para agrupar las features que estén a menos de dicha distancia:

strategy = new OpenLayers.Strategy.MultiLayerCluster({

distance: 15

});

Tras ésto nos definiremos una capa a la que le aplicaremos nuestro cluster y un estilo.

var clusterLayer = new OpenLayers.Layer.Vector(“Layer Name”, {

styleMap = new OpenLayers.StyleMap({

‘default’: style

}),

strategies: [strategy]

});

Ya por último añadimos la capa al mapa con


map.addLayer(clusterLayer);


A la hora de crear una capa a la que le vayamos a aplicar el cluster, tendremos que ejecutar de la clase ‘MultiLayerCluster’ el método addLayerToCluster.


strategy.addLayerToCluster(layer);


Además cada vez que añadamos o eliminemos una feature de la capa tendremos que ejecutar el método recluster de la MultiLayerCluster, para que así se vuelvan a reagrupar todas las features, incluida la última añadida.


strategy.recluster();

Anuncios

2 comentarios en “Cluster de OpenLayers multicapa y dinámico

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s