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

« back to all changes in this revision

Viewing changes to liblwgeom/lwline.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: lwline.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
/* basic LWLINE functions */
 
14
 
 
15
#include <stdio.h>
 
16
#include <stdlib.h>
 
17
#include <string.h>
 
18
#include "liblwgeom.h"
 
19
 
 
20
 
 
21
 
 
22
/*
 
23
 * Construct a new LWLINE.  points will *NOT* be copied
 
24
 * use SRID=-1 for unknown SRID (will have 8bit type's S = 0)
 
25
 */
 
26
LWLINE *
 
27
lwline_construct(int SRID, BOX2DFLOAT4 *bbox, POINTARRAY *points)
 
28
{
 
29
        LWLINE *result;
 
30
        result = (LWLINE*) lwalloc(sizeof(LWLINE));
 
31
 
 
32
        LWDEBUG(2, "lwline_construct called.");
 
33
 
 
34
        result->type = lwgeom_makeType_full(
 
35
                           TYPE_HASZ(points->dims),
 
36
                           TYPE_HASM(points->dims),
 
37
                           (SRID!=-1), LINETYPE,
 
38
                           0);
 
39
 
 
40
        LWDEBUGF(3, "lwline_construct type=%d", result->type);
 
41
 
 
42
        result->SRID = SRID;
 
43
        result->points = points;
 
44
        result->bbox = bbox;
 
45
 
 
46
        return result;
 
47
}
 
48
 
 
49
/*
 
50
 * given the LWGEOM serialized form (or a pointer into a muli* one)
 
51
 * construct a proper LWLINE.
 
52
 * serialized_form should point to the 8bit type format (with type = 2)
 
53
 * See serialized form doc
 
54
 */
 
55
LWLINE *
 
56
lwline_deserialize(uchar *serialized_form)
 
57
{
 
58
        uchar type;
 
59
        LWLINE *result;
 
60
        uchar *loc =NULL;
 
61
        uint32 npoints;
 
62
        POINTARRAY *pa;
 
63
 
 
64
        type = (uchar) serialized_form[0];
 
65
 
 
66
        if ( lwgeom_getType(type) != LINETYPE)
 
67
        {
 
68
                lwerror("lwline_deserialize: attempt to deserialize a line which is really a %s", lwgeom_typename(type));
 
69
                return NULL;
 
70
        }
 
71
 
 
72
        result = (LWLINE*) lwalloc(sizeof(LWLINE)) ;
 
73
        result->type = type;
 
74
 
 
75
        loc = serialized_form+1;
 
76
 
 
77
        if (lwgeom_hasBBOX(type))
 
78
        {
 
79
                LWDEBUG(3, "lwline_deserialize: input has bbox");
 
80
 
 
81
                result->bbox = lwalloc(sizeof(BOX2DFLOAT4));
 
82
                memcpy(result->bbox, loc, sizeof(BOX2DFLOAT4));
 
83
                loc += sizeof(BOX2DFLOAT4);
 
84
        }
 
85
        else
 
86
        {
 
87
                result->bbox = NULL;
 
88
                /*lwnotice("line has NO bbox"); */
 
89
        }
 
90
 
 
91
        if ( lwgeom_hasSRID(type))
 
92
        {
 
93
                /*lwnotice("line has srid"); */
 
94
                result->SRID = lw_get_int32(loc);
 
95
                loc +=4; /* type + SRID */
 
96
        }
 
97
        else
 
98
        {
 
99
                /*lwnotice("line has NO srid"); */
 
100
                result->SRID = -1;
 
101
        }
 
102
 
 
103
        /* we've read the type (1 byte) and SRID (4 bytes, if present) */
 
104
 
 
105
        npoints = lw_get_uint32(loc);
 
106
        /*lwnotice("line npoints = %d", npoints); */
 
107
        loc +=4;
 
108
        pa = pointArray_construct(loc, TYPE_HASZ(type), TYPE_HASM(type), npoints);
 
109
        result->points = pa;
 
110
 
 
111
        return result;
 
112
}
 
113
 
 
114
/*
 
115
 * convert this line into its serialize form
 
116
 * result's first char will be the 8bit type.  See serialized form doc
 
117
 */
 
