double lwgeom_interpolate_point(const LWGEOM *lwin, const LWPOINT *lwpt) { POINT4D p, p_proj; double ret = 0.0; if ( ! lwin ) lwerror("lwgeom_interpolate_point: null input geometry!"); if ( ! lwgeom_has_m(lwin) ) lwerror("Input geometry does not have a measure dimension"); if ( lwgeom_is_empty(lwin) || lwpoint_is_empty(lwpt) ) lwerror("Input geometry is empty"); switch ( lwin->type ) { case LINETYPE: { LWLINE *lwline = lwgeom_as_lwline(lwin); lwpoint_getPoint4d_p(lwpt, &p); ret = ptarray_locate_point(lwline->points, &p, NULL, &p_proj); ret = p_proj.m; break; } default: lwerror("This function does not accept %s geometries.", lwtype_name(lwin->type)); } return ret; }
void lwgeom_add_bbox_deep(LWGEOM *lwgeom, GBOX *gbox) { if ( lwgeom_is_empty(lwgeom) ) return; FLAGS_SET_BBOX(lwgeom->flags, 1); if ( ! ( gbox || lwgeom->bbox ) ) { lwgeom->bbox = gbox_new(lwgeom->flags); lwgeom_calculate_gbox(lwgeom, lwgeom->bbox); } else if ( gbox && ! lwgeom->bbox ) { lwgeom->bbox = gbox_clone(gbox); } if ( lwgeom_is_collection(lwgeom) ) { int i; LWCOLLECTION *lwcol = (LWCOLLECTION*)lwgeom; for ( i = 0; i < lwcol->ngeoms; i++ ) { lwgeom_add_bbox_deep(lwcol->geoms[i], lwgeom->bbox); } } }
LWPOINT* lwcompound_get_lwpoint(const LWCOMPOUND *lwcmp, int where) { int i; int count = 0; int npoints = 0; if ( lwgeom_is_empty((LWGEOM*)lwcmp) ) return NULL; npoints = lwgeom_count_vertices((LWGEOM*)lwcmp); if ( where < 0 || where >= npoints ) { lwerror("%s: index %d is not in range of number of vertices (%d) in input", __func__, where, npoints); return NULL; } for ( i = 0; i < lwcmp->ngeoms; i++ ) { LWGEOM* part = lwcmp->geoms[i]; int npoints_part = lwgeom_count_vertices(part); if ( where >= count && where < count + npoints_part ) { return lwline_get_lwpoint((LWLINE*)part, where - count); } else { count += npoints_part; } } return NULL; }
int lwcompound_add_lwgeom(LWCOMPOUND *comp, LWGEOM *geom) { LWCOLLECTION *col = (LWCOLLECTION*)comp; /* Empty things can't continuously join up with other things */ if ( lwgeom_is_empty(geom) ) { LWDEBUG(4, "Got an empty component for a compound curve!"); return LW_FAILURE; } if( col->ngeoms > 0 ) { POINT4D last, first; /* First point of the component we are adding */ LWLINE *newline = (LWLINE*)geom; /* Last point of the previous component */ LWLINE *prevline = (LWLINE*)(col->geoms[col->ngeoms-1]); getPoint4d_p(newline->points, 0, &first); getPoint4d_p(prevline->points, prevline->points->npoints-1, &last); if ( !(FP_EQUALS(first.x,last.x) && FP_EQUALS(first.y,last.y)) ) { LWDEBUG(4, "Components don't join up end-to-end!"); LWDEBUGF(4, "first pt (%g %g %g %g) last pt (%g %g %g %g)", first.x, first.y, first.z, first.m, last.x, last.y, last.z, last.m); return LW_FAILURE; } } col = lwcollection_add_lwgeom(col, geom); return LW_SUCCESS; }
Datum LWGEOM_z_point(PG_FUNCTION_ARGS) { GSERIALIZED *geom; LWPOINT *point = NULL; LWGEOM *lwgeom; POINT3DZ p; geom = PG_GETARG_GSERIALIZED_P(0); if ( gserialized_get_type(geom) != POINTTYPE ) lwpgerror("Argument to ST_Z() must be a point"); lwgeom = lwgeom_from_gserialized(geom); point = lwgeom_as_lwpoint(lwgeom); if ( lwgeom_is_empty(lwgeom) ) PG_RETURN_NULL(); /* no Z in input */ if ( ! gserialized_has_z(geom) ) PG_RETURN_NULL(); getPoint3dz_p(point->point, 0, &p); PG_FREE_IF_COPY(geom, 0); PG_RETURN_FLOAT8(p.z); }
Datum LWGEOM_m_point(PG_FUNCTION_ARGS) { GSERIALIZED *geom; LWPOINT *point = NULL; LWGEOM *lwgeom; POINT3DM p; geom = (GSERIALIZED *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0)); if ( gserialized_get_type(geom) != POINTTYPE ) lwerror("Argument to M() must be a point"); lwgeom = lwgeom_from_gserialized(geom); point = lwgeom_as_lwpoint(lwgeom); if ( lwgeom_is_empty(lwgeom) ) PG_RETURN_NULL(); /* no M in input */ if ( ! FLAGS_GET_M(point->flags) ) PG_RETURN_NULL(); getPoint3dm_p(point->point, 0, &p); PG_FREE_IF_COPY(geom, 0); PG_RETURN_FLOAT8(p.m); }
/* takes a GEOMETRY and returns a KML representation */ char* lwgeom_to_kml2(const LWGEOM *geom, int precision, const char *prefix) { stringbuffer_t *sb; int rv; char *kml; /* Can't do anything with empty */ if( lwgeom_is_empty(geom) ) return NULL; sb = stringbuffer_create(); rv = lwgeom_to_kml2_sb(geom, precision, prefix, sb); if ( rv == LW_FAILURE ) { stringbuffer_destroy(sb); return NULL; } kml = stringbuffer_getstringcopy(sb); stringbuffer_destroy(sb); return kml; }
Datum LWGEOM_length_ellipsoid_linestring(PG_FUNCTION_ARGS) { GSERIALIZED *geom = PG_GETARG_GSERIALIZED_P(0); LWGEOM *lwgeom = lwgeom_from_gserialized(geom); SPHEROID *sphere = (SPHEROID *) PG_GETARG_POINTER(1); double length = 0.0; /* EMPTY things have no length */ if ( lwgeom_is_empty(lwgeom) ) { lwgeom_free(lwgeom); PG_RETURN_FLOAT8(0.0); } length = lwgeom_length_spheroid(lwgeom, sphere); lwgeom_free(lwgeom); PG_FREE_IF_COPY(geom, 0); /* Something went wrong... */ if ( length < 0.0 ) { elog(ERROR, "lwgeom_length_spheroid returned length < 0.0"); PG_RETURN_NULL(); } /* Clean up */ PG_RETURN_FLOAT8(length); }
CIRC_NODE* lwgeom_calculate_circ_tree(const LWGEOM* lwgeom) { if ( lwgeom_is_empty(lwgeom) ) return NULL; switch ( lwgeom->type ) { case POINTTYPE: return lwpoint_calculate_circ_tree((LWPOINT*)lwgeom); case LINETYPE: return lwline_calculate_circ_tree((LWLINE*)lwgeom); case POLYGONTYPE: return lwpoly_calculate_circ_tree((LWPOLY*)lwgeom); case MULTIPOINTTYPE: case MULTILINETYPE: case MULTIPOLYGONTYPE: case COLLECTIONTYPE: return lwcollection_calculate_circ_tree((LWCOLLECTION*)lwgeom); default: lwerror("Unable to calculate spherical index tree for type %s", lwtype_name(lwgeom->type)); return NULL; } }
Datum ST_CleanGeometry(PG_FUNCTION_ARGS) { #if POSTGIS_GEOS_VERSION < 33 elog(ERROR, "You need GEOS-3.3.0 or up for ST_CleanGeometry"); PG_RETURN_NULL(); #else /* POSTGIS_GEOS_VERSION >= 33 */ GSERIALIZED *in, *out; LWGEOM *lwgeom_in, *lwgeom_out; in = PG_GETARG_GSERIALIZED_P(0); lwgeom_in = lwgeom_from_gserialized(in); /* Short-circuit: empty geometry are the cleanest ! */ #if 0 if ( lwgeom_is_empty(lwgeom_in) ) { out = geometry_serialize(lwgeom_in); PG_FREE_IF_COPY(in, 0); PG_RETURN_POINTER(out); } #endif lwgeom_out = lwgeom_clean(lwgeom_in); if ( ! lwgeom_out ) { PG_FREE_IF_COPY(in, 0); PG_RETURN_NULL(); } out = geometry_serialize(lwgeom_out); PG_RETURN_POINTER(out); #endif /* POSTGIS_GEOS_VERSION >= 33 */ }
LWGEOM* lwgeom_buildarea(const LWGEOM *geom) { GEOSGeometry* geos_in; GEOSGeometry* geos_out; LWGEOM* geom_out; int SRID = (int)(geom->srid); int is3d = FLAGS_GET_Z(geom->flags); /* Can't build an area from an empty! */ if ( lwgeom_is_empty(geom) ) { return (LWGEOM*)lwpoly_construct_empty(SRID, is3d, 0); } LWDEBUG(3, "buildarea called"); LWDEBUGF(3, "ST_BuildArea got geom @ %p", geom); initGEOS(lwnotice, lwgeom_geos_error); geos_in = LWGEOM2GEOS(geom); if ( 0 == geos_in ) /* exception thrown at construction */ { lwerror("First argument geometry could not be converted to GEOS: %s", lwgeom_geos_errmsg); return NULL; } geos_out = LWGEOM_GEOS_buildArea(geos_in); GEOSGeom_destroy(geos_in); if ( ! geos_out ) /* exception thrown.. */ { lwerror("LWGEOM_GEOS_buildArea: %s", lwgeom_geos_errmsg); return NULL; } /* If no geometries are in result collection, return NULL */ if ( GEOSGetNumGeometries(geos_out) == 0 ) { GEOSGeom_destroy(geos_out); return NULL; } geom_out = GEOS2LWGEOM(geos_out, is3d); GEOSGeom_destroy(geos_out); #if PARANOIA_LEVEL > 0 if ( geom_out == NULL ) { lwerror("serialization error"); return NULL; } #endif return geom_out; }
static int lwmulti_to_twkb_buf(const LWCOLLECTION *col, TWKB_GLOBALS *globals, TWKB_STATE *ts) { int i; int nempty = 0; LWDEBUGF(2, "Entered %s", __func__); LWDEBUGF(4, "Number of geometries in multi is %d", col->ngeoms); /* Deal with special case for MULTIPOINT: skip any empty points */ if ( col->type == MULTIPOINTTYPE ) { for ( i = 0; i < col->ngeoms; i++ ) if ( lwgeom_is_empty(col->geoms[i]) ) nempty++; } /* Set the number of geometries */ bytebuffer_append_uvarint(ts->geom_buf, (uint64_t) (col->ngeoms - nempty)); /* We've been handed an idlist, so write it in */ if ( ts->idlist ) { for ( i = 0; i < col->ngeoms; i++ ) { /* Skip empty points in multipoints, we can't represent them */ if ( col->type == MULTIPOINTTYPE && lwgeom_is_empty(col->geoms[i]) ) continue; bytebuffer_append_varint(ts->geom_buf, ts->idlist[i]); } /* Empty it out to nobody else uses it now */ ts->idlist = NULL; } for ( i = 0; i < col->ngeoms; i++ ) { /* Skip empty points in multipoints, we can't represent them */ if ( col->type == MULTIPOINTTYPE && lwgeom_is_empty(col->geoms[i]) ) continue; lwgeom_to_twkb_buf(col->geoms[i], globals, ts); } return 0; }
/** * Calculate the area of an LWGEOM. Anything except POLYGON, MULTIPOLYGON * and GEOMETRYCOLLECTION return zero immediately. Multi's recurse, polygons * calculate external ring area and subtract internal ring area. A GBOX is * required to check relationship to equator an outside point. * WARNING: Does NOT WORK for polygons over equator or pole. */ double lwgeom_area_spheroid(const LWGEOM *lwgeom, const GBOX *gbox, const SPHEROID *spheroid) { int type; assert(lwgeom); /* No area in nothing */ if ( lwgeom_is_empty(lwgeom) ) return 0.0; /* Read the geometry type number */ type = TYPE_GETTYPE(lwgeom->type); /* Anything but polygons and collections returns zero */ if ( ! ( type == POLYGONTYPE || type == MULTIPOLYGONTYPE || type == COLLECTIONTYPE ) ) return 0.0; /* Actually calculate area */ if ( type == POLYGONTYPE ) { LWPOLY *poly = (LWPOLY*)lwgeom; int i; double area = 0.0; /* Just in case there's no rings */ if ( poly->nrings < 1 ) return 0.0; /* First, the area of the outer ring */ area += ptarray_area_spheroid(poly->rings[0], spheroid); /* Subtract areas of inner rings */ for ( i = 1; i < poly->nrings; i++ ) { area -= ptarray_area_spheroid(poly->rings[i], spheroid); } return area; } /* Recurse into sub-geometries to get area */ if ( type == MULTIPOLYGONTYPE || type == COLLECTIONTYPE ) { LWCOLLECTION *col = (LWCOLLECTION*)lwgeom; int i; double area = 0.0; for ( i = 0; i < col->ngeoms; i++ ) { area += lwgeom_area_spheroid(col->geoms[i], gbox, spheroid); } return area; } /* Shouldn't get here. */ return 0.0; }
/** * Transform given SERIALIZED geometry * from inpj projection to outpj projection */ int lwgeom_transform(LWGEOM *geom, projPJ inpj, projPJ outpj) { int i; /* No points to transform in an empty! */ if ( lwgeom_is_empty(geom) ) return LW_SUCCESS; switch(geom->type) { case POINTTYPE: case LINETYPE: case CIRCSTRINGTYPE: case TRIANGLETYPE: { LWLINE *g = (LWLINE*)geom; if ( ! ptarray_transform(g->points, inpj, outpj) ) return LW_FAILURE; break; } case POLYGONTYPE: { LWPOLY *g = (LWPOLY*)geom; for ( i = 0; i < g->nrings; i++ ) { if ( ! ptarray_transform(g->rings[i], inpj, outpj) ) return LW_FAILURE; } break; } case MULTIPOINTTYPE: case MULTILINETYPE: case MULTIPOLYGONTYPE: case COLLECTIONTYPE: case COMPOUNDTYPE: case CURVEPOLYTYPE: case MULTICURVETYPE: case MULTISURFACETYPE: case POLYHEDRALSURFACETYPE: case TINTYPE: { LWCOLLECTION *g = (LWCOLLECTION*)geom; for ( i = 0; i < g->ngeoms; i++ ) { if ( ! lwgeom_transform(g->geoms[i], inpj, outpj) ) return LW_FAILURE; } break; } default: { lwerror("lwgeom_transform: Cannot handle type '%s'", lwtype_name(geom->type)); return LW_FAILURE; } } return LW_SUCCESS; }
/** * Re-write the measure ordinate (or add one, if it isn't already there) interpolating * the measure between the supplied start and end values. */ LWMLINE* lwmline_measured_from_lwmline(const LWMLINE *lwmline, double m_start, double m_end) { int i = 0; int hasm = 0, hasz = 0; double length = 0.0, length_so_far = 0.0; double m_range = m_end - m_start; LWGEOM **geoms = NULL; if ( lwmline->type != MULTILINETYPE ) { lwerror("lwmline_measured_from_lmwline: only multiline types supported"); return NULL; } hasz = FLAGS_GET_Z(lwmline->flags); hasm = 1; /* Calculate the total length of the mline */ for ( i = 0; i < lwmline->ngeoms; i++ ) { LWLINE *lwline = (LWLINE*)lwmline->geoms[i]; if ( lwline->points && lwline->points->npoints > 1 ) { length += ptarray_length_2d(lwline->points); } } if ( lwgeom_is_empty((LWGEOM*)lwmline) ) { return (LWMLINE*)lwcollection_construct_empty(MULTILINETYPE, lwmline->srid, hasz, hasm); } geoms = lwalloc(sizeof(LWGEOM*) * lwmline->ngeoms); for ( i = 0; i < lwmline->ngeoms; i++ ) { double sub_m_start, sub_m_end; double sub_length = 0.0; LWLINE *lwline = (LWLINE*)lwmline->geoms[i]; if ( lwline->points && lwline->points->npoints > 1 ) { sub_length = ptarray_length_2d(lwline->points); } sub_m_start = (m_start + m_range * length_so_far / length); sub_m_end = (m_start + m_range * (length_so_far + sub_length) / length); geoms[i] = (LWGEOM*)lwline_measured_from_lwline(lwline, sub_m_start, sub_m_end); length_so_far += sub_length; } return (LWMLINE*)lwcollection_construct(lwmline->type, lwmline->srid, NULL, lwmline->ngeoms, geoms); }
/** * Ensure there's a box in the LWGEOM. * If the box is already there just return, * else compute it. */ void lwgeom_add_bbox(LWGEOM *lwgeom) { /* an empty LWGEOM has no bbox */ if ( lwgeom_is_empty(lwgeom) ) return; if ( lwgeom->bbox ) return; FLAGS_SET_BBOX(lwgeom->flags, 1); lwgeom->bbox = gbox_new(lwgeom->flags); lwgeom_calculate_gbox(lwgeom, lwgeom->bbox); }
double lwcompound_length_2d(const LWCOMPOUND *comp) { double length = 0.0; LWLINE *line; if ( lwgeom_is_empty((LWGEOM*)comp) ) return 0.0; line = lwcompound_stroke(comp, 32); length = lwline_length_2d(line); lwline_free(line); return length; }
int lwcollection_is_empty(const LWCOLLECTION *col) { int i; if ( (col->ngeoms == 0) || (!col->geoms) ) return LW_TRUE; for( i = 0; i < col->ngeoms; i++ ) { if ( ! lwgeom_is_empty(col->geoms[i]) ) return LW_FALSE; } return LW_TRUE; }
/** * This should be rewritten to make use of the curve itself. */ double lwcurvepoly_area(const LWCURVEPOLY *curvepoly) { double area = 0.0; LWPOLY *poly; if( lwgeom_is_empty((LWGEOM*)curvepoly) ) return 0.0; poly = lwcurvepoly_segmentize(curvepoly, 32); area = lwpoly_area(poly); lwpoly_free(poly); return area; }
double lwcompound_length_2d(const LWCOMPOUND *comp) { int i; double length = 0.0; if ( lwgeom_is_empty((LWGEOM*)comp) ) return 0.0; for (i = 0; i < comp->ngeoms; i++) { length += lwgeom_length_2d(comp->geoms[i]); } return length; }
/** * 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 (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(geom->type)); break; } LWDEBUGF(3, "counted %d rings", result); return result; }
/** * Count points in an #LWGEOM. */ int lwgeom_count_vertices(const LWGEOM *geom) { int result = 0; /* Null? Zero. */ if( ! geom ) return 0; LWDEBUGF(4, "lwgeom_count_vertices got type %s", lwtype_name(geom->type)); /* Empty? Zero. */ if( lwgeom_is_empty(geom) ) return 0; switch (geom->type) { case POINTTYPE: result = 1; break; case TRIANGLETYPE: case CIRCSTRINGTYPE: case LINETYPE: result = lwline_count_vertices((LWLINE *)geom); break; case POLYGONTYPE: result = lwpoly_count_vertices((LWPOLY *)geom); break; case COMPOUNDTYPE: case CURVEPOLYTYPE: case MULTICURVETYPE: case MULTISURFACETYPE: case MULTIPOINTTYPE: case MULTILINETYPE: case MULTIPOLYGONTYPE: case POLYHEDRALSURFACETYPE: case TINTYPE: case COLLECTIONTYPE: result = lwcollection_count_vertices((LWCOLLECTION *)geom); break; default: lwerror("lwgeom_count_vertices: unsupported input geometry type: %s", lwtype_name(geom->type)); break; } LWDEBUGF(3, "counted %d vertices", result); return result; }
/** * Takes a GEOMETRY and returns a SVG representation */ char * lwgeom_to_svg(const LWGEOM *geom, int precision, int relative) { char *ret = NULL; int type = geom->type; /* Empty string for empties */ if( lwgeom_is_empty(geom) ) { ret = lwalloc(1); ret[0] = '\0'; return ret; } switch (type) { case POINTTYPE: ret = assvg_point((LWPOINT*)geom, relative, precision); break; case LINETYPE: ret = assvg_line((LWLINE*)geom, relative, precision); break; case POLYGONTYPE: ret = assvg_polygon((LWPOLY*)geom, relative, precision); break; case MULTIPOINTTYPE: ret = assvg_multipoint((LWMPOINT*)geom, relative, precision); break; case MULTILINETYPE: ret = assvg_multiline((LWMLINE*)geom, relative, precision); break; case MULTIPOLYGONTYPE: ret = assvg_multipolygon((LWMPOLY*)geom, relative, precision); break; case COLLECTIONTYPE: ret = assvg_collection((LWCOLLECTION*)geom, relative, precision); break; default: lwerror("lwgeom_to_svg: '%s' geometry type not supported", lwtype_name(type)); } return ret; }
/** * Create a new LWGEOM of the appropriate MULTI* type. */ LWGEOM * lwgeom_as_multi(const LWGEOM *lwgeom) { LWGEOM **ogeoms; LWGEOM *ogeom = NULL; GBOX *box = NULL; int type; /* ** This funx is a no-op only if a bbox cache is already present ** in input. */ if ( lwgeom_is_collection(lwgeom) ) { return lwgeom_clone(lwgeom); } type = lwgeom->type; if ( ! MULTITYPE[type] ) return lwgeom_clone(lwgeom); if( lwgeom_is_empty(lwgeom) ) { ogeom = (LWGEOM *)lwcollection_construct_empty( MULTITYPE[type], lwgeom->srid, FLAGS_GET_Z(lwgeom->flags), FLAGS_GET_M(lwgeom->flags) ); } else { ogeoms = lwalloc(sizeof(LWGEOM*)); ogeoms[0] = lwgeom_clone(lwgeom); /* Sub-geometries are not allowed to have bboxes or SRIDs, move the bbox to the collection */ box = ogeoms[0]->bbox; ogeoms[0]->bbox = NULL; ogeoms[0]->srid = SRID_UNKNOWN; ogeom = (LWGEOM *)lwcollection_construct(MULTITYPE[type], lwgeom->srid, box, 1, ogeoms); } return ogeom; }
int lwgeom_is_closed(const LWGEOM *geom) { int type = geom->type; if( lwgeom_is_empty(geom) ) return LW_FALSE; /* Test linear types for closure */ switch (type) { case LINETYPE: return lwline_is_closed((LWLINE*)geom); case POLYGONTYPE: return lwpoly_is_closed((LWPOLY*)geom); case CIRCSTRINGTYPE: return lwcircstring_is_closed((LWCIRCSTRING*)geom); case COMPOUNDTYPE: return lwcompound_is_closed((LWCOMPOUND*)geom); case TINTYPE: return lwtin_is_closed((LWTIN*)geom); case POLYHEDRALSURFACETYPE: return lwpsurface_is_closed((LWPSURFACE*)geom); } /* Recurse into collections and see if anything is not closed */ if ( lwgeom_is_collection(geom) ) { LWCOLLECTION *col = lwgeom_as_lwcollection(geom); int i; int closed; for ( i = 0; i < col->ngeoms; i++ ) { closed = lwgeom_is_closed(col->geoms[i]); if ( ! closed ) return LW_FALSE; } return LW_TRUE; } /* All non-linear non-collection types we will call closed */ return LW_TRUE; }
Datum LWGEOM_numgeometries_collection(PG_FUNCTION_ARGS) { GSERIALIZED *geom = (GSERIALIZED *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0)); LWGEOM *lwgeom; int32 ret = 1; lwgeom = lwgeom_from_gserialized(geom); if ( lwgeom_is_empty(lwgeom) ) { ret = 0; } else if ( lwgeom_is_collection(lwgeom) ) { LWCOLLECTION *col = lwgeom_as_lwcollection(lwgeom); ret = col->ngeoms; } lwgeom_free(lwgeom); PG_FREE_IF_COPY(geom, 0); PG_RETURN_INT32(ret); }
Datum LWGEOM_to_BOX2D(PG_FUNCTION_ARGS) { GSERIALIZED *geom = (GSERIALIZED *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0)); LWGEOM *lwgeom = lwgeom_from_gserialized(geom); GBOX gbox; /* Cannot box empty! */ if ( lwgeom_is_empty(lwgeom) ) PG_RETURN_NULL(); /* Cannot calculate box? */ if ( lwgeom_calculate_gbox(lwgeom, &gbox) == LW_FAILURE ) PG_RETURN_NULL(); /* Strip out higher dimensions */ FLAGS_SET_Z(gbox.flags, 0); FLAGS_SET_M(gbox.flags, 0); PG_RETURN_POINTER(gbox_copy(&gbox)); }
/* ** Given a generic collection, return the "simplest" form. ** ** eg: GEOMETRYCOLLECTION(MULTILINESTRING()) => MULTILINESTRING() ** ** GEOMETRYCOLLECTION(MULTILINESTRING(), MULTILINESTRING(), POINT()) ** => GEOMETRYCOLLECTION(MULTILINESTRING(), POINT()) ** ** In general, if the subcomponents are homogeneous, return a properly ** typed collection. ** Otherwise, return a generic collection, with the subtypes in minimal ** typed collections. */ static void lwcollection_build_buffer(const LWCOLLECTION *col, HomogenizeBuffer *buffer) { int i; if ( ! col ) return; if ( lwgeom_is_empty(lwcollection_as_lwgeom(col)) ) return; for ( i = 0; i < col->ngeoms; i++ ) { LWGEOM *geom = col->geoms[i]; switch(geom->type) { case POINTTYPE: case LINETYPE: case CIRCSTRINGTYPE: case COMPOUNDTYPE: case TRIANGLETYPE: case CURVEPOLYTYPE: case POLYGONTYPE: { /* Init if necessary */ if ( ! buffer->buf[geom->type] ) { LWCOLLECTION *bufcol = lwcollection_construct_empty(COLLECTIONTYPE, col->srid, FLAGS_GET_Z(col->flags), FLAGS_GET_M(col->flags)); bufcol->type = lwtype_get_collectiontype(geom->type); buffer->buf[geom->type] = bufcol; } /* Add sub-geom to buffer */ lwcollection_add_lwgeom(buffer->buf[geom->type], lwgeom_clone(geom)); /* Increment count for this singleton type */ buffer->cnt[geom->type] = buffer->cnt[geom->type] + 1; } default: { lwcollection_build_buffer(lwgeom_as_lwcollection(geom), buffer); } } } return; }
Datum LWGEOM_x_point(PG_FUNCTION_ARGS) { GSERIALIZED *geom; LWGEOM *lwgeom; LWPOINT *point = NULL; POINT2D p; geom = (GSERIALIZED *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0)); if ( gserialized_get_type(geom) != POINTTYPE ) lwerror("Argument to X() must be a point"); lwgeom = lwgeom_from_gserialized(geom); point = lwgeom_as_lwpoint(lwgeom); if ( lwgeom_is_empty(lwgeom) ) PG_RETURN_NULL(); getPoint2d_p(point->point, 0, &p); PG_FREE_IF_COPY(geom, 0); PG_RETURN_FLOAT8(p.x); }
/** * Force the dimensionality of a geometry to match the dimensionality * of a set of flags (usually derived from a ZM WKT tag). */ static int wkt_parser_set_dims(LWGEOM *geom, uint8_t flags) { int hasz = FLAGS_GET_Z(flags); int hasm = FLAGS_GET_M(flags); int i = 0; /* Error on junk */ if( ! geom ) return LW_FAILURE; FLAGS_SET_Z(geom->flags, hasz); FLAGS_SET_M(geom->flags, hasm); if( ! lwgeom_is_empty(geom) ) { if( geom->type == POINTTYPE ) { LWPOINT *pt = (LWPOINT*)geom; FLAGS_SET_Z(pt->point->flags, hasz); FLAGS_SET_M(pt->point->flags, hasm); return LW_SUCCESS; } else if ( (geom->type == TRIANGLETYPE) || (geom->type == CIRCSTRINGTYPE) || (geom->type == LINETYPE) ) { LWLINE *ln = (LWLINE*)geom; FLAGS_SET_Z(ln->points->flags, hasz); FLAGS_SET_M(ln->points->flags, hasm); return LW_SUCCESS; } else if ( geom->type == POLYGONTYPE ) { LWPOLY *poly = (LWPOLY*)geom; for ( i = 0; i < poly->nrings; i++ ) { FLAGS_SET_Z(poly->rings[i]->flags, hasz); FLAGS_SET_M(poly->rings[i]->flags, hasm); } return LW_SUCCESS; } else if ( geom->type == CURVEPOLYTYPE ) { LWCURVEPOLY *poly = (LWCURVEPOLY*)geom; for ( i = 0; i < poly->nrings; i++ ) wkt_parser_set_dims(poly->rings[i], flags); return LW_SUCCESS; } else if ( lwtype_is_collection(geom->type) ) { LWCOLLECTION *col = (LWCOLLECTION*)geom; for ( i = 0; i < col->ngeoms; i++ ) wkt_parser_set_dims(col->geoms[i], flags); return LW_SUCCESS; } else { LWDEBUGF(2,"Unknown geometry type: %d", geom->type); return LW_FAILURE; } } return LW_SUCCESS; }