/********************************************************************** * * PostGIS - Spatial Types for PostgreSQL * http://postgis.refractions.net * * Copyright (C) 2001-2006 Refractions Research Inc. * * This is free software; you can redistribute and/or modify it under * the terms of the GNU General Public Licence. See the COPYING file. * **********************************************************************/ /* basic LWCIRCSTRING functions */ #include #include #include #include "liblwgeom_internal.h" #include "lwgeom_log.h" void printLWCIRCSTRING(LWCIRCSTRING *curve); void lwcircstring_reverse(LWCIRCSTRING *curve); void lwcircstring_release(LWCIRCSTRING *lwcirc); char lwcircstring_same(const LWCIRCSTRING *me, const LWCIRCSTRING *you); LWCIRCSTRING *lwcircstring_from_lwpointarray(int srid, uint32_t npoints, LWPOINT **points); LWCIRCSTRING *lwcircstring_from_lwmpoint(int srid, LWMPOINT *mpoint); LWCIRCSTRING *lwcircstring_addpoint(LWCIRCSTRING *curve, LWPOINT *point, uint32_t where); LWCIRCSTRING *lwcircstring_removepoint(LWCIRCSTRING *curve, uint32_t index); void lwcircstring_setPoint4d(LWCIRCSTRING *curve, uint32_t index, POINT4D *newpoint); /* * Construct a new LWCIRCSTRING. points will *NOT* be copied * use SRID=SRID_UNKNOWN for unknown SRID (will have 8bit type's S = 0) */ LWCIRCSTRING * lwcircstring_construct(int srid, GBOX *bbox, POINTARRAY *points) { LWCIRCSTRING *result; /* * The first arc requires three points. Each additional * arc requires two more points. Thus the minimum point count * is three, and the count must be odd. */ if (points->npoints % 2 != 1 || points->npoints < 3) { lwnotice("lwcircstring_construct: invalid point count %d", points->npoints); } result = (LWCIRCSTRING*) lwalloc(sizeof(LWCIRCSTRING)); result->type = CIRCSTRINGTYPE; result->flags = points->flags; FLAGS_SET_BBOX(result->flags, bbox?1:0); result->srid = srid; result->points = points; result->bbox = bbox; return result; } LWCIRCSTRING * lwcircstring_construct_empty(int srid, char hasz, char hasm) { LWCIRCSTRING *result = lwalloc(sizeof(LWCIRCSTRING)); result->type = CIRCSTRINGTYPE; result->flags = gflags(hasz,hasm,0); result->srid = srid; result->points = ptarray_construct_empty(hasz, hasm, 1); result->bbox = NULL; return result; } void lwcircstring_release(LWCIRCSTRING *lwcirc) { lwgeom_release(lwcircstring_as_lwgeom(lwcirc)); } void lwcircstring_free(LWCIRCSTRING *curve) { if ( curve->bbox ) lwfree(curve->bbox); if ( curve->points ) ptarray_free(curve->points); lwfree(curve); } void printLWCIRCSTRING(LWCIRCSTRING *curve) { lwnotice("LWCIRCSTRING {"); lwnotice(" ndims = %i", (int)FLAGS_NDIMS(curve->flags)); lwnotice(" srid = %i", (int)curve->srid); printPA(curve->points); lwnotice("}"); } /* @brief Clone LWCIRCSTRING object. Serialized point lists are not copied. * * @see ptarray_clone */ LWCIRCSTRING * lwcircstring_clone(const LWCIRCSTRING *g) { return (LWCIRCSTRING *)lwline_clone((LWLINE *)g); } void lwcircstring_reverse(LWCIRCSTRING *curve) { ptarray_reverse(curve->points); } /* check coordinate equality */ char lwcircstring_same(const LWCIRCSTRING *me, const LWCIRCSTRING *you) { return ptarray_same(me->points, you->points); } /* * Construct a LWCIRCSTRING from an array of LWPOINTs * LWCIRCSTRING dimensions are large enough to host all input dimensions. */ LWCIRCSTRING * lwcircstring_from_lwpointarray(int srid, uint32_t npoints, LWPOINT **points) { int zmflag=0; uint32_t i; POINTARRAY *pa; uint8_t *newpoints, *ptr; size_t ptsize, size; /* * Find output dimensions, check integrity */ for (i = 0; i < npoints; i++) { if (points[i]->type != POINTTYPE) { lwerror("lwcurve_from_lwpointarray: invalid input type: %s", lwtype_name(points[i]->type)); return NULL; } if (FLAGS_GET_Z(points[i]->flags)) zmflag |= 2; if (FLAGS_GET_M(points[i]->flags)) zmflag |= 1; if (zmflag == 3) break; } if (zmflag == 0) ptsize = 2 * sizeof(double); else if (zmflag == 3) ptsize = 4 * sizeof(double); else ptsize = 3 * sizeof(double); /* * Allocate output points array */ size = ptsize * npoints; newpoints = lwalloc(size); memset(newpoints, 0, size); ptr = newpoints; for (i = 0; i < npoints; i++) { size = ptarray_point_size(points[i]->point); memcpy(ptr, getPoint_internal(points[i]->point, 0), size); ptr += ptsize; } pa = ptarray_construct_reference_data(zmflag&2, zmflag&1, npoints, newpoints); return lwcircstring_construct(srid, NULL, pa); } /* * Construct a LWCIRCSTRING from a LWMPOINT */ LWCIRCSTRING * lwcircstring_from_lwmpoint(int srid, LWMPOINT *mpoint) { uint32_t i; POINTARRAY *pa; char zmflag = FLAGS_GET_ZM(mpoint->flags); size_t ptsize, size; uint8_t *newpoints, *ptr; if (zmflag == 0) ptsize = 2 * sizeof(double); else if (zmflag == 3) ptsize = 4 * sizeof(double); else ptsize = 3 * sizeof(double); /* Allocate space for output points */ size = ptsize * mpoint->ngeoms; newpoints = lwalloc(size); memset(newpoints, 0, size); ptr = newpoints; for (i = 0; i < mpoint->ngeoms; i++) { memcpy(ptr, getPoint_internal(mpoint->geoms[i]->point, 0), ptsize); ptr += ptsize; } pa = ptarray_construct_reference_data(zmflag&2, zmflag&1, mpoint->ngeoms, newpoints); LWDEBUGF(3, "lwcurve_from_lwmpoint: constructed pointarray for %d points, %d zmflag", mpoint->ngeoms, zmflag); return lwcircstring_construct(srid, NULL, pa); } LWCIRCSTRING * lwcircstring_addpoint(LWCIRCSTRING *curve, LWPOINT *point, uint32_t where) { POINTARRAY *newpa; LWCIRCSTRING *ret; newpa = ptarray_addPoint(curve->points, getPoint_internal(point->point, 0), FLAGS_NDIMS(point->flags), where); ret = lwcircstring_construct(curve->srid, NULL, newpa); return ret; } LWCIRCSTRING * lwcircstring_removepoint(LWCIRCSTRING *curve, uint32_t index) { POINTARRAY *newpa; LWCIRCSTRING *ret; newpa = ptarray_removePoint(curve->points, index); ret = lwcircstring_construct(curve->srid, NULL, newpa); return ret; } /* * Note: input will be changed, make sure you have permissions for this. * */ void lwcircstring_setPoint4d(LWCIRCSTRING *curve, uint32_t index, POINT4D *newpoint) { ptarray_set_point4d(curve->points, index, newpoint); } int lwcircstring_is_closed(const LWCIRCSTRING *curve) { if (FLAGS_GET_Z(curve->flags)) return ptarray_isclosed3d(curve->points); return ptarray_isclosed2d(curve->points); } int lwcircstring_is_empty(const LWCIRCSTRING *circ) { if ( !circ->points || circ->points->npoints == 0 ) return LW_TRUE; return LW_FALSE; } double lwcircstring_length(const LWCIRCSTRING *circ) { double length = 0.0; LWLINE *line; if ( lwcircstring_is_empty(circ) ) return 0.0; line = lwcircstring_segmentize(circ, 32); length = lwline_length(line); lwline_free(line); return length; } double lwcircstring_length_2d(const LWCIRCSTRING *circ) { double length = 0.0; LWLINE *line; if ( lwcircstring_is_empty(circ) ) return 0.0; line = lwcircstring_segmentize(circ, 32); length = lwline_length_2d(line); lwline_free(line); return length; }