]> granicus.if.org Git - postgis/commitdiff
Added lwgeom_add(LWGEOM *to, int where, LWGEOM *what).
authorSandro Santilli <strk@keybit.net>
Fri, 1 Oct 2004 14:49:34 +0000 (14:49 +0000)
committerSandro Santilli <strk@keybit.net>
Fri, 1 Oct 2004 14:49:34 +0000 (14:49 +0000)
Added LWGEOM2GEOS keeping input geometry structure.

git-svn-id: http://svn.osgeo.org/postgis/trunk@919 b70326c6-7e19-0410-871a-916f4a2858ee

12 files changed:
lwgeom/liblwgeom.h
lwgeom/lwcollection.c
lwgeom/lwgeom.c
lwgeom/lwgeom_api.c
lwgeom/lwgeom_geos.c
lwgeom/lwgeom_geos_wrapper.cpp
lwgeom/lwline.c
lwgeom/lwmline.c
lwgeom/lwmpoint.c
lwgeom/lwmpoly.c
lwgeom/lwpoint.c
lwgeom/lwpoly.c

index 1bc4e0d6c8e7eb8caeab6ecdd33480373fac52e0..031187d665d12f1e6499006aeda1ce95a4e30ef7 100644 (file)
@@ -486,7 +486,18 @@ extern void lwgeom_serialize_buf(LWGEOM *geom, char *buf, int *size);
 extern char *lwgeom_serialize(LWGEOM *geom);
 extern void lwcollection_serialize_buf(LWCOLLECTION *mcoll, char *buf, int *size);
 
+//-----------------------------------------------------
+
+// Deserialize an lwgeom serialized form.
+// The deserialized (recursive) structure will store
+// pointers to the serialized form (POINTARRAYs).
 LWGEOM *lwgeom_deserialize(char *serializedform);
+
+// Release memory associated with LWGEOM.
+// POINTARRAYs are not released as they are usually
+// pointers to user-managed memory.
+void lwgeom_release(LWGEOM *lwgeom);
+
 LWMPOINT *lwmpoint_deserialize(char *serializedform);
 LWMLINE *lwmline_deserialize(char *serializedform);
 LWMPOLY *lwmpoly_deserialize(char *serializedform);
@@ -900,10 +911,37 @@ extern int lwpoint_compute_bbox_p(LWPOINT *point, BOX2DFLOAT4 *box);
 extern int lwline_compute_bbox_p(LWLINE *line, BOX2DFLOAT4 *box);
 extern int lwpoly_compute_bbox_p(LWPOLY *poly, BOX2DFLOAT4 *box);
 extern int lwcollection_compute_bbox_p(LWCOLLECTION *col, BOX2DFLOAT4 *box);
+extern BOX2DFLOAT4 *lwgeom_compute_bbox(LWGEOM *lwgeom);
+int lwgeom_compute_bbox_p(LWGEOM *lwgeom, BOX2DFLOAT4 *buf);
 // return alloced memory
 extern BOX2DFLOAT4 *box2d_union(BOX2DFLOAT4 *b1, BOX2DFLOAT4 *b2);
 // args may overlap !
 extern int box2d_union_p(BOX2DFLOAT4 *b1, BOX2DFLOAT4 *b2, BOX2DFLOAT4 *ubox);
 extern int lwgeom_compute_bbox_p(LWGEOM *lwgeom, BOX2DFLOAT4 *box);
 
