~ubuntu-branches/ubuntu/jaunty/mapserver/jaunty-updates

« back to all changes in this revision

Viewing changes to mapgeos.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Fabio Tranchitella
  • Date: 2006-11-02 11:44:17 UTC
  • mfrom: (1.1.3 upstream)
  • Revision ID: james.westby@ubuntu.com-20061102114417-pnutjb20kqzl23ua
Tags: 4.10.0-3
debian/control: build-depends on libpq-dev. (Closes: #396565)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/******************************************************************************
2
 
 *
3
 
 * Project:  MapServer
4
 
 * Purpose:  MapServer-GEOS integration.
5
 
 * Author:   Steve Lime and the MapServer team.
6
 
 *
7
 
 ******************************************************************************
8
 
 * Copyright (c) 1996-2005 Regents of the University of Minnesota.
9
 
 *
10
 
 * Permission is hereby granted, free of charge, to any person obtaining a
11
 
 * copy of this software and associated documentation files (the "Software"),
12
 
 * to deal in the Software without restriction, including without limitation
13
 
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
14
 
 * and/or sell copies of the Software, and to permit persons to whom the
15
 
 * Software is furnished to do so, subject to the following conditions:
16
 
 *
17
 
 * The above copyright notice and this permission notice shall be included in 
18
 
 * all copies of this Software or works derived from this Software.
19
 
 *
20
 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
21
 
 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22
 
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
23
 
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24
 
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
25
 
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
26
 
 * DEALINGS IN THE SOFTWARE.
27
 
 ******************************************************************************
28
 
 *
29
 
 * $Log: mapgeos.cpp,v $
30
 
 * Revision 1.14.2.1  2006/01/18 07:14:38  sdlime
31
 
 * Update GEOS toWKT function to produce a malloc'd pointer. Updated shape.i to produce a new object. (bug 1466)
32
 
 *
33
 
 * Revision 1.14  2005/10/31 04:59:43  sdlime
34
 
 * Now catching exceptions when reading WKT strings.
35
 
 *
36
 
 * Revision 1.13  2005/10/30 05:05:07  sdlime
37
 
 * Initial support for WKT via GEOS. The reader is only integrated via the map file reader, with MapScript, CGI and URL support following ASAP. (bug 1466)
38
 
 *
39
 
 * Revision 1.12  2005/06/14 16:03:33  dan
40
 
 * Updated copyright date to 2005
41
 
 *
42
 
 * Revision 1.11  2005/06/14 04:28:44  sdlime
43
 
 * Fixed GEOS to shapeObj for multipolgon geometries.
44
 
 *
45
 
 * Revision 1.10  2005/05/19 05:57:08  sdlime
46
 
 * More interface clean up, added msGEOSFreeGeometry and updated geometry2shape code to so the new shapeObj contains a reference to the geometry used to create it.
47
 
 *
48
 
 * Revision 1.9  2005/05/17 13:59:57  sdlime
49
 
 * More GEOS interface improvements (global GeometryFactory).
50
 
 *
51
 
 * Revision 1.8  2005/05/11 07:10:21  sdlime
52
 
 * Finished the rest of the wrapper funtions for initial GEOS support which basically ammounts to buffer and convex hull creation from MapScript at the moment. There are likely a number of memory leaks associated with the implementation at the moment.
53
 
 *
54
 
 * Revision 1.7  2005/02/23 05:16:50  sdlime
55
 
 * Added GEOS=>shape conversion for GEOS_MULTILINE geometries.
56
 
 *
57
 
 * Revision 1.6  2005/02/23 04:52:33  sdlime
58
 
 * Added GEOS=>shape conversion for GEOS_MULTIPOINT geometries.
59
 
 *
60
 
 * Revision 1.5  2005/02/23 04:40:17  sdlime
61
 
 * Added wrapper for creating convex hulls to GEOS support. Added to MapScript as well.
62
 
 *
63
 
 * Revision 1.4  2005/02/22 18:33:37  dan
64
 
 * Fixes to build without USE_GEOS
65
 
 *
66
 
 * Revision 1.3  2005/02/22 07:40:27  sdlime
67
 
 * A bunch of updates to GEOS integration. Can move many primatives between
68
 
 * MapServer and GEOS, still need to do collections (e.g. multi-point/line/polygon).
69
 
 * Added buffer method to mapscript (mapscript/shape.i).
70
 
 *
71
 
 * Revision 1.2  2004/10/28 02:23:35  frank
72
 
 * added standard header
73
 
 *
74
 
 */
75
 
 
76
 
#include "map.h"
77
 
 
78
 
#ifdef USE_GEOS
79
 
#include <string>
80
 
#include <iostream>
81
 
#include <fstream>
82
 
 
83
 
#include "geos.h"
84
 
 
85
 
MS_CVSID("$Id: mapgeos.cpp,v 1.14.2.1 2006/01/18 07:14:38 sdlime Exp $")
86
 
 
87
 
using namespace geos;
88
 
 
89
 
/*
90
 
** Global variables: only the read-only GeometryFactory.
91
 
*/
92
 
GeometryFactory *gf=NULL;
93
 
 
94
 
static void msGEOSCreateGeometryFactory() 
95
 
{
96
 
  if(!gf) 
97
 
    gf = new GeometryFactory();
98
 
}
99
 
 
100
 
/*
101
 
** Translation functions
102
 
*/
103
 
static Geometry *msGEOSShape2Geometry_point(pointObj *point)
104
 
{
105
 
  try {
106
 
    Coordinate *c = new Coordinate(point->x, point->y);
107
 
    Geometry *g = gf->createPoint(*c);
108
 
    delete c;
109
 
    return g;
110
 
  } catch (GEOSException *ge) {
111
 
    msSetError(MS_GEOSERR, "%s", "msGEOSShape2Geometry_point()", (char *) ge->toString().c_str());
112
 
    delete ge;
113
 
    return NULL;
114
 
  } catch (...) {
115
 
    return NULL;
116
 
  }
117
 
}
118
 
 
119
 
static Geometry *msGEOSShape2Geometry_multipoint(lineObj *multipoint)
120
 
{
121
 
  try {
122
 
    int i;
123
 
    vector<Geometry *> *parts=NULL;
124
 
 
125
 
    parts = new vector<Geometry *>(multipoint->numpoints);
126
 
    for(i=0; i<multipoint->numpoints; i++)
127
 
      (*parts)[i] = msGEOSShape2Geometry_point(&(multipoint->point[i]));
128
 
 
129
 
    Geometry *g = gf->createMultiPoint(parts);
130
 
 
131
 
    return g;
132
 
  } catch (GEOSException *ge) {
133
 
    msSetError(MS_GEOSERR, "%s", "msGEOSShape2Geometry_multiline()", (char *) ge->toString().c_str());
134
 
    delete ge;
135
 
    return NULL;
136
 
  } catch (...) {
137
 
    return NULL;
138
 
  }
139
 
}
140
 
 
141
 
static Geometry *msGEOSShape2Geometry_line(lineObj *line)
142
 
{
143
 
  try {
144
 
    int i;
145
 
    Coordinate c;
146
 
 
147
 
    DefaultCoordinateSequence *coords = new DefaultCoordinateSequence(line->numpoints);
148
 
 
149
 
    c.z = DoubleNotANumber; /* same for all points in the line (TODO: support z) */
150
 
    for(i=0; i<line->numpoints; i++) {
151
 
      c.x = line->point[i].x;
152
 
      c.y = line->point[i].y;
153
 
      coords->setAt(c, i);
154
 
    }
155
 
 
156
 
    Geometry *g = gf->createLineString(coords);
157
 
 
158
 
    return g;
159
 
  } catch (GEOSException *ge) {
160
 
    msSetError(MS_GEOSERR, "%s", "msGEOSShape2Geometry_line()", (char *) ge->toString().c_str());
161
 
    delete ge;
162
 
    return NULL;
163
 
  } catch (...) {
164
 
    return NULL;
165
 
  }
166
 
}
167
 
 
168
 
static Geometry *msGEOSShape2Geometry_multiline(shapeObj *multiline)
169
 
{
170
 
  try {
171
 
    int i;
172
 
    vector<Geometry *> *parts=NULL;
173
 
 
174
 
    parts = new vector<Geometry *>(multiline->numlines);
175
 
    for(i=0; i<multiline->numlines; i++)
176
 
      (*parts)[i] = msGEOSShape2Geometry_line(&(multiline->line[i]));
177
 
 
178
 
    Geometry *g = gf->createMultiLineString(parts);
179
 
 
180
 
    return g;
181
 
  } catch (GEOSException *ge) {
182
 
    msSetError(MS_GEOSERR, "%s", "msGEOSShape2Geometry_multiline()", (char *) ge->toString().c_str());
183
 
    delete ge;
184
 
    return NULL;
185
 
  } catch (...) {
186
 
    return NULL;
187
 
  }
188
 
}
189
 
 
190
 
static Geometry *msGEOSShape2Geometry_simplepolygon(shapeObj *shape, int r, int *outerList)
191
 
{
192
 
  try {
193
 
    int i, j, k;
194
 
    Coordinate c;
195
 
    LinearRing *outerRing, *innerRing;
196
 
    vector<Geometry *> *innerRings=NULL;
197
 
    int numInnerRings=0, *innerList;
198
 
    
199
 
    /* build the outer ring */
200
 
    DefaultCoordinateSequence *coords = new DefaultCoordinateSequence(shape->line[r].numpoints);
201
 
    
202
 
    c.z = DoubleNotANumber; /* same for all points in the line (TODO: support z) */
203
 
    for(i=0; i<shape->line[r].numpoints; i++) {
204
 
      c.x = shape->line[r].point[i].x;
205
 
      c.y = shape->line[r].point[i].y;
206
 
      coords->setAt(c, i);
207
 
    }
208
 
    
209
 
    outerRing = (LinearRing *) gf->createLinearRing(coords);
210
 
    
211
 
    /* build the inner rings */
212
 
    innerList = msGetInnerList(shape, r, outerList);    
213
 
    for(j=0; j<shape->numlines; j++)
214
 
      if(innerList[j] == MS_TRUE) numInnerRings++;
215
 
 
216
 
    /* printf("\tnumber of inner rings=%d\n", numInnerRings); */
217
 
 
218
 
    if(numInnerRings > 0) {
219
 
      k = 0; /* inner ring counter */
220
 
      innerRings = new vector<Geometry *>(numInnerRings);
221
 
      for(j=0; j<shape->numlines; j++) {
222
 
        if(innerList[j] == MS_FALSE) continue;
223
 
        
224
 
        DefaultCoordinateSequence *coords = new DefaultCoordinateSequence(shape->line[j].numpoints);
225
 
        
226
 
        c.z = DoubleNotANumber; /* same for all points in the line (TODO: support z) */
227
 
        for(i=0; i<shape->line[j].numpoints; i++) {
228
 
          c.x = shape->line[j].point[i].x;
229
 
          c.y = shape->line[j].point[i].y;
230
 
          coords->setAt(c, i);
231
 
        }
232
 
 
233
 
        innerRing = (LinearRing *) gf->createLinearRing(coords);
234
 
        (*innerRings)[k] = innerRing;
235
 
        k++;
236
 
      }
237
 
    }
238
 
 
239
 
    Geometry *g = gf->createPolygon(outerRing, innerRings);
240
 
 
241
 
    free(innerList); /* clean up */
242
 
   
243
 
    return g;
244
 
  } catch (GEOSException *ge) {
245
 
    msSetError(MS_GEOSERR, "%s", "msGEOSShape2Geometry_simplepolygon()", (char *) ge->toString().c_str());
246
 
    delete ge;
247
 
    return NULL;
248
 
  } catch (...) {
249
 
    return NULL;
250
 
  }
251
 
}
252
 
 
253
 
static Geometry *msGEOSShape2Geometry_polygon(shapeObj *shape)
254
 
{
255
 
  try {
256
 
    int i, j;
257
 
    vector<Geometry *> *parts=NULL;
258
 
    int *outerList, numOuterRings=0, lastOuterRing=0;
259
 
    Geometry *g=NULL;
260
 
 
261
 
    outerList = msGetOuterList(shape);
262
 
    for(i=0; i<shape->numlines; i++) {
263
 
      if(outerList[i] == MS_TRUE) {
264
 
        numOuterRings++;
265
 
        lastOuterRing = i; /* save for the simple case */
266
 
      }
267
 
    }
268
 
 
269
 
    /* printf("number of outer rings=%d\n", numOuterRings); */
270
 
 
271
 
    if(numOuterRings == 1) { 
272
 
      g = msGEOSShape2Geometry_simplepolygon(shape, lastOuterRing, outerList);
273
 
    } else { /* a true multipolygon */
274
 
      parts = new vector<Geometry *>(numOuterRings);
275
 
 
276
 
      j = 0; /* part counter */
277
 
      for(i=0; i<shape->numlines; i++) {
278
 
        if(outerList[i] == MS_FALSE) continue;
279
 
        /* printf("working on ring, id=%d (part %d)\n", i, j); */
280
 
        (*parts)[j] = msGEOSShape2Geometry_simplepolygon(shape, i, outerList); /* TODO: account for NULL return values */
281
 
        j++;
282
 
      }
283
 
 
284
 
      g = gf->createMultiPolygon(parts);
285
 
    }
286
 
 
287
 
    free(outerList);
288
 
    return g;
289
 
  } catch (GEOSException *ge) {
290
 
    msSetError(MS_GEOSERR, "%s", "msGEOSShape2Geometry_line()", (char *) ge->toString().c_str());
291
 
    delete ge;
292
 
    return NULL;
293
 
  } catch (...) {
294
 
    return NULL;
295
 
  }
296
 
}
297
 
 
298
 
Geometry *msGEOSShape2Geometry(shapeObj *shape)
299
 
{
300
 
  if(!shape)
301
 
    return NULL; /* a NULL shape generates a NULL geometry */
302
 
 
303
 
  /* if there is not an instance of a GeometeryFactory, create one */
304
 
  if(!gf) 
305
 
    msGEOSCreateGeometryFactory();
306
 
 
307
 
  switch(shape->type) {
308
 
  case MS_SHAPE_POINT:
309
 
    if(shape->numlines == 0 || shape->line[0].numpoints == 0) /* not enough info for a point */
310
 
      return NULL;
311
 
 
312
 
    if(shape->line[0].numpoints == 1) /* simple point */
313
 
      return msGEOSShape2Geometry_point(&(shape->line[0].point[0]));
314
 
    else /* multi-point */
315
 
      return msGEOSShape2Geometry_multipoint(&(shape->line[0]));
316
 
    break;
317
 
  case MS_SHAPE_LINE:
318
 
    if(shape->numlines == 0 || shape->line[0].numpoints < 2) /* not enough info for a line */
319
 
      return NULL;
320
 
 
321
 
    if(shape->numlines == 1) /* simple line */
322
 
      return msGEOSShape2Geometry_line(&(shape->line[0]));
323
 
    else /* multi-line */
324
 
      return msGEOSShape2Geometry_multiline(shape);
325
 
    break;
326
 
  case MS_SHAPE_POLYGON:
327
 
    if(shape->numlines == 0 || shape->line[0].numpoints < 4) /* not enough info for a polygon (first=last) */
328
 
      return NULL;
329
 
 
330
 
    return msGEOSShape2Geometry_polygon(shape); /* simple and multipolygon cases are addressed */
331
 
    break;
332
 
  default:
333
 
    break;
334
 
  }
335
 
 
336
 
  return NULL; /* should not get here */
337
 
}
338
 
 
339
 
static shapeObj *msGEOSGeometry2Shape_point(Geometry *g)
340
 
{
341
 
  try {
342
 
    const Coordinate *c = g->getCoordinate();
343
 
    shapeObj *shape=NULL;
344
 
    
345
 
    shape = (shapeObj *) malloc(sizeof(shapeObj));
346
 
    msInitShape(shape);
347
 
    
348
 
    shape->type = MS_SHAPE_POINT;
349
 
    shape->line = (lineObj *) malloc(sizeof(lineObj));
350
 
    shape->numlines = 1;
351
 
    shape->line[0].point = (pointObj *) malloc(sizeof(pointObj));
352
 
    shape->line[0].numpoints = 1;
353
 
    shape->geometry = g;
354
 
 
355
 
    shape->line[0].point[0].x = c->x;
356
 
    shape->line[0].point[0].y = c->y;  
357
 
    /* shape->line[0].point[0].z = c->z; */
358
 
 
359
 
    return shape;
360
 
  } catch (GEOSException *ge) {
361
 
    msSetError(MS_GEOSERR, "%s", "msGEOSGeometry2Shape_point()", (char *) ge->toString().c_str());
362
 
    delete ge;
363
 
    return NULL;
364
 
  } catch (...) {
365
 
    return NULL;
366
 
  }
367
 
}
368
 
 
369
 
static shapeObj *msGEOSGeometry2Shape_multipoint(Geometry *g)
370
 
{
371
 
  try {
372
 
    int i;
373
 
    int numPoints = g->getNumPoints();
374
 
    CoordinateSequence *coords = g->getCoordinates(); /* would be nice to have read-only access */
375
 
    Coordinate c;
376
 
    shapeObj *shape=NULL;
377
 
 
378
 
    shape = (shapeObj *) malloc(sizeof(shapeObj));
379
 
    msInitShape(shape);
380
 
 
381
 
    shape->type = MS_SHAPE_POINT;
382
 
    shape->line = (lineObj *) malloc(sizeof(lineObj));
383
 
    shape->numlines = 1;
384
 
    shape->line[0].point = (pointObj *) malloc(sizeof(pointObj)*numPoints);
385
 
    shape->line[0].numpoints = numPoints;
386
 
    shape->geometry = g;
387
 
 
388
 
    for(i=0; i<numPoints; i++) {
389
 
      c = coords->getAt(i);
390
 
 
391
 
      shape->line[0].point[i].x = c.x;
392
 
      shape->line[0].point[i].y = c.y;
393
 
      /* shape->line[0].point[i].z = c.z; */
394
 
    }
395
 
 
396
 
    delete coords;
397
 
    return shape;
398
 
  } catch (GEOSException *ge) {
399
 
    msSetError(MS_GEOSERR, "%s", "msGEOSGeometry2Shape_multipoint()", (char *) ge->toString().c_str());
400
 
    delete ge;
401
 
    return NULL;
402
 
  } catch (...) {
403
 
    return NULL;
404
 
  }
405
 
}
406
 
 
407
 
static shapeObj *msGEOSGeometry2Shape_line(LineString *g)
408
 
{
409
 
  shapeObj *shape=NULL;
410
 
 
411
 
  try {
412
 
    int i;
413
 
    int numPoints = g->getNumPoints();
414
 
    const CoordinateSequence *coords = g->getCoordinatesRO(); /* a pointer to coordinates, do not delete */
415
 
    Coordinate c;
416
 
 
417
 
    shape = (shapeObj *) malloc(sizeof(shapeObj));
418
 
    msInitShape(shape);
419
 
 
420
 
    shape->type = MS_SHAPE_LINE;
421
 
    shape->line = (lineObj *) malloc(sizeof(lineObj));
422
 
    shape->numlines = 1;
423
 
    shape->line[0].point = (pointObj *) malloc(sizeof(pointObj)*numPoints);
424
 
    shape->line[0].numpoints = numPoints;
425
 
    shape->geometry = g;
426
 
 
427
 
    for(i=0; i<numPoints; i++) {
428
 
      c = coords->getAt(i);
429
 
 
430
 
      shape->line[0].point[i].x = c.x;
431
 
      shape->line[0].point[i].y = c.y;
432
 
      /* shape->line[0].point[i].z = c.z; */
433
 
    }
434
 
 
435
 
    return shape;
436
 
  } catch (GEOSException *ge) {
437
 
    msSetError(MS_GEOSERR, "%s", "msGEOSGeometry2Shape_line()", (char *) ge->toString().c_str());
438
 
    delete ge;
439
 
    return NULL;
440
 
  } catch (...) {
441
 
    return NULL;
442
 
  }
443
 
}
444
 
 
445
 
static shapeObj *msGEOSGeometry2Shape_multiline(MultiLineString *g)
446
 
{
447
 
  try {
448
 
    int i, j;
449
 
    int numPoints, numLines = g->getNumGeometries();
450
 
    const CoordinateSequence *coords;
451
 
    const LineString *lineString;
452
 
    Coordinate c;
453
 
 
454
 
    shapeObj *shape=NULL;
455
 
    lineObj line;
456
 
 
457
 
    shape = (shapeObj *) malloc(sizeof(shapeObj));
458
 
    msInitShape(shape);
459
 
 
460
 
    shape->type = MS_SHAPE_LINE;
461
 
    shape->line = (lineObj *) malloc(sizeof(lineObj)*numLines);
462
 
    shape->numlines = numLines;
463
 
    shape->geometry = g;
464
 
 
465
 
    for(j=0; j<numLines; j++) {
466
 
      lineString = (LineString *) g->getGeometryN(j);
467
 
      coords = lineString->getCoordinatesRO();
468
 
      numPoints = lineString->getNumPoints();
469
 
 
470
 
      line.point = (pointObj *) malloc(sizeof(pointObj)*numPoints);
471
 
      line.numpoints = numPoints;
472
 
 
473
 
      for(i=0; i<numPoints; i++) {
474
 
        c = coords->getAt(i);
475
 
 
476
 
        line.point[i].x = c.x;
477
 
        line.point[i].y = c.y;
478
 
        /* line.point[i].z = c.z; */    
479
 
      }
480
 
      msAddLine(shape, &line);
481
 
      free(line.point);
482
 
    }
483
 
 
484
 
    return shape;
485
 
  } catch (GEOSException *ge) {
486
 
    msSetError(MS_GEOSERR, "%s", "msGEOSGeometry2Shape_multiline()", (char *) ge->toString().c_str());
487
 
    delete ge;
488
 
    return NULL;
489
 
  } catch (...) {
490
 
    return NULL;
491
 
  }
492
 
}
493
 
 
494
 
static shapeObj *msGEOSGeometry2Shape_polygon(Polygon *g)
495
 
{
496
 
  try {
497
 
    shapeObj *shape=NULL;
498
 
    lineObj line;
499
 
    int numPoints, numRings;
500
 
    int i, j;
501
 
 
502
 
    Coordinate c;
503
 
    const CoordinateSequence *coords;
504
 
    const LineString *ring;
505
 
 
506
 
    shape = (shapeObj *) malloc(sizeof(shapeObj));
507
 
    msInitShape(shape);
508
 
    shape->type = MS_SHAPE_POLYGON;
509
 
    shape->geometry = g;
510
 
 
511
 
    /* exterior ring */
512
 
    ring = g->getExteriorRing();
513
 
    coords = ring->getCoordinatesRO();
514
 
    numPoints = ring->getNumPoints();
515
 
 
516
 
    line.point = (pointObj *) malloc(sizeof(pointObj)*numPoints);
517
 
    line.numpoints = numPoints;
518
 
 
519
 
    for(i=0; i<numPoints; i++) {
520
 
      c = coords->getAt(i);
521
 
      
522
 
      line.point[i].x = c.x;
523
 
      line.point[i].y = c.y;
524
 
      /* line.point[i].z = c.z; */
525
 
    }
526
 
    msAddLine(shape, &line);
527
 
    free(line.point);
528
 
 
529
 
    /* interior rings */
530
 
    numRings = g->getNumInteriorRing();
531
 
    for(j=0; j<numRings; j++) {
532
 
      ring = g->getInteriorRingN(j);
533
 
      coords = ring->getCoordinatesRO();
534
 
      numPoints = ring->getNumPoints();
535
 
 
536
 
      line.point = (pointObj *) malloc(sizeof(pointObj)*numPoints);
537
 
      line.numpoints = numPoints;
538
 
 
539
 
      for(i=0; i<numPoints; i++) {
540
 
        c = coords->getAt(i);
541
 
        
542
 
        line.point[i].x = c.x;
543
 
        line.point[i].y = c.y;
544
 
        /* line.point[i].z = 0;
545
 
           line.point[i].m = 0; */
546
 
      }
547
 
      msAddLine(shape, &line);
548
 
      free(line.point);
549
 
    }
550
 
 
551
 
    return shape;
552
 
  } catch (GEOSException *ge) {
553
 
    msSetError(MS_GEOSERR, "%s", "msGEOSGeometry2Shape_polygon()", (char *) ge->toString().c_str());
554
 
    delete ge;
555
 
    return NULL;
556
 
  } catch (...) {
557
 
    return NULL;
558
 
  }
559
 
}
560
 
 
561
 
static shapeObj *msGEOSGeometry2Shape_multipolygon(MultiPolygon *g)
562
 
{
563
 
  try {
564
 
    int i, j, k;
565
 
    shapeObj *shape=NULL;
566
 
    lineObj line;
567
 
    int numPoints, numRings, numPolygons=g->getNumGeometries();
568
 
 
569
 
    Coordinate c;
570
 
    const CoordinateSequence *coords;
571
 
    const LineString *ring;
572
 
    const Polygon *polygon;
573
 
 
574
 
    shape = (shapeObj *) malloc(sizeof(shapeObj));
575
 
    msInitShape(shape);
576
 
 
577
 
    shape->type = MS_SHAPE_POLYGON;
578
 
    shape->geometry = g;
579
 
 
580
 
    for(k=0; k<numPolygons; k++) { /* for each polygon */
581
 
      polygon = (Polygon *) g->getGeometryN(k);
582
 
 
583
 
      /* exterior ring */
584
 
      ring = polygon->getExteriorRing();
585
 
      coords = ring->getCoordinatesRO();
586
 
      numPoints = ring->getNumPoints();
587
 
 
588
 
      line.point = (pointObj *) malloc(sizeof(pointObj)*numPoints);
589
 
      line.numpoints = numPoints;
590
 
 
591
 
      for(i=0; i<numPoints; i++) {
592
 
        c = coords->getAt(i);
593
 
 
594
 
        line.point[i].x = c.x;
595
 
        line.point[i].y = c.y;
596
 
        /* line.point[i].z = c.z;
597
 
           line.point[i].m = 0; */
598
 
      }
599
 
      msAddLine(shape, &line);
600
 
      free(line.point);
601
 
 
602
 
      /* interior rings */
603
 
      numRings = polygon->getNumInteriorRing();
604
 
      for(j=0; j<numRings; j++) {
605
 
        ring = polygon->getInteriorRingN(j);
606
 
        coords = ring->getCoordinatesRO();
607
 
        numPoints = ring->getNumPoints();
608
 
 
609
 
        line.point = (pointObj *) malloc(sizeof(pointObj)*numPoints);
610
 
        line.numpoints = numPoints;
611
 
 
612
 
        for(i=0; i<numPoints; i++) {
613
 
          c = coords->getAt(i);
614
 
 
615
 
          line.point[i].x = c.x;
616
 
          line.point[i].y = c.y;
617
 
          /* line.point[i].z = 0;
618
 
             line.point[i].m = 0; */
619
 
        }
620
 
        msAddLine(shape, &line);
621
 
        free(line.point);
622
 
      }
623
 
    } /* next polygon */
624
 
 
625
 
    return shape;
626
 
  } catch (GEOSException *ge) {
627
 
    msSetError(MS_GEOSERR, "%s", "msGEOSGeometry2Shape_multipolygon()", (char *) ge->toString().c_str());
628
 
    delete ge;
629
 
    return NULL;
630
 
  } catch (...) {
631
 
    return NULL;
632
 
  }
633
 
}
634
 
 
635
 
shapeObj *msGEOSGeometry2Shape(Geometry *g)
636
 
{
637
 
  if(!g) 
638
 
    return NULL; /* a NULL geometry generates a NULL shape */
639
 
 
640
 
  try {
641
 
    switch(g->getGeometryTypeId()) {
642
 
    case GEOS_POINT:
643
 
      return msGEOSGeometry2Shape_point(g);
644
 
      break;
645
 
    case GEOS_MULTIPOINT:
646
 
      return msGEOSGeometry2Shape_multipoint(g);
647
 
      break;
648
 
    case GEOS_LINESTRING:
649
 
      return msGEOSGeometry2Shape_line((LineString *)g);
650
 
      break;
651
 
    case GEOS_MULTILINESTRING:
652
 
      return msGEOSGeometry2Shape_multiline((MultiLineString *)g);
653
 
      break;
654
 
    case GEOS_POLYGON:
655
 
      return msGEOSGeometry2Shape_polygon((Polygon *)g);
656
 
      break;
657
 
    case GEOS_MULTIPOLYGON:
658
 
      return msGEOSGeometry2Shape_multipolygon((MultiPolygon *)g);
659
 
      break;
660
 
    default:
661
 
      msSetError(MS_GEOSERR, "Unsupported GEOS geometry type (%d).", "msGEOSGeometry2Shape()", g->getGeometryTypeId());
662
 
      return NULL;
663
 
    }
664
 
  } catch (GEOSException *ge) {
665
 
    msSetError(MS_GEOSERR, "%s", "msGEOSGeometry2Shape()", (char *) ge->toString().c_str());
666
 
    delete ge;
667
 
    return NULL;
668
 
  } catch (...) {
669
 
    return NULL;
670
 
  }
671
 
}
672
 
#endif
673
 
 
674
 
/*
675
 
** Maintenence functions exposed to MapServer/MapScript.
676
 
*/
677
 
 
678
 
void msGEOSFreeGeometry(shapeObj *shape)
679
 
{
680
 
#ifdef USE_GEOS
681
 
  if(!shape || !shape->geometry || !gf) 
682
 
    return;
683
 
 
684
 
  try {
685
 
    Geometry *g = (Geometry *) shape->geometry;
686
 
    gf->destroyGeometry(g);
687
 
  } catch (GEOSException *ge) {
688
 
    msSetError(MS_GEOSERR, "%s", "msGEOSDeleteGeometry()", (char *) ge->toString().c_str());
689
 
    delete ge;
690
 
    return;
691
 
  } catch (...) {
692
 
    return;
693
 
  }
694
 
#else
695
 
  msSetError(MS_GEOSERR, "GEOS support is not available.", "msGEOSFreeGeometry()");
696
 
  return;
697
 
#endif
698
 
}
699
 
 
700
 
/*
701
 
** WKT input and output functions
702
 
*/
703
 
shapeObj *msGEOSShapeFromWKT(const char *string)
704
 
{
705
 
#ifdef USE_GEOS
706
 
  if(!string) 
707
 
    return NULL;
708
 
 
709
 
  /* if there is not an instance of a GeometeryFactory, create one */
710
 
  if(!gf) 
711
 
    msGEOSCreateGeometryFactory();
712
 
 
713
 
  try {
714
 
    WKTReader *r = new WKTReader(gf);
715
 
    Geometry *g = r->read(string);
716
 
    return msGEOSGeometry2Shape(g);
717
 
  } catch (GEOSException *ge) {
718
 
    msSetError(MS_GEOSERR, "%s", "msGEOSShapeFromWKT()", (char *) ge->toString().c_str());
719
 
    delete ge;
720
 
    return NULL;
721
 
  } catch (...) {
722
 
    return NULL;
723
 
  }
724
 
 
725
 
#else
726
 
  msSetError(MS_GEOSERR, "GEOS support is not available.", "msGEOSShapeFromWKT()");
727
 
  return NULL;
728
 
#endif
729
 
}
730
 
 
731
 
char *msGEOSShapeToWKT(shapeObj *shape)
732
 
{
733
 
#ifdef USE_GEOS
734
 
  char *wkt=NULL;
735
 
 
736
 
  if(!shape) 
737
 
    return NULL;
738
 
 
739
 
  if(!shape->geometry) /* if no geometry for the shape then build one */
740
 
    shape->geometry = msGEOSShape2Geometry(shape);
741
 
  Geometry *g = (Geometry *) shape->geometry;
742
 
  if(!g) 
743
 
    return NULL;
744
 
 
745
 
  wkt = strdup((char *) g->toString().c_str());
746
 
 
747
 
  return wkt;
748
 
#else
749
 
  msSetError(MS_GEOSERR, "GEOS support is not available.", "msGEOSShapeToWKT()");
750
 
  return NULL;
751
 
#endif
752
 
}
753
 
 
754
 
/*
755
 
** Analytical functions exposed to MapServer/MapScript.
756
 
*/
757
 
 
758
 
shapeObj *msGEOSBuffer(shapeObj *shape, double width)
759
 
{
760
 
#ifdef USE_GEOS
761
 
  if(!shape) 
762
 
    return NULL;
763
 
 
764
 
  if(!shape->geometry) /* if no geometry for the shape then build one */
765
 
    shape->geometry = msGEOSShape2Geometry(shape);
766
 
  Geometry *g = (Geometry *) shape->geometry;
767
 
  if(!g) 
768
 
    return NULL;
769
 
 
770
 
  try {
771
 
      Geometry *bg = g->buffer(width);
772
 
      return msGEOSGeometry2Shape(bg);
773
 
  } catch (GEOSException *ge) {     
774
 
    msSetError(MS_GEOSERR, "%s", "msGEOSBuffer()", (char *) ge->toString().c_str());
775
 
    delete ge;
776
 
    return NULL;
777
 
  } catch (...) {
778
 
    return NULL;
779
 
  }
780
 
#else
781
 
  msSetError(MS_GEOSERR, "GEOS support is not available.", "msGEOSBuffer()");
782
 
  return NULL;
783
 
#endif
784
 
}
785
 
 
786
 
shapeObj *msGEOSConvexHull(shapeObj *shape)
787
 
{
788
 
#ifdef USE_GEOS
789
 
  if(!shape)
790
 
    return NULL;
791
 
 
792
 
  if(!shape->geometry) /* if no geometry for the shape then build one */
793
 
    shape->geometry = msGEOSShape2Geometry(shape);
794
 
  Geometry *g = (Geometry *) shape->geometry;
795
 
  if(!g)
796
 
    return NULL;
797
 
 
798
 
  try {
799
 
    Geometry *bg = g->convexHull();
800
 
    return msGEOSGeometry2Shape(bg);
801
 
  } catch (GEOSException *ge) {
802
 
    msSetError(MS_GEOSERR, "%s", "msGEOSConvexHull()", (char *) ge->toString().c_str());
803
 
    delete ge;
804
 
    return NULL;
805
 
  } catch (...) {
806
 
    return NULL;
807
 
  }
808
 
#else
809
 
  msSetError(MS_GEOSERR, "GEOS support is not available.", "msGEOSConvexHull()");
810
 
  return NULL;
811
 
#endif
812
 
}