char compound_is_closed(LWCOMPOUND *compound) { POINT3DZ sp, ep; LWGEOM *tmp; LWDEBUG(2, "compound_is_closed called."); tmp = compound->geoms[0]; if (lwgeom_getType(tmp->type) == LINETYPE) { getPoint3dz_p(((LWLINE *)tmp)->points, 0, &sp); } else { getPoint3dz_p(((LWCIRCSTRING *)tmp)->points, 0, &sp); } tmp = compound->geoms[compound->ngeoms - 1]; if (lwgeom_getType(tmp->type) == LINETYPE) { getPoint3dz_p(((LWLINE *)tmp)->points, ((LWLINE *)tmp)->points->npoints - 1, &ep); } else { getPoint3dz_p(((LWCIRCSTRING *)tmp)->points, ((LWCIRCSTRING *)tmp)->points->npoints - 1, &ep); } if (sp.x != ep.x) return 0; if (sp.y != ep.y) return 0; if (TYPE_HASZ(compound->type)) { if (sp.z != ep.z) return 0; } return 1; }
LWCURVEPOLY * lwcurvepoly_deserialize(uchar *srl) { LWCURVEPOLY *result; LWGEOM_INSPECTED *insp; int type = lwgeom_getType(srl[0]); int i; LWDEBUG(3, "lwcurvepoly_deserialize called."); if (type != CURVEPOLYTYPE) { lwerror("lwcurvepoly_deserialize called on NON curvepoly: %d", type); return NULL; } insp = lwgeom_inspect(srl); result = lwalloc(sizeof(LWCURVEPOLY)); result->type = insp->type; result->SRID = insp->SRID; result->nrings = insp->ngeometries; result->rings = lwalloc(sizeof(LWGEOM *)*insp->ngeometries); if (lwgeom_hasBBOX(srl[0])) { result->bbox = lwalloc(sizeof(BOX2DFLOAT4)); memcpy(result->bbox, srl + 1, sizeof(BOX2DFLOAT4)); } else result->bbox = NULL; for (i = 0; i < insp->ngeometries; i++) { result->rings[i] = lwgeom_deserialize(insp->sub_geoms[i]); if (lwgeom_getType(result->rings[i]->type) != CIRCSTRINGTYPE && lwgeom_getType(result->rings[i]->type) != LINETYPE && lwgeom_getType(result->rings[i]->type) != COMPOUNDTYPE) { lwerror("Only Circular curves, Linestrings and Compound curves are supported as rings, not %s (%d)", lwgeom_typename(result->rings[i]->type), result->rings[i]->type); lwfree(result); lwfree(insp); return NULL; } if (TYPE_NDIMS(result->rings[i]->type) != TYPE_NDIMS(result->type)) { lwerror("Mixed dimensions (curvepoly %d, ring %d)", TYPE_NDIMS(result->type), i, TYPE_NDIMS(result->rings[i]->type)); lwfree(result); lwfree(insp); return NULL; } } return result; }
/* Find length of this serialized point */ size_t lwgeom_size_point(const uchar *serialized_point) { uint32 result = 1; uchar type; const uchar *loc; type = serialized_point[0]; if ( lwgeom_getType(type) != POINTTYPE) return 0; LWDEBUGF(2, "lwgeom_size_point called (%d)", result); loc = serialized_point+1; if (lwgeom_hasBBOX(type)) { loc += sizeof(BOX2DFLOAT4); result +=sizeof(BOX2DFLOAT4); LWDEBUGF(3, "lwgeom_size_point: has bbox (%d)", result); } if ( lwgeom_hasSRID(type)) { LWDEBUGF(3, "lwgeom_size_point: has srid (%d)", result); loc +=4; /* type + SRID */ result +=4; } result += lwgeom_ndims(type)*sizeof(double); return result; }
Datum geometry_geometrytype(PG_FUNCTION_ARGS) { PG_LWGEOM *lwgeom; char *type_text; char *type_str = palloc(32); size_t size; lwgeom = (PG_LWGEOM*)PG_DETOAST_DATUM(PG_GETARG_DATUM(0)); /* Make it empty string to start */ *type_str = 0; /* Build up the output string */ strncat(type_str, "ST_", 32); strncat(type_str, lwgeom_typename(lwgeom_getType(lwgeom->type)), 32); size = strlen(type_str) + VARHDRSZ; /* Build a text type to store things in */ type_text = lwalloc(size); memcpy(VARDATA(type_text),type_str, size - VARHDRSZ); pfree(type_str); SET_VARSIZE(type_text, size); PG_FREE_IF_COPY(lwgeom, 0); PG_RETURN_POINTER(type_text); }
/** * Serializes a LWGEOM to a char*. This is a helper function that partially * writes the appropriate draw, stroke, and fill commands used to generate an * SVG image using ImageMagick's "convert" command. * @param output a char reference to write the LWGEOM to * @param lwgeom a reference to a LWGEOM * @return the numbers of character written to *output */ static size_t drawGeometry(char *output, LWGEOM *lwgeom, LAYERSTYLE *styles ) { char *ptr = output; int i; int type = lwgeom_getType(lwgeom->type); switch (type) { case POINTTYPE: ptr += drawPoint(ptr, (LWPOINT*)lwgeom, styles ); break; case LINETYPE: ptr += drawLineString(ptr, (LWLINE*)lwgeom, styles ); break; case POLYGONTYPE: ptr += drawPolygon(ptr, (LWPOLY*)lwgeom, styles ); break; case MULTIPOINTTYPE: case MULTILINETYPE: case MULTIPOLYGONTYPE: case COLLECTIONTYPE: for (i=0; i<((LWCOLLECTION*)lwgeom)->ngeoms; i++) { ptr += drawGeometry( ptr, lwcollection_getsubgeom ((LWCOLLECTION*)lwgeom, i), styles ); } break; } return (ptr - output); }
LWCOMPOUND * lwcompound_deserialize(uchar *serialized) { LWCOMPOUND *result; LWGEOM_INSPECTED *insp; int type = lwgeom_getType(serialized[0]); int i; if(type != COMPOUNDTYPE) { lwerror("lwcompound_deserialize called on non compound: %d", type); return NULL; } insp = lwgeom_inspect(serialized); result = lwalloc(sizeof(LWCOMPOUND)); result->type = insp->type; result->SRID = insp->SRID; result->ngeoms = insp->ngeometries; result->geoms = lwalloc(sizeof(LWGEOM *)*insp->ngeometries); if(lwgeom_hasBBOX(serialized[0])) { result->bbox = lwalloc(sizeof(BOX2DFLOAT4)); memcpy(result->bbox, serialized + 1, sizeof(BOX2DFLOAT4)); } else result->bbox = NULL; for(i = 0; i < insp->ngeometries; i++) { if(lwgeom_getType(insp->sub_geoms[i][0]) == LINETYPE) result->geoms[i] = (LWGEOM *)lwline_deserialize(insp->sub_geoms[i]); else result->geoms[i] = (LWGEOM *)lwcircstring_deserialize(insp->sub_geoms[i]); if(TYPE_NDIMS(result->geoms[i]->type) != TYPE_NDIMS(result->type)) { lwerror("Mixed dimensions (compound: %d, line/circularstring %d:%d)", TYPE_NDIMS(result->type), i, TYPE_NDIMS(result->geoms[i]->type) ); lwfree(result); return NULL; } } return result; }
/* * given the LWGEOM serialized form (or a pointer into a muli* one) * construct a proper LWLINE. * serialized_form should point to the 8bit type format (with type = 2) * See serialized form doc */ LWLINE * lwline_deserialize(uchar *serialized_form) { uchar type; LWLINE *result; uchar *loc =NULL; uint32 npoints; POINTARRAY *pa; type = (uchar) serialized_form[0]; if ( lwgeom_getType(type) != LINETYPE) { lwerror("lwline_deserialize: attempt to deserialize a line which is really a %s", lwgeom_typename(type)); return NULL; } result = (LWLINE*) lwalloc(sizeof(LWLINE)) ; result->type = type; loc = serialized_form+1; if (lwgeom_hasBBOX(type)) { LWDEBUG(3, "lwline_deserialize: input has bbox"); result->bbox = lwalloc(sizeof(BOX2DFLOAT4)); memcpy(result->bbox, loc, sizeof(BOX2DFLOAT4)); loc += sizeof(BOX2DFLOAT4); } else { result->bbox = NULL; /*lwnotice("line has NO bbox"); */ } if ( lwgeom_hasSRID(type)) { /*lwnotice("line has srid"); */ result->SRID = lw_get_int32(loc); loc +=4; /* type + SRID */ } else { /*lwnotice("line has NO srid"); */ result->SRID = -1; } /* we've read the type (1 byte) and SRID (4 bytes, if present) */ npoints = lw_get_uint32(loc); /*lwnotice("line npoints = %d", npoints); */ loc +=4; pa = pointArray_construct(loc, TYPE_HASZ(type), TYPE_HASM(type), npoints); result->points = pa; return result; }
Datum LWGEOM_startpoint_linestring(PG_FUNCTION_ARGS) { PG_LWGEOM *geom; LWGEOM_INSPECTED *inspected; LWLINE *line = NULL; POINTARRAY *pts; LWPOINT *point; PG_LWGEOM *result; int i, type; POSTGIS_DEBUG(2, "LWGEOM_startpoint_linestring called."); geom = (PG_LWGEOM *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0)); /* * Curved polygons and compound curves are both collections * that should not be traversed looking for linestrings. */ type = lwgeom_getType((uchar)SERIALIZED_FORM(geom)[0]); if (type == CURVEPOLYTYPE || type == COMPOUNDTYPE) { PG_FREE_IF_COPY(geom, 0); PG_RETURN_NULL(); } inspected = lwgeom_inspect(SERIALIZED_FORM(geom)); for (i=0; i<inspected->ngeometries; i++) { line = lwgeom_getline_inspected(inspected, i); if ( line ) break; } if ( line == NULL ) { PG_FREE_IF_COPY(geom, 0); PG_RETURN_NULL(); } /* Ok, now we have a line. */ /* Construct a point array */ pts = pointArray_construct(getPoint_internal(line->points, 0), TYPE_HASZ(line->type), TYPE_HASM(line->type), 1); lwgeom_release((LWGEOM *)line); /* Construct an LWPOINT */ point = lwpoint_construct(pglwgeom_getSRID(geom), NULL, pts); /* Construct a PG_LWGEOM */ result = pglwgeom_serialize((LWGEOM *)point); lwgeom_release((LWGEOM *)point); PG_FREE_IF_COPY(geom, 0); PG_RETURN_POINTER(result); }
/* * Given the LWPOINT serialized form (or a pointer into a muli* one) * construct a proper LWPOINT. * serialized_form should point to the 8bit type format (with type = 1) * See serialized form doc */ LWPOINT * lwpoint_deserialize(uchar *serialized_form) { uchar type; int geom_type; LWPOINT *result; uchar *loc = NULL; POINTARRAY *pa; LWDEBUG(2, "lwpoint_deserialize called"); result = (LWPOINT*) lwalloc(sizeof(LWPOINT)) ; type = serialized_form[0]; geom_type = lwgeom_getType(type); if ( geom_type != POINTTYPE) { lwerror("lwpoint_deserialize: attempt to deserialize a point which is really a %s", lwgeom_typename(geom_type)); return NULL; } result->type = type; loc = serialized_form+1; if (lwgeom_hasBBOX(type)) { LWDEBUG(3, "lwpoint_deserialize: input has bbox"); result->bbox = lwalloc(sizeof(BOX2DFLOAT4)); memcpy(result->bbox, loc, sizeof(BOX2DFLOAT4)); loc += sizeof(BOX2DFLOAT4); } else { result->bbox = NULL; } if ( lwgeom_hasSRID(type)) { LWDEBUG(3, "lwpoint_deserialize: input has SRID"); result->SRID = lw_get_int32(loc); loc += 4; /* type + SRID */ } else { result->SRID = -1; } /* we've read the type (1 byte) and SRID (4 bytes, if present) */ pa = pointArray_construct(loc, TYPE_HASZ(type), TYPE_HASM(type), 1); result->point = pa; return result; }
Datum LWGEOM_endpoint_linestring(PG_FUNCTION_ARGS) { PG_LWGEOM *geom; LWGEOM_INSPECTED *inspected; LWLINE *line = NULL; POINTARRAY *pts; LWGEOM *point; PG_LWGEOM *result; int i, type; POSTGIS_DEBUG(2, "LWGEOM_endpoint_linestring called."); geom = (PG_LWGEOM *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0)); type = lwgeom_getType((uchar)SERIALIZED_FORM(geom)[0]); if (type == CURVEPOLYTYPE || type == COMPOUNDTYPE) { PG_FREE_IF_COPY(geom, 0); PG_RETURN_NULL(); } inspected = lwgeom_inspect(SERIALIZED_FORM(geom)); for (i=0; i<inspected->ngeometries; i++) { line = lwgeom_getline_inspected(inspected, i); if ( line ) break; } lwinspected_release(inspected); if ( line == NULL ) { PG_FREE_IF_COPY(geom, 0); PG_RETURN_NULL(); } /* Ok, now we have a line. */ /* Construct a point array */ pts = pointArray_construct( getPoint_internal(line->points, line->points->npoints-1), TYPE_HASZ(line->type), TYPE_HASM(line->type), 1); lwgeom_release((LWGEOM *)line); /* Construct an LWPOINT */ point = (LWGEOM *)lwpoint_construct(pglwgeom_getSRID(geom), NULL, pts); /* Serialize an PG_LWGEOM */ result = pglwgeom_serialize(point); lwgeom_release(point); PG_FREE_IF_COPY(geom, 0); PG_RETURN_POINTER(result); }
LWMPOLY * lwmpoly_deserialize(uchar *srl) { LWMPOLY *result; LWGEOM_INSPECTED *insp; int type = lwgeom_getType(srl[0]); int i; LWDEBUG(2, "lwmpoly_deserialize called"); if ( type != MULTIPOLYGONTYPE ) { lwerror("lwmpoly_deserialize called on NON multipoly: %d", type); return NULL; } insp = lwgeom_inspect(srl); result = lwalloc(sizeof(LWMPOLY)); result->type = insp->type; result->SRID = insp->SRID; result->ngeoms = insp->ngeometries; if ( insp->ngeometries ) { result->geoms = lwalloc(sizeof(LWPOLY *)*insp->ngeometries); } else { result->geoms = NULL; } if (lwgeom_hasBBOX(srl[0])) { result->bbox = lwalloc(sizeof(BOX2DFLOAT4)); memcpy(result->bbox, srl+1, sizeof(BOX2DFLOAT4)); } else result->bbox = NULL; for (i=0; i<insp->ngeometries; i++) { result->geoms[i] = lwpoly_deserialize(insp->sub_geoms[i]); if ( TYPE_NDIMS(result->geoms[i]->type) != TYPE_NDIMS(result->type) ) { lwerror("Mixed dimensions (multipoly:%d, poly%d:%d)", TYPE_NDIMS(result->type), i, TYPE_NDIMS(result->geoms[i]->type) ); return NULL; } } return result; }
Datum LWGEOM_getTYPE(PG_FUNCTION_ARGS) { PG_LWGEOM *lwgeom; char *text_ob; char *result; int32 size; uchar type; lwgeom = (PG_LWGEOM *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0)); text_ob = lwalloc(20+VARHDRSZ); result = text_ob+VARHDRSZ; type = lwgeom_getType(lwgeom->type); memset(VARDATA(text_ob), 0, 20); if (type == POINTTYPE) strcpy(result,"POINT"); else if (type == MULTIPOINTTYPE) strcpy(result,"MULTIPOINT"); else if (type == LINETYPE) strcpy(result,"LINESTRING"); else if (type == CIRCSTRINGTYPE) strcpy(result,"CIRCULARSTRING"); else if (type == COMPOUNDTYPE) strcpy(result, "COMPOUNDCURVE"); else if (type == MULTILINETYPE) strcpy(result,"MULTILINESTRING"); else if (type == MULTICURVETYPE) strcpy(result, "MULTICURVE"); else if (type == POLYGONTYPE) strcpy(result,"POLYGON"); else if (type == CURVEPOLYTYPE) strcpy(result,"CURVEPOLYGON"); else if (type == MULTIPOLYGONTYPE) strcpy(result,"MULTIPOLYGON"); else if (type == MULTISURFACETYPE) strcpy(result, "MULTISURFACE"); else if (type == COLLECTIONTYPE) strcpy(result,"GEOMETRYCOLLECTION"); else strcpy(result,"UNKNOWN"); if ( TYPE_HASM(lwgeom->type) && ! TYPE_HASZ(lwgeom->type) ) strcat(result, "M"); size = strlen(result) + VARHDRSZ ; SET_VARSIZE(text_ob, size); /* size of string */ PG_FREE_IF_COPY(lwgeom, 0); PG_RETURN_POINTER(text_ob); }
Datum LWGEOM_exteriorring_polygon(PG_FUNCTION_ARGS) { PG_LWGEOM *geom = (PG_LWGEOM *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0)); LWPOLY *poly = NULL; LWCURVEPOLY *curvepoly = NULL; POINTARRAY *extring; LWGEOM *ring; LWLINE *line; PG_LWGEOM *result; BOX2DFLOAT4 *bbox=NULL; POSTGIS_DEBUG(2, "LWGEOM_exteriorring_polygon called."); if ( TYPE_GETTYPE(geom->type) != POLYGONTYPE && TYPE_GETTYPE(geom->type) != CURVEPOLYTYPE) { elog(ERROR, "ExteriorRing: geom is not a polygon"); PG_RETURN_NULL(); } if (lwgeom_getType((uchar)SERIALIZED_FORM(geom)[0]) == POLYGONTYPE) { poly = lwpoly_deserialize(SERIALIZED_FORM(geom)); /* Ok, now we have a polygon. Here is its exterior ring. */ extring = poly->rings[0]; /* * This is a LWLINE constructed by exterior ring POINTARRAY * If the input geom has a bbox, use it for * the output geom, as exterior ring makes it up ! */ if ( poly->bbox ) bbox=box2d_clone(poly->bbox); line = lwline_construct(poly->SRID, bbox, extring); result = pglwgeom_serialize((LWGEOM *)line); lwgeom_release((LWGEOM *)line); lwgeom_release((LWGEOM *)poly); } else { curvepoly = lwcurvepoly_deserialize(SERIALIZED_FORM(geom)); ring = curvepoly->rings[0]; result = pglwgeom_serialize(ring); lwgeom_release(ring); } PG_FREE_IF_COPY(geom, 0); PG_RETURN_POINTER(result); }
Datum LWGEOM_geometryn_collection(PG_FUNCTION_ARGS) { PG_LWGEOM *geom = (PG_LWGEOM *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0)); PG_LWGEOM *result; int type = lwgeom_getType(geom->type); int32 idx; LWCOLLECTION *coll; LWGEOM *subgeom; POSTGIS_DEBUG(2, "LWGEOM_geometryn_collection called."); /* elog(NOTICE, "GeometryN called"); */ /* call is valid on multi* geoms only */ if (type==POINTTYPE || type==LINETYPE || type==CIRCSTRINGTYPE || type==COMPOUNDTYPE || type==POLYGONTYPE || type==CURVEPOLYTYPE) { /* elog(NOTICE, "geometryn: geom is of type %d, requires >=4", type); */ PG_RETURN_NULL(); } idx = PG_GETARG_INT32(1); idx -= 1; /* index is 1-based */ coll = (LWCOLLECTION *)lwgeom_deserialize(SERIALIZED_FORM(geom)); if ( idx < 0 ) PG_RETURN_NULL(); if ( idx >= coll->ngeoms ) PG_RETURN_NULL(); subgeom = coll->geoms[idx]; subgeom->SRID = coll->SRID; /* COMPUTE_BBOX==TAINTING */ if ( coll->bbox ) lwgeom_add_bbox(subgeom); result = pglwgeom_serialize(subgeom); lwgeom_release((LWGEOM *)coll); PG_FREE_IF_COPY(geom, 0); PG_RETURN_POINTER(result); }
Datum LWGEOM_numgeometries_collection(PG_FUNCTION_ARGS) { PG_LWGEOM *geom = (PG_LWGEOM *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0)); int type; int32 ret; uchar *serialized = SERIALIZED_FORM(geom); type = lwgeom_getType(geom->type); if (type==MULTIPOINTTYPE || type==MULTILINETYPE || type==MULTICURVETYPE || type==MULTIPOLYGONTYPE || type==MULTISURFACETYPE || type==COLLECTIONTYPE) { ret = lwgeom_getnumgeometries(serialized); PG_FREE_IF_COPY(geom, 0); PG_RETURN_INT32(ret); } PG_FREE_IF_COPY(geom, 0); PG_RETURN_NULL(); }
/* find length of this serialized line */ size_t lwgeom_size_line(const uchar *serialized_line) { int type = (uchar) serialized_line[0]; uint32 result = 1; /*type */ const uchar *loc; uint32 npoints; LWDEBUG(2, "lwgeom_size_line called"); if ( lwgeom_getType(type) != LINETYPE) lwerror("lwgeom_size_line::attempt to find the length of a non-line"); loc = serialized_line+1; if (lwgeom_hasBBOX(type)) { loc += sizeof(BOX2DFLOAT4); result +=sizeof(BOX2DFLOAT4); } if ( lwgeom_hasSRID(type)) { loc += 4; /* type + SRID */ result +=4; } /* we've read the type (1 byte) and SRID (4 bytes, if present) */ npoints = lw_get_uint32(loc); result += sizeof(uint32); /* npoints */ result += TYPE_NDIMS(type) * sizeof(double) * npoints; LWDEBUGF(3, "lwgeom_size_line returning %d", result); return result; }
Datum LWGEOM_pointn_linestring(PG_FUNCTION_ARGS) { PG_LWGEOM *geom; int32 wanted_index; LWGEOM_INSPECTED *inspected; LWLINE *line = NULL; LWCIRCSTRING *curve = NULL; LWGEOM *tmp = NULL; POINTARRAY *pts; LWPOINT *point; uchar *serializedpoint; PG_LWGEOM *result; int i, type; wanted_index = PG_GETARG_INT32(1); if ( wanted_index < 1 ) PG_RETURN_NULL(); /* index out of range */ geom = (PG_LWGEOM *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0)); type = lwgeom_getType((uchar)SERIALIZED_FORM(geom)[0]); if (type == COMPOUNDTYPE || type == CURVEPOLYTYPE) { PG_FREE_IF_COPY(geom, 0); PG_RETURN_NULL(); } else { inspected = lwgeom_inspect(SERIALIZED_FORM(geom)); for (i=0; i<inspected->ngeometries; i++) { tmp = lwgeom_getgeom_inspected(inspected, i); if (lwgeom_getType(tmp->type) == LINETYPE || lwgeom_getType(tmp->type) == CIRCSTRINGTYPE) break; } if ( tmp == NULL ) { lwinspected_release(inspected); PG_FREE_IF_COPY(geom, 0); PG_RETURN_NULL(); } if (lwgeom_getType(tmp->type) == CIRCSTRINGTYPE) { curve = (LWCIRCSTRING *)tmp; if (wanted_index > curve->points->npoints) { lwinspected_release(inspected); PG_FREE_IF_COPY(geom, 0); lwgeom_release(tmp); PG_RETURN_NULL(); } lwinspected_release(inspected); pts = pointArray_construct(getPoint_internal( curve->points, wanted_index-1), TYPE_HASZ(curve->type), TYPE_HASM(curve->type), 1); } else if (lwgeom_getType(tmp->type) == LINETYPE) { line = (LWLINE *)tmp; /* Ok, now we have a line. Let's see if it has enough points. */ if ( wanted_index > line->points->npoints ) { lwinspected_release(inspected); PG_FREE_IF_COPY(geom, 0); lwgeom_release(tmp); PG_RETURN_NULL(); } lwinspected_release(inspected); /* Construct a point array */ pts = pointArray_construct(getPoint_internal(line->points, wanted_index-1), TYPE_HASZ(line->type), TYPE_HASM(line->type), 1); } else { lwinspected_release(inspected); PG_FREE_IF_COPY(geom, 0); lwgeom_release(tmp); PG_RETURN_NULL(); } } /* Construct an LWPOINT */ point = lwpoint_construct(pglwgeom_getSRID(geom), NULL, pts); /* Serialized the point */ serializedpoint = lwpoint_serialize(point); /* And we construct the line * TODO: use serialize_buf above, instead .. */ result = PG_LWGEOM_construct(serializedpoint, pglwgeom_getSRID(geom), 0); pfree(point); pfree(serializedpoint); PG_FREE_IF_COPY(geom, 0); lwgeom_release(tmp); PG_RETURN_POINTER(result); }
Datum LWGEOM_numinteriorrings_polygon(PG_FUNCTION_ARGS) { PG_LWGEOM *geom = (PG_LWGEOM *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0)); LWGEOM_INSPECTED *inspected = NULL; LWGEOM *tmp = NULL; LWPOLY *poly = NULL; LWCURVEPOLY *curvepoly = NULL; int32 result; int i; POSTGIS_DEBUG(2, "LWGEOM_numinteriorrings called."); if (lwgeom_getType((uchar)SERIALIZED_FORM(geom)[0]) == CURVEPOLYTYPE) { tmp = (LWGEOM *)lwcurvepoly_deserialize(SERIALIZED_FORM(geom)); } else { inspected = lwgeom_inspect(SERIALIZED_FORM(geom)); for (i=0; i<inspected->ngeometries; i++) { tmp = lwgeom_getgeom_inspected(inspected, i); if (lwgeom_getType(tmp->type) == POLYGONTYPE || lwgeom_getType(tmp->type) == CURVEPOLYTYPE) break; } } if ( tmp == NULL ) { PG_FREE_IF_COPY(geom, 0); lwinspected_release(inspected); PG_RETURN_NULL(); } POSTGIS_DEBUGF(3, "Geometry of type %d found.", lwgeom_getType(tmp->type)); if (lwgeom_getType(tmp->type) == POLYGONTYPE) { poly = (LWPOLY *)tmp; /* Ok, now we have a polygon. Here is its number of holes */ result = poly->nrings-1; } else if (lwgeom_getType(tmp->type) == CURVEPOLYTYPE) { POSTGIS_DEBUG(3, "CurvePolygon found."); curvepoly = (LWCURVEPOLY *)tmp; result = curvepoly->nrings-1; } else { PG_FREE_IF_COPY(geom, 0); lwinspected_release(inspected); PG_RETURN_NULL(); } PG_FREE_IF_COPY(geom, 0); if (inspected != NULL) lwinspected_release(inspected); lwgeom_release((LWGEOM *)tmp); PG_RETURN_INT32(result); }
/** * @brief returns 0 for points, 1 for lines, 2 for polygons. * returns max dimension for a collection. * returns -1 for the empty geometry (TODO) * returns -2 on error */ static int32 lwgeom_dimension_recursive(const uchar *serialized) { LWGEOM_INSPECTED *inspected; int ret = -1; int i; /** @todo * This has the unfortunate habit of traversing the CURVEPOLYTYPe * geoms and returning 1, as all contained geoms are linear. * Here we preempt this problem. * TODO: This should handle things a bit better. Only * GEOMETRYCOLLECTION should ever need to be traversed. */ if (lwgeom_getType(serialized[0]) == CURVEPOLYTYPE) return 2; inspected = lwgeom_inspect(serialized); for (i=0; i<inspected->ngeometries; i++) { uchar *subgeom; char typeflags = lwgeom_getsubtype_inspected(inspected, i); int type = lwgeom_getType(typeflags); int dims=-1; LWDEBUGF(3, "lwgeom_dimension_recursive: type %d", type); if ( type == POINTTYPE ) dims = 0; else if ( type == MULTIPOINTTYPE ) dims=0; else if ( type == LINETYPE ) dims=1; else if ( type == CIRCSTRINGTYPE ) dims=1; else if ( type == COMPOUNDTYPE ) dims=1; else if ( type == MULTILINETYPE ) dims=1; else if ( type == MULTICURVETYPE ) dims=1; else if ( type == POLYGONTYPE ) dims=2; else if ( type == CURVEPOLYTYPE ) dims=2; else if ( type == MULTIPOLYGONTYPE ) dims=2; else if ( type == MULTISURFACETYPE ) dims=2; else if ( type == COLLECTIONTYPE ) { subgeom = lwgeom_getsubgeometry_inspected(inspected, i); if ( subgeom == NULL ) { lwinspected_release(inspected); return -2; } dims = lwgeom_dimension_recursive(subgeom); } if ( dims == 2 ) { /* nothing can be higher */ lwinspected_release(inspected); return 2; } if ( dims > ret ) ret = dims; } lwinspected_release(inspected); return ret; }
/** * Find first linestring in serialized geometry and return * the number of points in it. If no linestrings are found * return -1. */ static int32 lwgeom_numpoints_linestring_recursive(const uchar *serialized) { LWGEOM_INSPECTED *inspected = lwgeom_inspect(serialized); int i; LWDEBUG(2, "lwgeom_numpoints_linestring_recursive called."); /* * CURVEPOLY and COMPOUND have no concept of numpoints but look like * collections once inspected. Fast-fail on these here. */ if (lwgeom_getType(inspected->type) == COMPOUNDTYPE || lwgeom_getType(inspected->type) == CURVEPOLYTYPE) { return -1; } for (i=0; i<inspected->ngeometries; i++) { int32 npoints; int type; LWGEOM *geom=NULL; uchar *subgeom; geom = lwgeom_getgeom_inspected(inspected, i); LWDEBUGF(3, "numpoints_recursive: type=%d", lwgeom_getType(geom->type)); if (lwgeom_getType(geom->type) == LINETYPE) { return ((LWLINE *)geom)->points->npoints; } else if (lwgeom_getType(geom->type) == CIRCSTRINGTYPE) { return ((LWCIRCSTRING *)geom)->points->npoints; } subgeom = lwgeom_getsubgeometry_inspected(inspected, i); if ( subgeom == NULL ) { elog(ERROR, "What ? lwgeom_getsubgeometry_inspected returned NULL??"); } type = lwgeom_getType(subgeom[0]); /* MULTILINESTRING && GEOMETRYCOLLECTION are worth checking */ if ( type != MULTILINETYPE && type != COLLECTIONTYPE ) continue; npoints = lwgeom_numpoints_linestring_recursive(subgeom); if ( npoints == -1 ) continue; lwinspected_release(inspected); return npoints; } lwinspected_release(inspected); return -1; }
LWMSURFACE * lwmsurface_deserialize(uchar *srl) { LWMSURFACE *result; LWGEOM_INSPECTED *insp; int stype; int type = lwgeom_getType(srl[0]); int i; LWDEBUG(2, "lwmsurface_deserialize called"); if (type != MULTISURFACETYPE) { lwerror("lwmsurface_deserialize called on a non-multisurface: %d", type); return NULL; } insp = lwgeom_inspect(srl); result = lwalloc(sizeof(LWMSURFACE)); result->type = insp->type; result->SRID = insp->SRID; result->ngeoms = insp->ngeometries; if ( insp->ngeometries ) { result->geoms = lwalloc(sizeof(LWPOLY *)*insp->ngeometries); } else { result->geoms = NULL; } if (lwgeom_hasBBOX(srl[0])) { result->bbox = lwalloc(sizeof(BOX2DFLOAT4)); memcpy(result->bbox, srl + 1, sizeof(BOX2DFLOAT4)); } else result->bbox = NULL; for (i = 0; i < insp->ngeometries; i++) { stype = lwgeom_getType(insp->sub_geoms[i][0]); if (stype == POLYGONTYPE) { result->geoms[i] = (LWGEOM *)lwpoly_deserialize(insp->sub_geoms[i]); } else if (stype == CURVEPOLYTYPE) { result->geoms[i] = (LWGEOM *)lwcurvepoly_deserialize(insp->sub_geoms[i]); } else { lwerror("Only Polygons and Curved Polygons are supported in a MultiSurface."); lwfree(result); lwfree(insp); return NULL; } if (TYPE_NDIMS(result->geoms[i]->type) != TYPE_NDIMS(result->type)) { lwerror("Mixed dimensions (multisurface: %d, surface %d:%d", TYPE_NDIMS(result->type), i, TYPE_NDIMS(result->geoms[i]->type)); lwfree(result); lwfree(insp); return NULL; } } return result; }
Datum LWGEOM_isclosed_linestring(PG_FUNCTION_ARGS) { PG_LWGEOM *geom; LWGEOM_INSPECTED *inspected; LWGEOM *sub = NULL; LWCOMPOUND *compound = NULL; int linesfound=0; int i; POSTGIS_DEBUG(2, "LWGEOM_isclosed_linestring called."); geom = (PG_LWGEOM *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0)); if (lwgeom_getType((uchar)SERIALIZED_FORM(geom)[0]) == COMPOUNDTYPE) { compound = lwcompound_deserialize(SERIALIZED_FORM(geom)); if (compound_is_closed(compound)) { lwgeom_release((LWGEOM *)compound); PG_FREE_IF_COPY(geom, 0); PG_RETURN_BOOL(TRUE); } else { lwgeom_release((LWGEOM *)compound); PG_FREE_IF_COPY(geom, 0); PG_RETURN_BOOL(FALSE); } } inspected = lwgeom_inspect(SERIALIZED_FORM(geom)); for (i=0; i<inspected->ngeometries; i++) { sub = lwgeom_getgeom_inspected(inspected, i); if ( sub == NULL ) continue; else if (lwgeom_getType(sub->type) == LINETYPE && !line_is_closed((LWLINE *)sub)) { lwgeom_release(sub); lwinspected_release(inspected); PG_FREE_IF_COPY(geom, 0); PG_RETURN_BOOL(FALSE); } else if (lwgeom_getType(sub->type) == CIRCSTRINGTYPE && !circstring_is_closed((LWCIRCSTRING *)sub)) { lwgeom_release(sub); lwinspected_release(inspected); PG_FREE_IF_COPY(geom, 0); PG_RETURN_BOOL(FALSE); } else if (lwgeom_getType(sub->type) == COMPOUNDTYPE && !compound_is_closed((LWCOMPOUND *)sub)) { lwgeom_release(sub); lwinspected_release(inspected); PG_FREE_IF_COPY(geom, 0); PG_RETURN_BOOL(FALSE); } lwgeom_release(sub); linesfound++; } lwinspected_release(inspected); if ( ! linesfound ) { PG_FREE_IF_COPY(geom, 0); PG_RETURN_NULL(); } PG_FREE_IF_COPY(geom, 0); PG_RETURN_BOOL(TRUE); }
/* * given the LWGEOM serialized form (or a point into a multi* one) * construct a proper LWCIRCSTRING. * serialized_form should point to the 8bit type format (with type = 8) * See serialized form doc */ LWCIRCSTRING * lwcircstring_deserialize(uchar *serialized_form) { uchar type; LWCIRCSTRING *result; uchar *loc=NULL; uint32 npoints; POINTARRAY *pa; type = (uchar)serialized_form[0]; if (lwgeom_getType(type) != CIRCSTRINGTYPE) { lwerror("lwcircstring_deserialize: attempt to deserialize a circularstring which is really a %s", lwgeom_typename(type)); return NULL; } result = (LWCIRCSTRING*) lwalloc(sizeof(LWCIRCSTRING)); result->type = type; loc = serialized_form + 1; if (lwgeom_hasBBOX(type)) { LWDEBUG(3, "lwcircstring_deserialize: input has bbox"); result->bbox = lwalloc(sizeof(BOX2DFLOAT4)); memcpy(result->bbox, loc, sizeof(BOX2DFLOAT4)); loc += sizeof(BOX2DFLOAT4); } else { LWDEBUG(3, "lwcircstring_deserialize: input lacks bbox"); result->bbox = NULL; } if (lwgeom_hasSRID(type)) { LWDEBUG(3, "lwcircstring_deserialize: input has srid"); result->SRID = lw_get_int32(loc); loc += 4; /* type + SRID */ } else { LWDEBUG(3, "lwcircstring_deserialize: input lacks srid"); result->SRID = -1; } /* we've read the type (1 byte) and SRID (4 bytes, if present) */ npoints = lw_get_uint32(loc); LWDEBUGF(3, "circstring npoints = %d", npoints); loc += 4; pa = pointArray_construct(loc, TYPE_HASZ(type), TYPE_HASM(type), npoints); result->points = pa; return result; }
LWMCURVE * lwmcurve_deserialize(uchar *srl) { LWMCURVE *result; LWGEOM_INSPECTED *insp; int stype; int type = lwgeom_getType(srl[0]); int i; if (type != MULTICURVETYPE) { lwerror("lwmcurve_deserialize called on NON multicurve: %d", type); return NULL; } insp = lwgeom_inspect(srl); result = lwalloc(sizeof(LWMCURVE)); result->type = insp->type; result->SRID = insp->SRID; result->ngeoms = insp->ngeometries; if ( insp->ngeometries ) { result->geoms = lwalloc(sizeof(LWGEOM *)*insp->ngeometries); } else { result->geoms = NULL; } if (lwgeom_hasBBOX(srl[0])) { result->bbox = lwalloc(sizeof(BOX2DFLOAT4)); memcpy(result->bbox, srl+1, sizeof(BOX2DFLOAT4)); } else result->bbox = NULL; for (i = 0; i < insp->ngeometries; i++) { stype = lwgeom_getType(insp->sub_geoms[i][0]); if (stype == CIRCSTRINGTYPE) { result->geoms[i] = (LWGEOM *)lwcircstring_deserialize(insp->sub_geoms[i]); } else if (stype == LINETYPE) { result->geoms[i] = (LWGEOM *)lwline_deserialize(insp->sub_geoms[i]); } else if (stype == COMPOUNDTYPE) { result->geoms[i] = (LWGEOM *)lwcompound_deserialize(insp->sub_geoms[i]); } else { lwerror("Only Circular strings, Line strings or Compound curves are permitted in a MultiCurve."); lwfree(result); lwfree(insp); return NULL; } if (TYPE_NDIMS(result->geoms[i]->type) != TYPE_NDIMS(result->type)) { lwerror("Mixed dimensions (multicurve: %d, curve %d:%d)", TYPE_NDIMS(result->type), i, TYPE_NDIMS(result->geoms[i]->type)); lwfree(result); lwfree(insp); return NULL; } } return result; }