Per quanto riguarda l’interrogazione di strati di tipo vettoriale l’approccio da considerare dipende dal tipo di sorgente che stiamo utilizzando. Se gli elementi vettoriali da interrogare sono già caricati e presenti nella ol.source.Vector possiamao considerare due metodi alternativi.

Il primo, più semplice, può sfruttare i metodi ol.source.Vector.getFeaturesAtCoordinate() e ol.source.Vector.getFeaturesInExtent(). Entrambi ritornano un array di features che intersecano la coordinata o l’extent che gli avremo passato come argomento:

map.on('click', function(event) {
    var features = layer.getSource().getFeaturesAtCoordinate(event.coordinate);
});

L’altro approccio, più articolato ma molto più efficiente per il browser, sfrutta il metodo ol.Map.forEachfeatureAtPixel(): chiediamo alla mappa di elencarci tutti gli elementi vettoriali non trasparenti presenti ad un determinato pixel. Il metodo richiede due argomenti più uno opzionale:

  • pixel: coordinate pixel da interrogare, ottenute ad esempio da event.pixel
  • callback: la funzione che vogliamo che venga chiamata per ogni feature trovata
  • (opzionale) options: un oggetto contenente una o entrambe le seguenti proprietà:
    • layerFilter: una funzione che viene chiamata per ogni layer presente nella mappa e che dovrà ritornare true o false se vogliamo che vengano individate le feature per quel layer.
    • hitTolerance: tolleranza - in pixel - attorno al pixel richiesto per allargare l’area di ricerca delle feature. Consigliata nell’utilizzo all’interno di browser su smartphone, dove il tocco con le dita non è molto preciso.
map.on('click', function(event) {
  function hit(feature){
    // eseguo qualcosa sulla feature individuata
  };

  var options = {
    layerFilter: function(layer){
      return layer == mylayer; // assumendo che mylayer si riferisca al nostro strato d'interesse, voglio individare soltanto le sue feature
    },
    hitTolerance: 10
  };

  map.forEachFeatureAtPixel(event.pixel, hit, options);
});

Questo metodo è più performante perché sfrutta una tecnica di hit detection, tipica della computer grafica, molto più efficiente rispetto al confronto geometrico usanto nella soluzione precedente.

Nel caso in cui gli elementi vettoriali non siano già presenti nella mappa è necessario interrogare il server, secondo le API e/o il protocollo specifici della sorgente remota. Nel caso ad esempio di un servizio WFS dovremo eseguire una richiesta POST di tipo GetFeature inserendo nel suo corpo un filtro OGC per limitare la risposta ai soli elementi d’interesse.

A questo riguardo OpenLayers mette a diposizione un metodo molto utile per la costruzione di una richiesta GetFeature: ol.format.WFS.writeGetFeature. Questo meotdo può essere costruito con molte opzioni. Le due più importanti sono:

  • bbox: ol.Extent dell’area di cui vogliamo ottenere le feature
  • filter: un oggetto ol.format.filter.Filter che permette di costruire facilmente un filtro XML OGC.

Supponiamo di avere una feature che rappresenti il fiume arno (nel SR EPSG:3857) e di voler ottenere, da un dato servizio WFS, i comuni che ilo intersecano e che abbiano un campo “area” con un valore >= 50000000. Possiamo generare il corpo della richiesta POST usando ol.format.WFS.writeGetFeature, e poi eseguire la richiesta stessa gestendone i risultati secondo le necessità.

var f = ol.format.filter;
var requestXML = new ol.format.WFS().writeGetFeature({
    featureTypes: ['comuni'],
    outputFormat: 'text/gml',
    filter: f.and(
      f.bbox('the_geom', arno.getGeometry(), 'urn:ogc:def:crs:EPSG::3857'),
      f.greaterThanOrEqualTo('area', 50000000)
    )
});

var c = (new XMLSerializer()).serializeToString(requestXML);
$.post(wfsUrl,requestXML)
.done(function(response){
    var features = (new ol.format.GML()).readFeatures(response);
})