]> granicus.if.org Git - postgis/commitdiff
Added force_4d(geometry)
authorSandro Santilli <strk@keybit.net>
Mon, 20 Sep 2004 17:03:41 +0000 (17:03 +0000)
committerSandro Santilli <strk@keybit.net>
Mon, 20 Sep 2004 17:03:41 +0000 (17:03 +0000)
git-svn-id: http://svn.osgeo.org/postgis/trunk@855 b70326c6-7e19-0410-871a-916f4a2858ee

doc/postgis.xml
lwgeom/lwgeom.h
lwgeom/lwgeom_functions_basic.c
lwgeom/lwpostgis.sql.in

index 82387d617829302533b4f99279c3864c2473fbe1..500e82769378029ab7420310ff8dad1ba2d8ade3 100644 (file)
@@ -3572,6 +3572,16 @@ dimension
           </listitem>
         </varlistentry>
 
+        <varlistentry id="force_4d">
+          <term>force_4d(geometry)</term>
+
+          <listitem>
+            <para>Forces the geometries into a "4-dimensional mode" so that
+            all output representations will have the X, Y, Z and M
+            coordinates.</para>
+          </listitem>
+        </varlistentry>
+
         <varlistentry>
           <term>length2d(geometry)</term>
 
index a45784a47b1bbc360f5cabaae26f9eb7d97d8728..0b4828bef8494004048c84027a67b4a5c8a7f0d9 100644 (file)
@@ -759,6 +759,7 @@ double lwgeom_pointarray_length2d(POINTARRAY *pts);
 double lwgeom_pointarray_length(POINTARRAY *pts);
 void lwgeom_force2d_recursive(char *serialized, char *optr, int *retsize);
 void lwgeom_force3d_recursive(char *serialized, char *optr, int *retsize);
+void lwgeom_force4d_recursive(char *serialized, char *optr, int *retsize);
 double distance2d_pt_pt(POINT2D *p1, POINT2D *p2);
 double distance2d_pt_seg(POINT2D *p, POINT2D *A, POINT2D *B);
 double distance2d_seg_seg(POINT2D *A, POINT2D *B, POINT2D *C, POINT2D *D);
index c3264caf8fff7274a5fb947e18693c6ab371547e..1b6574fc5ae18e2a5c12a005513ad03c090f67ec 100644 (file)
@@ -28,6 +28,7 @@ Datum LWGEOM_perimeter2d_poly(PG_FUNCTION_ARGS);
 Datum LWGEOM_perimeter_poly(PG_FUNCTION_ARGS);
 Datum LWGEOM_force_2d(PG_FUNCTION_ARGS);
 Datum LWGEOM_force_3d(PG_FUNCTION_ARGS);
+Datum LWGEOM_force_4d(PG_FUNCTION_ARGS);
 Datum LWGEOM_force_collection(PG_FUNCTION_ARGS);
 Datum LWGEOM_force_multi(PG_FUNCTION_ARGS);
 Datum LWGEOM_mindistance2d(PG_FUNCTION_ARGS);
@@ -1451,7 +1452,7 @@ elog(NOTICE, "lwgeom_force3d_recursive: it's a line, size:%d", *retsize);
                        {
                                POINTARRAY *ring = poly->rings[j];
                                POINTARRAY *nring = palloc(sizeof(POINTARRAY));
-                               nring->ndims = 2;
+                               nring->ndims = 3;
                                nring->npoints = ring->npoints;
                                nring->serialized_pointlist =
                                        palloc(ring->npoints*24);
@@ -1531,6 +1532,176 @@ elog(NOTICE, " elem %d size: %d (tot: %d)", i, size, totsize);
        *retsize = totsize;
 }
 
