Date post: | 10-May-2015 |
Category: |
Technology |
Upload: | jared-erickson |
View: | 1,206 times |
Download: | 7 times |
Scripting GeoServer Jared Erickson
CUGOSDecember 2012
GEOSERVER
Open Source (GPL) WMS Server
Main language is Java
Also implements WFS, WCS, WPS, ect...
Uses GeoTools and JTS libraries
Scripting ModuleGeoserver Community Module
Developed by: Justin Deoliveira and Tim Schaub
I am adding Geoscript Groovy supporthttps://github.com/jericks/geoserver/tree/script_groovy
Python, JavaScript, Groovy, BeanShell, Ruby
Uses javax.scripting to execute scripts
Extend GeoServer on the fly
Scripting Hooks
Applications
Web Processing Services (WPS)
Geospatial web services
Rendering Transformations in SLD
Filter Functions
String, Date, Geometry Functions in SLD
Script Location
$DATA_DIR/scripts/appsfunctionwpslib
Scripts dynamically reloaded
Python, JavaScript, and Groovy have GeoScript API
Applications
Generic web applications or web services
Python - WSGI
JavaScript - JSGI
Groovy - Restlet
Hello World App
1 import org.restlet.data.*2 3 def run(request, response) {4 response.setEntity("Groovy rocks!", MediaType.TEXT_PLAIN)5 }
$DATA_DIR/scripts/apps/hello/main.groovy
Color Brewer App
1 import org.restlet.data.* 2 import org.restlet.resource.OutputRepresentation 3 import javax.imageio.ImageIO 4 import geoscript.filter.Color 5 import groovy.xml.MarkupBuilder 6 7 def run(request, response) { 8 String name = request.getResourceRef().getQueryAsForm().getFirstValue("name") 9 if (name) {10 def image = Color.drawToImage(Color.getPaletteColors(name))11 def output = new OutputRepresentation(MediaType.IMAGE_PNG) {12 void write(OutputStream out) throws IOException {13 ImageIO.write(image,"png",out)14 }15 }16 response.setEntity(output)17 }18 else {19 def out = new StringWriter()20 def html = new MarkupBuilder(out)21 html.html {22 head {23 title: "Color Brewer Palettes"24 }25 body {26 h1 "Color Brewer Palettes"27 ul {28 Color.paletteNames.each { nm ->29 li {30 a href: "colorbrewer?name=${nm}", "${nm}"31 }32 }33 }34 }35 }36 response.setEntity(out.toString(), MediaType.TEXT_HTML)37 }38 }
$DATA_DIR/scripts/apps/colorbrewer/main.groovy
Color Brewer App
Function List app
1 import org.restlet.data.* 2 import geoscript.filter.Function 3 import groovy.xml.MarkupBuilder 4 5 def run(request, response) { 6 def out = new StringWriter() 7 def html = new MarkupBuilder(out) 8 html.html { 9 head {10 titie: "Filter Functions"11 }12 body {13 h1 "Filter Function"14 ul {15 Function.functionNames.each { nm ->16 li "${nm}"17 }18 }19 }20 }21 response.setEntity(out.toString(), MediaType.TEXT_HTML)22 23 }
$DATA_DIR/scripts/apps/functions/main.groovy
Function List app
Groovy Geoserver APIgeoserver
Geoserver: Main entry point for Catalog and Config
Config: Metadata about GeoServer
geoserver.catalog
Catalog: Contains Workspaces, Layers, Stores
Workspace: Contains Stores
Store: Contains Layers, Converts to GeoScript Workspace
Layer: Converts to GeoScript Layer
layer as table app
1 import org.restlet.data.* 2 import geoserver.* 3 import groovy.xml.MarkupBuilder 4 5 def run(request, response) { 6 7 def layer = new GeoServer().catalog.getLayer("sf:archsites") 8 def gsLayer = layer.geoScriptLayer 9 10 def out = new StringWriter()11 def html = new MarkupBuilder(out)12 html.html {13 head {14 title: "Layer Table"15 }16 body {17 h1 "${layer.name}"18 table(border:1) {19 tr {20 gsLayer.schema.fields.each {fld ->21 td "${fld.name}"22 }23 }24 gsLayer.eachFeature { f ->25 tr {26 f.attributes.each { att ->27 td "${att.value}"28 }29 }30 }31 }32 }33 }34 response.setEntity(out.toString(), MediaType.TEXT_HTML)35 }
$DATA_DIR/scripts/apps/table/main.groovy
Layer as table app
Filter FunctionsTransform a value before displaying it
Format a date or a number
Capitalize a string
Manipulate a geometry
GeoTools input objects are wrapped as GeoScript objects
GeoScript result objects are unwrapped as GeoTools objects
Filter Function
1 /** 2 * Convert a Geometry into a buffered centroid 3 * @param value The Feature 4 * @param args A List of arguments 5 * args[0] is the Geometry 6 * args[1] is the buffer distance 7 */ 8 def run(value, args) { 9 args[0].centroid.buffer(args[1] as double)10 }
$DATA_DIR/scripts/function/bufferCentroid.groovy
Geometry filter function 1 <?xml version="1.0" encoding="ISO-8859-1"?> 2 <StyledLayerDescriptor version="1.0.0" 3 xsi:schemaLocation="http://www.opengis.net/sld StyledLayerDescriptor.xsd" 4 xmlns="http://www.opengis.net/sld" xmlns:ogc="http://www.opengis.net/ogc" 5 xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> 6 <NamedLayer> 7 <Name>Buffered Centroid</Name> 8 <UserStyle> 9 <Title>Buffered Centroids Polygons</Title>10 <Abstract>Draw buffered centroids of polygons</Abstract>11 <FeatureTypeStyle>12 <Rule>13 <Name>Rule 1</Name>14 <Title>Gray Polygon with Black Outline</Title>15 <Abstract>A polygon with a gray fill and a 1 pixel black outline</Abstract>16 <PolygonSymbolizer>17 <Geometry>18 <ogc:Function name="bufferCentroid">19 <ogc:PropertyName>the_geom</ogc:PropertyName>20 <ogc:Literal>1</ogc:Literal>21 </ogc:Function>22 </Geometry>23 <Fill>24 <CssParameter name="fill">#AAAAAA</CssParameter>25 </Fill>26 <Stroke>27 <CssParameter name="stroke">#000000</CssParameter>28 <CssParameter name="stroke-width">1</CssParameter>29 </Stroke>30 </PolygonSymbolizer>31 </Rule>32 </FeatureTypeStyle>33 </UserStyle>34 </NamedLayer>35 </StyledLayerDescriptor>
Geometry Filter Function
WPS
Web Processing Service
Model builder for the web
Generic web services for spatial data
GeoTools inputs are wrapped as GeoScript objects
GeoScript results are unwrapped as GeoTools objects
Geometry Buffer WPS
1 import geoscript.geom.Geometry 2 3 title = 'Buffer' 4 description = 'Buffers a geometry' 5 6 inputs = [ 7 geom: [name: 'geom', title: 'The geometry to buffer', type: Geometry.class], 8 distance: [name: 'distance', title: 'The buffer distance', type: Double.class] 9 ]10 11 outputs = [12 result: [name: 'result', title: 'The buffered geometry', type: Geometry.class]13 ]14 15 def run(input) {16 [result: input.geom.buffer(input.distance as double)]17 }18
$DATA_DIR/scripts/wps/buffer.groovy
WPS REQUEST BUILDER
Buffer geometry WPS
POLYGON ((11 1, 10.807852804032304 -0.9509032201612824, 10.238795325112868 -2.826834323650898, 9.314696123025453 -4.555702330196022, 8.071067811865476 -6.071067811865475, 6.555702330196023 -7.314696123025453, 4.826834323650898 -8.238795325112868, 2.9509032201612833 -8.807852804032304, 1.0000000000000007 -9, -0.9509032201612819 -8.807852804032304, -2.826834323650897 -8.238795325112868, -4.55570233019602 -7.314696123025453, -6.071067811865475 -6.0710678118654755,
-7.314696123025453 -4.555702330196022, -8.238795325112868 -2.8268343236508944, -8.807852804032306 -0.9509032201612773, -9 1.0000000000000075, -8.807852804032303 2.950903220161292, -8.238795325112862 4.826834323650909, -7.3146961230254455 6.555702330196034, -6.071067811865463 8.071067811865486,
-4.555702330196008 9.314696123025463, -2.826834323650879 10.238795325112875, -0.9509032201612606 10.807852804032308, 1.0000000000000249 11, 2.950903220161309 10.807852804032299, 4.826834323650925 10.238795325112857, 6.555702330196048 9.314696123025435, 8.071067811865499 8.07106781186545,
9.314696123025472 6.555702330195993, 10.238795325112882 4.826834323650862, 10.807852804032311 2.9509032201612437, 11 1))
http://localhost:8080/geoserver/wps?service=WPS&version=1.0.0&request=Execute&identifier=groovy:buffer&datainputs=geom=POINT%20(1%201)@mimetype=application/wkt;distance=10&RawDataOutput=result=@mimetype=application/wkt
Voronoi Layer WPS
1 import geoscript.geom.* 2 import geoscript.layer.* 3 4 title = 'VoronoiLayer' 5 description = 'Create a voronoi diagram around the features of a Layer' 6 7 inputs = [ 8 layer: [name: 'layer', title: 'The Layer', type: Layer.class], 9 ]10 11 outputs = [12 result: [name: 'result', title: 'The voronoi diagram as a Layer', type: Layer.class]13 ]14 15 def run(input) {16 def geoms = new GeometryCollection(input.layer.features*.geom.centroid)17 def output = new Layer()18 output.add([geoms.voronoiDiagram])19 [result: output]20 }21
$DATA_DIR/scripts/wps/voronoi.groovy
WPS Request Builder
Rendering transformations
Modify an entire dataset
Buffer the entire layer not each feature
Create a heatmap from points (vector to raster)
http://docs.geoserver.org/latest/en/user/styling/sld-extensions/rendering-transform.html
Rendering Transform sld
1 <?xml version="1.0" encoding="ISO-8859-1"?> 2 <StyledLayerDescriptor version="1.0.0" 3 xsi:schemaLocation="http://www.opengis.net/sld StyledLayerDescriptor.xsd" 4 xmlns="http://www.opengis.net/sld" 5 xmlns:ogc="http://www.opengis.net/ogc" 6 xmlns:xlink="http://www.w3.org/1999/xlink" 7 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> 8 <!-- a Named Layer is the basic building block of an SLD document --> 9 <NamedLayer>10 <Name>default_polygon</Name>11 <UserStyle>12 <!-- Styles can have names, titles and abstracts -->13 <Title>Default Polygon</Title>14 <Abstract>A sample style that draws a polygon</Abstract>15 <!-- FeatureTypeStyles describe how to render different features -->16 <!-- A FeatureTypeStyle for rendering polygons -->17 <FeatureTypeStyle>18 <Transformation>19 <ogc:Function name="groovy:voronoi">20 <ogc:Function name="parameter">21 <ogc:Literal>layer</ogc:Literal>22 </ogc:Function>23 </ogc:Function>24 </Transformation>25 <Rule>26 <Name>rule1</Name>27 <Title>Gray Polygon with Black Outline</Title>28 <Abstract>A polygon with a gray fill and a 1 pixel black outline</Abstract>29 <PolygonSymbolizer>30 <Fill>31 <CssParameter name="fill">#AAAAAA</CssParameter>32 </Fill>33 <Stroke>34 <CssParameter name="stroke">#000000</CssParameter>35 <CssParameter name="stroke-width">1</CssParameter>36 </Stroke>37 </PolygonSymbolizer>38 </Rule>39 </FeatureTypeStyle>40 </UserStyle>41 </NamedLayer>42 </StyledLayerDescriptor>43
Voronoi Diagram
Conclusion
GeoServer is well known as a WMS, WFS, WCS, WPS server
GeoServer is also a platform for spatial web services
Scripting just finally makes it easy
Thank you!