In a previous entry, Martin explains the creation of a GeoServer WPS process for splitting polygons. In this follow-up, we'll describe how a web client can take advantage of this process to split polygons using sketches drawn in the browser.
First, let's see it in action:
The above example makes use of utilities in OpenLayers to draw vector features and execute WPS processes. Stitching it all together involves four basic steps.
Creating the map
In a real application that takes advantage of a polygon splitting process, you'd likely be allowing users to digitize features over some base layer and persisting changes to the server (via a WFS transaction for example). To keep things simple for this example, we've just created a map with a single base layer using tiles from MapQuest and a single vector layer to render the geometry sketches.
Adding drawing controls
This simple demo application allows the user to draw one or more polygons (with optional holes), draw "splitter" lines to split any intersecting polygons, and then drag the pieces apart to verify that the splits worked. To accomplish this, we've added three additional controls to the map (named
dragPoly). These controls are activated and deactivated by the user with three radio buttons.
drawPoly control is active, the user can digitize any number of polygons - using the shift key to enable freehand drawing and the alt/option key to digitize holes in existing polygons.
splitPoly control active, the user can draw a linestring. To engage the splitting process, we wait for the
sketchcomplete event by adding a listener to the vector layer. This listener will be called before any digitized feature is added to the layer. If the sketched feature has a linestring geometry, we want to consider splitting any intersecting polygons. For every intersecting polygon, the listener removes the original feature and calls a method (named
executeSplit) to execute the split process.
Issuing the request to execute the process
gs:SplitPolygon process accepts geometry inputs named
line and returns the result of a split with the name
result. GeoServer will accept GML (2.1.2 or 3.1.1) or WKT for the input geometries and can produce the same for the result. Our client uses WKT for inputs and outputs. When the
executeSplit method is called, it creates a data structure with the required inputs and desired output. OpenLayers serializes this data structure as a WPS Execute request and POSTs it to the
/geoserver/wps endpoint for execution.
Handling the results of the split
When GeoServer returns the results from the
gs:SplitPolygon process, our client code parses the result (expecting a WKT
GEOMETRYCOLLECTION). Since we previously removed each of the target polygons before splitting, if the response includes multiple geometries (a successful split), we add a feature for each new polygon geometry to the layer.
If the response doesn't include any geometries (for example, if the line crosses the exterior of a polygon only once), we add the original target feature back. Because the handler for the posted request is defined in the
executeSplit closure, we aren't concerned about the order of returned responses. Any number of requests can be executed and returned in any order, and we always have access to the original polygon in case the process didn't result in a split.
Finally, when the
dragPoly control is active, the user can drag existing polygon features around the map to confirm that the split process works as advertised.
Running the Demo at Home
gs:SplitPolygon process should be included the upcoming OpenGeo Suite 3.0 release. If you'd like to try it out before, download the splitpoly.jar archive and drop it in your GeoServer
WEB-INF/lib directory. Restart GeoServer and issue a
DescribeProcess request to verify that the process is there.
Find the client side of the demo application on GitHub (see examples/split-poly.js). You'll need to serve up the client side of the application on the same origin as GeoSever. The readme in the repository describes how you can proxy GeoServer on port 80 if you're serving the client-side resources with Apache.