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);
// internal
char * lwgeom_summary_recursive(char *serialized, int offset);
int32 lwgeom_npoints_recursive(char *serialized);
+
+// general utilities (might be moved in lwgeom_api.c)
double lwgeom_polygon_area(LWPOLY *poly);
double lwgeom_polygon_perimeter(LWPOLY *poly);
double lwgeom_polygon_perimeter2d(LWPOLY *poly);
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);
/*------------------------------------------------------------------*/
/*
* Write to already allocated memory 'optr' a 2d version of
* the given serialized form.
+ * Higher dimensions in input geometry are discarder.
* Return number bytes written in given int pointer.
*/
void
*retsize = totsize;
}
+/*
+ * Write to already allocated memory 'optr' a 3d version of
+ * the given serialized form.
+ * Higher dimensions in input geometry are discarder.
+ * If the given version is 2d Z is set to 0.
+ * Return number bytes written in given int pointer.
+ */
+void
+lwgeom_force3d_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_force3d_recursive: call");
+#endif
+
+ type = lwgeom_getType(serialized[0]);
+
+ if ( type == POINTTYPE )
+ {
+ point = lwpoint_deserialize(serialized);
+ if ( point->ndims < 3 )
+ {
+ newpts.ndims = 3;
+ newpts.npoints = 1;
+ newpts.serialized_pointlist = palloc(sizeof(POINT3D));
+ loc = newpts.serialized_pointlist;
+ getPoint3d_p(point->point, 0, loc);
+ point->point = &newpts;
+ }
+ point->ndims = 3;
+ lwpoint_serialize_buf(point, optr, retsize);
+#ifdef DEBUG
+elog(NOTICE, "lwgeom_force3d_recursive: it's a point, size:%d", *retsize);
+#endif
+ return;
+ }
+
+ if ( type == LINETYPE )
+ {
+#ifdef DEBUG
+elog(NOTICE, "lwgeom_force3d_recursive: it's a line");
+#endif
+ line = lwline_deserialize(serialized);
+ if ( line->ndims < 3 )
+ {
+ newpts.ndims = 3;
+ newpts.npoints = line->points->npoints;
+ newpts.serialized_pointlist = palloc(24*line->points->npoints);
+ loc = newpts.serialized_pointlist;
+ for (j=0; j<line->points->npoints; j++)
+ {
+ getPoint3d_p(line->points, j, loc);
+ loc+=24;
+ }
+ line->points = &newpts;
+ }
+
+ line->ndims = 3;
+ lwline_serialize_buf(line, optr, retsize);
+#ifdef DEBUG
+elog(NOTICE, "lwgeom_force3d_recursive: it's a line, size:%d", *retsize);
+#endif
+ return;
+ }
+
+ if ( type == POLYGONTYPE )
+ {
+ poly = lwpoly_deserialize(serialized);
+ if ( poly->ndims < 3 )
+ {
+ newpts.ndims = 3;
+ 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 = 2;
+ nring->npoints = ring->npoints;
+ nring->serialized_pointlist =
+ palloc(ring->npoints*24);
+ loc = nring->serialized_pointlist;
+ for (k=0; k<ring->npoints; k++)
+ {
+ getPoint3d_p(ring, k, loc);
+ loc+=24;
+ }
+ nrings[j] = nring;
+ }
+ poly->rings = nrings;
+ }
+ poly->ndims = 3;
+ lwpoly_serialize_buf(poly, optr, retsize);
+#ifdef DEBUG
+elog(NOTICE, "lwgeom_force3d_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_force3d_recursive: it's a collection (type:%d)", type);
+#endif
+
+ // Add type
+ *optr = lwgeom_makeType_full(3, 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_force3d_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)
PG_RETURN_POINTER(result);
}
+
+// transform input geometry to 3d if not 2d already
+PG_FUNCTION_INFO_V1(LWGEOM_force_3d);
+Datum LWGEOM_force_3d(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 3d
+ if ( olddims == 3 ) PG_RETURN_POINTER(geom);
+
+ if ( olddims > 3 ) {
+ result = (LWGEOM *) palloc(geom->size);
+ } else {
+ // allocate double as memory a larger for safety
+ result = (LWGEOM *) palloc(geom->size*1.5);
+ }
+
+ lwgeom_force3d_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);
+}