+// Add 'what' to 'to' at position 'where'.
+// where=0 == prepend
+// where=-1 == append
+// Mix of dimensions is not allowed (TODO: allow it?).
+// Returns a newly allocated LWGEOM
+extern LWGEOM *lwgeom_add(const LWGEOM *to, uint32 where, const LWGEOM *what);
+
+LWGEOM *lwpoint_add(const LWPOINT *to, uint32 where, const LWGEOM *what);
+LWGEOM *lwline_add(const LWLINE *to, uint32 where, const LWGEOM *what);
+LWGEOM *lwpoly_add(const LWPOLY *to, uint32 where, const LWGEOM *what);
+LWGEOM *lwmpoly_add(const LWMPOLY *to, uint32 where, const LWGEOM *what);
+LWGEOM *lwmline_add(const LWMLINE *to, uint32 where, const LWGEOM *what);
+LWGEOM *lwmpoint_add(const LWMPOINT *to, uint32 where, const LWGEOM *what);
+LWGEOM *lwcollection_add(const LWCOLLECTION *to, uint32 where, const LWGEOM *what);
+
+// Clone an LWGEOM (pointarray are not copied)
+extern LWGEOM *lwgeom_clone(const LWGEOM *lwgeom);
+extern LWPOINT *lwpoint_clone(const LWPOINT *lwgeom);
+extern LWLINE *lwline_clone(const LWLINE *lwgeom);
+extern LWPOLY *lwpoly_clone(const LWPOLY *lwgeom);
+extern LWCOLLECTION *lwcollection_clone(const LWCOLLECTION *lwgeom);
+
+extern LWCOLLECTION *lwcollection_construct(int type, int ndims, uint32 SRID, char hasbbox, int ngeoms, LWGEOM **geoms);
+
+
 #endif // !defined _LIBLWGEOM_H 
index 076bd582cadecf31a0fecb93f7105c3aa8f99182..2e4cf94051ab20c276fa1691c013375bae67d60a 100644 (file)
@@ -123,3 +123,72 @@ lwcollection_compute_bbox_p(LWCOLLECTION *col, BOX2DFLOAT4 *box)
        }
        return 1;
 }
+
+LWCOLLECTION *
+lwcollection_construct(int type, int ndims, uint32 SRID, char hasbbox,
+       int ngeoms, LWGEOM **geoms)
+{
+       LWCOLLECTION *ret;
+       ret = lwalloc(sizeof(LWCOLLECTION));
+       ret->type = type;
+       ret->ndims = ndims;
+       ret->SRID = SRID;
+       ret->hasbbox = hasbbox;
+       ret->ngeoms = ngeoms;
+       ret->geoms = geoms;
+       return ret;
+}
+
+// Clone LWCOLLECTION object. POINTARRAY are not copied.
+LWCOLLECTION *
+lwcollection_clone(const LWCOLLECTION *g)
+{
+       uint32 i;
+       LWCOLLECTION *ret = lwalloc(sizeof(LWCOLLECTION));
+       memcpy(ret, g, sizeof(LWCOLLECTION));
+       for (i=0; i<g->ngeoms; i++)
+       {
+               ret->geoms[i] = lwgeom_clone(g->geoms[i]);
+       }
+       return ret;
+}
+
+// Add 'what' to this collection at position 'where'.
+// where=0 == prepend
+// where=-1 == append
+// Returns a GEOMETRYCOLLECTION
+LWGEOM *
+lwcollection_add(const LWCOLLECTION *to, uint32 where, const LWGEOM *what)
+{
+       LWCOLLECTION *col;
+       LWGEOM **geoms;
+       uint32 i;
+
+       if ( where == -1 ) where = to->ngeoms;
+       else if ( where < -1 || where > to->ngeoms )
+       {
+               lwerror("lwcollection_add: add position out of range %d..%d",
+                       -1, to->ngeoms);
+               return NULL;
+       }
+
+       // dimensions compatibility are checked by caller
+
+       // Construct geoms array
+       geoms = lwalloc(sizeof(LWGEOM *)*(to->ngeoms+1));
+       for (i=0; i<where; i++)
+       {
+               geoms[i] = lwgeom_clone(to->geoms[i]);
+       }
+       geoms[where] = lwgeom_clone(what);
+       for (i=where; i<to->ngeoms; i++)
+       {
+               geoms[i+1] = lwgeom_clone(to->geoms[i]);
+       }
+
+       col = lwcollection_construct(COLLECTIONTYPE, to->ndims, to->SRID,
+               (what->hasbbox || to->hasbbox ), to->ngeoms+1, geoms);
+       
+       return (LWGEOM *)col;
+
+}
index bc96c441830babad35790c6ce15856cda3cdd587..7cf950c4d993e60c3e9a27027b5500cc066bd298 100644 (file)
@@ -178,6 +178,7 @@ lwgeom_compute_bbox_p(LWGEOM *lwgeom, BOX2DFLOAT4 *buf)
 }
 
 //dont forget to lwfree() result
