Garantire l’ordine di rendering con la vestizione SLD

State preparando una mappa del centro urbano: strade, aree verdi, edifici, zone industriali e con tutte le specificità di un piano di assetto del territorio. Per ogni layer avete preparato la sua vestizione secondo lo standard SLD: siete sicuri di ottenere sempre quanto voluto?

Garantire la consistenza del rendering del server geospaziale, indipendentemente da quale scegliate, è di fondamentale importanza per ottenere risultati di qualità. Nel caso dobbiate disegnare un layer con feature sovrapposte, vi dovreste preoccupare dell’ordine con cui sono disegnate le feature.

Un classico esempio di questo problema è dato dal layer delle strade, in presenza di cavalcavia o sottopassi. Vorrete, infatti, che queste feature siano disegnate dopo le altre al piano stradale e che magari abbiano uno stile particolare, che ne evidenzi le peculiarità.

Fortunatamente lo standard OGC SLD, e anche la sua recente evoluzione OGC SE, ci viene in aiuto con le Rule.

“Basterà definire due regole per ottenere quanto voluto”, direte voi.

Verissimo, ma potreste incappare in spiacevoli conseguenze.

Considerate questo caso molto semplice: uno strato informativo poligonale delle aree verdi, che contiene sia le geometrie dei parchi che geometrie sovrapposte degli specchi d’acqua.

Due regole per lo stesso stile

La logica vuole far disegnare gli specchi d’acqua sopra le aree verdi e quindi potreste pensare ad un SLD così fatto:

<?xml version="1.0" encoding="ISO-8859-1"?>
<StyledLayerDescriptor version="1.0.0" xmlns="http://www.opengis.net/sld" xmlns:ogc="http://www.opengis.net/ogc"
 xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://www.opengis.net/sld http://schemas.opengis.net/sld/1.0.0/StyledLayerDescriptor.xsd">
 <NamedLayer>
 <Name>Multirule</Name>
 <UserStyle>

 <FeatureTypeStyle>

 <Rule>
 <ogc:Filter>
 <ogc:PropertyIsEqualTo>
 <ogc:PropertyName>CFCC</ogc:PropertyName>
 <ogc:Literal>H41</ogc:Literal>
 </ogc:PropertyIsEqualTo>
 </ogc:Filter>
 <PolygonSymbolizer>
 <Fill>
 <CssParameter name="fill">#3366ff</CssParameter>
 <CssParameter name="fill-opacity">0.5</CssParameter>
 </Fill>
 <Stroke>
 <CssParameter name="stroke">#3366ff</CssParameter>
 <CssParameter name="stroke-width">1</CssParameter>
 </Stroke>
 </PolygonSymbolizer>
 </Rule>

 <Rule>
 <PolygonSymbolizer>
 <Fill>
 <CssParameter name="fill">#339933</CssParameter>
 <CssParameter name="fill-opacity">0.5</CssParameter>
 </Fill>
 <Stroke>
 <CssParameter name="stroke">#339933</CssParameter>
 <CssParameter name="stroke-width">1</CssParameter>
 </Stroke>
 </PolygonSymbolizer>
 </Rule>

 </FeatureTypeStyle>

 </UserStyle>
 </NamedLayer>
</StyledLayerDescriptor>

La prima regola filtra gli specchi d’acqua mentre tutto il resto viene disegnato dalla seconda. Dal punto di vista umano, la regola in alto dovrebbe consentire agli specchi d’acqua di apparire sopra ai parchi.

Usando Geoserver come server geospaziale otterrete tuttavia la sequenza opposta dato che il rendering è incrementale, quindi le regole sono applicate in sequenza, e funziona secondo una logica basata sull’arrivo dei dati così come sono inviati dalla sorgente dati:

geoserver-sld-wrong

Il primo approccio potrebbe essere quello di dire “Basterà quindi girare le regole per sistemare il problema.” ma non avrete risolto il problema alla radice. Funziona con il caso in questione (e infatti lo faremo) ma non potrete mai sapere con certezza come vengano forniti i dati dalla sorgente, soprattutto se non avete il completo controllo dei file o del database, e anche in questo caso sarà sufficiente modificare il tipo di un record esistente per vanificare le nostre speranze.

Inoltre basterebbe cambiare server geospaziale (ad esempio usando QGIS) per ottenere risultati diversi dato che non esiste una regola generale ma il rendering dipende dall’implementazione fatta dai programmatori.

Utilizzare FeatureTypeStyle per garantire l’ordine di rendering

L’unico modo efficace di risolvere quindi il problema è modificare concettualmente l’applicazione dell’SLD. Invece di aggiungere due o più regole allo stesso FeatureTypeStyle, aggiungeremo più FeatureTypeStyle ognuno contenente una Rule.

Qual è la differenza principale? I FeatureTypeStyle sono definiti dallo standard come un foglio di acetato sovrapponibile, ovvero un raggruppamento logico delle feature del layer ed è garantita la consistenza e l’applicazione di un ordine deterministico. Le Rule invece sono considerate dallo standard come un symbolizer e quindi privo di ogni raggruppamento logico.

Cambiamo quindi l’SLD come segue:

<?xml version="1.0" encoding="ISO-8859-1"?>
<StyledLayerDescriptor version="1.0.0" xmlns="http://www.opengis.net/sld" xmlns:ogc="http://www.opengis.net/ogc"
 xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://www.opengis.net/sld http://schemas.opengis.net/sld/1.0.0/StyledLayerDescriptor.xsd">
 <NamedLayer>
 <Name>Multirule</Name>

 <FeatureTypeStyle>
 <Rule>
 <PolygonSymbolizer>
 <Fill>
 <CssParameter name="fill">#339933</CssParameter>
 <CssParameter name="fill-opacity">0.5</CssParameter>
 </Fill>
 <Stroke>
 <CssParameter name="stroke">#339933</CssParameter>
 <CssParameter name="stroke-width">1</CssParameter>
 </Stroke>
 </PolygonSymbolizer>
 </Rule>
 </FeatureTypeStyle>

 <FeatureTypeStyle>
 <Rule>
 <ogc:Filter>
 <ogc:PropertyIsEqualTo>
 <ogc:PropertyName>CFCC</ogc:PropertyName>
 <ogc:Literal>H41</ogc:Literal>
 </ogc:PropertyIsEqualTo>
 </ogc:Filter>
 <PolygonSymbolizer>
 <Fill>
 <CssParameter name="fill">#3366ff</CssParameter>
 <CssParameter name="fill-opacity">0.5</CssParameter>
 </Fill>
 <Stroke>
 <CssParameter name="stroke">#3366ff</CssParameter>
 <CssParameter name="stroke-width">1</CssParameter>
 </Stroke>
 </PolygonSymbolizer>
 </Rule>
 </FeatureTypeStyle>

 </UserStyle>
 </NamedLayer>
</StyledLayerDescriptor>

Ecco il risultato corretto:

geoserver-sld-right

Pubblicato il 16 febbraio 2016 da Eduard Roccatello
Tag: , ,