118
uchar *
 
119
lwline_serialize(LWLINE *line)
 
120
{
 
121
        size_t size, retsize;
 
122
        uchar * result;
 
123
 
 
124
        if (line == NULL) lwerror("lwline_serialize:: given null line");
 
125
 
 
126
        size = lwline_serialize_size(line);
 
127
        result = lwalloc(size);
 
128
        lwline_serialize_buf(line, result, &retsize);
 
129
 
 
130
        if ( retsize != size )
 
131
        {
 
132
                lwerror("lwline_serialize_size returned %d, ..serialize_buf returned %d", size, retsize);
 
133
        }
 
134
 
 
135
        return result;
 
136
}
 
137
 
 
138
/*
 
139
 * convert this line into its serialize form writing it into
 
140
 * the given buffer, and returning number of bytes written into
 
141
 * the given int pointer.
 
142
 * result's first char will be the 8bit type.  See serialized form doc
 
143
 */
 
144
void
 
145
lwline_serialize_buf(LWLINE *line, uchar *buf, size_t *retsize)
 
146
{
 
147
        char hasSRID;
 
148
        uchar *loc;
 
149
        int ptsize;
 
150
        size_t size;
 
151
 
 
152
        LWDEBUGF(2, "lwline_serialize_buf(%p, %p, %p) called",
 
153
                 line, buf, retsize);
 
154
 
 
155
        if (line == NULL)
 
156
                lwerror("lwline_serialize:: given null line");
 
157
 
 
158
        if ( TYPE_GETZM(line->type) != TYPE_GETZM(line->points->dims) )
 
159
                lwerror("Dimensions mismatch in lwline");
 
160
 
 
161
        ptsize = pointArray_ptsize(line->points);
 
162
 
 
163
        hasSRID = (line->SRID != -1);
 
164
 
 
165
        buf[0] = (uchar) lwgeom_makeType_full(
 
166
                     TYPE_HASZ(line->type), TYPE_HASM(line->type),
 
167
                     hasSRID, LINETYPE, line->bbox ? 1 : 0);
 
168
        loc = buf+1;
 
169
 
 
170
        LWDEBUGF(3, "lwline_serialize_buf added type (%d)", line->type);
 
171
 
 
172
        if (line->bbox)
 
173
        {
 
174
                memcpy(loc, line->bbox, sizeof(BOX2DFLOAT4));
 
175
                loc += sizeof(BOX2DFLOAT4);
 
176
 
 
177
                LWDEBUG(3, "lwline_serialize_buf added BBOX");
 
178
        }
 
179
 
 
180
        if (hasSRID)
 
181
        {
 
182
                memcpy(loc, &line->SRID, sizeof(int32));
 
183
                loc += sizeof(int32);
 
184
 
 
185
                LWDEBUG(3, "lwline_serialize_buf added SRID");
 
186
        }
 
187
 
 
188
        memcpy(loc, &line->points->npoints, sizeof(uint32));
 
189
        loc += sizeof(uint32);
 
190
 
 
191
        LWDEBUGF(3, "lwline_serialize_buf added npoints (%d)",
 
192
                 line->points->npoints);
 
193
 
 
194
        /*copy in points */
 
195
        size = line->points->npoints*ptsize;
 
196
        memcpy(loc, getPoint_internal(line->points, 0), size);
 
197
        loc += size;
 
198
 
 
199
        LWDEBUGF(3, "lwline_serialize_buf copied serialized_pointlist (%d bytes)",
 
200
                 ptsize * line->points->npoints);
 
201
 
 
202
        if (retsize) *retsize = loc-buf;
 
203
 
 
204
        /*printBYTES((uchar *)result, loc-buf); */
 
205
 
 
206
        LWDEBUGF(3, "lwline_serialize_buf returning (loc: %p, size: %d)",
 
207
                 loc, loc-buf);
 
208
}
 
209
 
 
210
/*
 
211
 * Find bounding box (standard one)
 
212
 * zmin=zmax=NO_Z_VALUE if 2d
 
213
 */
 
214
BOX3D *
 
215
lwline_compute_box3d(LWLINE *line)
 
