source: trunk/docs/workshop/2010/building_wps_client_using_ol.txt @ 262

Last change on this file since 262 was 262, checked in by jmckenna, 13 years ago

fix formatting of workshop files

File size: 13.0 KB
Line 
1.. _building_wps_client_using_ol:
2
3Building a WPS client using OpenLayers
4######################################
5
6.. contents:: Table of Contents
7    :depth: 5
8    :backlinks: top
9
10The next step of our workshop is to connect to the OGR Services we have created
11from an OpenLayers map. This will allow to apply single or multiple geometries
12processes on user-selected polygons and to display the new generated geometries.
13
14Creating a simple map showing the dataset as WMS
15************************************************
16
17OpenLayers is also included in OSGeoLive default distribution, so it is convenient
18to use it for our needs. Please open ``/var/www/zoo-ogr.html`` using your favorite
19text editor and paste the following HTML snippet:
20
21.. code-block:: guess
22
23    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"><html xmlns="http://www.w3.org/1999/xhtml" xml:lang="EN" lang="EN">
24     <head>
25      <meta content="text/html; charset=UTF-8" http-equiv="content-type"/>
26      <title>ZOO WPS Client example</title>
27      <style>
28      #map{width:700px;height:600px;}
29      </style>
30      <link rel="stylesheet" href="/openlayers/theme/default/style.css" type="text/css" />
31      <script type="text/javascript" src="/openlayers/lib/OpenLayers.js"></script>
32     </head>
33     <body onload="init()">
34      <div id="map"></div>
35     </body>
36    </html>
37
38The following JavaScript code must then be added in a ``<script></script>`` section within the
39``<head>`` one. This will setup a map showing the japanese regions data as WMS.
40
41.. code-block:: guess
42
43    var map, layer, select, hover, multi, control;
44   
45    var typename="regions";
46    var main_url="http://localhost/cgi-bin/mapserv?map=/var/www/wfs.map";
47   
48    function init(){
49      map = new OpenLayers.Map('map', {
50        controls: [
51          new OpenLayers.Control.PanZoom(),
52          new OpenLayers.Control.Permalink(),
53          new OpenLayers.Control.Navigation()
54        ]
55      });
56      layer = new OpenLayers.Layer.WMS(typename,main_url, {
57            layers: 'regions',
58            transparent: 'true',
59            format: 'image/png'
60          },
61          {
62            isBaseLayer: true,
63            visibility: true,
64            buffer: 0,
65            singleTile: true
66          }
67    );
68      map.addLayers([layer]);
69      map.setCenter(new OpenLayers.LonLat(138,33.5),5);
70    }
71
72Once done, please save your HTML file as ``zoo-ogr.html`` in your workshop directory,
73then copy it in ``/var/www`` and visualize it with your favorite Web browser using this link : 
74``http://localhost/zoo-ogr.html``. You should obtain a map centered on the Japan with the WMS layer activated.
75
76.. image:: ./images/OL-JP-1.png
77   :width: 356px
78   :height: 280px
79   :align: center
80
81Fetching the data layer as WFS and adding selection controls
82************************************************************
83
84Before accessing the displayed data via WFS, you first have to create new vector layers
85dedicated to host the several interactions we are going to create. Please add the following
86lines within the ``init()`` function, and do not forget to add the newly created layer in
87the map.addLayers method:
88
89.. code-block:: guess
90
91    select = new OpenLayers.Layer.Vector("Selection", {
92      styleMap: new OpenLayers.Style(OpenLayers.Feature.Vector.style["select"])
93    });
94         
95    hover = new OpenLayers.Layer.Vector("Hover");
96    multi = new OpenLayers.Layer.Vector("Multi", { styleMap:
97      new OpenLayers.Style({
98        fillColor:"red",
99        fillOpacity:0.4,
100        strokeColor:"red",
101        strokeOpacity:1,
102        strokeWidth:2
103      })
104    });
105   
106    map.addLayers([layer, select, hover, multi]);
107
108Then, you can now access the data by creating new controls to select polygons, as the
109following. Please note that ``OpenLayers.Protocol.WFS.fromWMSLayer`` is used to access
110geometries and that several state of selection are declared and append to the control variable.
111
112.. code-block:: guess
113
114    var protocol = OpenLayers.Protocol.WFS.fromWMSLayer(layer, {
115            featurePrefix: 'ms',
116            geometryName: 'msGeometry',
117            featureType: typename
118    });
119   
120    control = new OpenLayers.Control.GetFeature({
121            protocol: protocol,
122            box: false,
123            hover: false,
124            multipleKey: "shiftKey",
125            toggleKey: "ctrlKey"
126    });
127    control.events.register("featureselected", this, function(e) {
128                    select.addFeatures([e.feature]);
129    });
130    control.events.register("featureunselected", this, function(e) {
131                    select.removeFeatures([e.feature]);
132    });
133    map.addControl(control);
134    control.activate();
135
136Please save your HTML file again. You should now be able to select a polygon only by
137clicking on it. The selected polygon should appear in blue color.
138
139.. image:: ./images/OL-JP-2.png
140   :width: 356px
141   :height: 280px
142   :align: center
143
144Calling the single geometry services from JavaScript
145****************************************************
146
147Now that everything is setup, we can go on and call our OGR ZOO services with JavaScript.
148Please add the following lines after the ``init()`` function, which will call the single
149geometry processes. You can notice that we use a specific ``parseMapServerId`` function
150which let us remove the unecessary white space returned as fid value.
151
152.. code-block:: guess
153
154    function parseMapServerId(){
155      var sf=arguments[0].split(".");
156      return sf[0]+"."+sf[1].replace(/ /g,'');
157    }
158   
159    function simpleProcessing(aProcess) {
160      if (select.features.length == 0)
161        return alert("No feature selected!");
162      if(multi.features.length>=1)
163        multi.removeFeatures(multi.features);
164      var url = '/cgi-bin/zoo_loader.cgi?request=Execute&service=WPS&version=1.0.0&';
165      if (aProcess == 'Buffer') {
166        var dist = document.getElementById('bufferDist')?document.getElementById('bufferDist').value:'1';
167        if (isNaN(dist)) return alert("Distance is not a Number!");
168        url+='Identifier=Buffer&DataInputs=BufferDistance='+dist+'@datatype=interger;InputPolygon=Reference@xlink:href=';
169      } else
170        url += 'Identifier='+aProcess+'&DataInputs=InputPolygon=Reference@xlink:href=';
171      var xlink = control.protocol.url +"&SERVICE=WFS&REQUEST=GetFeature&VERSION=1.0.0";
172      xlink += '&typename='+control.protocol.featurePrefix;
173      xlink += ':'+control.protocol.featureType;
174      xlink += '&SRS='+control.protocol.srsName;
175      xlink += '&FeatureID='+parseMapServerId(select.features[0].fid);
176      url += encodeURIComponent(xlink);
177      url += '&RawDataOutput=Result@mimeType=application/json';
178     
179      var request = new OpenLayers.Request.XMLHttpRequest();
180      request.open('GET',url,true);
181      request.onreadystatechange = function() {
182        if(request.readyState == OpenLayers.Request.XMLHttpRequest.DONE) {
183          var GeoJSON = new OpenLayers.Format.GeoJSON();
184          var features = GeoJSON.read(request.responseText);
185          hover.removeFeatures(hover.features);
186          hover.addFeatures(features);
187        }
188      }
189      request.send();
190    }
191
192
193Then, some specific buttons must be added in the HTML, in order to be able to call
194the different processes we just declared. You can add them on top of the map by writing
195the following lines before the ``<div id="map"></div>``.
196
197.. code-block:: guess
198
199    <div style="float: right;padding-left: 5px;">
200     <h3>Single geometry processing</h3>
201     <ul>
202       <li>
203        <input type="button" onclick="simpleProcessing(this.value);" value="Buffer" />
204        <input id="bufferDist" value="1" />
205       </li>
206       <li>
207        <input type="button" onclick="simpleProcessing(this.value);" value="ConvexHull" />
208       </li>
209       <li>
210        <input type="button" onclick="simpleProcessing(this.value);" value="Boundary" />
211       </li>
212       <li>
213        <input type="button" onclick="simpleProcessing(this.value);" value="Centroid" />
214       </li>
215     </ul>
216    </div>
217
218Save your HTML file again. You should now be able to select a polygon and to launch a Buffer,
219ConvexHull, Boundary or Centroid on it by clicking one of the button. The result of the
220process should appear as GeoJSON layer on the map, in orange color.
221
222.. image:: ./images/OL-JP-3.png
223   :width: 536px
224   :height: 270px
225   :align: center
226
227Calling the multiples geometries processes from JavaScript
228**********************************************************
229
230Using the same technique, you can now write a function dedicated to the multiple geometries
231processes. Please add the following lines after the ``simpleProcessing()`` function, we will
232guide you during the exercise in section 5 on how to create such a function.
233
234.. code-block:: guess
235
236    function multiProcessing(aProcess) {
237      if (select.features.length == 0 || hover.features.length == 0)
238        return alert("No feature created!");
239      var url = '/cgi-bin/zoo_loader.cgi';
240      var xlink = control.protocol.url +"&SERVICE=WFS&REQUEST=GetFeature&VERSION=1.0.0";
241      xlink += '&typename='+control.protocol.featurePrefix;
242      xlink += ':'+control.protocol.featureType;
243      xlink += '&SRS='+control.protocol.srsName;
244      xlink += '&FeatureID='+parseMapServerId(select.features[0].fid);
245      var GeoJSON = new OpenLayers.Format.GeoJSON();
246      try {
247        var params = '<wps:Execute service="WPS" version="1.0.0" xmlns:wps="http://www.opengis.net/wps/1.0.0" xmlns:ows="http://www.opengis.net/ows/1.1" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.opengis.net/wps/1.0.0/../wpsExecute_request.xsd">';
248        params += '<ows:Identifier>'+aProcess+'</ows:Identifier>';
249        params += '<wps:DataInputs>';
250        params += '<wps:Input>';
251        params += '<ows:Identifier>InputEntity1</ows:Identifier>';
252        params += '<wps:Reference xlink:href="'+xlink.replace(/&/gi,'&amp;')+'"/>';
253        params += '</wps:Input>';
254        params += '<wps:Input>';
255        params += '<ows:Identifier>InputEntity2</ows:Identifier>';
256        params += '<wps:Data>';
257        params += '<wps:ComplexData mimeType="application/json"> '+GeoJSON.write(hover.features[0].geometry)+' </wps:ComplexData>';
258        params += '</wps:Data>';
259        params += '</wps:Input>';
260        params += '</wps:DataInputs>';
261        params += '<wps:ResponseForm>';
262        params += '<wps:RawDataOutput>';
263        params += '<ows:Identifier>Result</ows:Identifier>';
264        params += '</wps:RawDataOutput>';
265        params += '</wps:ResponseForm>';
266        params += '</wps:Execute>';
267      } catch(e) {
268        alert(e);
269        return false;
270      }
271      var request = new OpenLayers.Request.XMLHttpRequest();
272      request.open('POST',url,true);
273      request.setRequestHeader('Content-Type','text/xml');
274      request.onreadystatechange = function() {
275        if(request.readyState == OpenLayers.Request.XMLHttpRequest.DONE) {
276          var GeoJSON = new OpenLayers.Format.GeoJSON();
277          var features = GeoJSON.read(request.responseText);
278          multi.removeFeatures(multi.features);
279          multi.addFeatures(features);
280        }
281      }
282      request.send(params);
283    }
284
285Note that this time we didn't use the GET method to request the ZOO Kernel but a XML POST.
286We did that because if you use the GET method you will get error due to the HTTP GET method
287limitation based on the length of your request. Using JSON string representing the geometry
288will make your request longer.
289
290Once you get the functions to call your multiple geometries processes, you' must add some
291buttons to fire the request call. Here is the HTML code to add to your current ``zoo-ogr.html`` file :
292
293.. code-block:: guess
294
295    <h3>Multiple geometries processing</h3>
296    <ul>
297      <li>
298        <input type="button" onclick="multiProcessing(this.value);" value="Union"/>
299      </li>
300      <li>
301        <input type="button" onclick="multiProcessing(this.value);" value="Difference"/>
302      </li>
303      <li>
304        <input type="button" onclick="multiProcessing(this.value);" value="SymDifference"/>
305      </li>
306      <li>
307        <input type="button" onclick="multiProcessing(this.value);" value="Intersection"/>
308      </li>
309    </ul>
310
311Please reload the page. You should then be able to run your multiple geometries services and
312you should get results displayed in red as shown by the following screenshots :
313
314
315.. image:: ./images/OL-JP-4.png
316   :width: 406px
317   :height: 140px
318.. image:: ./images/OL-JP-5.png
319   :width: 406px
320   :height: 140px
321.. image:: ./images/OL-JP-6.png
322   :width: 406px
323   :height: 140px
324.. image:: ./images/OL-JP-7.png
325   :width: 406px
326   :height: 140px
327   
328It seems that something is missing in your Services Provider to get the same results …
329The multiple geometries Services ! This is what we are going to do together in the next section.
Note: See TracBrowser for help on using the repository browser.

Search

ZOO Sponsors

http://www.zoo-project.org/trac/chrome/site/img/geolabs-logo.pnghttp://www.zoo-project.org/trac/chrome/site/img/neogeo-logo.png http://www.zoo-project.org/trac/chrome/site/img/apptech-logo.png http://www.zoo-project.org/trac/chrome/site/img/3liz-logo.png http://www.zoo-project.org/trac/chrome/site/img/gateway-logo.png

Become a sponsor !

Knowledge partners

http://www.zoo-project.org/trac/chrome/site/img/ocu-logo.png http://www.zoo-project.org/trac/chrome/site/img/gucas-logo.png http://www.zoo-project.org/trac/chrome/site/img/polimi-logo.png http://www.zoo-project.org/trac/chrome/site/img/fem-logo.png http://www.zoo-project.org/trac/chrome/site/img/supsi-logo.png http://www.zoo-project.org/trac/chrome/site/img/cumtb-logo.png

Become a knowledge partner

Related links

http://zoo-project.org/img/ogclogo.png http://zoo-project.org/img/osgeologo.png