Rendering Transformation in GeoServer: calcolo dinamico di interpolated surface e di contour map
Partendo da un post sul blog di OpenGeo ho voluto approfondire un po’ la potenzialità che GeoServer offre sia in termini di:
- rendering transformation
- chaining di processi
- utilizzo di processi WPS all’interno di stili SLD
Ho provato a replicare l’esempio del calcolo delle isoterme partendo da dei dati “inventati” che simulano la presenza di centraline meteo sul territorio piemontese: non ho infatti trovato in rete dati analoghi georeferenziati e disponibili. Per chi volesse replicare ecco i dati che ho utilizzato.
Ho quindi creato per prima cosa un layer in GeoServer delle Centraline Meteo la cui visualizzazione corrisponde ad una getMap WMS con la seguente struttura
La creazione delle isoterme la si può ottenere concatenando (chaining), due processi WPS messi a disposizione da GeoServer e precisamente, Barnes Surface Process e Contour Process, usando il meccanismo delle rendering transformation definite come stile SLD. L’output del primo processo (il calcolo della superficie, che è sostanzialmente quello delle fasce di temperatura), costituisce l’input del secondo processo (che è il calcolo delle isoterme).
Vediamo quindi dapprima il solo calcolo delle fasce di temperatura la cui visualizzazzione viene ottenuta con la medesima getMap vista in precedenza con in più l’utilizzo di un opportuno stile SLD al cui interno viene utilizzato il processo WPS Barnes Surface valorizzando opportunamente i parametri necessari.
La nuova getMap WMS sarà quindi di questo tipo (in evidenza l’utilizzo dello stile):
http://localhost:8080/geoserver/MyWorkspace/wms?service=WMS&version=1.1.0&request=GetMap&layers=MyWorkspace:CentralineMeteo&styles=FasceTemperatura&bbox=318287.0,4880823.0,515945.0,5142603.0&width=386&height=512&srs=EPSG:32632&format=application/openlayers
Ecco invece la definizione dello stile SLD utilizzato
<?xml version=”1.0″ encoding=”ISO-8859-1″?>
<StyledLayerDescriptor version=”1.0.0″
xsi:schemaLocation=”http://www.opengis.net/sld StyledLayerDescriptor.xsd”
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”>
<NamedLayer>
<Name>Barnes surface</Name>
<UserStyle>
<Title>Barnes Surface</Title>
<Abstract>A style that produces a Barnes surface using a rendering transformation</Abstract>
<FeatureTypeStyle>
<Transformation>
<ogc:Function name=”gs:BarnesSurface”>
<ogc:Function name=”parameter”>
<ogc:Literal>data</ogc:Literal>
</ogc:Function>
<ogc:Function name=”parameter”>
<ogc:Literal>valueAttr</ogc:Literal>
<ogc:Literal>Temperatur</ogc:Literal>
</ogc:Function>
<ogc:Function name=”parameter”>
<ogc:Literal>scale</ogc:Literal>
<ogc:Literal>1000</ogc:Literal>
</ogc:Function>
<ogc:Function name=”parameter”>
<ogc:Literal>convergence</ogc:Literal>
<ogc:Literal>0.3</ogc:Literal>
</ogc:Function>
<ogc:Function name=”parameter”>
<ogc:Literal>passes</ogc:Literal>
<ogc:Literal>100</ogc:Literal>
</ogc:Function>
<ogc:Function name=”parameter”>
<ogc:Literal>minObservations</ogc:Literal>
<ogc:Literal>2</ogc:Literal>
</ogc:Function>
<ogc:Function name=”parameter”>
<ogc:Literal>maxObservationDistance</ogc:Literal>
<ogc:Literal>0</ogc:Literal>
</ogc:Function>
<ogc:Function name=”parameter”>
<ogc:Literal>pixelsPerCell</ogc:Literal>
<ogc:Literal>25</ogc:Literal>
</ogc:Function>
<ogc:Function name=”parameter”>
<ogc:Literal>queryBuffer</ogc:Literal>
<ogc:Literal>2000</ogc:Literal>
</ogc:Function>
<ogc:Function name=”parameter”>
<ogc:Literal>outputBBOX</ogc:Literal>
<ogc:Function name=”env”>
<ogc:Literal>wms_bbox</ogc:Literal>
</ogc:Function>
</ogc:Function>
<ogc:Function name=”parameter”>
<ogc:Literal>outputWidth</ogc:Literal>
<ogc:Function name=”env”>
<ogc:Literal>wms_width</ogc:Literal>
</ogc:Function>
</ogc:Function>
<ogc:Function name=”parameter”>
<ogc:Literal>outputHeight</ogc:Literal>
<ogc:Function name=”env”>
<ogc:Literal>wms_height</ogc:Literal>
</ogc:Function>
</ogc:Function>
</ogc:Function>
</Transformation>
<Rule>
<RasterSymbolizer>
<!– specify geometry attribute of input to pass validation –>
<Geometry><ogc:PropertyName>the_geom</ogc:PropertyName></Geometry>
<Opacity>0.8</Opacity>
<ColorMap type=”ramp” >
<ColorMapEntry color=”#FFFF00″ quantity=”-990″ label=”nodata” opacity=”0″/>
<ColorMapEntry color=”#2E4AC9″ quantity=”-6″ label=”nodata”/>
<ColorMapEntry color=”#41A0FC” quantity=”-5″ label=”values” />
<ColorMapEntry color=”#58CCFB” quantity=”-4″ label=”values” />
<ColorMapEntry color=”#76F9FC” quantity=”-3″ label=”values” />
<ColorMapEntry color=”#6AC597″ quantity=”-2″ label=”values” />
<ColorMapEntry color=”#479364″ quantity=”-1″ label=”values” />
<ColorMapEntry color=”#2E6000″ quantity=”0″ label=”values” />
<ColorMapEntry color=”#579102″ quantity=”1″ label=”values” />
<ColorMapEntry color=”#9AF20C” quantity=”2″ label=”values” />
<ColorMapEntry color=”#B7F318″ quantity=”3″ label=”values” />
<ColorMapEntry color=”#DBF525″ quantity=”4″ label=”values” />
<ColorMapEntry color=”#FAF833″ quantity=”5″ label=”values” />
<ColorMapEntry color=”#F9C933″ quantity=”6″ label=”values” />
<ColorMapEntry color=”#F19C33″ quantity=”7″ label=”values” />
<ColorMapEntry color=”#ED7233″ quantity=”8″ label=”values” />
<ColorMapEntry color=”#EA3F33″ quantity=”9″ label=”values” />
<ColorMapEntry color=”#BB3026″ quantity=”10″ label=”values” />
</ColorMap>
</RasterSymbolizer>
</Rule>
</FeatureTypeStyle>
</UserStyle>
</NamedLayer>
</StyledLayerDescriptor>
Occorre osservare che, mentre è piuttosto semplice l’applicazione del processo, è molto più delicato il processo che porta alla corretta definizione e valorizzazione dei parametri che ne governano il risultato e la sua rappresentazione. Non è infatti chiarissima la documentazione riportata in GeoServer a tale scopo e per raggiungere un qualche risultato apprezzabile sono dovuto ricorrrere al supporto della GeoServer user list di cui vi lascio il riferimento per i dettagli.
Per la creazione delle isoterme la visualizzazzione viene ottenuta sempre con la stessa getMap vista in precedenza con l’utilizzo di un nuovo stile SLD al cui interno sono concatenati il processo di WPS Barnes Surface visto in precedenza che fornisce in input il proprio risulttao al processo WPS Contours.
La nuova getMap WMS sarà quindi di questo tipo (in evidenza l’utilizzo dello stile):
http://localhost:8080/geoserver/MyWorkspace/wms?service=WMS&version=1.1.0&request=GetMap&layers=MyWorkspace:CentralineMeteo&styles=FasceTemperatura-Isoterme&bbox=318287.0,4880823.0,515945.0,5142603.0&width=386&height=512&srs=EPSG:32632&format=application/openlayers
Ecco invece la definizione dello stile SLD utilizzato
<?xml version=”1.0″ encoding=”ISO-8859-1″?>
<StyledLayerDescriptor version=”1.0.0″
xsi:schemaLocation=”http://www.opengis.net/sld StyledLayerDescriptor.xsd”
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”>
<NamedLayer>
<Name>BarnesContours</Name>
<UserStyle>
<Title>Barnes Surface Contours</Title>
<Abstract>Extracts contours from a computed surface</Abstract>
<FeatureTypeStyle>
<Transformation>
<ogc:Function name=”gs:Contour”>
<ogc:Function name=”parameter”>
<ogc:Literal>data</ogc:Literal>
<ogc:Function name=”gs:BarnesSurface”>
<ogc:Function name=”parameter”>
<ogc:Literal>data</ogc:Literal>
</ogc:Function>
<ogc:Function name=”parameter”>
<ogc:Literal>valueAttr</ogc:Literal>
<ogc:Literal>Temperatur</ogc:Literal>
</ogc:Function>
<ogc:Function name=”parameter”>
<ogc:Literal>scale</ogc:Literal>
<ogc:Literal>10000</ogc:Literal>
</ogc:Function>
<ogc:Function name=”parameter”>
<ogc:Literal>convergence</ogc:Literal>
<ogc:Literal>0.5</ogc:Literal>
</ogc:Function>
<ogc:Function name=”parameter”>
<ogc:Literal>passes</ogc:Literal>
<ogc:Literal>3</ogc:Literal>
</ogc:Function>
<ogc:Function name=”parameter”>
<ogc:Literal>minObservations</ogc:Literal>
<ogc:Literal>1</ogc:Literal>
</ogc:Function>
<ogc:Function name=”parameter”>
<ogc:Literal>maxObservationDistance</ogc:Literal>
<ogc:Literal>70000</ogc:Literal>
</ogc:Function>
<ogc:Function name=”parameter”>
<ogc:Literal>pixelsPerCell</ogc:Literal>
<ogc:Literal>10</ogc:Literal>
</ogc:Function>
<ogc:Function name=”parameter”>
<ogc:Literal>outputBBOX</ogc:Literal>
<ogc:Function name=”env”>
<ogc:Literal>wms_bbox</ogc:Literal>
</ogc:Function>
</ogc:Function>
<ogc:Function name=”parameter”>
<ogc:Literal>outputWidth</ogc:Literal>
<ogc:Function name=”env”>
<ogc:Literal>wms_width</ogc:Literal>
</ogc:Function>
</ogc:Function>
<ogc:Function name=”parameter”>
<ogc:Literal>outputHeight</ogc:Literal>
<ogc:Function name=”env”>
<ogc:Literal>wms_height</ogc:Literal>
</ogc:Function>
</ogc:Function>
<ogc:Function name=”parameter”>
<ogc:Literal>queryBuffer</ogc:Literal>
<ogc:Literal>10000</ogc:Literal>
</ogc:Function>
</ogc:Function>
</ogc:Function>
<ogc:Function name=”parameter”>
<ogc:Literal>levels</ogc:Literal>
<ogc:Literal>-6</ogc:Literal>
<ogc:Literal>-5</ogc:Literal>
<ogc:Literal>-4</ogc:Literal>
<ogc:Literal>-3</ogc:Literal>
<ogc:Literal>-2</ogc:Literal>
<ogc:Literal>-1</ogc:Literal>
<ogc:Literal>0</ogc:Literal>
<ogc:Literal>1</ogc:Literal>
<ogc:Literal>2</ogc:Literal>
<ogc:Literal>3</ogc:Literal>
<ogc:Literal>4</ogc:Literal>
<ogc:Literal>5</ogc:Literal>
<ogc:Literal>6</ogc:Literal>
<ogc:Literal>7</ogc:Literal>
<ogc:Literal>8</ogc:Literal>
<ogc:Literal>9</ogc:Literal>
<ogc:Literal>10</ogc:Literal>
</ogc:Function>
<ogc:Function name=”parameter”>
<ogc:Literal>simplify</ogc:Literal>
<ogc:Literal>true</ogc:Literal>
</ogc:Function>
</ogc:Function>
</Transformation>
<Rule>
<Name>rule1</Name>
<Title>Isotherm</Title>
<ogc:Filter>
<ogc:PropertyIsEqualTo>
<ogc:Function name=”IEEERemainder”>
<ogc:Function name=”int2ddouble”>
<ogc:PropertyName>value</ogc:PropertyName>
</ogc:Function>
<ogc:Function name=”parseDouble”>
<ogc:Literal>1.0</ogc:Literal>
</ogc:Function>
</ogc:Function>
<ogc:Literal>0</ogc:Literal>
</ogc:PropertyIsEqualTo>
</ogc:Filter>
<LineSymbolizer>
<Stroke>
<CssParameter name=”stroke”>#000000</CssParameter>
<CssParameter name=”stroke-width”>1</CssParameter>
</Stroke>
</LineSymbolizer>
<TextSymbolizer>
<Label>
<ogc:Function name=”round”>
<ogc:PropertyName>value</ogc:PropertyName>
</ogc:Function>
</Label>
<Font>
<CssParameter name=”font-family”>Arial</CssParameter>
<CssParameter name=”font-style”>Normal</CssParameter>
<CssParameter name=”font-size”>12</CssParameter>
</Font>
<LabelPlacement>
<LinePlacement/>
</LabelPlacement>
<Halo>
<Radius>
<ogc:Literal>2</ogc:Literal>
</Radius>
<Fill>
<CssParameter name=”fill”>#FFFFFF</CssParameter>
<CssParameter name=”fill-opacity”>0.6</CssParameter>
</Fill>
</Halo>
<Fill>
<CssParameter name=”fill”>#000000</CssParameter>
</Fill>
<Priority>2000</Priority>
<VendorOption name=”followLine”>true</VendorOption>
<VendorOption name=”repeat”>100</VendorOption>
<VendorOption name=”maxDisplacement”>50</VendorOption>
<VendorOption name=”maxAngleDelta”>30</VendorOption>
</TextSymbolizer>
</Rule>
</FeatureTypeStyle>
</UserStyle>
</NamedLayer>
</StyledLayerDescriptor>
Ecco infine la visualizzazione contemporanea dei tre layers
Come si vede la mappa è sempre ottenuta grazie ad una chiamata http su un protocollo OGC standard quale il WMS ampiamente adottato nel mondo GIS e questo permette di rendere indipendente il “servzio di business” dal suo fruitore, tant’è che la medesima mappa la si può fruire da un client GIS Desktop quale QGIS come mostra l’immagine successiva.
come pure un’applicazione gis mobile in grado di “consumare” WMS: ho provato con Locus Free installato su un Samsung Galaxy e via wi-fi non ho avuto problemi ad agganciare il mio GeoServer installato localmente sul mio pc e a visualizzare le mie isoterme anche da questo tipo di fruitore.
Al tempo stesso questo approccio permette di nascondere completamente la complessità del processo (anzi, nel caso specidico “dei” processi visto che sono due e concatenati …..), sottostanti mentre ne permette la fruizone secondo meccanismi noti e standard (chiamata wms via http ….), che qualunque fruitore GIS sa già utilizzare.
Concludo con un paio di punti:
- quanto ho provato è una sorta di proof of concepts ed è ben lungi dall’essere un’algoritmo definitivo: non sono state fatte ad esempio considerazioni sui dati che probabilmente andrebbero fatte, quali ad esempio la valutazione della quota altimetrica a cui si trova la stazione meteo (sfruttando un DEM?): i dati al momento sono stati considerati “piatti” tutti allo stesso livello
- ho untilizzato GeoServer 2.2.3 su un pc Windows 7, 4 CPU, 8 Gbyte di RAM
Cerca
Calendario
Numero Accessi
- 162.228 hits
Articoli Recenti
- Open Pronto Soccorsi: aggiornamento con nuovi dati
- Open Pronto Soccorsi: rendere disponibili, ed accessibili, i dati, di numeri e tempi di attesa per tipologia, dei pronto soccorsi italiani
- Open Pronto Soccorsi: come è fatto “dentro”
- Street Image Compare: how to compare Google Street View and Mapillary in the same web page
- Street Image Compare: confrontare Google Street View e Mapillary nella stessa pagina web
Top Posts & Pages
- Come convertire indirizzi in coordinate geografiche (geocoding) usando i servizi WFS del GeoPortale Nazionale e Open Refine
- Mappe temporali o "isocrone"
- Vuoi calcolare la distanza tra punti georiferiti? OSRMdistance
- Note sull'accuratezza di Google Maps
- Numeri civici Open Data in Italia: disponibile la release 2.0 della raccolta
- Numeri civici Open Data in Italia: disponibile la release 3.0 della raccolta
- Mappa del Trentino: un esempio di un uso sinergico di dati open
- About
- Confronto tra routing engine API
- Realizzare automaticamente storytelling usando Mapillary? Ci si può provare …
Top Rated
Categorie
Tag Cloud
Blogroll
- All Points Blog
- ArcGIS Explorer Desktop Blog
- ArcGIS Mobile Blog
- ArcGIS On Line Blog
- ArcGIS Server Blog
- Between the poles
- cesaregerbino.it
- Challenge.gov
- CloudPeople
- de.straba.us
- Directions Magazine
- edparson.com
- ESRI Geoprocessing blog
- ESRI Insider
- ESRI Java Technology Blog
- ESRI News
- ESRI UC Blog
- ESRI Video
- Free Geography Tools
- Geo-Mobile Blog
- GeoExt Blog
- GEOforUS
- GeoServer Blog
- GIS Lounge
- Google Earth Blog
- Google Geo Developers Blog
- Google LatLong Blog
- Google Maps Mania
- Google SketchUp Blog
- gvSIG Blog
- INSPIRE
- Lin.ear th.inking
- Linfiniti Geo Blog
- MapFish Blog
- Mapperz
- massimozotti.it
- Open Geospatial Consortium
- Open Knowledge Foundation Italia
- OpenGeo
- OpenLayers Blog
- OSGeo
- PaoloGIS – ArcView, ArcGIS e dintorni
- planetgis.it
- PostGIS
- Quantum GIS Blog
- Slashgeo
- Spatial Roundtable
- Spatial Sustain
- Spatially Adjusted
- Spatialytics.org
- TANTO
- Technical Ramblings
- TED Blog
- The Geospatial Desktop
- The Ushahidi Blog
- Thinking in GIS
- Vector One
- VerySpatial
Archivi
- dicembre 2018
- luglio 2018
- agosto 2017
- aprile 2017
- ottobre 2016
- luglio 2016
- febbraio 2016
- ottobre 2015
- settembre 2015
- agosto 2015
- giugno 2015
- maggio 2015
- marzo 2015
- febbraio 2015
- gennaio 2015
- ottobre 2014
- settembre 2014
- luglio 2014
- marzo 2014
- febbraio 2014
- gennaio 2014
- novembre 2013
- ottobre 2013
- settembre 2013
- agosto 2013
- luglio 2013
- giugno 2013
- maggio 2013
- aprile 2013
- marzo 2013
- febbraio 2013
- gennaio 2013
- dicembre 2012
- novembre 2012
- ottobre 2012
- settembre 2012
- agosto 2012
- luglio 2012
- giugno 2012
- maggio 2012
- aprile 2012
- marzo 2012
- febbraio 2012
- gennaio 2012
- dicembre 2011
- novembre 2011
- ottobre 2011
- settembre 2011
- luglio 2011
- giugno 2011
- maggio 2011
- aprile 2011
- marzo 2011
- febbraio 2011
Latest Tweets
- RT @skampus1967: L'ITIS Avogadro di Torino a #foss4g_IT2019 tiene un workshop su Open Refine e UMAP https://t.co/C4CrKeotmS 20 hours ago
- RT @cascafico: Ho scoperto con piacere che nel programma di #foss4g_IT2019 i ragazzi dell'istituto Avogadro di Torino presenteranno anche u… 20 hours ago
- RT @GiorgiaLodi: Io ho una stima veramente profonda per tutti quelli che devono riutilizzare dati geospaziali: il più delle volte si è diro… 1 day ago
- RT @nifreddo: Tutti tacciono, non ci sono manuali o istruzioni, eppure da più di 2 mesi su #ANNCSU esiste la possibilità di georeferenziare… 4 days ago
- RT @AdresseDataGouv: La barre des 1000 communes ayant ouvert leurs adresses a été franchie ! 🎊 Merci aux nouvelles communes des Côtes-d'Arm… 5 days ago