216
{
 
217
        BOX3D *ret;
 
218
 
 
219
        if (line == NULL) return NULL;
 
220
 
 
221
        ret = ptarray_compute_box3d(line->points);
 
222
        return ret;
 
223
}
 
224
 
 
225
/* find length of this deserialized line */
 
226
size_t
 
227
lwline_serialize_size(LWLINE *line)
 
228
{
 
229
        size_t size = 1;  /* type */
 
230
 
 
231
        LWDEBUG(2, "lwline_serialize_size called");
 
232
 
 
233
        if ( line->SRID != -1 ) size += 4; /* SRID */
 
234
        if ( line->bbox ) size += sizeof(BOX2DFLOAT4);
 
235
 
 
236
        size += 4; /* npoints */
 
237
        size += pointArray_ptsize(line->points)*line->points->npoints;
 
238
 
 
239
        LWDEBUGF(3, "lwline_serialize_size returning %d", size);
 
240
 
 
241
        return size;
 
242
}
 
243
 
 
244
void lwline_free (LWLINE  *line)
 
245
{
 
246
        if ( line->bbox )
 
247
                lwfree(line->bbox);
 
248
 
 
249
        ptarray_free(line->points);
 
250
        lwfree(line);
 
251
}
 
252
 
 
253
/* find length of this serialized line */
 
254
size_t
 
255
lwgeom_size_line(const uchar *serialized_line)
 
256
{
 
257
        int type = (uchar) serialized_line[0];
 
258
        uint32 result = 1;  /*type */
 
259
        const uchar *loc;
 
260
        uint32 npoints;
 
261
 
 
262
        LWDEBUG(2, "lwgeom_size_line called");
 
263
 
 
264
        if ( lwgeom_getType(type) != LINETYPE)
 
265
                lwerror("lwgeom_size_line::attempt to find the length of a non-line");
 
266
 
 
267
 
 
268
        loc = serialized_line+1;
 
269
 
 
270
        if (lwgeom_hasBBOX(type))
 
271
        {
 
272
                loc += sizeof(BOX2DFLOAT4);
 
273
                result +=sizeof(BOX2DFLOAT4);
 
274
        }
 
275
 
 
276
        if ( lwgeom_hasSRID(type))
 
277
        {
 
278
                loc += 4; /* type + SRID */
 
279
                result +=4;
 
280
        }
 
281
 
 
282
        /* we've read the type (1 byte) and SRID (4 bytes, if present) */
 
283
        npoints = lw_get_uint32(loc);
 
284
        result += sizeof(uint32); /* npoints */
 
285
 
 
286
        result += TYPE_NDIMS(type) * sizeof(double) * npoints;
 
287
 
 
288
        LWDEBUGF(3, "lwgeom_size_line returning %d", result);
 
289
 
 
290
        return result;
 
291
}
 
292
 
 
293
void printLWLINE(LWLINE *line)
 
294
{
 
295
        lwnotice("LWLINE {");
 
296
        lwnotice("    ndims = %i", (int)TYPE_NDIMS(line->type));
 
297
        lwnotice("    SRID = %i", (int)line->SRID);
 
298
        printPA(line->points);
 
299
        lwnotice("}");
 
300
}
 
301
 
 
302
int
 
303
lwline_compute_box2d_p(LWLINE *line, BOX2DFLOAT4 *box)
 
304
{
 
305
        return ptarray_compute_box2d_p(line->points, box);
 
306
}
 
307
 
 
308
/* Clone LWLINE object. POINTARRAY is not copied. */
 
309
LWLINE *
 
310
lwline_clone(const LWLINE *g)
 
311
{
 
312
        LWLINE *ret = lwalloc(sizeof(LWLINE));
 
313
 
 
314
        LWDEBUGF(2, "lwline_clone called with %p", g);
 
315
 
 
316
        memcpy(ret, g, sizeof(LWLINE));
 
317
        if ( g->bbox ) ret->bbox = box2d_clone(g->bbox);
 
318
        return ret;
 
319
}
 
320
 
 
321
/*
 
322
 * Add 'what' to this line at position 'where'.
 
323
 * where=0 == prepend
 
324
 * where=-1 == append
 
325
 * Returns a MULTILINE or a GEOMETRYCOLLECTION
 
326
 */
 