+/*
+ * Write to already allocated memory 'optr' a 4d version of
+ * the given serialized form. 
+ * Pad dimensions are set to 0.
+ * Return number bytes written in given int pointer.
+ */
+void
+lwgeom_force4d_recursive(char *serialized, char *optr, int *retsize)
+{
+       LWGEOM_INSPECTED *inspected;
+       int i,j,k;
+       int totsize=0;
+       int size=0;
+       int type;
+       LWPOINT *point = NULL;
+       LWLINE *line = NULL;
+       LWPOLY *poly = NULL;
+       POINTARRAY newpts;
+       POINTARRAY **nrings;
+       char *loc;
+
+               
+#ifdef DEBUG
+       elog(NOTICE, "lwgeom_force4d_recursive: call");
+#endif
+
+       type = lwgeom_getType(serialized[0]);
+
+       if ( type == POINTTYPE )
+       {
+               point = lwpoint_deserialize(serialized);
+               if ( point->ndims < 4 )
+               {
+                       newpts.ndims = 4;
+                       newpts.npoints = 1;
+                       newpts.serialized_pointlist = palloc(sizeof(POINT4D));
+                       loc = newpts.serialized_pointlist;
+                       getPoint4d_p(point->point, 0, loc);
+                       point->point = &newpts;
+               }
+               point->ndims = 4;
+               lwpoint_serialize_buf(point, optr, retsize);
+#ifdef DEBUG
+elog(NOTICE, "lwgeom_force4d_recursive: it's a point, size:%d", *retsize);
+#endif
+               return;
+       }
+
+       if ( type == LINETYPE )
+       {
+#ifdef DEBUG
+elog(NOTICE, "lwgeom_force4d_recursive: it's a line");
+#endif
+               line = lwline_deserialize(serialized);
+               if ( line->ndims < 4 )
+               {
+                       newpts.ndims = 4;
+                       newpts.npoints = line->points->npoints;
+                       newpts.serialized_pointlist = palloc(sizeof(POINT4D)*line->points->npoints);
+                       loc = newpts.serialized_pointlist;
+                       for (j=0; j<line->points->npoints; j++)
+                       {
+                               getPoint4d_p(line->points, j, loc);
+                               loc+=sizeof(POINT4D);
+                       }
+                       line->points = &newpts;
+               }
+
+               line->ndims = 4;
+               lwline_serialize_buf(line, optr, retsize);
+#ifdef DEBUG
+elog(NOTICE, "lwgeom_force4d_recursive: it's a line, size:%d", *retsize);
+#endif
+               return;
+       }
+
+       if ( type == POLYGONTYPE )
+       {
+               poly = lwpoly_deserialize(serialized);
+               if ( poly->ndims < 4 )
+               {
+                       newpts.ndims = 4;
+                       newpts.npoints = 0;
+                       newpts.serialized_pointlist = palloc(1);
+                       nrings = palloc(sizeof(POINTARRAY *)*poly->nrings);
+                       loc = newpts.serialized_pointlist;
+                       for (j=0; j<poly->nrings; j++)
+                       {
+                               POINTARRAY *ring = poly->rings[j];
+                               POINTARRAY *nring = palloc(sizeof(POINTARRAY));
+                               nring->ndims = 4;
+                               nring->npoints = ring->npoints;
+                               nring->serialized_pointlist =
+                                       palloc(ring->npoints*sizeof(POINT4D));
+                               loc = nring->serialized_pointlist;
+                               for (k=0; k<ring->npoints; k++)
+                               {
+                                       getPoint4d_p(ring, k, loc);
+                                       loc+=sizeof(POINT4D);
+                               }
+                               nrings[j] = nring;
+                       }
+                       poly->rings = nrings;
+               }
+               poly->ndims = 4;
+               lwpoly_serialize_buf(poly, optr, retsize);
+#ifdef DEBUG
+elog(NOTICE, "lwgeom_force4d_recursive: it's a poly, size:%d", *retsize);
+#endif
+               return;
+       }
+
+       // OK, this is a collection, so we write down its metadata
+       // first and then call us again
+
+#ifdef DEBUG
+elog(NOTICE, "lwgeom_force4d_recursive: it's a collection (type:%d)", type);
+#endif
+
+       // Add type
+       *optr = lwgeom_makeType_full(4, lwgeom_hasSRID(serialized[0]),
+               type, lwgeom_hasBBOX(serialized[0]));
+       optr++;
+       totsize++;
+       loc=serialized+1;
+
+       // Add BBOX if any
+       if (lwgeom_hasBBOX(serialized[0]))
+       {
+               memcpy(optr, loc, sizeof(BOX2DFLOAT4));
+               optr += sizeof(BOX2DFLOAT4);
+               totsize += sizeof(BOX2DFLOAT4);
+               loc += sizeof(BOX2DFLOAT4);
+       }
+
+       // Add SRID if any
+       if (lwgeom_hasSRID(serialized[0]))
+       {
+               memcpy(optr, loc, 4);
+               optr += 4;
+               totsize += 4;
+               loc += 4;
+       }
+
+       // Add numsubobjects
+       memcpy(optr, loc, 4);
+       optr += 4;
+       totsize += 4;
+
+#ifdef DEBUG
+elog(NOTICE, " collection header size:%d", totsize);
+#endif
+
+       // Now recurse for each suboject
+       inspected = lwgeom_inspect(serialized);
+       for (i=0; i<inspected->ngeometries; i++)
+       {
+               char *subgeom = lwgeom_getsubgeometry_inspected(inspected, i);
+               lwgeom_force4d_recursive(subgeom, optr, &size);
+               totsize += size;
+               optr += size;
+#ifdef DEBUG
+elog(NOTICE, " elem %d size: %d (tot: %d)", i, size, totsize);
+#endif
+       }
+       pfree_inspected(inspected);
+
+       *retsize = totsize;
+}
+
 // transform input geometry to 2d if not 2d already
 PG_FUNCTION_INFO_V1(LWGEOM_force_2d);
 Datum LWGEOM_force_2d(PG_FUNCTION_ARGS)