+
 BOX2DFLOAT4 *
 lwgeom_compute_bbox(LWGEOM *lwgeom)
 {
@@ -242,3 +243,78 @@ LWGEOM *lwcollection_as_lwgeom(LWCOLLECTION *obj) { return (LWGEOM *)obj; }
 LWGEOM *lwpoly_as_lwgeom(LWPOLY *obj) { return (LWGEOM *)obj; }
 LWGEOM *lwline_as_lwgeom(LWLINE *obj) { return (LWGEOM *)obj; }
 LWGEOM *lwpoint_as_lwgeom(LWPOINT *obj) { return (LWGEOM *)obj; }
+
+void
+lwgeom_release(LWGEOM *lwgeom)
+{
+       uint32 i;
+       LWCOLLECTION *col;
+
+       // Collection
+       if ( (col=lwgeom_as_lwcollection(lwgeom)) )
+       {
+               for (i=0; i<col->ngeoms; i++)
+               {
+                       lwgeom_release(col->geoms[i]);
+               }
+               lwfree(lwgeom);
+       }
+
+       // Single element
+       else lwfree(lwgeom);
+
+}
+
+// Clone an LWGEOM object. POINTARRAY are not copied.
+LWGEOM *
+lwgeom_clone(const LWGEOM *lwgeom)
+{
+       switch(lwgeom->type)
+       {
+               case POINTTYPE:
+                       return (LWGEOM *)lwpoint_clone((LWPOINT *)lwgeom);
+               case LINETYPE:
+                       return (LWGEOM *)lwline_clone((LWLINE *)lwgeom);
+               case POLYGONTYPE:
+                       return (LWGEOM *)lwpoly_clone((LWPOLY *)lwgeom);
+               case MULTIPOINTTYPE:
+               case MULTILINETYPE:
+               case MULTIPOLYGONTYPE:
+               case COLLECTIONTYPE:
+                       return (LWGEOM *)lwcollection_clone((LWCOLLECTION *)lwgeom);
+               default:
+                       return NULL;
+       }
+}
+
+// Add 'what' to 'to' at position 'where'.
+// where=0 == prepend
+// where=-1 == append
+// Appended-to LWGEOM gets a new type based on new condition.
+// Mix of dimensions is not allowed (TODO: allow it?).
+LWGEOM *
+lwgeom_add(const LWGEOM *to, uint32 where, const LWGEOM *what)
+{
+       if ( what->ndims != to->ndims )
+       {
+               lwerror("lwgeom_add: mixed dimensions not supported");
+               return NULL;
+       }
+
+       switch(to->type)
+       {
+               case POINTTYPE:
+                       return (LWGEOM *)lwpoint_add((const LWPOINT *)to, where, what);
+               case LINETYPE:
+                       return (LWGEOM *)lwline_add((const LWLINE *)to, where, what);
+               case POLYGONTYPE:
+                       return (LWGEOM *)lwpoly_add((const LWPOLY *)to, where, what);
+
+               case MULTIPOINTTYPE:
+               case MULTILINETYPE:
+               case MULTIPOLYGONTYPE:
+                       return (LWGEOM *)lwcollection_add((const LWCOLLECTION *)to, where, what);
+               default:
+                       return NULL;
+       }
+}
index 4f7c9824671dc0a2e555ea8dc625fd291b6413bc..dea11b88b6e44775f937cf51069a67b7cac83b6a 100644 (file)
@@ -608,6 +608,11 @@ getPoint(const POINTARRAY *pa, int n)
 {
        int size;
 
+       if ( pa == NULL ) {
+               lwerror("getPoint got NULL pointarray");
+               return NULL;
+       }
+
        if ( (n<0) || (n>=pa->npoints))
        {
                return NULL; //error
index f963c05aa6d3d3df04e6f11b9e28849dfea598f9..9991d4f5d56c772c659a881078acd517b70997eb 100644 (file)
@@ -4,8 +4,8 @@
 #include "utils/builtins.h"
 #include "fmgr.h"
 
-#include "liblwgeom.h"
 #include "lwgeom_pg.h"
+#include "liblwgeom.h"
 #include "profile.h"
 #include "wktparse.h"
 
@@ -44,8 +44,8 @@ Datum centroid(PG_FUNCTION_ARGS);
  * during postgis->geos and geos->postgis conversions
  */
 #undef DEBUG_CONVERTER
-#undef DEBUG_POSTGIS2GEOS
-#undef DEBUG_GEOS2POSTGIS
+#undef DEBUG_POSTGIS2GEOS 
+#undef DEBUG_GEOS2POSTGIS 
 
 typedef  struct Geometry Geometry;
 
@@ -2008,6 +2008,7 @@ char *PolyFromGeometry(Geometry *g, char want3d)
 
 //-----=GEOS2POSTGIS=
 
+
 /*
  * Recursively add a Geometry to the LWGEOM_EXPLODED structure
  * The exploded struct contains note about the number of dimensions
@@ -2133,8 +2134,67 @@ GEOS2POSTGIS(Geometry *geom, char want3d)
 
 //-----=POSTGIS2GEOS=
 
+Geometry *LWGEOM2GEOS(LWGEOM *lwgeom);
+
+Geometry *
+LWGEOM2GEOS(LWGEOM *lwgeom)
+{
+       uint32 i;
+       Geometry **collected;
+       LWCOLLECTION *col;
+       if ( ! lwgeom ) return NULL;
+
+#ifdef DEBUG_POSTGIS2GEOS
+       elog(NOTICE, "LWGEOM2GEOS: got lwgeom[%p]", lwgeom);
+#endif
+
+       switch (lwgeom->type)
+       {
+               LWPOINT *p;
+
+               case POINTTYPE:
+                       p = (LWPOINT *)lwgeom;
+                       elog(NOTICE, "LWGEOM2GEOS: lwpoint[%p]", p);
+                       return PostGIS2GEOS_point(p);
+
+               case LINETYPE:
+                       return PostGIS2GEOS_linestring((LWLINE *)lwgeom);
+
+               case POLYGONTYPE:
+                       return PostGIS2GEOS_polygon((LWPOLY *)lwgeom);
+
+               case MULTIPOINTTYPE:
+               case MULTILINETYPE:
+               case MULTIPOLYGONTYPE:
+               case COLLECTIONTYPE:
+                       col = (LWCOLLECTION *)lwgeom;
+                       collected = (Geometry **)lwalloc(sizeof(Geometry *)*col->ngeoms);
+                       for (i=0; i<col->ngeoms; i++)
+                       {
+                               collected[i] = LWGEOM2GEOS(col->geoms[i]);
+                       }
+                       return PostGIS2GEOS_collection(collected, col->ngeoms,
+                               col->SRID, col->ndims > 2);
+
+               default:
+                       lwerror("Unknown geometry type: %d", lwgeom->type);
+                       return NULL;
+       }
+
+}
+
 Geometry *
 POSTGIS2GEOS(PG_LWGEOM *geom)
+{
+       Geometry *ret;
+       LWGEOM *lwgeom = lwgeom_deserialize(SERIALIZED_FORM(geom));
+       ret = LWGEOM2GEOS(lwgeom);
+       lwgeom_release(lwgeom);
+       return ret;
+}
+
+Geometry *
+_POSTGIS2GEOS(PG_LWGEOM *geom)
 {
        LWPOINT *point;
        LWLINE *line;
index 8b3cfb60b43536808102576fd6542781f4966f3e..5709c159128f7cf8dd0416e6c0f429c5075bce55 100644 (file)
@@ -10,6 +10,8 @@
 #include "geos/geom.h"
 #include "geos/util.h"
 
+#define DEBUG_POSTGIS2GEOS 1
+
 using namespace geos;
 
 //WARNING THIS *MUST* BE SET CORRECTLY.
@@ -45,25 +47,33 @@ typedef struct
 
 typedef struct
 {
-       char     ndims; 
-       int      SRID;
-       POINTARRAY  *point;
+       int type; // POINTTYPE
+       char ndims;
+       uint32 SRID;    
+       char hasbbox; 
+       POINTARRAY *point;  // hide 2d/3d (this will be an array of 1 point)
 }  LWPOINT; // "light-weight point"
 
+// LINETYPE
 typedef struct
 {
-       char  ndims; 
-       int  SRID;
-       POINTARRAY *points; 
-} LWLINE; 
-
+       int type; // LINETYPE
+       char ndims;
+       uint32 SRID;    
+       char hasbbox; 
+       POINTARRAY    *points; // array of POINT3D
+} LWLINE; //"light-weight line"
+
+// POLYGONTYPE
 typedef struct
 {
-       int32 SRID;
-       char ndims;
+       int type; // POLYGONTYPE
+       char ndims;
+       uint32 SRID;    
+       char hasbbox; 
        int  nrings;
-       POINTARRAY **rings; 
-} LWPOLY; 
+       POINTARRAY **rings; // list of rings (list of points)
+} LWPOLY; // "light-weight polygon"
 
 extern "C" char *getPoint(POINTARRAY *pa, int n);
 
@@ -213,9 +223,26 @@ Geometry *PostGIS2GEOS_box3d(BOX3D *box, int SRID)
 
 Geometry *PostGIS2GEOS_point(const LWPOINT *lwpoint)
 {
-       POINT3D *point = (POINT3D *)getPoint(lwpoint->point, 0);
-       int SRID = lwpoint->SRID;
-       bool is3d = lwpoint->point->ndims > 2 ? 1 : 0;
+       POINT3D *point;
+       int SRID;
+       bool is3d;
+
+#ifdef DEBUG_POSTGIS2GEOS
+       char buf[256];
+       sprintf(buf, "PostGIS2GEOS_point got lwpoint[%p]", lwpoint);
+       NOTICE_MESSAGE(buf);
+#endif
+
+       if ( lwpoint == NULL )
+       {
+               NOTICE_MESSAGE("PostGIS2GEOS_point got a NULL lwpoint");
+               return NULL;
+       }
+
+       point = (POINT3D *)getPoint(lwpoint->point, 0);
+       SRID = lwpoint->SRID;
+       is3d = lwpoint->point->ndims > 2 ? 1 : 0;
+
        try
        {
                Coordinate *c;
index df8ff1e6ccb7954d850fb4132960124a4b2acbd4..ab99a7a2d833b0ffe2f4b70a37c10c0090de2660 100644 (file)
@@ -120,12 +120,6 @@ void lwline_serialize_buf(LWLINE *line, char *buf, int *retsize)
 
        hasSRID = (line->SRID != -1);
 
-       if (hasSRID) size +=4;  //4 byte SRID
-       if (line->hasbbox) size += sizeof(BOX2DFLOAT4); // bvol
-       size += ptsize * line->points->npoints; 
-
-       size+=4; // npoints
-
        buf[0] = (unsigned char) lwgeom_makeType_full(line->ndims,
                hasSRID, LINETYPE, line->hasbbox);
        loc = buf+1;
@@ -134,16 +128,20 @@ void lwline_serialize_buf(LWLINE *line, char *buf, int *retsize)
        {
                lwgeom_compute_bbox_p((LWGEOM *)line, (BOX2DFLOAT4 *)loc);
                loc += sizeof(BOX2DFLOAT4);
+               size += sizeof(BOX2DFLOAT4); // bvol
        }
 
        if (hasSRID)
        {
                memcpy(loc, &line->SRID, sizeof(int32));
+               size +=4;  //4 byte SRID
                loc += 4;
        }
 
        memcpy(loc, &line->points->npoints, sizeof(int32));
        loc +=4;
+       size+=4; // npoints
+
        //copy in points
 
 //lwnotice(" line serialize - size = %i", size);
@@ -172,6 +170,8 @@ void lwline_serialize_buf(LWLINE *line, char *buf, int *retsize)
                        loc += 32; // size of a 2d point
                }
        }
+       size += ptsize * line->points->npoints; 
+
        //printBYTES((unsigned char *)result, size);
 
        if (retsize) *retsize = size;
@@ -199,6 +199,7 @@ lwline_serialize_size(LWLINE *line)
        if ( line->hasbbox ) size += sizeof(BOX2DFLOAT4);
 
        size += sizeof(double)*line->ndims*line->points->npoints; // points
+       size += 4; // npoints
 
        return size;
 }
@@ -271,3 +272,57 @@ lwline_compute_bbox_p(LWLINE *line, BOX2DFLOAT4 *box)
 {
        return ptarray_compute_bbox_p(line->points, box);
 }
+
+// Clone LWLINE object. POINTARRAY is not copied.
+LWLINE *
+lwline_clone(const LWLINE *g)
+{
+       LWLINE *ret = lwalloc(sizeof(LWLINE));
+       memcpy(ret, g, sizeof(LWLINE));
+       return ret;
+}
+
+// Add 'what' to this line at position 'where'.
+// where=0 == prepend
+// where=-1 == append
+// Returns a MULTILINE or a GEOMETRYCOLLECTION
+LWGEOM *
+lwline_add(const LWLINE *to, uint32 where, const LWGEOM *what)
+{
+       LWCOLLECTION *col;
+       LWGEOM **geoms;
+       int newtype;
+
+       if ( where != -1 && where != 0 )
+       {
+               lwerror("lwline_add only supports 0 or -1 as second argument, got %d", where);
+               return NULL;
+       }
+
+       // dimensions compatibility are checked by caller
+
+       // Construct geoms array
+       geoms = lwalloc(sizeof(LWGEOM *)*2);
+       if ( where == -1 ) // append
+       {
+               geoms[0] = lwgeom_clone((LWGEOM *)to);
+               geoms[1] = lwgeom_clone(what);
+       }
+       else // prepend
+       {
+               geoms[0] = lwgeom_clone(what);
+               geoms[1] = lwgeom_clone((LWGEOM *)to);
+       }
+       // reset SRID and wantbbox flag from component types
+       geoms[0]->SRID = geoms[1]->SRID = -1;
+       geoms[0]->hasbbox = geoms[1]->hasbbox = 0;
+
+       // Find appropriate geom type
+       if ( what->type == LINETYPE ) newtype = MULTILINETYPE;
+       else newtype = COLLECTIONTYPE;
+
+       col = lwcollection_construct(newtype, to->ndims, to->SRID,
+               (what->hasbbox || to->hasbbox ), 2, geoms);
+       
+       return (LWGEOM *)col;
+}
index d6002118a50652fca20214e9d7591a4896c1d850..e45378c50902cd77be76deda6467c4b2724b9f8d 100644 (file)
@@ -42,3 +42,46 @@ lwmline_deserialize(char *srl)
        return result;
 }
 
+// Add 'what' to this multiline at position 'where'.
+// where=0 == prepend
+// where=-1 == append
+// Returns a MULTILINE or a COLLECTION
+LWGEOM *
+lwmline_add(const LWMLINE *to, uint32 where, const LWGEOM *what)
+{
+       LWCOLLECTION *col;
+       LWGEOM **geoms;
+       int newtype;
+       uint32 i;
+
+       if ( where == -1 ) where = to->ngeoms;
+       else if ( where < -1 || where > to->ngeoms )
+       {
+               lwerror("lwmline_add: add position out of range %d..%d",
+                       -1, to->ngeoms);
+               return NULL;
+       }
+
+       // dimensions compatibility are checked by caller
+
+       // Construct geoms array
+       geoms = lwalloc(sizeof(LWGEOM *)*(to->ngeoms+1));
+       for (i=0; i<where; i++)
+       {
+               geoms[i] = lwgeom_clone((LWGEOM *)to->geoms[i]);
+       }
+       geoms[where] = lwgeom_clone(what);
+       for (i=where; i<to->ngeoms; i++)
+       {
+               geoms[i+1] = lwgeom_clone((LWGEOM *)to->geoms[i]);
+       }
+
+       if ( what->type == LINETYPE ) newtype = MULTILINETYPE;
+       else newtype = COLLECTIONTYPE;
+
+       col = lwcollection_construct(newtype, to->ndims, to->SRID,
+               (what->hasbbox || to->hasbbox ), to->ngeoms+1, geoms);
+       
+       return (LWGEOM *)col;
+
+}
index b8413f37d02ea601d10cd7037b72db9d229349d4..8a40df0802ab4ec5b27806fbe70009a3791200c5 100644 (file)
@@ -42,3 +42,46 @@ lwmpoint_deserialize(char *srl)
        return result;
 }
 
+// Add 'what' to this multipoint at position 'where'.
+// where=0 == prepend
+// where=-1 == append
+// Returns a MULTIPOINT or a COLLECTION
+LWGEOM *
+lwmpoint_add(const LWMPOINT *to, uint32 where, const LWGEOM *what)
+{
+       LWCOLLECTION *col;
+       LWGEOM **geoms;
+       int newtype;
+       uint32 i;
+
+       if ( where == -1 ) where = to->ngeoms;
+       else if ( where < -1 || where > to->ngeoms )
+       {
+               lwerror("lwmpoint_add: add position out of range %d..%d",
+                       -1, to->ngeoms);
+               return NULL;
+       }
+
+       // dimensions compatibility are checked by caller
+
+       // Construct geoms array
+       geoms = lwalloc(sizeof(LWGEOM *)*(to->ngeoms+1));
+       for (i=0; i<where; i++)
+       {
+               geoms[i] = lwgeom_clone((LWGEOM *)to->geoms[i]);
+       }
+       geoms[where] = lwgeom_clone(what);
+       for (i=where; i<to->ngeoms; i++)
+       {
+               geoms[i+1] = lwgeom_clone((LWGEOM *)to->geoms[i]);
+       }
+
+       if ( what->type == POINTTYPE ) newtype = MULTIPOINTTYPE;
+       else newtype = COLLECTIONTYPE;
+
+       col = lwcollection_construct(newtype, to->ndims, to->SRID,
+               (what->hasbbox || to->hasbbox ), to->ngeoms+1, geoms);
+       
+       return (LWGEOM *)col;
+
+}
index dfb4edded07e3dc81d9642169b9f4bf4c0a97d5a..3ccbcf38f0841d72888ebe0e5a0a0a27f2010c83 100644 (file)
@@ -48,3 +48,46 @@ lwmpoly_deserialize(char *srl)
        return result;
 }
 
+// Add 'what' to this multiline at position 'where'.
+// where=0 == prepend
+// where=-1 == append
+// Returns a MULTIPOLY or a COLLECTION
+LWGEOM *
+lwmpoly_add(const LWMPOLY *to, uint32 where, const LWGEOM *what)
+{
+       LWCOLLECTION *col;
+       LWGEOM **geoms;
+       int newtype;
+       uint32 i;
+
+       if ( where == -1 ) where = to->ngeoms;
+       else if ( where < -1 || where > to->ngeoms )
+       {
+               lwerror("lwmline_add: add position out of range %d..%d",
+                       -1, to->ngeoms);
+               return NULL;
+       }
+
+       // dimensions compatibility are checked by caller
+
+       // Construct geoms array
+       geoms = lwalloc(sizeof(LWGEOM *)*(to->ngeoms+1));
+       for (i=0; i<where; i++)
+       {
+               geoms[i] = lwgeom_clone((LWGEOM *)to->geoms[i]);
+       }
+       geoms[where] = lwgeom_clone(what);
+       for (i=where; i<to->ngeoms; i++)
+       {
+               geoms[i+1] = lwgeom_clone((LWGEOM *)to->geoms[i]);
+       }
+
+       if ( what->type == POLYGONTYPE ) newtype = MULTIPOLYGONTYPE;
+       else newtype = COLLECTIONTYPE;
+
+       col = lwcollection_construct(newtype, to->ndims, to->SRID,
+               (what->hasbbox || to->hasbbox ), to->ngeoms+1, geoms);
+       
+       return (LWGEOM *)col;
+
+}
index d6a29c4ba180478b349ce99aba6bfe5a07fb3e7a..2e7c86d91c5710f5763b11b917d1c14f50969db3 100644 (file)
@@ -228,3 +228,58 @@ lwpoint_compute_bbox_p(LWPOINT *point, BOX2DFLOAT4 *box)
 {
        return ptarray_compute_bbox_p(point->point, box);
 }
+
+// Clone LWPOINT object. POINTARRAY is not copied.
+LWPOINT *
+lwpoint_clone(const LWPOINT *g)
+{
+       LWPOINT *ret = lwalloc(sizeof(LWPOINT));
+       memcpy(ret, g, sizeof(LWPOINT));
+       return ret;
+}
+
+// Add 'what' to this point at position 'where'.
+// where=0 == prepend
+// where=-1 == append
+// Returns a MULTIPOINT or a GEOMETRYCOLLECTION
+LWGEOM *
+lwpoint_add(const LWPOINT *to, uint32 where, const LWGEOM *what)
+{
+       LWCOLLECTION *col;
+       LWGEOM **geoms;
+       int newtype;
+
+       if ( where != -1 && where != 0 )
+       {
+               lwerror("lwpoint_add only supports 0 or -1 as second argument, got %d", where);
+               return NULL;
+       }
+
+       // dimensions compatibility are checked by caller
+
+
+       // Construct geoms array
+       geoms = lwalloc(sizeof(LWGEOM *)*2);
+       if ( where == -1 ) // append
+       {
+               geoms[0] = lwgeom_clone((LWGEOM *)to);
+               geoms[1] = lwgeom_clone(what);
+       }
+       else // prepend
+       {
+               geoms[0] = lwgeom_clone(what);
+               geoms[1] = lwgeom_clone((LWGEOM *)to);
+       }
+       // reset SRID and wantbbox flag from component types
+       geoms[0]->SRID = geoms[1]->SRID = -1;
+       geoms[0]->hasbbox = geoms[1]->hasbbox = 0;
+
+       // Find appropriate geom type
+       if ( what->type == POINTTYPE ) newtype = MULTIPOINTTYPE;
+       else newtype = COLLECTIONTYPE;
+
+       col = lwcollection_construct(newtype, to->ndims, to->SRID,
+               (what->hasbbox || to->hasbbox ), 2, geoms);
+       
+       return (LWGEOM *)col;
+}
index 0d8a3f397feff9e7aaea3080cdb3b7b53eaa6060..9dc6db2319f87f4a3f2d773929cd966aa2c09470 100644 (file)
@@ -376,3 +376,59 @@ lwpoly_compute_bbox_p(LWPOLY *poly, BOX2DFLOAT4 *box)
        }
        return 1;
 }
+
+// Clone LWLINE object. POINTARRAY are not copied, it's ring array is.
+LWPOLY *
+lwpoly_clone(const LWPOLY *g)
+{
+       LWPOLY *ret = lwalloc(sizeof(LWPOLY));
+       memcpy(ret, g, sizeof(LWPOLY));
+       ret->rings = lwalloc(sizeof(POINTARRAY *)*g->nrings);
+       memcpy(ret->rings, g->rings, sizeof(POINTARRAY *)*g->nrings);
+       return ret;
+}
+
+// Add 'what' to this poly at position 'where'.
+// where=0 == prepend
+// where=-1 == append
+// Returns a MULTIPOLYGON or a GEOMETRYCOLLECTION
+LWGEOM *
+lwpoly_add(const LWPOLY *to, uint32 where, const LWGEOM *what)
+{
+       LWCOLLECTION *col;
+       LWGEOM **geoms;
+       int newtype;
+
+       if ( where != -1 && where != 0 )
+       {
+               lwerror("lwpoly_add only supports 0 or -1 as second argument, got %d", where);
+               return NULL;
+       }
+
+       // dimensions compatibility are checked by caller
+
+       // Construct geoms array
+       geoms = lwalloc(sizeof(LWGEOM *)*2);
+       if ( where == -1 ) // append
+       {
+               geoms[0] = lwgeom_clone((LWGEOM *)to);
+               geoms[1] = lwgeom_clone(what);
+       }
+       else // prepend
+       {
+               geoms[0] = lwgeom_clone(what);
+               geoms[1] = lwgeom_clone((LWGEOM *)to);
+       }
+       // reset SRID and wantbbox flag from component types
+       geoms[0]->SRID = geoms[1]->SRID = -1;
+       geoms[0]->hasbbox = geoms[1]->hasbbox = 0;
+
+       // Find appropriate geom type
+       if ( what->type == POLYGONTYPE ) newtype = MULTIPOLYGONTYPE;
+       else newtype = COLLECTIONTYPE;
+
+       col = lwcollection_construct(newtype, to->ndims, to->SRID,
+               (what->hasbbox || to->hasbbox ), 2, geoms);
+       
+       return (LWGEOM *)col;
+}