Changes between Version 1 and Version 2 of ZooWorkshop/FOSS4GJapan/BuildingWPSClientUsingOL


Ignore:
Timestamp:
Oct 15, 2010, 7:45:36 PM (9 years ago)
Author:
djay
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • ZooWorkshop/FOSS4GJapan/BuildingWPSClientUsingOL

    v1 v2  
    1 = Building a WPS client using OpenLayers =
     1= Building a WPS client using !OpenLayers =
    22
    33The next step of our workshop is to connect to the OGR Services we have created from an OpenLayers map. This will allow to apply single or multiple geometries processes on user-selected polygons  and to display the new generated geometries.
     
    55== Creating a simple map showing the dataset as WMS ==
    66
     7OpenLayers is also included in OSGeoLive default distribution, so it is convenient to use it for our needs. Please open your text editor and write the following HTML snippet:
     8
     9{{{
     10#!xml
     11<!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">
     12 <head>
     13  <meta content="text/html; charset=UTF-8" http-equiv="content-type"/>
     14  <title>ZOO WPS Client example</title>
     15  <style>
     16  #map{width:600px;height:600px;}
     17  </style>
     18  <link rel="stylesheet" href="/openlayers/theme/default/style.css" type="text/css" />
     19  <script type="text/javascript" src="/openlayers/lib/OpenLayers.js"></script>
     20 </head>
     21 <body onload="init()">
     22  <div id="map"></div>
     23 </body>
     24</html>
     25}}}
     26
     27The following JavaScript code must then be added in a <script></script> section within the <head> one. This will setup a map showing the United States data as WMS.
     28
     29{{{
     30#!js
     31var map, layer, select, hover, multi, control;
     32
     33function init(){
     34  OpenLayers.ProxyHost= "../cgi-bin/proxy.cgi?url=";
     35  map = new OpenLayers.Map('map', {
     36    controls: [
     37      new OpenLayers.Control.PanZoom(),
     38      new OpenLayers.Control.Permalink(),
     39      new OpenLayers.Control.Navigation()
     40    ]
     41  });
     42  layer = new OpenLayers.Layer.WMS(
     43    "States WMS/WFS",
     44    "http://localhost:8082/geoserver/ows",
     45    {layers: 'topp:states', format: 'image/png'},
     46    {buffer:1, singleTile:true}
     47  );
     48  map.addLayers([layer]);
     49  map.zoomToExtent(new OpenLayers.Bounds(-140.444336,25.115234,-44.438477,50.580078));
     50}
     51}}}
     52
     53Once done, please save your HTML file as zoo-ogr.html in your workshop directory, then copy it in /var/www and visualize it with your favorite Web browser using this link : http://localhost/zoo-ogr.html. You should obtain a map centered on the USA with the WMS layer activated.
     54
     55== Fetching the data layer as WFS and adding selection controls ==
     56
     57Before accessing the displayed data via WFS, you first have to create new vector layers dedicated to host the several interactions we are going to create. Please add the following lines within the init() function, and do not forget to add the newly created layer in the map.addLayers method:
     58
     59{{{
     60#!js
     61select = new OpenLayers.Layer.Vector("Selection", {styleMap:
     62                new OpenLayers.Style(OpenLayers.Feature.Vector.style["select"])
     63            });
     64hover = new OpenLayers.Layer.Vector("Hover");
     65
     66multi = new OpenLayers.Layer.Vector("Multi", {styleMap:
     67                new OpenLayers.Style({
     68                  fillColor:"red",
     69                  fillOpacity:0.4,
     70                  strokeColor:"red",
     71                  strokeOpacity:1,
     72                  strokeWidth:2
     73                })
     74            });
     75
     76map.addLayers([layer, select, hover, multi]);
     77}}}
     78
     79Then, you can now access tdata by creating new controls to select polygons, as the following. Please note that OpenLayers.Protocol.WFS.fromWMSLayer(layer) is used to access geometries and that several state of selection are declared and append to the control variable.
     80
     81{{{
     82#!js
     83control = new OpenLayers.Control.GetFeature({
     84                protocol: OpenLayers.Protocol.WFS.fromWMSLayer(layer)
     85            });
     86control.events.register("featureselected", this, function(e) {
     87                select.addFeatures([e.feature]);
     88            });
     89control.events.register("featureunselected", this, function(e) {
     90                select.removeFeatures([e.feature]);
     91            });
     92control.events.register("hoverfeature", this, function(e) {
     93                hover.addFeatures([e.feature]);
     94            });
     95control.events.register("outfeature", this, function(e) {
     96                hover.removeFeatures([e.feature]);
     97            });
     98map.addControl(control);
     99control.activate();
     100}}}
     101
     102Please save your HTML file again. You should now be able to select a polygon only by clicking on it. The selected polygon should appear in blue color.
     103
     104== Calling the single geometrie processes from JavaScript ==
     105
     106Now that everything is setup, we can go on and call our OGR ZOO services with JavaScript. Please add the following lines after the init() function, which will call the single geometry processes.
     107
     108{{{
     109#!c
     110function simpleProcessing(aProcess) {
     111   if (select.features.length == 0)
     112    return alert("No feature selected!");
     113  var url = '/zoo/?request=Execute&service=WPS&version=1.0.0&';
     114  if (aProcess == 'Buffer') {
     115    var dist = document.getElementById('bufferDist').value;
     116    if (isNaN(dist))
     117      return alert("Distance is not a Number!");
     118    url+='Identifier=Buffer&DataInputs=BufferDistance='+dist+'@datatype=interger;InputPolygon=Reference@xlink:href=';
     119  } else
     120      url += 'Identifier='+aProcess+'&DataInputs=InputPolygon=Reference@xlink:href=';
     121  var xlink = control.protocol.url +"?SERVICE=WFS&REQUEST=GetFeature&VERSION=1.0.0";
     122  xlink += '&typename='+control.protocol.featurePrefix;
     123  xlink += ':'+control.protocol.featureType;
     124  xlink += '&SRS='+control.protocol.srsName;
     125  xlink += '&FeatureID='+select.features[0].fid;
     126  url += encodeURIComponent(xlink);
     127  url += '&RawDataOutput=Result@mimeType=application/json';
     128  var request = new OpenLayers.Request.XMLHttpRequest();
     129  request.open('GET',url,true);
     130  request.onreadystatechange = function() {
     131   if(request.readyState == OpenLayers.Request.XMLHttpRequest.DONE) {
     132      var GeoJSON = new OpenLayers.Format.GeoJSON();
     133      var features = GeoJSON.read(request.responseText);
     134      hover.removeFeatures(hover.features);
     135      hover.addFeatures(features);
     136    }
     137  }
     138  request.send();
     139}
     140}}}
     141
     142Then, some specific buttons must be added in the HTML, in order to be able to call the different processes we just declared. You can add them on top of the map by writing the following lines before the <div id="map"></div>.
     143
     144{{{
     145#!xml
     146<h3>Single geometry processing</h3>
     147<ul>
     148  <li>
     149    <input type="button" onclick="simpleProcessing(this.value);" value="Buffer" />
     150    <input id="bufferDist" value="1" />
     151  </li>
     152  <li>
     153    <input type="button" onclick="simpleProcessing(this.value);" value="ConvexHull" />
     154  </li>
     155  <li>
     156    <input type="button" onclick="simpleProcessing(this.value);" value="Boundary" />
     157  </li>
     158  <li>
     159    <input type="button" onclick="simpleProcessing(this.value);" value="Centroid" />
     160  </li>
     161</ul>
     162}}}
     163
     164Save your HTML file again. You should now be able to select a polygon and to launch a Buffer, ConvexHull, Boundary or Centroid on it by clicking one of the button. The result of the process should appear as GeoJSON layer on the map, in orange color.
     165
     166== Calling the multiples geometries processes from JavaScript ==
     167
     168Using the same technique, you can now write a function dedicated to the multiple geometries processes. Please add the following lines after the simpleProcessing() function, we will guide you during the exercise in section 5 on how to create such a function.
     169
     170{{{
     171#!js
     172function multiProcessing(aProcess) {
     173 if (select.features.length == 0 || hover.features.length == 0)
     174   return alert("No feature created!");
     175 var url = '/zoo/';
     176 var xlink = control.protocol.url +"?SERVICE=WFS&REQUEST=GetFeature&VERSION=1.0.0";
     177 xlink += '&typename='+control.protocol.featurePrefix;
     178 xlink += ':'+control.protocol.featureType;
     179 xlink += '&SRS='+control.protocol.srsName;
     180 xlink += '&FeatureID='+select.features[0].fid;
     181 var GeoJSON = new OpenLayers.Format.GeoJSON();
     182 try {
     183    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">';
     184    params += ' <ows:Identifier>'+aProcess+'</ows:Identifier>';
     185    params += ' <wps:DataInputs>';
     186    params += ' <wps:Input>';
     187    params += ' <ows:Identifier>InputEntity1</ows:Identifier>';
     188    params += ' <wps:Reference xlink:href="'+xlink.replace(/&/gi,'&amp;')+'"/>';
     189    params += ' </wps:Input>';
     190    params += ' <wps:Input>';
     191    params += ' <ows:Identifier>InputEntity2</ows:Identifier>';
     192    params += ' <wps:Data>';
     193    params += ' <wps:ComplexData mimeType="application/json"> '+GeoJSON.write(hover.features[0].geometry)+' </wps:ComplexData>';
     194    params += ' </wps:Data>';
     195    params += ' </wps:Input>';
     196    params += ' </wps:DataInputs>';
     197    params += ' <wps:ResponseForm>';
     198    params += ' <wps:RawDataOutput>';
     199    params += ' <ows:Identifier>Result</ows:Identifier>';
     200    params += ' </wps:RawDataOutput>';
     201    params += ' </wps:ResponseForm>';
     202    params += ' </wps:Execute>';
     203 } catch(e) {
     204    alert(e);
     205    return false;
     206 }
     207 var request = new OpenLayers.Request.XMLHttpRequest();
     208 request.open('POST',url,true);
     209 request.setRequestHeader('Content-Type','text/xml');
     210 request.onreadystatechange = function() {
     211   if(request.readyState == OpenLayers.Request.XMLHttpRequest.DONE) {
     212     var GeoJSON = new OpenLayers.Format.GeoJSON();
     213     var features = GeoJSON.read(request.responseText);
     214     multi.removeFeatures(multi.features);
     215     multi.addFeatures(features);
     216   }
     217 }
     218 request.send(params);
     219}
     220}}}
     221
     222Note that this time we didn't use the GET method to request the ZOO Kernel but a XML POST. We did that because if you use the GET method you will get error due to the HTTP GET method limitation based on the length of your request. Using JSON string representing the geometry will make your request longer.
     223
     224Once you get the functions to call your multiple geometries processes, you' must add some buttons to fire the request call. Here is the HTML code to add to your current zoo-ogr.html file :
     225
     226{{{
     227#!xml
     228<h3>Multiple geometries processing</h3>
     229<ul>
     230  <li>
     231    <input type="button" onclick="multiProcessing(this.name);" value="Union"/>
     232  </li>
     233  <li>
     234    <input type="button" onclick="multiProcessing(this.name);" value="Difference"/>
     235  </li>
     236  <li>
     237    <input type="button" onclick="multiProcessing(this.value);" value="SymDifference"/>
     238  </li>
     239  <li>
     240    <input type="button" onclick="multiProcessing(this.name);" value="Intersection"/>
     241  </li>
     242</ul>
     243}}}
     244
     245Please reload the page. You should then be able to run your multiple geometries services and you should get results displayed in red as shown by the following screenshots :
     246
     247It seems that something is missing in your Services Provider to get the same results … The multiple geometries Services ! This is what we are going to do together in the next section.

Search

Context Navigation

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