~ubuntu-branches/ubuntu/trusty/postgis/trusty-security

« back to all changes in this revision

Viewing changes to liblwgeom/lwgeom.c

  • Committer: Bazaar Package Importer
  • Author(s): Francesco Paolo Lovergine
  • Date: 2009-12-11 13:10:34 UTC
  • mfrom: (1.1.9 upstream) (5.2.1 experimental)
  • Revision ID: james.westby@ubuntu.com-20091211131034-wmsz69wxvt95pe5r
Tags: 1.4.0-2
* Upload to unstable.
* Better parameterized debian/rules against postgis $(VERSION).
* Added dblatex and libcunit1-dev among build-deps.
* Added postgis_comments.sql to contrib/ SQL templates.
* Dropping 8.3 support, no more supported for squeeze.
  (closes: #559587)
* Do not stop on error in postrm if the target dir does not exist.
  (closes: #560409)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/**********************************************************************
 
2
 * $Id: lwgeom.c 4168 2009-06-11 16:44:03Z pramsey $
 
3
 *
 
4
 * PostGIS - Spatial Types for PostgreSQL
 
5
 * http://postgis.refractions.net
 
6
 * Copyright 2001-2006 Refractions Research Inc.
 
7
 *
 
8
 * This is free software; you can redistribute and/or modify it under
 
9
 * the terms of the GNU General Public Licence. See the COPYING file.
 
10
 *
 
11
 **********************************************************************/
 
12
 
 
13
#include <stdio.h>
 
14
#include <stdlib.h>
 
15
#include <stdarg.h>
 
16
 
 
17
#include "liblwgeom.h"
 
18
#include "wktparse.h"
 
19
 
 
20
 
 
21
LWGEOM *
 
22
lwgeom_deserialize(uchar *srl)
 
23
{
 
24
        int type = lwgeom_getType(srl[0]);
 
25
 
 
26
        LWDEBUGF(2, "lwgeom_deserialize got %d - %s", type, lwgeom_typename(type));
 
27
 
 
28
        switch (type)
 
29
        {
 
30
        case POINTTYPE:
 
31
                return (LWGEOM *)lwpoint_deserialize(srl);
 
32
        case LINETYPE:
 
33
                return (LWGEOM *)lwline_deserialize(srl);
 
34
        case CIRCSTRINGTYPE:
 
35
                return (LWGEOM *)lwcircstring_deserialize(srl);
 
36
        case POLYGONTYPE:
 
37
                return (LWGEOM *)lwpoly_deserialize(srl);
 
38
        case MULTIPOINTTYPE:
 
39
                return (LWGEOM *)lwmpoint_deserialize(srl);
 
40
        case MULTILINETYPE:
 
41
                return (LWGEOM *)lwmline_deserialize(srl);
 
42
        case MULTIPOLYGONTYPE:
 
43
                return (LWGEOM *)lwmpoly_deserialize(srl);
 
44
        case COLLECTIONTYPE:
 
45
                return (LWGEOM *)lwcollection_deserialize(srl);
 
46
        case COMPOUNDTYPE:
 
47
                return (LWGEOM *)lwcompound_deserialize(srl);
 
48
        case CURVEPOLYTYPE:
 
49
                return (LWGEOM *)lwcurvepoly_deserialize(srl);
 
50
        case MULTICURVETYPE:
 
51
                return (LWGEOM *)lwmcurve_deserialize(srl);
 
52
        case MULTISURFACETYPE:
 
53
                return (LWGEOM *)lwmsurface_deserialize(srl);
 
54
        default:
 
55
                lwerror("Unknown geometry type: %d", type);
 
56
 
 
57
                return NULL;
 
58
        }
 
59
 
 
60
}
 
61
 
 
62
size_t
 
63
lwgeom_serialize_size(LWGEOM *lwgeom)
 
64
{
 
65
        int type = TYPE_GETTYPE(lwgeom->type);
 
66
 
 
67
        LWDEBUGF(2, "lwgeom_serialize_size(%s) called", lwgeom_typename(type));
 
68
 
 
69
        switch (type)
 
70
        {
 
71
        case POINTTYPE:
 
72
                return lwpoint_serialize_size((LWPOINT *)lwgeom);
 
73
        case LINETYPE:
 
74
                return lwline_serialize_size((LWLINE *)lwgeom);
 
75
        case POLYGONTYPE:
 
76
                return lwpoly_serialize_size((LWPOLY *)lwgeom);
 
77
        case CIRCSTRINGTYPE:
 
78
                return lwcircstring_serialize_size((LWCIRCSTRING *)lwgeom);
 
79
        case CURVEPOLYTYPE:
 
80
        case COMPOUNDTYPE:
 
81
        case MULTIPOINTTYPE:
 
82
        case MULTILINETYPE:
 
83
        case MULTICURVETYPE:
 
84
        case MULTIPOLYGONTYPE:
 
85
        case MULTISURFACETYPE:
 
86
        case COLLECTIONTYPE:
 
87
                return lwcollection_serialize_size((LWCOLLECTION *)lwgeom);
 
88
        default:
 
89
                lwerror("Unknown geometry type: %d", type);
 
90
 
 
91
                return 0;
 
92
        }
 
93
}
 
94
 
 
95
void
 
96
lwgeom_serialize_buf(LWGEOM *lwgeom, uchar *buf, size_t *retsize)
 
97
{
 
98
        int type = TYPE_GETTYPE(lwgeom->type);
 
99
 
 
100
        LWDEBUGF(2, "lwgeom_serialize_buf called with a %s",
 
101
                 lwgeom_typename(type));
 
102
 
 
103
        switch (type)
 
104
        {
 
105
        case POINTTYPE:
 
106
                lwpoint_serialize_buf((LWPOINT *)lwgeom, buf, retsize);
 
107
                break;
 
108
        case LINETYPE:
 
109
                lwline_serialize_buf((LWLINE *)lwgeom, buf, retsize);
 
110
                break;
 
111
        case POLYGONTYPE:
 
112
                lwpoly_serialize_buf((LWPOLY *)lwgeom, buf, retsize);
 
113
                break;
 
114
        case CIRCSTRINGTYPE:
 
115
                lwcircstring_serialize_buf((LWCIRCSTRING *)lwgeom, buf, retsize);
 
116
                break;
 
117
        case CURVEPOLYTYPE:
 
118
        case COMPOUNDTYPE:
 
119
        case MULTIPOINTTYPE:
 
120
        case MULTILINETYPE:
 
121
        case MULTICURVETYPE:
 
122
        case MULTIPOLYGONTYPE:
 
123
        case MULTISURFACETYPE:
 
124
        case COLLECTIONTYPE:
 
125
                lwcollection_serialize_buf((LWCOLLECTION *)lwgeom, buf,
 
126
                                           retsize);
 
127
                break;
 
128
        default:
 
129
                lwerror("Unknown geometry type: %d", type);
 
130
                return;
 
131
        }
 
132
        return;
 
133
}
 
134
 
 
135
uchar *
 
136
lwgeom_serialize(LWGEOM *lwgeom)
 
137
{
 
138
        size_t size = lwgeom_serialize_size(lwgeom);
 
139
        size_t retsize;
 
140
        uchar *serialized = lwalloc(size);
 
141
 
 
142
        lwgeom_serialize_buf(lwgeom, serialized, &retsize);
 
143
 
 
144
#if POSTGIS_DEBUG_LEVEL > 0
 
145
        if ( retsize != size )
 
146
        {
 
147
                lwerror("lwgeom_serialize: computed size %d, returned size %d",
 
148
                        size, retsize);
 
149
        }
 
150
#endif
 
151
 
 
152
        return serialized;
 
153
}
 
154
 
 
155
/** Force Right-hand-rule on LWGEOM polygons **/
 
156
void
 
157
lwgeom_force_rhr(LWGEOM *lwgeom)
 
158
{
 
159
        LWCOLLECTION *coll;
 
160
        int i;
 
161
 
 
162
        switch (TYPE_GETTYPE(lwgeom->type))
 
163
        {
 
164
        case POLYGONTYPE:
 
165
                lwpoly_forceRHR((LWPOLY *)lwgeom);
 
166
                return;
 
167
 
 
168
        case MULTIPOLYGONTYPE:
 
169
        case COLLECTIONTYPE:
 
170
                coll = (LWCOLLECTION *)lwgeom;
 
171
                for (i=0; i<coll->ngeoms; i++)
 
172
                        lwgeom_force_rhr(coll->geoms[i]);
 
173
                return;
 
174
        }
 
175
}
 
176
 
 
177
/** Reverse vertex order of LWGEOM **/
 
178
void
 
179
lwgeom_reverse(LWGEOM *lwgeom)
 
180
{
 
181
        int i;
 
182
        LWCOLLECTION *col;
 
183
 
 
184
        switch (TYPE_GETTYPE(lwgeom->type))
 
185
        {
 
186
        case LINETYPE:
 
187
                lwline_reverse((LWLINE *)lwgeom);
 
188
                return;
 
189
        case POLYGONTYPE:
 
190
                lwpoly_reverse((LWPOLY *)lwgeom);
 
191
                return;
 
192
        case MULTILINETYPE:
 
193
        case MULTIPOLYGONTYPE:
 
194
        case COLLECTIONTYPE:
 
195
                col = (LWCOLLECTION *)lwgeom;
 
196
                for (i=0; i<col->ngeoms; i++)
 
197
                        lwgeom_reverse(col->geoms[i]);
 
198
                return;
 
199
        }
 
200
}
 
201
 
 
202
BOX3D *lwgeom_compute_box3d(const LWGEOM *lwgeom)
 
203
{
 
204
        if ( ! lwgeom ) return NULL;
 
205
 
 
206
        switch (TYPE_GETTYPE(lwgeom->type))
 
207
        {
 
208
        case POINTTYPE:
 
209
                return lwpoint_compute_box3d((LWPOINT *)lwgeom);
 
210
        case LINETYPE:
 
211
                return lwline_compute_box3d((LWLINE *)lwgeom);
 
212
        case CIRCSTRINGTYPE:
 
213
                return lwcircstring_compute_box3d((LWCIRCSTRING *)lwgeom);
 
214
        case POLYGONTYPE:
 
215
                return lwpoly_compute_box3d((LWPOLY *)lwgeom);
 
216
        case COMPOUNDTYPE:
 
217
        case CURVEPOLYTYPE:
 
218
        case MULTIPOINTTYPE:
 
219
        case MULTILINETYPE:
 
220
        case MULTICURVETYPE:
 
221
        case MULTIPOLYGONTYPE:
 
222
        case MULTISURFACETYPE:
 
223
        case COLLECTIONTYPE:
 
224
                return lwcollection_compute_box3d((LWCOLLECTION *)lwgeom);
 
225
        }
 
226
        /* Never get here, please. */
 
227
        return NULL;
 
228
}
 
229
 
 
230
int
 
231
lwgeom_compute_box2d_p(LWGEOM *lwgeom, BOX2DFLOAT4 *buf)
 
232
{
 
233
        LWDEBUGF(2, "lwgeom_compute_box2d_p called of %p of type %d.", lwgeom, TYPE_GETTYPE(lwgeom->type));
 
234
 
 
235
        switch (TYPE_GETTYPE(lwgeom->type))
 
236
        {
 
237
        case POINTTYPE:
 
238
                return lwpoint_compute_box2d_p((LWPOINT *)lwgeom, buf);
 
239
        case LINETYPE:
 
240
                return lwline_compute_box2d_p((LWLINE *)lwgeom, buf);
 
241
        case CIRCSTRINGTYPE:
 
242
                return lwcircstring_compute_box2d_p((LWCIRCSTRING *)lwgeom, buf);
 
243
        case POLYGONTYPE:
 
244
                return lwpoly_compute_box2d_p((LWPOLY *)lwgeom, buf);
 
245
        case COMPOUNDTYPE:
 
246
        case CURVEPOLYTYPE:
 
247
        case MULTIPOINTTYPE:
 
248
        case MULTILINETYPE:
 
249
        case MULTICURVETYPE:
 
250
        case MULTIPOLYGONTYPE:
 
251
        case MULTISURFACETYPE:
 
252
        case COLLECTIONTYPE:
 
253
                return lwcollection_compute_box2d_p((LWCOLLECTION *)lwgeom, buf);
 
254
        }
 
255
        return 0;
 
256
}
 
257
 
 
258
/**
 
259
 * do not forget to lwfree() result
 
260
 */
 
261
BOX2DFLOAT4 *
 
262
lwgeom_compute_box2d(LWGEOM *lwgeom)
 
263
{
 
264
        BOX2DFLOAT4 *result = lwalloc(sizeof(BOX2DFLOAT4));
 
265
        if ( lwgeom_compute_box2d_p(lwgeom, result) ) return result;
 
266
        else
 
267
        {
 
268
                lwfree(result);
 
269
                return NULL;
 
270
        }
 
271
}
 
272
 
 
273
LWPOINT *
 
274
lwgeom_as_lwpoint(LWGEOM *lwgeom)
 
275
{
 
276
        if ( TYPE_GETTYPE(lwgeom->type) == POINTTYPE )
 
277
                return (LWPOINT *)lwgeom;
 
278
        else return NULL;
 
279
}
 
280
 
 
281
LWLINE *
 
282
lwgeom_as_lwline(LWGEOM *lwgeom)
 
283
{
 
284
        if ( TYPE_GETTYPE(lwgeom->type) == LINETYPE )
 
285
                return (LWLINE *)lwgeom;
 
286
        else return NULL;
 
287
}
 
288
 
 
289
LWCIRCSTRING *
 
290
lwgeom_as_lwcircstring(LWGEOM *lwgeom)
 
291
{
 
292
        if ( TYPE_GETTYPE(lwgeom->type) == CIRCSTRINGTYPE )
 
293
                return (LWCIRCSTRING *)lwgeom;
 
294
        else return NULL;
 
295
}
 
296
 
 
297
LWPOLY *
 
298
lwgeom_as_lwpoly(LWGEOM *lwgeom)
 
299
{
 
300
        if ( TYPE_GETTYPE(lwgeom->type) == POLYGONTYPE )
 
301
                return (LWPOLY *)lwgeom;
 
302
        else return NULL;
 
303
}
 
304
 
 
305
LWCOLLECTION *
 
306
lwgeom_as_lwcollection(LWGEOM *lwgeom)
 
307
{
 
308
        if ( TYPE_GETTYPE(lwgeom->type) >= MULTIPOINTTYPE
 
309
                && TYPE_GETTYPE(lwgeom->type) <= COLLECTIONTYPE)
 
310
                return (LWCOLLECTION *)lwgeom;
 
311
        else return NULL;
 
312
}
 
313
 
 
314
LWMPOINT *
 
315
lwgeom_as_lwmpoint(LWGEOM *lwgeom)
 
316
{
 
317
        if ( TYPE_GETTYPE(lwgeom->type) == MULTIPOINTTYPE )
 
318
                return (LWMPOINT *)lwgeom;
 
319
        else return NULL;
 
320
}
 
321
 
 
322
LWMLINE *
 
323
lwgeom_as_lwmline(LWGEOM *lwgeom)
 
324
{
 
325
        if ( TYPE_GETTYPE(lwgeom->type) == MULTILINETYPE )
 
326
                return (LWMLINE *)lwgeom;
 
327
        else return NULL;
 
328
}
 
329
 
 
330
LWMPOLY *
 
331
lwgeom_as_lwmpoly(LWGEOM *lwgeom)
 
332
{
 
333
        if ( TYPE_GETTYPE(lwgeom->type) == MULTIPOLYGONTYPE )
 
334
                return (LWMPOLY *)lwgeom;
 
335
        else return NULL;
 
336
}
 
337
 
 
338
LWGEOM *lwmpoly_as_lwgeom(LWMPOLY *obj)
 
339
{
 
340
        return (LWGEOM *)obj;
 
341
}
 
342
LWGEOM *lwmline_as_lwgeom(LWMLINE *obj)
 
343
{
 
344
        return (LWGEOM *)obj;
 
345
}
 
346
LWGEOM *lwmpoint_as_lwgeom(LWMPOINT *obj)
 
347
{
 
348
        return (LWGEOM *)obj;
 
349
}
 
350
LWGEOM *lwcollection_as_lwgeom(LWCOLLECTION *obj)
 
351
{
 
352
        return (LWGEOM *)obj;
 
353
}
 
354
LWGEOM *lwcircstring_as_lwgeom(LWCIRCSTRING *obj)
 
355
{
 
356
        return (LWGEOM *)obj;
 
357
}
 
358
LWGEOM *lwpoly_as_lwgeom(LWPOLY *obj)
 
359
{
 
360
        return (LWGEOM *)obj;
 
361
}
 
362
LWGEOM *lwline_as_lwgeom(LWLINE *obj)
 
363
{
 
364
        return (LWGEOM *)obj;
 
365
}
 
366
LWGEOM *lwpoint_as_lwgeom(LWPOINT *obj)
 
367
{
 
368
        return (LWGEOM *)obj;
 
369
}
 
370
 
 
371
 
 
372
/**
 
373
** Look-up for the correct MULTI* type promotion for singleton types.
 
374
*/
 
375
static unsigned char MULTITYPE[16] =
 
376
    {
 
377
        0,
 
378
        MULTIPOINTTYPE,
 
379
        MULTILINETYPE,
 
380
        MULTIPOLYGONTYPE,
 
381
        0,0,0,0,
 
382
        MULTICURVETYPE,
 
383
        MULTICURVETYPE,
 
384
        0,0,0,
 
385
        MULTISURFACETYPE,
 
386
        0,0
 
387
    };
 
388
 
 
389
/**
 
390
* Create a new LWGEOM of the appropriate MULTI* type.
 
391
*/
 
392
LWGEOM *
 
393
lwgeom_as_multi(LWGEOM *lwgeom)
 
394
{
 
395
        LWGEOM **ogeoms;
 
396
        LWGEOM *ogeom = NULL;
 
397
        BOX2DFLOAT4 *box = NULL;
 
398
        int type;
 
399
 
 
400
        ogeoms = lwalloc(sizeof(LWGEOM*));
 
401
 
 
402
        /*
 
403
        ** This funx is a no-op only if a bbox cache is already present
 
404
        ** in input.
 
405
        */
 
406
        if ( lwgeom_contains_subgeoms(TYPE_GETTYPE(lwgeom->type)) )
 
407
        {
 
408
                return lwgeom_clone(lwgeom);
 
409
        }
 
410
 
 
411
        type = TYPE_GETTYPE(lwgeom->type);
 
412
 
 
413
        if ( MULTITYPE[type] )
 
414
        {
 
415
                ogeoms[0] = lwgeom_clone(lwgeom);
 
416
 
 
417
                /* Sub-geometries are not allowed to have bboxes or SRIDs, move the bbox to the collection */
 
418
                box = ogeoms[0]->bbox;
 
419
                ogeoms[0]->bbox = NULL;
 
420
                ogeoms[0]->SRID = -1;
 
421
 
 
422
                ogeom = (LWGEOM *)lwcollection_construct(MULTITYPE[type], lwgeom->SRID, box, 1, ogeoms);
 
423
        }
 
424
        else
 
425
        {
 
426
                return lwgeom_clone(lwgeom);
 
427
        }
 
428
 
 
429
        return ogeom;
 
430
}
 
431
 
 
432
void
 
433
lwgeom_release(LWGEOM *lwgeom)
 
434
{
 
435
        uint32 i;
 
436
        LWCOLLECTION *col;
 
437
 
 
438
#ifdef INTEGRITY_CHECKS
 
439
        if ( ! lwgeom )
 
440
                lwerror("lwgeom_release: someone called on 0x0");
 
441
#endif
 
442
 
 
443
        /* Drop bounding box (always a copy) */
 
444
        if ( lwgeom->bbox )
 
445
        {
 
446
                LWDEBUG(3, "lwgeom_release: releasing bbox.");
 
447
 
 
448
                lwfree(lwgeom->bbox);
 
449
        }
 
450
 
 
451
        /* Collection */
 
452
        if ( (col=lwgeom_as_lwcollection(lwgeom)) )
 
453
        {
 
454
                LWDEBUG(3, "lwgeom_release: Releasing collection.");
 
455
 
 
456
                for (i=0; i<col->ngeoms; i++)
 
457
                {
 
458
                        lwgeom_release(col->geoms[i]);
 
459
                }
 
460
                lwfree(lwgeom);
 
461
        }
 
462
 
 
463
        /* Single element */
 
464
        else lwfree(lwgeom);
 
465
 
 
466
}
 
467
 
 
468
 
 
469
/** Clone an LWGEOM object. POINTARRAY are not copied. **/
 
470
LWGEOM *
 
471
lwgeom_clone(const LWGEOM *lwgeom)
 
472
{
 
473
        LWDEBUGF(2, "lwgeom_clone called with %p, %d", lwgeom, TYPE_GETTYPE(lwgeom->type));
 
474
 
 
475
        switch (TYPE_GETTYPE(lwgeom->type))
 
476
        {
 
477
        case POINTTYPE:
 
478
                return (LWGEOM *)lwpoint_clone((LWPOINT *)lwgeom);
 
479
        case LINETYPE:
 
480
                return (LWGEOM *)lwline_clone((LWLINE *)lwgeom);
 
481
        case CIRCSTRINGTYPE:
 
482
                return (LWGEOM *)lwcircstring_clone((LWCIRCSTRING *)lwgeom);
 
483
        case POLYGONTYPE:
 
484
                return (LWGEOM *)lwpoly_clone((LWPOLY *)lwgeom);
 
485
        case COMPOUNDTYPE:
 
486
        case CURVEPOLYTYPE:
 
487
        case MULTIPOINTTYPE:
 
488
        case MULTILINETYPE:
 
489
        case MULTICURVETYPE:
 
490
        case MULTIPOLYGONTYPE:
 
491
        case MULTISURFACETYPE:
 
492
        case COLLECTIONTYPE:
 
493
                return (LWGEOM *)lwcollection_clone((LWCOLLECTION *)lwgeom);
 
494
        default:
 
495
                return NULL;
 
496
        }
 
497
}
 
498
 
 
499
/**
 
500
 * Add 'what' to 'to' at position 'where'
 
501
 *
 
502
 * @param where =0 == prepend if -1 == append
 
503
 *
 
504
 * Appended-to LWGEOM gets a new type based on new condition.
 
505
 * Mix of dimensions is not allowed.
 
506
 * @todo TODO: allow mix of dimensions?
 
507
 */
 
508
LWGEOM *
 
509
lwgeom_add(const LWGEOM *to, uint32 where, const LWGEOM *what)
 
510
{
 
511
        if ( TYPE_NDIMS(what->type) != TYPE_NDIMS(to->type) )
 
512
        {
 
513
                lwerror("lwgeom_add: mixed dimensions not supported");
 
514
                return NULL;
 
515
        }
 
516
 
 
517
        LWDEBUGF(2, "lwgeom_add(%s, %d, %s) called",
 
518
                 lwgeom_typename(TYPE_GETTYPE(to->type)),
 
519
                 where,
 
520
                 lwgeom_typename(TYPE_GETTYPE(what->type)));
 
521
 
 
522
        switch (TYPE_GETTYPE(to->type))
 
523
        {
 
524
        case POINTTYPE:
 
525
                return (LWGEOM *)lwpoint_add((const LWPOINT *)to, where, what);
 
526
        case LINETYPE:
 
527
                return (LWGEOM *)lwline_add((const LWLINE *)to, where, what);
 
528
 
 
529
        case CIRCSTRINGTYPE:
 
530
                return (LWGEOM *)lwcircstring_add((const LWCIRCSTRING *)to, where, what);
 
531
 
 
532
        case POLYGONTYPE:
 
533
                return (LWGEOM *)lwpoly_add((const LWPOLY *)to, where, what);
 
534
 
 
535
        case COMPOUNDTYPE:
 
536
                return (LWGEOM *)lwcompound_add((const LWCOMPOUND *)to, where, what);
 
537
 
 
538
        case CURVEPOLYTYPE:
 
539
                return (LWGEOM *)lwcurvepoly_add((const LWCURVEPOLY *)to, where, what);
 
540
 
 
541
        case MULTIPOINTTYPE:
 
542
                return (LWGEOM *)lwmpoint_add((const LWMPOINT *)to,
 
543
                                              where, what);
 
544
 
 
545
        case MULTILINETYPE:
 
546
                return (LWGEOM *)lwmline_add((const LWMLINE *)to,
 
547
                                             where, what);
 
548
 
 
549
        case MULTICURVETYPE:
 
550
                return (LWGEOM *)lwmcurve_add((const LWMCURVE *)to,
 
551
                                              where, what);
 
552
 
 
553
        case MULTIPOLYGONTYPE:
 
554
                return (LWGEOM *)lwmpoly_add((const LWMPOLY *)to,
 
555
                                             where, what);
 
556
 
 
557
        case MULTISURFACETYPE:
 
558
                return (LWGEOM *)lwmsurface_add((const LWMSURFACE *)to,
 
559
                                                where, what);
 
560
 
 
561
        case COLLECTIONTYPE:
 
562
                return (LWGEOM *)lwcollection_add(
 
563
                           (const LWCOLLECTION *)to, where, what);
 
564
 
 
565
        default:
 
566
                lwerror("lwgeom_add: unknown geometry type: %d",
 
567
                        TYPE_GETTYPE(to->type));
 
568
                return NULL;
 
569
        }
 
570
}
 
571
 
 
572
 
 
573
/**
 
574
 * Return an alloced string
 
575
 */
 
576
char *
 
577
lwgeom_to_ewkt(LWGEOM *lwgeom, int flags)
 
578
{
 
579
        LWGEOM_UNPARSER_RESULT lwg_unparser_result;
 
580
        uchar *serialized = lwgeom_serialize(lwgeom);
 
581
        int result;
 
582
 
 
583
        if ( ! serialized )
 
584
        {
 
585
                lwerror("Error serializing geom %p", lwgeom);
 
586
        }
 
587
 
 
588
        result = unparse_WKT(&lwg_unparser_result, serialized, lwalloc, lwfree, flags);
 
589
        lwfree(serialized);
 
590
 
 
591
        return lwg_unparser_result.wkoutput;
 
592
}
 
593
 
 
594
/**
 
595
 * Return an alloced string
 
596
 */
 
597
char *
 
598
lwgeom_to_hexwkb(LWGEOM *lwgeom, int flags, unsigned int byteorder)
 
599
{
 
600
        LWGEOM_UNPARSER_RESULT lwg_unparser_result;
 
601
        uchar *serialized = lwgeom_serialize(lwgeom);
 
602
        int result;
 
603
 
 
604
        result = unparse_WKB(&lwg_unparser_result, serialized, lwalloc, lwfree, flags, byteorder,1);
 
605
 
 
606
        lwfree(serialized);
 
607
        return lwg_unparser_result.wkoutput;
 
608
}
 
609
 
 
610
/**
 
611
 * Return an alloced string
 
612
 */
 
613
uchar *
 
614
lwgeom_to_ewkb(LWGEOM *lwgeom, int flags, char byteorder, size_t *outsize)
 
615
{
 
616
        LWGEOM_UNPARSER_RESULT lwg_unparser_result;
 
617
        uchar *serialized = lwgeom_serialize(lwgeom);
 
618
        int result;
 
619
 
 
620
        /*
 
621
         * We cast return to "unsigned" char as we are
 
622
         * requesting a "binary" output, not HEX
 
623
         * (last argument set to 0)
 
624
         */
 
625
        result = unparse_WKB(&lwg_unparser_result, serialized, lwalloc, lwfree,
 
626
                             flags, byteorder, 0);
 
627
        lwfree(serialized);
 
628
        return (uchar *)lwg_unparser_result.wkoutput;
 
629
}
 
630
 
 
631
/**
 
632
 * Make an LWGEOM object from a EWKB binary representation.
 
633
 * Currently highly unoptimized as it:
 
634
 *      - convert EWKB to HEXEWKB
 
635
 *      - construct PG_LWGEOM
 
636
 *      - deserialize it
 
637
 */
 
638
LWGEOM *
 
639
lwgeom_from_ewkb(uchar *ewkb, int flags, size_t size)
 
640
{
 
641
        size_t hexewkblen = size*2;
 
642
        char *hexewkb;
 
643
        long int i;
 
644
        int result;
 
645
        LWGEOM *ret;
 
646
        LWGEOM_PARSER_RESULT lwg_parser_result;
 
647
 
 
648
        /* "HEXify" the EWKB */
 
649
        hexewkb = lwalloc(hexewkblen+1);
 
650
        for (i=0; i<size; ++i) deparse_hex(ewkb[i], &hexewkb[i*2]);
 
651
        hexewkb[hexewkblen] = '\0';
 
652
 
 
653
        /* Rely on grammar parser to construct a LWGEOM */
 
654
        result = serialized_lwgeom_from_ewkt(&lwg_parser_result, hexewkb, flags);
 
655
        if (result)
 
656
                lwerror("%s", (char *)lwg_parser_result.message);
 
657
 
 
658
        /* Free intermediate HEXified representation */
 
659
        lwfree(hexewkb);
 
660
 
 
661
        /* Deserialize */
 
662
        ret = lwgeom_deserialize(lwg_parser_result.serialized_lwgeom);
 
663
 
 
664
        return ret;
 
665
}
 
666
 
 
667
/**
 
668
 * Make an LWGEOM object from a EWKT representation.
 
669
 */
 
670
LWGEOM *
 
671
lwgeom_from_ewkt(char *ewkt, int flags)
 
672
{
 
673
        int result;
 
674
        LWGEOM *ret;
 
675
        LWGEOM_PARSER_RESULT lwg_parser_result;
 
676
 
 
677
        /* Rely on grammar parser to construct a LWGEOM */
 
678
        result = serialized_lwgeom_from_ewkt(&lwg_parser_result, ewkt, flags);
 
679
        if (result)
 
680
                lwerror("%s", (char *)lwg_parser_result.message);
 
681
 
 
682
        /* Deserialize */
 
683
        ret = lwgeom_deserialize(lwg_parser_result.serialized_lwgeom);
 
684
 
 
685
        return ret;
 
686
}
 
687
 
 
688
/*
 
689
 * Parser functions for working with serialized LWGEOMs. Useful for cases where
 
690
 * the function input is already serialized, e.g. some input and output functions
 
691
 */
 
692
 
 
693
/**
 
694
 * Make a serialzed LWGEOM object from a WKT input string
 
695
 */
 
696
int
 
697
serialized_lwgeom_from_ewkt(LWGEOM_PARSER_RESULT *lwg_parser_result, char *wkt_input, int flags)
 
698
{
 
699
 
 
700
        int result = parse_lwg(lwg_parser_result, wkt_input, flags,
 
701
                               lwalloc, lwerror);
 
702
 
 
703
        LWDEBUGF(2, "serialized_lwgeom_from_ewkt with %s",wkt_input);
 
704
 
 
705
        return result;
 
706
}
 
707
 
 
708
/**
 
709
 * Return an alloced string
 
710
 */
 
711
int
 
712
serialized_lwgeom_to_ewkt(LWGEOM_UNPARSER_RESULT *lwg_unparser_result, uchar *serialized, int flags)
 
713
{
 
714
        int result;
 
715
 
 
716
        result = unparse_WKT(lwg_unparser_result, serialized, lwalloc, lwfree, flags);
 
717
 
 
718
        return result;
 
719
}
 
720
 
 
721
/**
 
722
 * Return an alloced string
 
723
 */
 
724
int
 
725
serialized_lwgeom_from_hexwkb(LWGEOM_PARSER_RESULT *lwg_parser_result, char *hexwkb_input, int flags)
 
726
{
 
727
        /* NOTE: it is actually the same combined WKT/WKB parser that decodes HEXEWKB into LWGEOMs! */
 
728
        int result = parse_lwg(lwg_parser_result, hexwkb_input, flags,
 
729
                               lwalloc, lwerror);
 
730
 
 
731
        LWDEBUGF(2, "serialized_lwgeom_from_hexwkb with %s", hexwkb_input);
 
732
 
 
733
        return result;
 
734
}
 
735
 
 
736
/**
 
737
 * Return an alloced string
 
738
 */
 
739
int
 
740
serialized_lwgeom_to_hexwkb(LWGEOM_UNPARSER_RESULT *lwg_unparser_result, uchar *serialized, int flags, unsigned int byteorder)
 
741
{
 
742
        int result;
 
743
 
 
744
        result = unparse_WKB(lwg_unparser_result, serialized, lwalloc, lwfree, flags, byteorder, 1);
 
745
 
 
746
        return result;
 
747
}
 
748
 
 
749
/**
 
750
 * Return an alloced string
 
751
 */
 
752
int
 
753
serialized_lwgeom_to_ewkb(LWGEOM_UNPARSER_RESULT *lwg_unparser_result, uchar *serialized, int flags, unsigned int byteorder)
 
754
{
 
755
        int result;
 
756
 
 
757
        result = unparse_WKB(lwg_unparser_result, serialized, lwalloc, lwfree, flags, byteorder, 0);
 
758
 
 
759
        return result;
 
760
}
 
761
 
 
762
/**
 
763
 * @brief geom1 same as geom2
 
764
 *      iff
 
765
 *              + have same type
 
766
 *                      + have same # objects
 
767
 *              + have same bvol
 
768
 *              + each object in geom1 has a corresponding object in geom2 (see above)
 
769
 *      @param lwgeom1
 
770
 *      @param lwgeom2
 
771
 */
 
772
char
 
773
lwgeom_same(const LWGEOM *lwgeom1, const LWGEOM *lwgeom2)
 
774
{
 
775
        LWDEBUGF(2, "lwgeom_same(%s, %s) called",
 
776
                 lwgeom_typename(TYPE_GETTYPE(lwgeom1->type)),
 
777
                 lwgeom_typename(TYPE_GETTYPE(lwgeom2->type)));
 
778
 
 
779
        if ( TYPE_GETTYPE(lwgeom1->type) != TYPE_GETTYPE(lwgeom2->type) )
 
780
        {
 
781
                LWDEBUG(3, " type differ");
 
782
 
 
783
                return 0;
 
784
        }
 
785
 
 
786
        if ( TYPE_GETZM(lwgeom1->type) != TYPE_GETZM(lwgeom2->type) )
 
787
        {
 
788
                LWDEBUG(3, " ZM flags differ");
 
789
 
 
790
                return 0;
 
791
        }
 
792
 
 
793
        /* Check boxes if both already computed  */
 
794
        if ( lwgeom1->bbox && lwgeom2->bbox )
 
795
        {
 
796
                /*lwnotice("bbox1:%p, bbox2:%p", lwgeom1->bbox, lwgeom2->bbox);*/
 
797
                if ( ! box2d_same(lwgeom1->bbox, lwgeom2->bbox) )
 
798
                {
 
799
                        LWDEBUG(3, " bounding boxes differ");
 
800
 
 
801
                        return 0;
 
802
                }
 
803
        }
 
804
 
 
805
        /* geoms have same type, invoke type-specific function */
 
806
        switch (TYPE_GETTYPE(lwgeom1->type))
 
807
        {
 
808
        case POINTTYPE:
 
809
                return lwpoint_same((LWPOINT *)lwgeom1,
 
810
                                    (LWPOINT *)lwgeom2);
 
811
        case LINETYPE:
 
812
                return lwline_same((LWLINE *)lwgeom1,
 
813
                                   (LWLINE *)lwgeom2);
 
814
        case POLYGONTYPE:
 
815
                return lwpoly_same((LWPOLY *)lwgeom1,
 
816
                                   (LWPOLY *)lwgeom2);
 
817
        case MULTIPOINTTYPE:
 
818
        case MULTILINETYPE:
 
819
        case MULTIPOLYGONTYPE:
 
820
        case COLLECTIONTYPE:
 
821
                return lwcollection_same((LWCOLLECTION *)lwgeom1,
 
822
                                         (LWCOLLECTION *)lwgeom2);
 
823
        default:
 
824
                lwerror("lwgeom_same: unsupported geometry type: %s",
 
825
                        lwgeom_typename(TYPE_GETTYPE(lwgeom1->type)));
 
826
                return 0;
 
827
        }
 
828
 
 
829
}
 
830
 
 
831
void
 
832
lwgeom_changed(LWGEOM *lwgeom)
 
833
{
 
834
        if ( lwgeom->bbox ) lwfree(lwgeom->bbox);
 
835
        lwgeom->bbox = NULL;
 
836
        TYPE_SETHASBBOX(lwgeom->type, 0);
 
837
}
 
838
 
 
839
void
 
840
lwgeom_drop_bbox(LWGEOM *lwgeom)
 
841
{
 
842
        if ( lwgeom->bbox ) lwfree(lwgeom->bbox);
 
843
        lwgeom->bbox = NULL;
 
844
        TYPE_SETHASBBOX(lwgeom->type, 0);
 
845
}
 
846
 
 
847
/**
 
848
 * Ensure there's a box in the LWGEOM.
 
849
 * If the box is already there just return,
 
850
 * else compute it.
 
851
 */
 
852
void
 
853
lwgeom_add_bbox(LWGEOM *lwgeom)
 
854
{
 
855
        if ( lwgeom->bbox ) return;
 
856
        lwgeom->bbox = lwgeom_compute_box2d(lwgeom);
 
857
        TYPE_SETHASBBOX(lwgeom->type, 1);
 
858
}
 
859
 
 
860
void
 
861
lwgeom_dropSRID(LWGEOM *lwgeom)
 
862
{
 
863
        TYPE_SETHASSRID(lwgeom->type, 0);
 
864
        lwgeom->SRID = -1;
 
865
}
 
866
 
 
867
LWGEOM *
 
868
lwgeom_segmentize2d(LWGEOM *lwgeom, double dist)
 
869
{
 
870
        switch (TYPE_GETTYPE(lwgeom->type))
 
871
        {
 
872
        case LINETYPE:
 
873
                return (LWGEOM *)lwline_segmentize2d((LWLINE *)lwgeom,
 
874
                                                     dist);
 
875
        case POLYGONTYPE:
 
876
                return (LWGEOM *)lwpoly_segmentize2d((LWPOLY *)lwgeom,
 
877
                                                     dist);
 
878
        case MULTILINETYPE:
 
879
        case MULTIPOLYGONTYPE:
 
880
        case COLLECTIONTYPE:
 
881
                return (LWGEOM *)lwcollection_segmentize2d(
 
882
                           (LWCOLLECTION *)lwgeom, dist);
 
883
 
 
884
        default:
 
885
                return lwgeom_clone(lwgeom);
 
886
        }
 
887
}
 
888
 
 
889
void
 
890
lwgeom_longitude_shift(LWGEOM *lwgeom)
 
891
{
 
892
        int i;
 
893
        switch (TYPE_GETTYPE(lwgeom->type))
 
894
        {
 
895
                LWPOINT *point;
 
896
                LWLINE *line;
 
897
                LWPOLY *poly;
 
898
                LWCOLLECTION *coll;
 
899
 
 
900
        case POINTTYPE:
 
901
                point = (LWPOINT *)lwgeom;
 
902
                ptarray_longitude_shift(point->point);
 
903
                return;
 
904
        case LINETYPE:
 
905
                line = (LWLINE *)lwgeom;
 
906
                ptarray_longitude_shift(line->points);
 
907
                return;
 
908
        case POLYGONTYPE:
 
909
                poly = (LWPOLY *)lwgeom;
 
910
                for (i=0; i<poly->nrings; i++)
 
911
                        ptarray_longitude_shift(poly->rings[i]);
 
912
                return;
 
913
        case MULTIPOINTTYPE:
 
914
        case MULTILINETYPE:
 
915
        case MULTIPOLYGONTYPE:
 
916
        case COLLECTIONTYPE:
 
917
                coll = (LWCOLLECTION *)lwgeom;
 
918
                for (i=0; i<coll->ngeoms; i++)
 
919
                        lwgeom_longitude_shift(coll->geoms[i]);
 
920
                return;
 
921
        default:
 
922
                lwerror("%s:%d: unsupported geom type: %s",
 
923
                        __FILE__, __LINE__,
 
924
                        lwgeom_typename(TYPE_GETTYPE(lwgeom->type)));
 
925
        }
 
926
}
 
927
 
 
928
/** Return TRUE if the geometry may contain sub-geometries, i.e. it is a MULTI* or COMPOUNDCURVE */
 
929
int
 
930
lwgeom_contains_subgeoms(int type)
 
931
{
 
932
 
 
933
        switch (type)
 
934
        {
 
935
        case MULTIPOINTTYPE:
 
936
        case MULTILINETYPE:
 
937
        case MULTIPOLYGONTYPE:
 
938
        case COLLECTIONTYPE:
 
939
        case COMPOUNDTYPE:
 
940
        case MULTICURVETYPE:
 
941
        case MULTISURFACETYPE:
 
942
                return -1;
 
943
                break;
 
944
 
 
945
        default:
 
946
                return 0;
 
947
        }
 
948
}
 
949
 
 
950
void lwgeom_free(LWGEOM *lwgeom)
 
951
{
 
952
 
 
953
        switch (TYPE_GETTYPE(lwgeom->type))
 
954
        {
 
955
        case POINTTYPE:
 
956
                lwpoint_free((LWPOINT *)lwgeom);
 
957
                break;
 
958
        case LINETYPE:
 
959
                lwline_free((LWLINE *)lwgeom);
 
960
                break;
 
961
        case POLYGONTYPE:
 
962
                lwpoly_free((LWPOLY *)lwgeom);
 
963
                break;
 
964
        case MULTIPOINTTYPE:
 
965
                lwmpoint_free((LWMPOINT *)lwgeom);
 
966
                break;
 
967
        case MULTILINETYPE:
 
968
                lwmline_free((LWMLINE *)lwgeom);
 
969
                break;
 
970
        case MULTIPOLYGONTYPE:
 
971
                lwmpoly_free((LWMPOLY *)lwgeom);
 
972
                break;
 
973
        case COLLECTIONTYPE:
 
974
                lwcollection_free((LWCOLLECTION *)lwgeom);
 
975
                break;
 
976
        }
 
977
        return;
 
978
 
 
979
};