327
LWGEOM *
 
328
lwline_add(const LWLINE *to, uint32 where, const LWGEOM *what)
 
329
{
 
330
        LWCOLLECTION *col;
 
331
        LWGEOM **geoms;
 
332
        int newtype;
 
333
 
 
334
        if ( where != -1 && where != 0 )
 
335
        {
 
336
                lwerror("lwline_add only supports 0 or -1 as second argument, got %d", where);
 
337
                return NULL;
 
338
        }
 
339
 
 
340
        /* dimensions compatibility are checked by caller */
 
341
 
 
342
        /* Construct geoms array */
 
343
        geoms = lwalloc(sizeof(LWGEOM *)*2);
 
344
        if ( where == -1 ) /* append */
 
345
        {
 
346
                geoms[0] = lwgeom_clone((LWGEOM *)to);
 
347
                geoms[1] = lwgeom_clone(what);
 
348
        }
 
349
        else /* prepend */
 
350
        {
 
351
                geoms[0] = lwgeom_clone(what);
 
352
                geoms[1] = lwgeom_clone((LWGEOM *)to);
 
353
        }
 
354
 
 
355
        /* reset SRID and wantbbox flag from component types */
 
356
        geoms[0]->SRID = geoms[1]->SRID = -1;
 
357
        TYPE_SETHASSRID(geoms[0]->type, 0);
 
358
        TYPE_SETHASSRID(geoms[1]->type, 0);
 
359
        TYPE_SETHASBBOX(geoms[0]->type, 0);
 
360
        TYPE_SETHASBBOX(geoms[1]->type, 0);
 
361
 
 
362
        /* Find appropriate geom type */
 
363
        if ( TYPE_GETTYPE(what->type) == LINETYPE ) newtype = MULTILINETYPE;
 
364
        else newtype = COLLECTIONTYPE;
 
365
 
 
366
        col = lwcollection_construct(newtype,
 
367
                                     to->SRID, NULL,
 
368
                                     2, geoms);
 
369
 
 
370
        return (LWGEOM *)col;
 
371
}
 
372
 
 
373
void
 
374
lwline_release(LWLINE *lwline)
 
375
{
 
376
        lwgeom_release(lwline_as_lwgeom(lwline));
 
377
}
 
378
 
 
379
void
 
380
lwline_reverse(LWLINE *line)
 
381
{
 
382
        ptarray_reverse(line->points);
 
383
}
 
384
 
 
385
LWLINE *
 
386
lwline_segmentize2d(LWLINE *line, double dist)
 
387
{
 
388
        return lwline_construct(line->SRID, NULL,
 
389
                                ptarray_segmentize2d(line->points, dist));
 
390
}
 
391
 
 
392
/* check coordinate equality  */
 
393
char
 
394
lwline_same(const LWLINE *l1, const LWLINE *l2)
 
395
{
 
396
        return ptarray_same(l1->points, l2->points);
 
397
}
 
398
 
 
399
/*
 
400
 * Construct a LWLINE from an array of LWPOINTs
 
401
 * LWLINE dimensions are large enough to host all input dimensions.
 
402
 */
 
403
LWLINE *
 
404
lwline_from_lwpointarray(int SRID, unsigned int npoints, LWPOINT **points)
 