@@ -1557,7 +1728,7 @@ Datum LWGEOM_force_2d(PG_FUNCTION_ARGS)
        PG_RETURN_POINTER(result);
 }
 
-// transform input geometry to 3d if not 2d already
+// transform input geometry to 3d if not 3d already
 PG_FUNCTION_INFO_V1(LWGEOM_force_3d);
 Datum LWGEOM_force_3d(PG_FUNCTION_ARGS)
 {
@@ -1590,6 +1761,35 @@ Datum LWGEOM_force_3d(PG_FUNCTION_ARGS)
        PG_RETURN_POINTER(result);
 }
 
+// transform input geometry to 4d if not 4d already
+PG_FUNCTION_INFO_V1(LWGEOM_force_4d);
+Datum LWGEOM_force_4d(PG_FUNCTION_ARGS)
+{
+       LWGEOM *geom = (LWGEOM *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
+       LWGEOM *result;
+       int olddims;
+       int32 size = 0;
+
+       olddims = lwgeom_ndims(geom->type);
+       
+       // already 4d
+       if ( olddims == 4 ) PG_RETURN_POINTER(geom);
+
+       // allocate double as memory a larger for safety 
+       result = (LWGEOM *) palloc(geom->size*2);
+
+       lwgeom_force4d_recursive(SERIALIZED_FORM(geom),
+               SERIALIZED_FORM(result), &size);
+
+       // we can safely avoid this... memory will be freed at
+       // end of query processing anyway.
+       //result = repalloc(result, size+4);
+
+       result->size = size+4;
+
+       PG_RETURN_POINTER(result);
+}
+
 // transform input geometry to a collection type
 PG_FUNCTION_INFO_V1(LWGEOM_force_collection);
 Datum LWGEOM_force_collection(PG_FUNCTION_ARGS)
index 06ab72bf0b823366ffdbbbf602dc1fdcd4d49b30..373883f9af2b0c00b1648bc18275aa29e818ebaf 100644 (file)
@@ -1544,6 +1544,11 @@ CREATEFUNCTION force_3d(geometry)
        AS '@MODULE_FILENAME@', 'LWGEOM_force_3d'
        LANGUAGE 'C' WITH (isstrict);
 
+CREATEFUNCTION force_4d(geometry) 
+       RETURNS geometry
+       AS '@MODULE_FILENAME@', 'LWGEOM_force_4d'
+       LANGUAGE 'C' WITH (isstrict);
+
 CREATEFUNCTION force_collection(geometry) 
        RETURNS geometry
        AS '@MODULE_FILENAME@', 'LWGEOM_force_collection'