Executing existing processes with a script¶
This tutorial will show how to create a script that executes existing WPS processes using Python bindings.
Process definition¶
This tutorial will create a process called “Buffer and Split”. As its name suggests, it will combine two separate processes, Buffer (geo:buffer
) and Split Polygon (geo:splitPolygon
). The Buffer process takes as input any geometry and a distance value, and returns a polygon representing the input geometry enlarged by the given distance around its exterior. The Split Polygon process takes as inputs a geometry (usually a polygon) and a linestring, and returns a geometry (usually a geometry collection) generated by splitting the input geometry by the linestring.
The Buffer and Split operation combines these two processes in the following way: it takes as input a geometry, a linestring, and a distance value. The input geometry is buffered by the distance value, and the resulting polygon is split by the linestring. The result, in all but the most trivial cases, will be a polygon or a geometry collection.
Distance is measured in the same units as the source geometry. It will be assumed that all input geometries are represented in the same units and coordinate reference system.
Note
There are optional inputs to these two source processes that won’t be provided in our script. In cases where optional process inputs are omitted, the processes will use defaults. To see more details about the geo:buffer
and geo:splitPolygon
processes, as well as a list of every process published in GeoServer, please go to the GeoServer web admin page and click on WPS Processes.
Authoring the script¶
The complete script is as follows (Download
):
:
from geoserver.wps import process
from geoscript.process import Process
from geoscript.geom import *
buffer = Process.lookup('geo:buffer')
split = Process.lookup('geo:splitPolygon')
@process(
title = 'Buffer and Split',
description = 'Buffers a geometry and splits the resulting polygon.',
inputs = {
'geom': (Geometry, 'The geometry to buffer'),
'dist': (float, 'The distance by which to buffer the target geometry'),
'line': (LineString, 'The line used for splitting the buffered geometry')
},
outputs = {
'result': (Geometry, 'The buffered and split geometry')
}
)
def run(geom, dist, line):
buffered = buffer.run(geom=geom, distance=dist)['result']
return split.run(polygon=buffered, line=line)['result']
Save as bufferSplit.py
. A description of the script functionality follows.
Process headers¶
The script requires a number of import statements, including geometry types and WPS process hooks. In particular, the Buffer and SplitPolygon processes are pulled in here for use later on.
from geoserver.wps import process
from geoscript.process import Process
from geoscript.geom import *
buffer = Process.lookup('geo:buffer')
split = Process.lookup('geo:splitPolygon')
Process inputs and metadata¶
Next define the process inputs and metadata. Enclose all of these definitions in a process block:
@process(
)
Add a title and description for better readability:
title = 'Buffer and Split',
description = 'Buffers a geometry and splits the resulting polygon.',
The process has three inputs as described above: a geometry (geom
), a distance (dist
) value to use when buffering the geometry, and a line (line
) to use to split the subsequent geometry. Create the inputs list with these three definitions, along with a description:
inputs = {
'geom': (Geometry, 'The geometry to buffer'),
'dist': (float, 'The distance by which to buffer the target geometry'),
'line': (LineString, 'The line used for splitting the buffered geometry')
},
The single output (result
) will return a geometry, and is defined similarly:
outputs = {
'result': (Geometry, 'The buffered and split geometry')
}
Process computation¶
Now that the inputs and outputs are defined, next create the computation through a function called run
. This function has only two steps. The first step buffers the geom
by the dist
value, and the result is stored in the buffered
variable. The second step splits the buffered
geometry by the line
. The final geometry is then returned.
def run(geom, dist, line):
buffered = buffer.run(geom=geom, distance=dist)['result']
return split.run(polygon=buffered, line=line)['result']
Activating the script¶
After the script is written, it must be added to GeoServer. Place the script in the GeoServer data directory in the location: <data_dir>/scripts/wps/
. (Create this path if it doesn’t already exist.) The script will be activated automatically when copied to that location, with no server restart necessary.
Testing the script¶
Once the script is in place and activated, the next step is to test it. Use the WPS Request Builder in the GeoServer UI to verify this script’s functionality.
Access the WPS Request Builder in the GeoServer UI by clicking on Demos then WPS Request Builder.
Select the process in the menu. It will be named
py:bufferSplit
.Fill out the form. The following values will work for testing:
Input Value line
LINESTRING(-4 0, 4 0)
geom
LINESTRING(0 -1, 0 1)
dist
1
Enter these values in the form, making sure to select sure to select TEXT and application/wkt as the source format for each input and output.
Click Execute process.
Note
If you are curious about what the actual process request looks like, click Generate XML from process inputs/outputs.
The output will look something like this:
GEOMETRYCOLLECTION (POLYGON ((1 0, 1 -1, 0.9807852804032304 -1.1950903220161282, 0.9238795325112867 -1.3826834323650898, 0.8314696123025452 -1.5555702330196022, 0.7071067811865476 -1.7071067811865475, 0.5555702330196023 -1.8314696123025453, 0.3826834323650898 -1.9238795325112867, 0.1950903220161283 -1.9807852804032304, 0.0000000000000001 -2, -0.1950903220161282 -1.9807852804032304, -0.3826834323650897 -1.9238795325112867, -0.555570233019602 -1.8314696123025453, -0.7071067811865475 -1.7071067811865475, -0.8314696123025453 -1.5555702330196022, -0.9238795325112868 -1.3826834323650894, -0.9807852804032305 -1.1950903220161277, -1 -1, -1 0, 1 0)), POLYGON ((-1 1, -0.9807852804032304 1.1950903220161286, -0.9238795325112867 1.3826834323650898, -0.8314696123025453 1.5555702330196022, -0.7071067811865475 1.7071067811865475, -0.555570233019602 1.8314696123025453, -0.3826834323650897 1.9238795325112867, -0.1950903220161282 1.9807852804032304, 0.0000000000000001 2, 0.1950903220161283 1.9807852804032304, 0.3826834323650898 1.9238795325112867, 0.5555702330196021 1.8314696123025453, 0.7071067811865476 1.7071067811865475, 0.8314696123025453 1.5555702330196022, 0.923879532511287 1.3826834323650894, 0.9807852804032305 1.1950903220161275, 1 1, 1 0, -1 0, -1 1)))
Or, graphically:
Note
The curved nature of the output geometry stems from the default values of the
geo:buffer
inputscapStyle
andquadrantSegments
, which are set toRound
and8
, respectively. These values can be explicitly set in the script, either by hard coding the values in the process call, or by adding new inputs to the process.