405
{
 
406
        int zmflag=0;
 
407
        unsigned int i;
 
408
        POINTARRAY *pa;
 
409
        uchar *newpoints, *ptr;
 
410
        size_t ptsize, size;
 
411
 
 
412
        /*
 
413
         * Find output dimensions, check integrity
 
414
         */
 
415
        for (i=0; i<npoints; i++)
 
416
        {
 
417
                if ( TYPE_GETTYPE(points[i]->type) != POINTTYPE )
 
418
                {
 
419
                        lwerror("lwline_from_lwpointarray: invalid input type: %s",
 
420
                                lwgeom_typename(TYPE_GETTYPE(points[i]->type)));
 
421
                        return NULL;
 
422
                }
 
423
                if ( TYPE_HASZ(points[i]->type) ) zmflag |= 2;
 
424
                if ( TYPE_HASM(points[i]->type) ) zmflag |= 1;
 
425
                if ( zmflag == 3 ) break;
 
426
        }
 
427
 
 
428
        if ( zmflag == 0 ) ptsize=2*sizeof(double);
 
429
        else if ( zmflag == 3 ) ptsize=4*sizeof(double);
 
430
        else ptsize=3*sizeof(double);
 
431
 
 
432
        /*
 
433
         * Allocate output points array
 
434
         */
 
435
        size = ptsize*npoints;
 
436
        newpoints = lwalloc(size);
 
437
        memset(newpoints, 0, size);
 
438
 
 
439
        ptr=newpoints;
 
440
        for (i=0; i<npoints; i++)
 
441
        {
 
442
                size=pointArray_ptsize(points[i]->point);
 
443
                memcpy(ptr, getPoint_internal(points[i]->point, 0), size);
 
444
                ptr+=ptsize;
 
445
        }
 
446
 
 
447
        pa = pointArray_construct(newpoints, zmflag&2, zmflag&1, npoints);
 
448
 
 
449
        return lwline_construct(SRID, NULL, pa);
 
450
}
 
451
 
 
452
/*
 
453
 * Construct a LWLINE from a LWMPOINT
 
454
 */
 
455
LWLINE *
 
456
lwline_from_lwmpoint(int SRID, LWMPOINT *mpoint)
 
457
{
 
458
        unsigned int i;
 
459
        POINTARRAY *pa;
 
460
        char zmflag = TYPE_GETZM(mpoint->type);
 
461
        size_t ptsize, size;
 
462
        uchar *newpoints, *ptr;
 
463
 
 
464
        if ( zmflag == 0 ) ptsize=2*sizeof(double);
 
465
        else if ( zmflag == 3 ) ptsize=4*sizeof(double);
 
466
        else ptsize=3*sizeof(double);
 
467
 
 
468
        /* Allocate space for output points */
 
469
        size = ptsize*mpoint->ngeoms;
 
470
        newpoints = lwalloc(size);
 
471
        memset(newpoints, 0, size);
 
472
 
 
473
        ptr=newpoints;
 
474
        for (i=0; i<mpoint->ngeoms; i++)
 
475
        {
 
476
                memcpy(ptr,
 
477
                       getPoint_internal(mpoint->geoms[i]->point, 0),
 
478
                       ptsize);
 
479
                ptr+=ptsize;
 
480
        }
 
481
 
 
482
        pa = pointArray_construct(newpoints, zmflag&2, zmflag&1,
 
483
                                  mpoint->ngeoms);
 
484
 
 
485
        LWDEBUGF(3, "lwline_from_lwmpoint: constructed pointarray for %d points, %d zmflag", mpoint->ngeoms, zmflag);
 
486
 
 
487
        return lwline_construct(SRID, NULL, pa);
 
488
}
 
489
 
 
490
LWLINE *
 
491
lwline_addpoint(LWLINE *line, LWPOINT *point, unsigned int where)
 
492
{
 
493
        POINTARRAY *newpa;
 
494
        LWLINE *ret;
 
495
 
 
496
        newpa = ptarray_addPoint(line->points,
 
497
                                 getPoint_internal(point->point, 0),
 
498
                                 TYPE_NDIMS(point->type), where);
 
499
 
 
500
        ret = lwline_construct(line->SRID, NULL, newpa);
 
501
 
 
502
        return ret;
 
503
}
 
504
 
 
505
LWLINE *
 
506
lwline_removepoint(LWLINE *line, unsigned int index)
 
507
{
 
508
        POINTARRAY *newpa;
 
509
        LWLINE *ret;
 
510
 
 
511
        newpa = ptarray_removePoint(line->points, index);
 
512
 
 
513
        ret = lwline_construct(line->SRID, NULL, newpa);
 
514
 
 
515
        return ret;
 
516
}
 
517
 
 
518
/*
 
519
 * Note: input will be changed, make sure you have permissions for this.
 
520
 */
 
521
void
 
522
lwline_setPoint4d(LWLINE *line, unsigned int index, POINT4D *newpoint)
 
523
{
 
524
        setPoint4d(line->points, index, newpoint);
 
525
}