Filtros - sigcorporativo-ja/Mapea4 GitHub Wiki

Con Mapea se pueden establecer filtros que permiten comprobar si los elementos (features) cumplen o no con determinadas condiciones. Los filtros pueden aplicarse de dos formas diferentes:

Lo más común es aplicarlos sobre capas vectoriales del mapa, de modo que apliquen a los features de la misma. Estos filtros se ejecutan en memoria, es decir, estando la capa cargada ya con todos sus features en el cliente, establecer un filtro no supone realizar ninguna nueva petición al servidor.

Hay que tener en cuenta que una vez se aplica un filtro a una capa, este es efectivo hasta que el mismo se elimine o se modifique, por lo que a todos los efectos, es como si la capa tuviese únicamente aquellos features que cumplen el filtro: dibujado en el mapa, recorrido por sus features, etc.

La segunda forma de usar un filtro es ejecutándolo sobre un array de features. Eso nos devolverá una lista únicamente con los features que cumplen el filtro. Más adelante se mostrarán ejemplos de ambos casos.

Los filtros actualmente implementados son:

Filtros alfanuméricos

Filtro Descripción
M.filter.AND Condición Y
M.filter.OR Condición O
M.filter.NOT Condición NO
M.filter.EQUAL Condición IGUAL
M.filter.LIKE Condición de PATRÓN
M.filter.LT Condición MENOR QUE
M.filter.GT Condición MAYOR QUE
M.filter.LTE Condición MENOR O IGUAL QUE
M.filter.GTE Condición MAYOR O IGUAL QUE

Mediante los filtros M.filter.AND y M.filter.OR podemos encadenar tantos filtros como queramos

let mapajs = M.map({
   container: "map",
   wmcfile: "mapa",
   controls: ["layerswitcher"]
 });

let lyProvincias = new M.layer.WFS({
   url: "http://geostematicos-sigc.juntadeandalucia.es/geoserver/tematicos/ows?",
   namespace: "tematicos",
   name: "Provincias",
   legend: "Provincias",
   geometry: 'MPOLYGON'
 });

mapajs.addLayers(lyProvincias);

lyProvincias.on(M.evt.LOAD, () => {

   //Filtro por atributo nombre
   let filter = M.filter.OR(
                     [M.filter.EQUAL("nombre", "Sevilla"),
                      M.filter.EQUAL("nombre", "Málaga")]);

   // Si quiero aplicar el filtro a la capa sobre el mapa:
   lyProvincias.setFilter(filter); 

   // Si solo quiero obtener los features que cumplen el filtro,
   // Sin afectar a la capa:
   let featuresFiltrados = filter.execute(layer.getFeatures());

   //lyProvincias.removeFilter(); eliminar el filtro

});

Filtros espaciales

Filtro Descripción
M.filter.spatial.CONTAIN Comprueba que el un elemento A esté dentro de otro B
M.filter.spatial.DISJOINT Comprueba que los elementos A y B no tengan ningún punto en común
M.filter.spatial.WITHIN Comprueba que el elemento B esté dentro de A
M.filter.spatial.INTERSECT Comprueba si los elementos A y B tienen puntos en común

Los filtros espaciales aceptan paŕametros en forma de Feature, o en forma de geometría GeoJSON.

:bulb: Para los filtros espaciales, se ha implementado la librería jsts. Esto permite acceder a ella y realizar multitud de operaciones espaciales adicionales. Ejemplo funcional

let mapajs = M.map({
  container: "map",
  wmcfile: "mapa",
  controls: ["layerswitcher"]
});

var lyProvincias = new M.layer.WFS({
  url: "http://geostematicos-sigc.juntadeandalucia.es/geoserver/tematicos/ows?",
  namespace: "tematicos",
  name: "Provincias",
  legend: "Provincias",
  geometry: 'MPOLYGON'
});

mapajs.addLayers(lyProvincias);
lyProvincias.on(M.evt.LOAD, () => {

  // Si queremos usar un feature
  let miFeature = new M.Feature("featurePrueba002", {
    "type": "Feature",
    "id": "prueba_pol_wfst.1985",
    "geometry": {
      "type": "Polygon",
      "coordinates": [
        [
          [263770.72265536943, 4085361.4590256726],
          [230910.00600234355, 4031901.3328427672],
          [288293.77947248437, 4017678.0840030923],
          [263770.72265536943, 4085361.4590256726]
        ]
      ]
    },
    "properties": {
      "nombre": "feature2"
    }
  });
  
  // Si queremos una geometría:
  let miGeometria = {
    'type': 'Polygon',
    'coordinates': [
      [
        [251853, 4200334],
        [326894, 4200334],
        [326894, 4129217],
        [251853, 4129217],
        [251853, 4200334]
      ]
    ]
  };

  //Filtro los features de la capa que intersecten con miFeature
  let filter = M.filter.spatial.INTERSECT(miFeature);
  // Si queremos usar GeoJSON
  //let filter = M.filter.spatial.INTERSECT(miGeometria);
  lyProvincias.setFilter(filter);

});

Aquí puede verse un ejemplo funcional

También se ofrece la posibilidad de transformar cualquier de estos filtros al estándar CQL, por si se quiere hacer uso de filtrado desde el servidor

let filtroCQL = filter.toCQL(); //devuelve un string con el filtro en formato CQL
lyProvincias.setCQL(filtroCQL);

Filtros personalizados

Si ninguno de los filtros disponibles se adaptan a nuestras necesidades, Mapea también ofrece la posibilidad de definir cualquier filtro mediante una función, de forma que no quedamos limitados a la hora de poder realizar cualquier filtro:

let mapajs = M.map({
   container: "map",
   wmcfile: "callejero",
   controls: ["layerswitcher"]
 });

 var lyProvincias = new M.layer.WFS({
   url: "http://geostematicos-sigc.juntadeandalucia.es/geoserver/tematicos/ows?",
   namespace: "tematicos",
   name: "Provincias",
   legend: "Provincias",
   geometry: 'MPOLYGON'
 });

 mapajs.addLayers(lyProvincias);

 //se crea un filtro personalizado que sólo devuelve las features 
 //que tengan la letra 'C' en el atributo nombre
 let filter = new M.filter.Function(feature => {
   return feature.getAttribute('nombre').indexOf('C') >= 0;
 });
 
 lyProvincias.setFilter(filter);

Ejemplo filtro personalizado

Documentación API: M.filter