Flip nrings function from serialized to lwgeom based.

git-svn-id: http://svn.osgeo.org/postgis/trunk@6177 b70326c6-7e19-0410-871a-916f4a2858ee
This commit is contained in:
Paul Ramsey 2010-11-18 18:37:27 +00:00
parent d490f9252b
commit 3c8910ea90
3 changed files with 63 additions and 821 deletions

View file

@ -1549,6 +1549,13 @@ extern int lwgeom_needs_bbox(const LWGEOM *geom);
extern int lwgeom_count_vertices(const LWGEOM *geom);
extern int lwgeom_npoints(uchar *serialized);
/**
* Count the total number of rings in any #LWGEOM. Multipolygons
* and other collections get counted, not the same as OGC st_numrings.
*/
extern int lwgeom_count_rings(const LWGEOM *geom);
/**
* Return true or false depending on whether a geometry has
* a valid SRID set.
@ -1637,9 +1644,6 @@ extern LWTRIANGLE *lwtriangle_from_lwline(const LWLINE *shell);
extern const char *lwgeom_typeflags(uchar type);
extern int32 lwgeom_nrings_recursive(uchar *serialized);
/*
* Given a point, returns the location of closest point on pointarray
* as a fraction of total length (0: first point -- 1: last point).

View file

@ -1197,6 +1197,57 @@ int lwgeom_count_vertices(const LWGEOM *geom)
return result;
}
/**
* Count rings in an #LWGEOM.
*/
int lwgeom_count_rings(const LWGEOM *geom)
{
int result = 0;
/* Null? Empty? Zero. */
if( ! geom || lwgeom_is_empty(geom) )
return 0;
switch (TYPE_GETTYPE(geom->type))
{
case POINTTYPE:
case CIRCSTRINGTYPE:
case COMPOUNDTYPE:
case MULTICURVETYPE:
case MULTIPOINTTYPE:
case MULTILINETYPE:
case LINETYPE:
result = 0;
break;
case TRIANGLETYPE:
result = 1;
break;
case POLYGONTYPE:
result = ((LWPOLY *)geom)->nrings;
break;
case CURVEPOLYTYPE:
result = ((LWCURVEPOLY *)geom)->nrings;
break;
case MULTISURFACETYPE:
case MULTIPOLYGONTYPE:
case POLYHEDRALSURFACETYPE:
case TINTYPE:
case COLLECTIONTYPE:
{
LWCOLLECTION *col = (LWCOLLECTION*)geom;
int i = 0;
for( i = 0; i < col->ngeoms; i++ )
result += lwgeom_count_rings(col->geoms[i]);
break;
}
default:
lwerror("lwgeom_count_rings: unsupported input geometry type: %s", lwtype_name(TYPE_GETTYPE(geom->type)));
break;
}
LWDEBUGF(3, "counted %d rings", result);
return result;
}
int lwgeom_is_empty(const LWGEOM *geom)
{
int result = LW_FALSE;

View file

@ -223,127 +223,13 @@ Datum postgis_libxml_version(PG_FUNCTION_ARGS)
PG_RETURN_POINTER(result);
}
/**
* Recursively count points in a SERIALIZED lwgeom
*/
int32
lwgeom_npoints(uchar *serialized)
{
LWGEOM_INSPECTED *inspected = lwgeom_inspect(serialized);
int i, j;
int npoints=0;
/* now have to do a scan of each object */
for (i=0; i<inspected->ngeometries; i++)
{
LWLINE *line=NULL;
LWPOINT *point=NULL;
LWPOLY *poly=NULL;
LWTRIANGLE *triangle=NULL;
LWCIRCSTRING *curve=NULL;
uchar *subgeom=NULL;
point = lwgeom_getpoint_inspected(inspected, i);
if (point !=NULL)
{
npoints++;
continue;
}
poly = lwgeom_getpoly_inspected(inspected, i);
if (poly !=NULL)
{
for (j=0; j<poly->nrings; j++)
{
npoints += poly->rings[j]->npoints;
}
continue;
}
line = lwgeom_getline_inspected(inspected, i);
if (line != NULL)
{
npoints += line->points->npoints;
continue;
}
triangle = lwgeom_gettriangle_inspected(inspected, i);
if (triangle != NULL)
{
npoints += triangle->points->npoints;
continue;
}
curve = lwgeom_getcircstring_inspected(inspected, i);
if (curve != NULL)
{
npoints += curve->points->npoints;
continue;
}
subgeom = lwgeom_getsubgeometry_inspected(inspected, i);
if ( subgeom != NULL )
{
npoints += lwgeom_npoints(subgeom);
}
else
{
elog(ERROR, "What ? lwgeom_getsubgeometry_inspected returned NULL??");
}
}
return npoints;
}
/**
* Recursively count rings in a SERIALIZED lwgeom
*/
int32
lwgeom_nrings_recursive(uchar *serialized)
{
LWGEOM_INSPECTED *inspected;
int i;
int nrings=0;
inspected = lwgeom_inspect(serialized);
/* now have to do a scan of each object */
for (i=0; i<inspected->ngeometries; i++)
{
LWPOLY *poly=NULL;
uchar *subgeom=NULL;
subgeom = lwgeom_getsubgeometry_inspected(inspected, i);
if ( lwgeom_getType(subgeom[0]) == POLYGONTYPE )
{
poly = lwpoly_deserialize(subgeom);
nrings += poly->nrings;
continue;
}
if ( lwgeom_getType(subgeom[0]) == COLLECTIONTYPE )
{
nrings += lwgeom_nrings_recursive(subgeom);
continue;
}
}
lwinspected_release(inspected);
return nrings;
}
/** number of points in an object */
PG_FUNCTION_INFO_V1(LWGEOM_npoints);
Datum LWGEOM_npoints(PG_FUNCTION_ARGS)
{
PG_LWGEOM *geom = (PG_LWGEOM *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
LWGEOM *lwgeom = pglwgeom_deserialize(geom);
int32 npoints = 0;
int npoints = 0;
npoints = lwgeom_count_vertices(lwgeom);
lwgeom_release(lwgeom);
@ -357,9 +243,11 @@ PG_FUNCTION_INFO_V1(LWGEOM_nrings);
Datum LWGEOM_nrings(PG_FUNCTION_ARGS)
{
PG_LWGEOM *geom = (PG_LWGEOM *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
int32 nrings = 0;
LWGEOM *lwgeom = pglwgeom_deserialize(geom);
int nrings = 0;
nrings = lwgeom_nrings_recursive(SERIALIZED_FORM(geom));
nrings = lwgeom_count_rings(lwgeom);
lwgeom_release(lwgeom);
PG_FREE_IF_COPY(geom, 0);
PG_RETURN_INT32(nrings);
@ -567,707 +455,6 @@ Datum LWGEOM_perimeter2d_poly(PG_FUNCTION_ARGS)
}
/**
* @brief Write to already allocated memory 'optr' a 3dz 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_force3dz_recursive(uchar *serialized, uchar *optr, size_t *retsize)
{
LWGEOM_INSPECTED *inspected;
int i,j,k;
size_t totsize=0;
size_t size=0;
int type;
LWPOINT *point = NULL;
LWLINE *line = NULL;
LWCIRCSTRING *curve = NULL;
LWPOLY *poly = NULL;
LWTRIANGLE *triangle = NULL;
POINTARRAY newpts;
POINTARRAY **nrings;
uchar *loc;
POINT3DZ point3dz;
LWDEBUG(2, "lwgeom_force3dz_recursive: call");
type = lwgeom_getType(serialized[0]);
if ( type == POINTTYPE )
{
point = lwpoint_deserialize(serialized);
TYPE_SETZM(newpts.dims, 1, 0);
newpts.npoints = 1;
newpts.serialized_pointlist = lwalloc(sizeof(POINT3DZ));
loc = newpts.serialized_pointlist;
getPoint3dz_p(point->point, 0, &point3dz);
memcpy(loc, &point3dz, sizeof(POINT3DZ));
point->point = &newpts;
TYPE_SETZM(point->type, 1, 0);
lwpoint_serialize_buf(point, optr, retsize);
LWDEBUGF(3, "lwgeom_force3dz_recursive: it's a point, size:%d", *retsize);
return;
}
if ( type == LINETYPE )
{
line = lwline_deserialize(serialized);
LWDEBUG(3, "lwgeom_force3dz_recursive: it's a line");
TYPE_SETZM(newpts.dims, 1, 0);
newpts.npoints = line->points->npoints;
newpts.serialized_pointlist = lwalloc(sizeof(POINT3DZ)*line->points->npoints);
loc = newpts.serialized_pointlist;
for (j=0; j<line->points->npoints; j++)
{
getPoint3dz_p(line->points, j, &point3dz);
memcpy(loc, &point3dz, sizeof(POINT3DZ));
loc+=sizeof(POINT3DZ);
}
line->points = &newpts;
TYPE_SETZM(line->type, 1, 0);
lwline_serialize_buf(line, optr, retsize);
LWDEBUGF(3, "lwgeom_force3dz_recursive: it's a line, size:%d", *retsize);
return;
}
if ( type == CIRCSTRINGTYPE )
{
curve = lwcircstring_deserialize(serialized);
LWDEBUG(3, "lwgeom_force3dz_recursize: it's a circularstring");
TYPE_SETZM(newpts.dims, 1, 0);
newpts.npoints = curve->points->npoints;
newpts.serialized_pointlist = lwalloc(sizeof(POINT3DZ)*curve->points->npoints);
loc = newpts.serialized_pointlist;
for (j=0; j<curve->points->npoints; j++)
{
getPoint3dz_p(curve->points, j, &point3dz);
memcpy(loc, &point3dz, sizeof(POINT3DZ));
loc+=sizeof(POINT3DZ);
}
curve->points = &newpts;
TYPE_SETZM(curve->type, 1, 0);
lwcircstring_serialize_buf(curve, optr, retsize);
LWDEBUGF(3, "lwgeom_force3dz_recursive: it's a circularstring, size:%d", *retsize);
return;
}
if ( type == POLYGONTYPE )
{
poly = lwpoly_deserialize(serialized);
TYPE_SETZM(newpts.dims, 1, 0);
newpts.npoints = 0;
newpts.serialized_pointlist = lwalloc(1);
nrings = lwalloc(sizeof(POINTARRAY *)*poly->nrings);
loc = newpts.serialized_pointlist;
for (j=0; j<poly->nrings; j++)
{
POINTARRAY *ring = poly->rings[j];
POINTARRAY *nring = lwalloc(sizeof(POINTARRAY));
TYPE_SETZM(nring->dims, 1, 0);
nring->npoints = ring->npoints;
nring->serialized_pointlist =
lwalloc(ring->npoints*sizeof(POINT3DZ));
loc = nring->serialized_pointlist;
for (k=0; k<ring->npoints; k++)
{
getPoint3dz_p(ring, k, &point3dz);
memcpy(loc, &point3dz, sizeof(POINT3DZ));
loc+=sizeof(POINT3DZ);
}
nrings[j] = nring;
}
poly->rings = nrings;
TYPE_SETZM(poly->type, 1, 0);
lwpoly_serialize_buf(poly, optr, retsize);
LWDEBUGF(3, "lwgeom_force3dz_recursive: it's a poly, size:%d", *retsize);
return;
}
if ( type == TRIANGLETYPE )
{
triangle = lwtriangle_deserialize(serialized);
LWDEBUG(3, "lwgeom_force3dz_recursive: it's a triangle");
TYPE_SETZM(newpts.dims, 1, 0);
newpts.npoints = triangle->points->npoints;
newpts.serialized_pointlist = lwalloc(sizeof(POINT3DZ)*triangle->points->npoints);
loc = newpts.serialized_pointlist;
for (j=0; j<triangle->points->npoints; j++)
{
getPoint3dz_p(triangle->points, j, &point3dz);
memcpy(loc, &point3dz, sizeof(POINT3DZ));
loc+=sizeof(POINT3DZ);
}
triangle->points = &newpts;
TYPE_SETZM(triangle->type, 1, 0);
lwtriangle_serialize_buf(triangle, optr, retsize);
LWDEBUGF(3, "lwgeom_force3dz_recursive: it's a triangle, size:%d", *retsize);
return;
}
if ( type != MULTIPOINTTYPE && type != MULTIPOLYGONTYPE &&
type != MULTILINETYPE && type != COLLECTIONTYPE &&
type != COMPOUNDTYPE && type != CURVEPOLYTYPE &&
type != MULTICURVETYPE && type != MULTISURFACETYPE &&
type != POLYHEDRALSURFACETYPE && type != TINTYPE )
{
lwerror("lwgeom_force3dz_recursive: unknown geometry: %d - %s",
type, lwtype_name(type));
}
/*
* OK, this is a collection, so we write down its metadata
* first and then call us again
*/
LWDEBUGF(3, "lwgeom_force3dz_recursive: it's a collection (type:%d)", type);
/* Add type */
*optr = lwgeom_makeType_full(1, 0, 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;
LWDEBUGF(3, " collection header size:%d", totsize);
/* Now recurse for each suboject */
inspected = lwgeom_inspect(serialized);
for (i=0; i<inspected->ngeometries; i++)
{
uchar *subgeom = lwgeom_getsubgeometry_inspected(inspected, i);
lwgeom_force3dz_recursive(subgeom, optr, &size);
totsize += size;
optr += size;
LWDEBUGF(3, " elem %d size: %d (tot: %d)", i, size, totsize);
}
lwinspected_release(inspected);
*retsize = totsize;
}
/**
* @brief Write to already allocated memory 'optr' a 3dm version of
* the given serialized form.
* Higher dimensions in input geometry are discarder.
* If the given version is 2d M is set to 0.
* @return number bytes written in given int pointer.
*/
void
lwgeom_force3dm_recursive(uchar *serialized, uchar *optr, size_t *retsize)
{
LWGEOM_INSPECTED *inspected;
int i,j,k;
size_t totsize=0;
size_t size=0;
int type;
uchar newtypefl;
LWPOINT *point = NULL;
LWLINE *line = NULL;
LWCIRCSTRING *curve = NULL;
LWPOLY *poly = NULL;
LWTRIANGLE *triangle = NULL;
POINTARRAY newpts;
POINTARRAY **nrings;
POINT3DM p3dm;
uchar *loc;
LWDEBUG(2, "lwgeom_force3dm_recursive: call");
type = lwgeom_getType(serialized[0]);
if ( type == POINTTYPE )
{
point = lwpoint_deserialize(serialized);
TYPE_SETZM(newpts.dims, 0, 1);
newpts.npoints = 1;
newpts.serialized_pointlist = lwalloc(sizeof(POINT3DM));
loc = newpts.serialized_pointlist;
getPoint3dm_p(point->point, 0, &p3dm);
memcpy(loc, &p3dm, sizeof(POINT3DM));
point->point = &newpts;
TYPE_SETZM(point->type, 0, 1);
lwpoint_serialize_buf(point, optr, retsize);
lwfree(newpts.serialized_pointlist);
lwfree(point);
LWDEBUG(3, "lwgeom_force3dm_recursive returning");
return;
}
if ( type == LINETYPE )
{
line = lwline_deserialize(serialized);
LWDEBUGF(3, "lwgeom_force3dm_recursive: it's a line with %d points", line->points->npoints);
TYPE_SETZM(newpts.dims, 0, 1);
newpts.npoints = line->points->npoints;
newpts.serialized_pointlist = lwalloc(sizeof(POINT3DM)*line->points->npoints);
LWDEBUGF(3, "lwgeom_force3dm_recursive: %d bytes pointlist allocated", sizeof(POINT3DM)*line->points->npoints);
loc = newpts.serialized_pointlist;
for (j=0; j<line->points->npoints; j++)
{
getPoint3dm_p(line->points, j, &p3dm);
memcpy(loc, &p3dm, sizeof(POINT3DM));
loc+=sizeof(POINT3DM);
}
line->points = &newpts;
TYPE_SETZM(line->type, 0, 1);
lwline_serialize_buf(line, optr, retsize);
lwfree(newpts.serialized_pointlist);
lwfree(line);
LWDEBUG(3, "lwgeom_force3dm_recursive returning");
return;
}
if ( type == CIRCSTRINGTYPE )
{
curve = lwcircstring_deserialize(serialized);
LWDEBUGF(3, "lwgeom_force3dm_recursize: it's a circularstring with %d points", curve->points->npoints);
TYPE_SETZM(newpts.dims, 0, 1);
newpts.npoints = curve->points->npoints;
newpts.serialized_pointlist = lwalloc(sizeof(POINT3DM)*curve->points->npoints);
loc = newpts.serialized_pointlist;
for (j=0; j<curve->points->npoints; j++)
{
getPoint3dm_p(curve->points, j, &p3dm);
memcpy(loc, &p3dm, sizeof(POINT3DM));
loc+=sizeof(POINT3DM);
}
curve->points = &newpts;
TYPE_SETZM(curve->type, 0, 1);
lwcircstring_serialize_buf(curve, optr, retsize);
lwfree(newpts.serialized_pointlist);
lwfree(curve);
return;
}
if ( type == POLYGONTYPE )
{
poly = lwpoly_deserialize(serialized);
TYPE_SETZM(newpts.dims, 0, 1);
newpts.npoints = 0;
newpts.serialized_pointlist = lwalloc(1);
nrings = lwalloc(sizeof(POINTARRAY *)*poly->nrings);
loc = newpts.serialized_pointlist;
for (j=0; j<poly->nrings; j++)
{
POINTARRAY *ring = poly->rings[j];
POINTARRAY *nring = lwalloc(sizeof(POINTARRAY));
TYPE_SETZM(nring->dims, 0, 1);
nring->npoints = ring->npoints;
nring->serialized_pointlist =
lwalloc(ring->npoints*sizeof(POINT3DM));
loc = nring->serialized_pointlist;
for (k=0; k<ring->npoints; k++)
{
getPoint3dm_p(ring, k, &p3dm);
memcpy(loc, &p3dm, sizeof(POINT3DM));
loc+=sizeof(POINT3DM);
}
nrings[j] = nring;
}
poly->rings = nrings;
TYPE_SETZM(poly->type, 0, 1);
lwpoly_serialize_buf(poly, optr, retsize);
lwfree(poly);
/** @todo TODO: free nrigs[*]->serialized_pointlist
*/
LWDEBUG(3, "lwgeom_force3dm_recursive returning");
return;
}
if ( type == TRIANGLETYPE )
{
triangle = lwtriangle_deserialize(serialized);
LWDEBUGF(3, "lwgeom_force3dm_recursive: it's a triangle with %d points", triangle->points->npoints);
TYPE_SETZM(newpts.dims, 0, 1);
newpts.npoints = triangle->points->npoints;
newpts.serialized_pointlist = lwalloc(sizeof(POINT3DM)*triangle->points->npoints);
LWDEBUGF(3, "lwgeom_force3dm_recursive: %d bytes pointlist allocated",
sizeof(POINT3DM)*triangle->points->npoints);
loc = newpts.serialized_pointlist;
for (j=0; j<triangle->points->npoints; j++)
{
getPoint3dm_p(triangle->points, j, &p3dm);
memcpy(loc, &p3dm, sizeof(POINT3DM));
loc+=sizeof(POINT3DM);
}
triangle->points = &newpts;
TYPE_SETZM(triangle->type, 0, 1);
lwtriangle_serialize_buf(triangle, optr, retsize);
lwfree(newpts.serialized_pointlist);
lwfree(triangle);
LWDEBUG(3, "lwgeom_force3dm_recursive returning");
return;
}
if ( type != MULTIPOINTTYPE && type != MULTIPOLYGONTYPE &&
type != MULTILINETYPE && type != COLLECTIONTYPE &&
type != COMPOUNDTYPE && type != CURVEPOLYTYPE &&
type != MULTICURVETYPE && type != MULTISURFACETYPE &&
type != POLYHEDRALSURFACETYPE && type != TINTYPE )
{
lwerror("lwgeom_force3dm_recursive: unknown geometry: %d - %s",
type, lwtype_name(type));
}
/*
* OK, this is a collection, so we write down its metadata
* first and then call us again
*/
LWDEBUGF(3, "lwgeom_force3dm_recursive: it's a collection (%s)", lwtype_name(type));
/* Add type */
newtypefl = lwgeom_makeType_full(0, 1, lwgeom_hasSRID(serialized[0]),
type, lwgeom_hasBBOX(serialized[0]));
optr[0] = newtypefl;
optr++;
totsize++;
loc=serialized+1;
LWDEBUGF(3, "lwgeom_force3dm_recursive: added collection type (%s[%s]) - size:%d", lwtype_name(type), lwgeom_typeflags(newtypefl), totsize);
if ( lwgeom_hasBBOX(serialized[0]) != lwgeom_hasBBOX(newtypefl) )
lwerror("typeflag mismatch in BBOX");
if ( lwgeom_hasSRID(serialized[0]) != lwgeom_hasSRID(newtypefl) )
lwerror("typeflag mismatch in SRID");
/* Add BBOX if any */
if (lwgeom_hasBBOX(serialized[0]))
{
memcpy(optr, loc, sizeof(BOX2DFLOAT4));
optr += sizeof(BOX2DFLOAT4);
totsize += sizeof(BOX2DFLOAT4);
loc += sizeof(BOX2DFLOAT4);
LWDEBUGF(3, "lwgeom_force3dm_recursive: added collection bbox - size:%d", totsize);
}
/* Add SRID if any */
if (lwgeom_hasSRID(serialized[0]))
{
memcpy(optr, loc, 4);
optr += 4;
totsize += 4;
loc += 4;
LWDEBUGF(3, "lwgeom_force3dm_recursive: added collection SRID - size:%d", totsize);
}
/* Add numsubobjects */
memcpy(optr, loc, sizeof(uint32));
optr += sizeof(uint32);
totsize += sizeof(uint32);
loc += sizeof(uint32);
LWDEBUGF(3, "lwgeom_force3dm_recursive: added collection ngeoms - size:%d", totsize);
LWDEBUG(3, "lwgeom_force3dm_recursive: inspecting subgeoms");
/* Now recurse for each subobject */
inspected = lwgeom_inspect(serialized);
for (i=0; i<inspected->ngeometries; i++)
{
uchar *subgeom = lwgeom_getsubgeometry_inspected(inspected, i);
lwgeom_force3dm_recursive(subgeom, optr, &size);
totsize += size;
optr += size;
LWDEBUGF(3, "lwgeom_force3dm_recursive: added elem %d size: %d (tot: %d)",
i, size, totsize);
}
lwinspected_release(inspected);
LWDEBUG(3, "lwgeom_force3dm_recursive returning");
if ( retsize ) *retsize = totsize;
}
/*
* Write to already allocated memory 'optr' a 4d version of
* the given serialized form.
* Pad dimensions are set to 0 (this might be z, m or both).
* Return number bytes written in given int pointer.
*/
void
lwgeom_force4d_recursive(uchar *serialized, uchar *optr, size_t *retsize)
{
LWGEOM_INSPECTED *inspected;
int i,j,k;
size_t totsize=0;
size_t size=0;
int type;
LWPOINT *point = NULL;
LWLINE *line = NULL;
LWCIRCSTRING *curve = NULL;
LWPOLY *poly = NULL;
LWTRIANGLE *triangle = NULL;
POINTARRAY newpts;
POINTARRAY **nrings;
POINT4D p4d;
uchar *loc;
LWDEBUG(2, "lwgeom_force4d_recursive: call");
type = lwgeom_getType(serialized[0]);
if ( type == POINTTYPE )
{
point = lwpoint_deserialize(serialized);
TYPE_SETZM(newpts.dims, 1, 1);
newpts.npoints = 1;
newpts.serialized_pointlist = lwalloc(sizeof(POINT4D));
loc = newpts.serialized_pointlist;
getPoint4d_p(point->point, 0, &p4d);
memcpy(loc, &p4d, sizeof(POINT4D));
point->point = &newpts;
TYPE_SETZM(point->type, 1, 1);
lwpoint_serialize_buf(point, optr, retsize);
LWDEBUGF(3, "lwgeom_force4d_recursive: it's a point, size:%d", *retsize);
return;
}
if ( type == LINETYPE )
{
LWDEBUG(3, "lwgeom_force4d_recursive: it's a line");
line = lwline_deserialize(serialized);
TYPE_SETZM(newpts.dims, 1, 1);
newpts.npoints = line->points->npoints;
newpts.serialized_pointlist = lwalloc(sizeof(POINT4D)*line->points->npoints);
loc = newpts.serialized_pointlist;
for (j=0; j<line->points->npoints; j++)
{
getPoint4d_p(line->points, j, &p4d);
memcpy(loc, &p4d, sizeof(POINT4D));
loc+=sizeof(POINT4D);
}
line->points = &newpts;
TYPE_SETZM(line->type, 1, 1);
lwline_serialize_buf(line, optr, retsize);
LWDEBUGF(3, "lwgeom_force4d_recursive: it's a line, size:%d", *retsize);
return;
}
if ( type == CIRCSTRINGTYPE )
{
curve = lwcircstring_deserialize(serialized);
TYPE_SETZM(newpts.dims, 1, 1);
newpts.npoints = curve->points->npoints;
newpts.serialized_pointlist = lwalloc(sizeof(POINT4D)*curve->points->npoints);
loc = newpts.serialized_pointlist;
for (j=0; j<curve->points->npoints; j++)
{
getPoint4d_p(curve->points, j, &p4d);
memcpy(loc, &p4d, sizeof(POINT4D));
loc+=sizeof(POINT4D);
}
curve->points = &newpts;
TYPE_SETZM(curve->type, 1, 1);
lwcircstring_serialize_buf(curve, optr, retsize);
LWDEBUGF(3, "lwgeom_force4d_recursive: it's a circularstring, size:%d", *retsize);
return;
}
if ( type == POLYGONTYPE )
{
poly = lwpoly_deserialize(serialized);
TYPE_SETZM(newpts.dims, 1, 1);
newpts.npoints = 0;
newpts.serialized_pointlist = lwalloc(1);
nrings = lwalloc(sizeof(POINTARRAY *)*poly->nrings);
loc = newpts.serialized_pointlist;
for (j=0; j<poly->nrings; j++)
{
POINTARRAY *ring = poly->rings[j];
POINTARRAY *nring = lwalloc(sizeof(POINTARRAY));
TYPE_SETZM(nring->dims, 1, 1);
nring->npoints = ring->npoints;
nring->serialized_pointlist =
lwalloc(ring->npoints*sizeof(POINT4D));
loc = nring->serialized_pointlist;
for (k=0; k<ring->npoints; k++)
{
getPoint4d_p(ring, k, &p4d);
memcpy(loc, &p4d, sizeof(POINT4D));
loc+=sizeof(POINT4D);
}
nrings[j] = nring;
}
poly->rings = nrings;
TYPE_SETZM(poly->type, 1, 1);
lwpoly_serialize_buf(poly, optr, retsize);
LWDEBUGF(3, "lwgeom_force4d_recursive: it's a poly, size:%d", *retsize);
return;
}
if ( type == TRIANGLETYPE )
{
LWDEBUG(3, "lwgeom_force4d_recursive: it's a triangle");
triangle = lwtriangle_deserialize(serialized);
TYPE_SETZM(newpts.dims, 1, 1);
newpts.npoints = triangle->points->npoints;
newpts.serialized_pointlist = lwalloc(sizeof(POINT4D)*triangle->points->npoints);
loc = newpts.serialized_pointlist;
for (j=0; j<triangle->points->npoints; j++)
{
getPoint4d_p(triangle->points, j, &p4d);
memcpy(loc, &p4d, sizeof(POINT4D));
loc+=sizeof(POINT4D);
}
triangle->points = &newpts;
TYPE_SETZM(triangle->type, 1, 1);
lwtriangle_serialize_buf(triangle, optr, retsize);
LWDEBUGF(3, "lwgeom_force4d_recursive: it's a triangle, size:%d", *retsize);
return;
}
if ( type != MULTIPOINTTYPE && type != MULTIPOLYGONTYPE &&
type != MULTILINETYPE && type != COLLECTIONTYPE &&
type != COMPOUNDTYPE && type != CURVEPOLYTYPE &&
type != MULTICURVETYPE && type != MULTISURFACETYPE &&
type != POLYHEDRALSURFACETYPE && type != TINTYPE )
{
lwerror("lwgeom_force4d_recursive: unknown geometry: %d - %s",
type, lwtype_name(type));
}
/*
* OK, this is a collection, so we write down its metadata
* first and then call us again
*/
LWDEBUGF(3, "lwgeom_force4d_recursive: it's a collection (type:%d)", type);
/* Add type */
*optr = lwgeom_makeType_full(
1, 1,
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;
LWDEBUGF(3, " collection header size:%d", totsize);
/* Now recurse for each suboject */
inspected = lwgeom_inspect(serialized);
for (i=0; i<inspected->ngeometries; i++)
{
uchar *subgeom = lwgeom_getsubgeometry_inspected(inspected, i);
lwgeom_force4d_recursive(subgeom, optr, &size);
totsize += size;
optr += size;
LWDEBUGF(3, " elem %d size: %d (tot: %d)", i, size, totsize);
}
lwinspected_release(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)