1
/**********************************************************************
2
* $Id: lwline.c 4168 2009-06-11 16:44:03Z pramsey $
4
* PostGIS - Spatial Types for PostgreSQL
5
* http://postgis.refractions.net
6
* Copyright 2001-2006 Refractions Research Inc.
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.
11
**********************************************************************/
13
/* basic LWLINE functions */
18
#include "liblwgeom.h"
23
* Construct a new LWLINE. points will *NOT* be copied
24
* use SRID=-1 for unknown SRID (will have 8bit type's S = 0)
27
lwline_construct(int SRID, BOX2DFLOAT4 *bbox, POINTARRAY *points)
30
result = (LWLINE*) lwalloc(sizeof(LWLINE));
32
LWDEBUG(2, "lwline_construct called.");
34
result->type = lwgeom_makeType_full(
35
TYPE_HASZ(points->dims),
36
TYPE_HASM(points->dims),
40
LWDEBUGF(3, "lwline_construct type=%d", result->type);
43
result->points = points;
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
56
lwline_deserialize(uchar *serialized_form)
64
type = (uchar) serialized_form[0];
66
if ( lwgeom_getType(type) != LINETYPE)
68
lwerror("lwline_deserialize: attempt to deserialize a line which is really a %s", lwgeom_typename(type));
72
result = (LWLINE*) lwalloc(sizeof(LWLINE)) ;
75
loc = serialized_form+1;
77
if (lwgeom_hasBBOX(type))
79
LWDEBUG(3, "lwline_deserialize: input has bbox");
81
result->bbox = lwalloc(sizeof(BOX2DFLOAT4));
82
memcpy(result->bbox, loc, sizeof(BOX2DFLOAT4));
83
loc += sizeof(BOX2DFLOAT4);
88
/*lwnotice("line has NO bbox"); */
91
if ( lwgeom_hasSRID(type))
93
/*lwnotice("line has srid"); */
94
result->SRID = lw_get_int32(loc);
95
loc +=4; /* type + SRID */
99
/*lwnotice("line has NO srid"); */
103
/* we've read the type (1 byte) and SRID (4 bytes, if present) */
105
npoints = lw_get_uint32(loc);
106
/*lwnotice("line npoints = %d", npoints); */
108
pa = pointArray_construct(loc, TYPE_HASZ(type), TYPE_HASM(type), npoints);
115
* convert this line into its serialize form
116
* result's first char will be the 8bit type. See serialized form doc
119
lwline_serialize(LWLINE *line)
121
size_t size, retsize;
124
if (line == NULL) lwerror("lwline_serialize:: given null line");
126
size = lwline_serialize_size(line);
127
result = lwalloc(size);
128
lwline_serialize_buf(line, result, &retsize);
130
if ( retsize != size )
132
lwerror("lwline_serialize_size returned %d, ..serialize_buf returned %d", size, retsize);
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
145
lwline_serialize_buf(LWLINE *line, uchar *buf, size_t *retsize)
152
LWDEBUGF(2, "lwline_serialize_buf(%p, %p, %p) called",
156
lwerror("lwline_serialize:: given null line");
158
if ( TYPE_GETZM(line->type) != TYPE_GETZM(line->points->dims) )
159
lwerror("Dimensions mismatch in lwline");
161
ptsize = pointArray_ptsize(line->points);
163
hasSRID = (line->SRID != -1);
165
buf[0] = (uchar) lwgeom_makeType_full(
166
TYPE_HASZ(line->type), TYPE_HASM(line->type),
167
hasSRID, LINETYPE, line->bbox ? 1 : 0);
170
LWDEBUGF(3, "lwline_serialize_buf added type (%d)", line->type);
174
memcpy(loc, line->bbox, sizeof(BOX2DFLOAT4));
175
loc += sizeof(BOX2DFLOAT4);
177
LWDEBUG(3, "lwline_serialize_buf added BBOX");
182
memcpy(loc, &line->SRID, sizeof(int32));
183
loc += sizeof(int32);
185
LWDEBUG(3, "lwline_serialize_buf added SRID");
188
memcpy(loc, &line->points->npoints, sizeof(uint32));
189
loc += sizeof(uint32);
191
LWDEBUGF(3, "lwline_serialize_buf added npoints (%d)",
192
line->points->npoints);
195
size = line->points->npoints*ptsize;
196
memcpy(loc, getPoint_internal(line->points, 0), size);
199
LWDEBUGF(3, "lwline_serialize_buf copied serialized_pointlist (%d bytes)",
200
ptsize * line->points->npoints);
202
if (retsize) *retsize = loc-buf;
204
/*printBYTES((uchar *)result, loc-buf); */
206
LWDEBUGF(3, "lwline_serialize_buf returning (loc: %p, size: %d)",
211
* Find bounding box (standard one)
212
* zmin=zmax=NO_Z_VALUE if 2d
215
lwline_compute_box3d(LWLINE *line)
219
if (line == NULL) return NULL;
221
ret = ptarray_compute_box3d(line->points);
225
/* find length of this deserialized line */
227
lwline_serialize_size(LWLINE *line)
229
size_t size = 1; /* type */
231
LWDEBUG(2, "lwline_serialize_size called");
233
if ( line->SRID != -1 ) size += 4; /* SRID */
234
if ( line->bbox ) size += sizeof(BOX2DFLOAT4);
236
size += 4; /* npoints */
237
size += pointArray_ptsize(line->points)*line->points->npoints;
239
LWDEBUGF(3, "lwline_serialize_size returning %d", size);
244
void lwline_free (LWLINE *line)
249
ptarray_free(line->points);
253
/* find length of this serialized line */
255
lwgeom_size_line(const uchar *serialized_line)
257
int type = (uchar) serialized_line[0];
258
uint32 result = 1; /*type */
262
LWDEBUG(2, "lwgeom_size_line called");
264
if ( lwgeom_getType(type) != LINETYPE)
265
lwerror("lwgeom_size_line::attempt to find the length of a non-line");
268
loc = serialized_line+1;
270
if (lwgeom_hasBBOX(type))
272
loc += sizeof(BOX2DFLOAT4);
273
result +=sizeof(BOX2DFLOAT4);
276
if ( lwgeom_hasSRID(type))
278
loc += 4; /* type + SRID */
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 */
286
result += TYPE_NDIMS(type) * sizeof(double) * npoints;
288
LWDEBUGF(3, "lwgeom_size_line returning %d", result);
293
void printLWLINE(LWLINE *line)
295
lwnotice("LWLINE {");
296
lwnotice(" ndims = %i", (int)TYPE_NDIMS(line->type));
297
lwnotice(" SRID = %i", (int)line->SRID);
298
printPA(line->points);
303
lwline_compute_box2d_p(LWLINE *line, BOX2DFLOAT4 *box)
305
return ptarray_compute_box2d_p(line->points, box);
308
/* Clone LWLINE object. POINTARRAY is not copied. */
310
lwline_clone(const LWLINE *g)
312
LWLINE *ret = lwalloc(sizeof(LWLINE));
314
LWDEBUGF(2, "lwline_clone called with %p", g);
316
memcpy(ret, g, sizeof(LWLINE));
317
if ( g->bbox ) ret->bbox = box2d_clone(g->bbox);
322
* Add 'what' to this line at position 'where'.
325
* Returns a MULTILINE or a GEOMETRYCOLLECTION
328
lwline_add(const LWLINE *to, uint32 where, const LWGEOM *what)
334
if ( where != -1 && where != 0 )
336
lwerror("lwline_add only supports 0 or -1 as second argument, got %d", where);
340
/* dimensions compatibility are checked by caller */
342
/* Construct geoms array */
343
geoms = lwalloc(sizeof(LWGEOM *)*2);
344
if ( where == -1 ) /* append */
346
geoms[0] = lwgeom_clone((LWGEOM *)to);
347
geoms[1] = lwgeom_clone(what);
351
geoms[0] = lwgeom_clone(what);
352
geoms[1] = lwgeom_clone((LWGEOM *)to);
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);
362
/* Find appropriate geom type */
363
if ( TYPE_GETTYPE(what->type) == LINETYPE ) newtype = MULTILINETYPE;
364
else newtype = COLLECTIONTYPE;
366
col = lwcollection_construct(newtype,
370
return (LWGEOM *)col;
374
lwline_release(LWLINE *lwline)
376
lwgeom_release(lwline_as_lwgeom(lwline));
380
lwline_reverse(LWLINE *line)
382
ptarray_reverse(line->points);
386
lwline_segmentize2d(LWLINE *line, double dist)
388
return lwline_construct(line->SRID, NULL,
389
ptarray_segmentize2d(line->points, dist));
392
/* check coordinate equality */
394
lwline_same(const LWLINE *l1, const LWLINE *l2)
396
return ptarray_same(l1->points, l2->points);
400
* Construct a LWLINE from an array of LWPOINTs
401
* LWLINE dimensions are large enough to host all input dimensions.
404
lwline_from_lwpointarray(int SRID, unsigned int npoints, LWPOINT **points)
409
uchar *newpoints, *ptr;
413
* Find output dimensions, check integrity
415
for (i=0; i<npoints; i++)
417
if ( TYPE_GETTYPE(points[i]->type) != POINTTYPE )
419
lwerror("lwline_from_lwpointarray: invalid input type: %s",
420
lwgeom_typename(TYPE_GETTYPE(points[i]->type)));
423
if ( TYPE_HASZ(points[i]->type) ) zmflag |= 2;
424
if ( TYPE_HASM(points[i]->type) ) zmflag |= 1;
425
if ( zmflag == 3 ) break;
428
if ( zmflag == 0 ) ptsize=2*sizeof(double);
429
else if ( zmflag == 3 ) ptsize=4*sizeof(double);
430
else ptsize=3*sizeof(double);
433
* Allocate output points array
435
size = ptsize*npoints;
436
newpoints = lwalloc(size);
437
memset(newpoints, 0, size);
440
for (i=0; i<npoints; i++)
442
size=pointArray_ptsize(points[i]->point);
443
memcpy(ptr, getPoint_internal(points[i]->point, 0), size);
447
pa = pointArray_construct(newpoints, zmflag&2, zmflag&1, npoints);
449
return lwline_construct(SRID, NULL, pa);
453
* Construct a LWLINE from a LWMPOINT
456
lwline_from_lwmpoint(int SRID, LWMPOINT *mpoint)
460
char zmflag = TYPE_GETZM(mpoint->type);
462
uchar *newpoints, *ptr;
464
if ( zmflag == 0 ) ptsize=2*sizeof(double);
465
else if ( zmflag == 3 ) ptsize=4*sizeof(double);
466
else ptsize=3*sizeof(double);
468
/* Allocate space for output points */
469
size = ptsize*mpoint->ngeoms;
470
newpoints = lwalloc(size);
471
memset(newpoints, 0, size);
474
for (i=0; i<mpoint->ngeoms; i++)
477
getPoint_internal(mpoint->geoms[i]->point, 0),
482
pa = pointArray_construct(newpoints, zmflag&2, zmflag&1,
485
LWDEBUGF(3, "lwline_from_lwmpoint: constructed pointarray for %d points, %d zmflag", mpoint->ngeoms, zmflag);
487
return lwline_construct(SRID, NULL, pa);
491
lwline_addpoint(LWLINE *line, LWPOINT *point, unsigned int where)
496
newpa = ptarray_addPoint(line->points,
497
getPoint_internal(point->point, 0),
498
TYPE_NDIMS(point->type), where);
500
ret = lwline_construct(line->SRID, NULL, newpa);
506
lwline_removepoint(LWLINE *line, unsigned int index)
511
newpa = ptarray_removePoint(line->points, index);
513
ret = lwline_construct(line->SRID, NULL, newpa);
519
* Note: input will be changed, make sure you have permissions for this.
522
lwline_setPoint4d(LWLINE *line, unsigned int index, POINT4D *newpoint)
524
setPoint4d(line->points, index, newpoint);