source: trunk/zoo-services/ogr/base-vect-ops/service.c @ 32

Last change on this file since 32 was 32, checked in by djay, 10 years ago

Add missing updated code from 26 ...

File size: 17.4 KB
Line 
1/**
2 * Author : Gérald FENOY
3 *
4 * Copyright 2008-2009 GeoLabs SARL. All rights reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
23 */
24
25#include "cpl_conv.h"
26#include "ogr_api.h"
27#include "ogr_geometry.h"
28#include "geos_c.h"
29#include "service.h"
30
31extern "C" {
32#include <libxml/tree.h>
33#include <libxml/parser.h>
34#include <libxml/xpath.h>
35#include <libxml/xpathInternals.h>
36
37#include <openssl/sha.h>
38#include <openssl/hmac.h>
39#include <openssl/evp.h>
40#include <openssl/bio.h>
41#include <openssl/buffer.h>
42
43  void printExceptionReportResponse(maps*,map*);
44  char *base64(const unsigned char *input, int length);
45
46  OGRGeometryH createGeometryFromGML(maps* conf,char* inputStr){
47    xmlInitParser();
48    xmlDocPtr doc = xmlParseMemory(inputStr,strlen(inputStr));
49    xmlChar *xmlbuff;
50    int buffersize;
51    xmlXPathContextPtr xpathCtx;
52    xmlXPathObjectPtr xpathObj;
53    char * xpathExpr="/*/*/*/*/*[local-name()='Polygon' or local-name()='MultiPolygon']";
54    xpathCtx = xmlXPathNewContext(doc);
55    xpathObj = xmlXPathEvalExpression(BAD_CAST xpathExpr,xpathCtx);
56    if(!xpathObj->nodesetval){
57      map* tmp=createMap("text","Unable to parse Input Polygon");
58      addToMap(tmp,"code","InvalidParameterValue");
59      printExceptionReportResponse(conf,tmp);
60      exit(0);
61    }
62    int size = (xpathObj->nodesetval) ? xpathObj->nodesetval->nodeNr : 0;
63    /**
64     * Create a temporary XML document
65     */
66    xmlDocPtr ndoc = xmlNewDoc(BAD_CAST "1.0");
67    /**
68     * Only one polygon should be provided so we use it as the root node.
69     */
70    for(int k=size-1;k>=0;k--){ 
71      xmlDocSetRootElement(ndoc, xpathObj->nodesetval->nodeTab[k]);
72    }
73    xmlDocDumpFormatMemory(ndoc, &xmlbuff, &buffersize, 1);
74    char *tmp=(char*)calloc((xmlStrlen(xmlStrstr(xmlbuff,BAD_CAST "?>"))-1),sizeof(char));
75    sprintf(tmp,"%s",xmlStrstr(xmlbuff,BAD_CAST "?>")+2);
76    xmlXPathFreeObject(xpathObj);
77    xmlXPathFreeContext(xpathCtx);
78    xmlFree(xmlbuff);
79    xmlFreeDoc(doc);
80    xmlFreeDoc(ndoc);
81    xmlCleanupParser();
82#ifdef DEBUG
83    fprintf(stderr,"\nService internal print\n Loading the geometry from GML string ...");
84#endif
85    OGRGeometryH res=OGR_G_CreateFromGML(tmp);
86    free(tmp);
87    if(res==NULL){
88      setMapInMaps(conf,"lenv","message","Unable to call OGR_G_CreatFromGML");
89      return NULL;
90    }
91    else
92      return res;
93  }
94
95  int Simplify(maps*& conf,maps*& inputs,maps*& outputs){
96    maps* cursor=inputs;
97    OGRGeometryH geometry,res;
98    double tolerance;
99    map* tmp0=getMapFromMaps(cursor,"Tolerance","value");
100    if(tmp0==NULL){
101      tolerance=atof("2.0");
102    }
103    else
104      tolerance=atof(tmp0->value);
105    fprintf(stderr,"Tolerance for Simplify %f",tolerance);
106    map* tmp=getMapFromMaps(inputs,"InputPolygon","value");
107    if(!tmp){
108      setMapInMaps(conf,"lenv","message","Unagle to parse the input geometry from InputPolygon");
109      return SERVICE_FAILED;
110    }
111    map* tmp1=getMapFromMaps(inputs,"InputPolygon","mimeType");
112    if(tmp1!=NULL){
113      if(strncmp(tmp1->value,"text/js",7)==0 ||
114         strncmp(tmp1->value,"application/json",16)==0)
115        geometry=OGR_G_CreateGeometryFromJson(tmp->value);
116      else
117        geometry=createGeometryFromGML(conf,tmp->value);
118    }
119    else{
120      setMapInMaps(conf,"lenv","message","Unable to find any geometry for InputPolygon");
121      return SERVICE_FAILED;
122    }
123    if(geometry==NULL){
124      setMapInMaps(conf,"lenv","message","Unagle to parse the input geometry from InputPolygon");
125      return SERVICE_FAILED;
126    }
127    fprintf(stderr,"Create GEOSGeometry object");
128    GEOSGeometry* ggeometry=((OGRGeometry *) geometry)->exportToGEOS();
129    GEOSGeometry* gres=GEOSTopologyPreserveSimplify(ggeometry,tolerance);
130    res=OGRGeometryFactory::createFromGEOS(gres);
131    tmp1=getMapFromMaps(outputs,"Result","mimeType");
132    if(tmp1!=NULL){
133      if(strncmp(tmp1->value,"text/js",7)==0 ||
134         strncmp(tmp1->value,"application/json",16)==0){
135        char *tmpS=OGR_G_ExportToJson(res);
136        setMapInMaps(outputs,"Result","value",tmpS);
137        setMapInMaps(outputs,"Result","mimeType","text/plain");
138        setMapInMaps(outputs,"Result","encoding","UTF-8");
139        free(tmpS);
140      }
141      else{
142        char *tmpS=OGR_G_ExportToGML(res);
143        setMapInMaps(outputs,"Result","value",tmpS);
144        setMapInMaps(outputs,"Result","mimeType","text/xml");
145        setMapInMaps(outputs,"Result","encoding","UTF-8");
146        setMapInMaps(outputs,"Result","schema","http://fooa/gml/3.1.0/polygon.xsd");
147        free(tmpS);
148      }
149    }else{
150      char *tmpS=OGR_G_ExportToJson(tmp->value);
151      setMapInMaps(outputs,"Result","value",tmpS);
152      setMapInMaps(outputs,"Result","mimeType","text/plain");
153      setMapInMaps(outputs,"Result","encoding","UTF-8");
154      free(tmpS);
155    }
156    outputs->next=NULL;
157    //GEOSFree(ggeometry);
158    //GEOSFree(gres);
159    OGR_G_DestroyGeometry(res);
160    OGR_G_DestroyGeometry(geometry);
161    return SERVICE_SUCCEEDED;
162  }
163
164
165  int applyOne(maps*& conf,maps*& inputs,maps*& outputs,OGRGeometryH (*myFunc)(OGRGeometryH)){
166#ifdef DEBUG
167    fprintf(stderr,"\nService internal print\n");
168#endif
169    maps* cursor=inputs;
170    OGRGeometryH geometry,res;
171#ifdef DEBUG
172    dumpMaps(cursor);
173#endif
174    map* tmp=getMapFromMaps(inputs,"InputPolygon","value");
175    if(!tmp)
176      return SERVICE_FAILED;
177    fprintf(stderr,"Service internal print \n");
178    dumpMaps(inputs);
179    fprintf(stderr,"/Service internal print \n");
180    map* tmp1=getMapFromMaps(inputs,"InputPolygon","mimeType");
181    fprintf(stderr,"Service internal print \n");
182    dumpMap(tmp1);
183    fprintf(stderr,"/Service internal print \n");
184    if(tmp1!=NULL){
185      if(strncmp(tmp1->value,"text/js",7)==0 ||
186         strncmp(tmp1->value,"application/json",7)==0)
187        geometry=OGR_G_CreateGeometryFromJson(tmp->value);
188      else
189        geometry=createGeometryFromGML(conf,tmp->value);
190    }
191    else
192      geometry=createGeometryFromGML(conf,tmp->value);
193    if(geometry==NULL)
194      return SERVICE_FAILED;
195    res=(*myFunc)(geometry);
196    fprintf(stderr,"Service internal print \n");
197    dumpMaps(outputs);
198    fprintf(stderr,"/Service internal print \n");
199    map *tmp_2=getMapFromMaps(outputs,"Result","mimeType");
200    fprintf(stderr,"Service internal print \n");
201    dumpMap(tmp_2);
202    fprintf(stderr,"/Service internal print \n");
203    if(tmp_2!=NULL){
204      if(strncmp(tmp_2->value,"text/js",7)==0 ||
205         strncmp(tmp_2->value,"application/json",16)==0){
206        char *tmpS=OGR_G_ExportToJson(res);
207        setMapInMaps(outputs,"Result","value",tmpS);
208        setMapInMaps(outputs,"Result","mimeType","text/plain");
209        setMapInMaps(outputs,"Result","encoding","UTF-8");
210        free(tmpS);
211      }
212      else{
213        char *tmpS=OGR_G_ExportToGML(res);
214        setMapInMaps(outputs,"Result","value",tmpS);
215        setMapInMaps(outputs,"Result","mimeType","text/plain");
216        setMapInMaps(outputs,"Result","encoding","UTF-8");
217        free(tmpS);
218
219      }
220    }else{
221      char *tmpS=OGR_G_ExportToJson(res);
222      setMapInMaps(outputs,"Result","value",tmpS);
223      setMapInMaps(outputs,"Result","mimeType","text/plain");
224      setMapInMaps(outputs,"Result","encoding","UTF-8");
225      free(tmpS);
226    }
227    outputs->next=NULL;
228#ifdef DEBUG
229    dumpMaps(outputs);
230    fprintf(stderr,"\nService internal print\n===\n");
231#endif
232    OGR_G_DestroyGeometry(res);
233    OGR_G_DestroyGeometry(geometry);
234    //CPLFree(res);
235    //CPLFree(geometry);
236    fprintf(stderr,"Service internal print \n");
237    dumpMaps(outputs);
238    fprintf(stderr,"/Service internal print \n");
239    return SERVICE_SUCCEEDED;
240  }
241
242#ifdef WIN32
243  __declspec(dllexport)
244#endif
245int Buffer(maps*& conf,maps*& inputs,maps*& outputs){
246   OGRGeometryH geometry,res;
247   map* tmp=getMapFromMaps(inputs,"InputPolygon","value");
248   if(tmp==NULL){
249     setMapInMaps(conf,"lenv","message","Unable to fetch input geometry");
250     return SERVICE_FAILED;
251   }else
252     if(strlen(tmp->value)<=0){
253       setMapInMaps(conf,"lenv","message","Unable to fetch input geometry");
254       return SERVICE_FAILED;
255     }
256   map* tmp1=getMapFromMaps(inputs,"InputPolygon","mimeType");
257   if(strncmp(tmp1->value,"application/json",16)==0)
258     geometry=OGR_G_CreateGeometryFromJson(tmp->value);
259   else
260     geometry=createGeometryFromGML(conf,tmp->value);
261   if(geometry==NULL){
262     setMapInMaps(conf,"lenv","message","Unable to parse input geometry");
263     return SERVICE_FAILED;
264   }
265   double bufferDistance;
266   tmp=getMapFromMaps(inputs,"BufferDistance","value");
267   if(tmp==NULL){
268     bufferDistance=atof("10.0");
269   }
270   else
271     bufferDistance=atof(tmp->value);
272   res=OGR_G_Buffer(geometry,bufferDistance,30);
273   tmp1=getMapFromMaps(outputs,"Result","mimeType");
274   if(strncmp(tmp1->value,"application/json",16)==0){
275     char *tmpS=OGR_G_ExportToJson(res);
276     setMapInMaps(outputs,"Result","value",tmpS);
277     setMapInMaps(outputs,"Result","mimeType","text/plain");
278     setMapInMaps(outputs,"Result","encoding","UTF-8");
279     free(tmpS);
280   }
281   else{
282     char *tmpS=OGR_G_ExportToGML(res);
283     setMapInMaps(outputs,"Result","value",tmpS);
284     setMapInMaps(outputs,"Result","mimeType","text/xml");
285     setMapInMaps(outputs,"Result","encoding","UTF-8");
286     setMapInMaps(outputs,"Result","schema","http://fooa/gml/3.1.0/polygon.xsd");
287   }
288   outputs->next=NULL;
289   OGR_G_DestroyGeometry(geometry);
290   OGR_G_DestroyGeometry(res);
291   return SERVICE_SUCCEEDED;
292}
293
294#ifdef WIN32
295  __declspec(dllexport)
296#endif
297  int Boundary(maps*& conf,maps*& inputs,maps*& outputs){
298    return applyOne(conf,inputs,outputs,&OGR_G_GetBoundary);
299  }
300
301#ifdef WIN32
302  __declspec(dllexport)
303#endif
304  int ConvexHull(maps*& conf,maps*& inputs,maps*& outputs){
305    return applyOne(conf,inputs,outputs,&OGR_G_ConvexHull);
306  }
307
308
309  OGRGeometryH MY_OGR_G_Centroid(OGRGeometryH hTarget){
310    OGRGeometryH res;
311    res=OGR_G_CreateGeometryFromJson("{\"type\": \"Point\", \"coordinates\": [0,0] }");
312    OGRwkbGeometryType gtype=OGR_G_GetGeometryType(hTarget);
313    if(gtype!=wkbPolygon){
314      hTarget=OGR_G_ConvexHull(hTarget);
315    }
316    int c=OGR_G_Centroid(hTarget,res);
317    return res;
318  }
319
320#ifdef WIN32
321  __declspec(dllexport)
322#endif
323  int Centroid(maps*& conf,maps*& inputs,maps*& outputs){
324    return applyOne(conf,inputs,outputs,&MY_OGR_G_Centroid);
325  }
326
327  int applyTwo(maps*& conf,maps*& inputs,maps*& outputs,OGRGeometryH (*myFunc)(OGRGeometryH,OGRGeometryH)){
328#ifdef DEBUG
329    fprintf(stderr,"\nService internal print1\n");
330    fflush(stderr);
331#endif
332    fprintf(stderr,"\nService internal print1\n");
333    dumpMaps(inputs);
334    fprintf(stderr,"\nService internal print1\n");
335
336    maps* cursor=inputs;
337    OGRGeometryH geometry1,geometry2;
338    OGRGeometryH res;
339    {
340      map* tmp=getMapFromMaps(inputs,"InputEntity1","value");
341      map* tmp1=getMapFromMaps(inputs,"InputEntity1","mimeType");
342      if(tmp1!=NULL){
343        if(strncmp(tmp1->value,"application/json",16)==0)
344          geometry1=OGR_G_CreateGeometryFromJson(tmp->value);
345        else
346          geometry1=createGeometryFromGML(conf,tmp->value);
347      }
348      else
349        geometry1=createGeometryFromGML(conf,tmp->value);
350    }
351    if(geometry1==NULL){
352      setMapInMaps(conf,"lenv","message","Unable to parse input geometry for InputEntity1.");
353      fprintf(stderr,"SERVICE FAILED !\n");
354      return SERVICE_FAILED;
355    }
356    fprintf(stderr,"\nService internal print1 InputEntity1\n");
357    {
358      map* tmp=getMapFromMaps(inputs,"InputEntity2","value");
359      map* tmp1=getMapFromMaps(inputs,"InputEntity2","mimeType");
360      //#ifdef DEBUG
361      fprintf(stderr,"MY MAP \n[%s] - %i\n",tmp1->value,strncmp(tmp1->value,"application/json",16));
362      //dumpMap(tmp);
363      fprintf(stderr,"MY MAP\n");
364      ///#endif
365      fprintf(stderr,"\nService internal print1 InputEntity2\n");
366      if(tmp1!=NULL){
367        if(strncmp(tmp1->value,"application/json",16)==0){
368          fprintf(stderr,"\nService internal print1 InputEntity2 as JSON\n");
369          geometry2=OGR_G_CreateGeometryFromJson(tmp->value);
370        }
371        else{
372          fprintf(stderr,"\nService internal print1 InputEntity2 as GML\n");
373          geometry2=createGeometryFromGML(conf,tmp->value);
374        }
375      }
376      else
377        geometry2=createGeometryFromGML(conf,tmp->value);
378      fprintf(stderr,"\nService internal print1 InputEntity2 PreFinal\n");
379    }
380    fprintf(stderr,"\nService internal print1 InputEntity2 Final\n");
381    if(geometry2==NULL){
382      setMapInMaps(conf,"lenv","message","Unable to parse input geometry for InputEntity2.");
383      fprintf(stderr,"SERVICE FAILED !\n");
384      return SERVICE_FAILED;
385    }
386    fprintf(stderr,"\nService internal print1\n");
387    res=(*myFunc)(geometry1,geometry2);
388    fprintf(stderr,"\nService internal print1\n");
389    char *tmpS=OGR_G_ExportToJson(res);
390    setMapInMaps(outputs,"Result","value",tmpS);
391    setMapInMaps(outputs,"Result","mimeType","text/plain");
392    setMapInMaps(outputs,"Result","encoding","UTF-8");
393    free(tmpS);
394    OGR_G_DestroyGeometry(geometry1);
395    OGR_G_DestroyGeometry(geometry2);
396    OGR_G_DestroyGeometry(res);
397    return SERVICE_SUCCEEDED;
398  }
399 
400#ifdef WIN32
401  __declspec(dllexport)
402#endif
403  int Difference(maps*& conf,maps*& inputs,maps*& outputs){
404    return applyTwo(conf,inputs,outputs,&OGR_G_Difference);
405  }
406
407#ifdef WIN32
408  __declspec(dllexport)
409#endif
410  int SymDifference(maps*& conf,maps*& inputs,maps*& outputs){
411    return applyTwo(conf,inputs,outputs,&OGR_G_SymmetricDifference);
412  }
413
414#ifdef WIN32
415  __declspec(dllexport)
416#endif
417  int Intersection(maps*& conf,maps*& inputs,maps*& outputs){
418    return applyTwo(conf,inputs,outputs,&OGR_G_Intersection);
419  }
420
421#ifdef WIN32
422  __declspec(dllexport)
423#endif
424  int Union(maps*& conf,maps*& inputs,maps*& outputs){
425    return applyTwo(conf,inputs,outputs,&OGR_G_Union);
426  }
427
428#ifdef WIN32
429  __declspec(dllexport)
430#endif
431  int Distance(maps*& conf,maps*& inputs,maps*& outputs){
432#ifdef DEBUG
433    fprintf(stderr,"\nService internal print1\n");
434#endif
435    fflush(stderr);
436    maps* cursor=inputs;
437    OGRGeometryH geometry1,geometry2;
438    double res;
439    {
440      map* tmp=getMapFromMaps(inputs,"InputEntity1","value");
441      map* tmp1=getMapFromMaps(inputs,"InputEntity1","mimeType");
442#ifdef DEBUG
443      fprintf(stderr,"MY MAP\n");
444      dumpMap(tmp1);
445      dumpMaps(inputs);
446      fprintf(stderr,"MY MAP\n");
447#endif
448      if(tmp1!=NULL){
449        if(strncmp(tmp1->value,"application/json",16)==0)
450          geometry1=OGR_G_CreateGeometryFromJson(tmp->value);
451        else
452          geometry1=createGeometryFromGML(conf,tmp->value);
453      }
454      else
455        geometry1=createGeometryFromGML(conf,tmp->value);
456    }
457    if(geometry1==NULL){
458      setMapInMaps(conf,"lenv","message","Unable to parse input geometry for InputEntity1.");
459      fprintf(stderr,"SERVICE FAILED !\n");
460      return SERVICE_FAILED;
461    }
462    {
463      map* tmp=getMapFromMaps(inputs,"InputEntity2","value");
464      map* tmp1=getMapFromMaps(inputs,"InputEntity2","mimeType");
465#ifdef DEBUG
466      fprintf(stderr,"MY MAP\n");
467      dumpMap(tmp1);
468      dumpMaps(inputs);
469      fprintf(stderr,"MY MAP\n");
470#endif
471      if(tmp1!=NULL){
472        if(strncmp(tmp1->value,"application/json",16)==0)
473          geometry2=OGR_G_CreateGeometryFromJson(tmp->value);
474        else
475          geometry2=createGeometryFromGML(conf,tmp->value);
476      }
477      else
478        geometry2=createGeometryFromGML(conf,tmp->value);
479    }
480    if(geometry2==NULL){
481      setMapInMaps(conf,"lenv","message","Unable to parse input geometry for InputEntity2.");
482      fprintf(stderr,"SERVICE FAILED !\n");
483      return SERVICE_FAILED;
484    }
485    res=OGR_G_Distance(geometry1,geometry2);   
486    char tmpres[100];
487    sprintf(tmpres,"%d",res);
488    setMapInMaps(outputs,"Distance","value",tmpres);
489    setMapInMaps(outputs,"Distance","dataType","float");
490#ifdef DEBUG
491    dumpMaps(outputs);
492    fprintf(stderr,"\nService internal print\n===\n");
493#endif
494    return SERVICE_SUCCEEDED;
495  }
496
497#ifdef WIN32
498  __declspec(dllexport)
499#endif
500  int GetArea(maps*& conf,maps*& inputs,maps*& outputs){
501    fprintf(stderr,"GETAREA \n");
502    double res;
503    /**
504     * Extract Geometry from the InputPolygon value
505     */
506    OGRGeometryH geometry;
507    map* tmp=getMapFromMaps(inputs,"InputPolygon","value");
508    if(tmp==NULL){
509      setMapInMaps(conf,"lenv","message","Unable to parse input geometry from InputPolygon");
510      return SERVICE_FAILED;
511    }
512    fprintf(stderr,"geometry creation %s \n",tmp->value);
513    geometry=createGeometryFromGML(conf,tmp->value);
514    if(geometry==NULL){
515      setMapInMaps(conf,"lenv","message","Unable to parse input geometry from InputPolygon");
516      return SERVICE_FAILED;
517    }
518    fprintf(stderr,"geometry created %s \n",tmp->value);
519    res=OGR_G_GetArea(geometry);
520    fprintf(stderr,"area %d \n",res);
521    /**
522     * Filling the outputs
523     */
524    char tmp1[100];
525    sprintf(tmp1,"%d",res);
526    setMapInMaps(outputs,"Area","value",tmp1);
527    setMapInMaps(outputs,"Area","dataType","float");
528#ifdef DEBUG
529    dumpMaps(outputs);
530#endif
531    return SERVICE_SUCCEEDED;
532  }
533
534}
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