static LWGEOM* lwgeom_clean(LWGEOM* lwgeom_in) { LWGEOM* lwgeom_out; lwgeom_out = lwgeom_make_valid(lwgeom_in); if ( ! lwgeom_out ) { return NULL; } /* Check dimensionality is the same as input */ if ( lwgeom_dimensionality(lwgeom_in) != lwgeom_dimensionality(lwgeom_out) ) { lwnotice("lwgeom_clean: dimensional collapse (%d to %d)", lwgeom_dimensionality(lwgeom_in), lwgeom_dimensionality(lwgeom_out)); return NULL; } /* Check that the output is not a collection if the input wasn't */ if ( lwgeom_out->type == COLLECTIONTYPE && lwgeom_in->type != COLLECTIONTYPE ) { lwnotice("lwgeom_clean: mixed-type output (%s) " "from single-type input (%s)", lwtype_name(lwgeom_out->type), lwtype_name(lwgeom_in->type)); return NULL; } /* Force right-hand-rule (will only affect polygons) */ /* gout := ST_ForceRHR(gout); */ /* Remove repeated duplicated points ? */ /* gout = ST_RemoveRepeatedPoints(gout); */ return lwgeom_out; }
void lwgeom_affine(LWGEOM *geom, const AFFINE *affine) { int type = geom->type; int i; switch(type) { /* Take advantage of fact tht pt/ln/circ/tri have same memory structure */ case POINTTYPE: case LINETYPE: case CIRCSTRINGTYPE: case TRIANGLETYPE: { LWLINE *l = (LWLINE*)geom; ptarray_affine(l->points, affine); break; } case POLYGONTYPE: { LWPOLY *p = (LWPOLY*)geom; for( i = 0; i < p->nrings; i++ ) ptarray_affine(p->rings[i], affine); break; } case CURVEPOLYTYPE: { LWCURVEPOLY *c = (LWCURVEPOLY*)geom; for( i = 0; i < c->nrings; i++ ) lwgeom_affine(c->rings[i], affine); break; } default: { if( lwgeom_is_collection(geom) ) { LWCOLLECTION *c = (LWCOLLECTION*)geom; for( i = 0; i < c->ngeoms; i++ ) { lwgeom_affine(c->geoms[i], affine); } } else { lwerror("lwgeom_affine: unable to handle type '%s'", lwtype_name(type)); } } } }
Datum postgis_typmod_out(PG_FUNCTION_ARGS) { char *s = (char*)palloc(64); char *str = s; uint32 typmod = PG_GETARG_INT32(0); uint32 srid = TYPMOD_GET_SRID(typmod); uint32 type = TYPMOD_GET_TYPE(typmod); uint32 hasz = TYPMOD_GET_Z(typmod); uint32 hasm = TYPMOD_GET_M(typmod); POSTGIS_DEBUGF(3, "Got typmod(srid = %d, type = %d, hasz = %d, hasm = %d)", srid, type, hasz, hasm); /* No SRID or type or dimensionality? Then no typmod at all. Return empty string. */ if ( ! ( srid || type || hasz || hasm ) ) { *str = '\0'; PG_RETURN_CSTRING(str); } /* Opening bracket. */ str += sprintf(str, "("); /* Has type? */ if ( type ) str += sprintf(str, "%s", lwtype_name(type)); else if ( (!type) && ( srid || hasz || hasm ) ) str += sprintf(str, "Geometry"); /* Has Z? */ if ( hasz ) str += sprintf(str, "%s", "Z"); /* Has M? */ if ( hasm ) str += sprintf(str, "%s", "M"); /* Comma? */ if ( srid ) str += sprintf(str, ","); /* Has SRID? */ if ( srid ) str += sprintf(str, "%d", srid); /* Closing bracket. */ str += sprintf(str, ")"); PG_RETURN_CSTRING(s); }
static LWGEOM* lwpoly_split(const LWPOLY* lwpoly_in, const LWGEOM* blade_in) { switch (blade_in->type) { case LINETYPE: return lwpoly_split_by_line(lwpoly_in, (LWLINE*)blade_in); default: lwerror("Splitting a Polygon by a %s is unsupported", lwtype_name(blade_in->type)); return NULL; } return NULL; }
/** * LINESTRING * Read a WKB linestring, starting just after the endian byte, * type number and optional srid number. Advance the parse state * forward appropriately. * There is only one pointarray in a linestring. Optionally * check for minimal following of rules (two point minimum). */ static LWLINE* lwline_from_wkb_state(wkb_parse_state *s) { POINTARRAY *pa = ptarray_from_wkb_state(s); if( pa == NULL || pa->npoints == 0 ) return lwline_construct_empty(s->srid, s->has_z, s->has_m); if( s->check & LW_PARSER_CHECK_MINPOINTS && pa->npoints < 2 ) { lwerror("%s must have at least two points", lwtype_name(s->lwtype)); return NULL; } return lwline_construct(s->srid, NULL, pa); }
/** Here the geometries are distributed for the new faster distance-calculations */ int lw_dist2d_distribute_fast(LWGEOM *lwg1, LWGEOM *lwg2, DISTPTS *dl) { POINTARRAY *pa1, *pa2; int type1 = lwg1->type; int type2 = lwg2->type; LWDEBUGF(2, "lw_dist2d_distribute_fast is called with typ1=%d, type2=%d", lwg1->type, lwg2->type); switch (type1) { case LINETYPE: pa1 = ((LWLINE *)lwg1)->points; break; case POLYGONTYPE: pa1 = ((LWPOLY *)lwg1)->rings[0]; break; default: lwerror("Unsupported geometry1 type: %s", lwtype_name(type1)); return LW_FALSE; } switch (type2) { case LINETYPE: pa2 = ((LWLINE *)lwg2)->points; break; case POLYGONTYPE: pa2 = ((LWPOLY *)lwg2)->rings[0]; break; default: lwerror("Unsupported geometry2 type: %s", lwtype_name(type1)); return LW_FALSE; } dl->twisted=1; return lw_dist2d_fast_ptarray_ptarray(pa1, pa2, dl, lwg1->bbox, lwg2->bbox); }
/* * @param icompound input compound curve * @param tol tolerance, semantic driven by tolerance_type * @param tolerance_type see LW_LINEARIZE_TOLERANCE_TYPE * @param flags see flags in lwarc_linearize * * @return a newly allocated LWLINE */ static LWLINE * lwcompound_linearize(const LWCOMPOUND *icompound, double tol, LW_LINEARIZE_TOLERANCE_TYPE tolerance_type, int flags) { LWGEOM *geom; POINTARRAY *ptarray = NULL, *ptarray_out = NULL; LWLINE *tmp = NULL; uint32_t i, j; POINT4D p; LWDEBUG(2, "lwcompound_stroke called."); ptarray = ptarray_construct_empty(FLAGS_GET_Z(icompound->flags), FLAGS_GET_M(icompound->flags), 64); for (i = 0; i < icompound->ngeoms; i++) { geom = icompound->geoms[i]; if (geom->type == CIRCSTRINGTYPE) { tmp = lwcircstring_linearize((LWCIRCSTRING *)geom, tol, tolerance_type, flags); for (j = 0; j < tmp->points->npoints; j++) { getPoint4d_p(tmp->points, j, &p); ptarray_append_point(ptarray, &p, LW_TRUE); } lwline_free(tmp); } else if (geom->type == LINETYPE) { tmp = (LWLINE *)geom; for (j = 0; j < tmp->points->npoints; j++) { getPoint4d_p(tmp->points, j, &p); ptarray_append_point(ptarray, &p, LW_TRUE); } } else { lwerror("Unsupported geometry type %d found.", geom->type, lwtype_name(geom->type)); return NULL; } } ptarray_out = ptarray_remove_repeated_points(ptarray, 0.0); ptarray_free(ptarray); return lwline_construct(icompound->srid, NULL, ptarray_out); }
/* * Construct a LWCIRCSTRING from an array of LWPOINTs * LWCIRCSTRING dimensions are large enough to host all input dimensions. */ LWCIRCSTRING * lwcircstring_from_lwpointarray(int srid, uint32_t npoints, LWPOINT **points) { int zmflag=0; uint32_t i; POINTARRAY *pa; uint8_t *newpoints, *ptr; size_t ptsize, size; /* * Find output dimensions, check integrity */ for (i = 0; i < npoints; i++) { if (points[i]->type != POINTTYPE) { lwerror("lwcurve_from_lwpointarray: invalid input type: %s", lwtype_name(points[i]->type)); return NULL; } if (FLAGS_GET_Z(points[i]->flags)) zmflag |= 2; if (FLAGS_GET_M(points[i]->flags)) zmflag |= 1; if (zmflag == 3) break; } if (zmflag == 0) ptsize = 2 * sizeof(double); else if (zmflag == 3) ptsize = 4 * sizeof(double); else ptsize = 3 * sizeof(double); /* * Allocate output points array */ size = ptsize * npoints; newpoints = lwalloc(size); memset(newpoints, 0, size); ptr = newpoints; for (i = 0; i < npoints; i++) { size = ptarray_point_size(points[i]->point); memcpy(ptr, getPoint_internal(points[i]->point, 0), size); ptr += ptsize; } pa = ptarray_construct_reference_data(zmflag&2, zmflag&1, npoints, newpoints); return lwcircstring_construct(srid, NULL, pa); }
/** * 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; }
LWGEOM* lwgeom_from_gserialized(const GSERIALIZED *g) { uint8_t g_flags = 0; int32_t g_srid = 0; uint32_t g_type = 0; uint8_t *data_ptr = NULL; LWGEOM *lwgeom = NULL; GBOX bbox; size_t g_size = 0; assert(g); g_srid = gserialized_get_srid(g); g_flags = g->flags; g_type = gserialized_get_type(g); LWDEBUGF(4, "Got type %d (%s), srid=%d", g_type, lwtype_name(g_type), g_srid); data_ptr = (uint8_t*)g->data; if ( FLAGS_GET_BBOX(g_flags) ) data_ptr += gbox_serialized_size(g_flags); lwgeom = lwgeom_from_gserialized_buffer(data_ptr, g_flags, &g_size); if ( ! lwgeom ) lwerror("lwgeom_from_gserialized: unable create geometry"); /* Ooops! */ lwgeom->type = g_type; lwgeom->flags = g_flags; if ( gserialized_read_gbox_p(g, &bbox) == LW_SUCCESS ) { lwgeom->bbox = gbox_copy(&bbox); } else if ( lwgeom_needs_bbox(lwgeom) && (lwgeom_calculate_gbox(lwgeom, &bbox) == LW_SUCCESS) ) { lwgeom->bbox = gbox_copy(&bbox); } else { lwgeom->bbox = NULL; } lwgeom_set_srid(lwgeom, g_srid); return lwgeom; }
/** * Free the containing LWGEOM and the associated BOX. Leave the underlying * geoms/points/point objects intact. Useful for functions that are stripping * out subcomponents of complex objects, or building up new temporary objects * on top of subcomponents. */ void lwgeom_release(LWGEOM *lwgeom) { if ( ! lwgeom ) lwerror("lwgeom_release: someone called on 0x0"); LWDEBUGF(3, "releasing type %s", lwtype_name(lwgeom->type)); /* Drop bounding box (always a copy) */ if ( lwgeom->bbox ) { LWDEBUGF(3, "lwgeom_release: releasing bbox. %p", lwgeom->bbox); lwfree(lwgeom->bbox); } lwfree(lwgeom); }
/* takes a GEOMETRY and returns an X3D representation */ extern char * lwgeom_to_x3d3(const LWGEOM *geom, char *srs, int precision, int opts, const char *defid) { int type = geom->type; switch (type) { case POINTTYPE: return asx3d3_point((LWPOINT*)geom, srs, precision, opts, defid); case LINETYPE: return asx3d3_line((LWLINE*)geom, srs, precision, opts, defid); case POLYGONTYPE: { /** We might change this later, but putting a polygon in an indexed face set * seems like the simplest way to go so treat just like a mulitpolygon */ LWCOLLECTION *tmp = (LWCOLLECTION*)lwgeom_as_multi(geom); char *ret = asx3d3_multi(tmp, srs, precision, opts, defid); lwcollection_free(tmp); return ret; } case TRIANGLETYPE: return asx3d3_triangle((LWTRIANGLE*)geom, srs, precision, opts, defid); case MULTIPOINTTYPE: case MULTILINETYPE: case MULTIPOLYGONTYPE: return asx3d3_multi((LWCOLLECTION*)geom, srs, precision, opts, defid); case POLYHEDRALSURFACETYPE: return asx3d3_psurface((LWPSURFACE*)geom, srs, precision, opts, defid); case TINTYPE: return asx3d3_tin((LWTIN*)geom, srs, precision, opts, defid); case COLLECTIONTYPE: return asx3d3_collection((LWCOLLECTION*)geom, srs, precision, opts, defid); default: lwerror("lwgeom_to_x3d3: '%s' geometry type not supported", lwtype_name(type)); return NULL; } }
/** * 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; }
static LWGEOM* lwline_split(const LWLINE* lwline_in, const LWGEOM* blade_in) { switch (blade_in->type) { case POINTTYPE: return lwline_split_by_point(lwline_in, (LWPOINT*)blade_in); case LINETYPE: return lwline_split_by_line(lwline_in, (LWLINE*)blade_in); default: lwerror("Splitting a Line by a %s is unsupported", lwtype_name(blade_in->type)); return NULL; } return NULL; }
/** * The geography type only support POINT, LINESTRING, POLYGON, MULTI* variants * of same, and GEOMETRYCOLLECTION. If the input type is not one of those, shut * down the query. */ void geography_valid_type(uint8_t type) { if ( ! ( type == POINTTYPE || type == LINETYPE || type == POLYGONTYPE || type == MULTIPOINTTYPE || type == MULTILINETYPE || type == MULTIPOLYGONTYPE || type == COLLECTIONTYPE ) ) { ereport(ERROR, ( errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("Geography type does not support %s", lwtype_name(type) ))); } }
void lwgeom_longitude_shift(LWGEOM *lwgeom) { int i; switch (lwgeom->type) { LWPOINT *point; LWLINE *line; LWPOLY *poly; LWTRIANGLE *triangle; LWCOLLECTION *coll; case POINTTYPE: point = (LWPOINT *)lwgeom; ptarray_longitude_shift(point->point); return; case LINETYPE: line = (LWLINE *)lwgeom; ptarray_longitude_shift(line->points); return; case POLYGONTYPE: poly = (LWPOLY *)lwgeom; for (i=0; i<poly->nrings; i++) ptarray_longitude_shift(poly->rings[i]); return; case TRIANGLETYPE: triangle = (LWTRIANGLE *)lwgeom; ptarray_longitude_shift(triangle->points); return; case MULTIPOINTTYPE: case MULTILINETYPE: case MULTIPOLYGONTYPE: case POLYHEDRALSURFACETYPE: case TINTYPE: case COLLECTIONTYPE: coll = (LWCOLLECTION *)lwgeom; for (i=0; i<coll->ngeoms; i++) lwgeom_longitude_shift(coll->geoms[i]); return; default: lwerror("lwgeom_longitude_shift: unsupported geom type: %s", lwtype_name(lwgeom->type)); } }
static int lwgeom_to_twkb_buf(const LWGEOM *geom, TWKB_GLOBALS *globals, TWKB_STATE *ts) { LWDEBUGF(2, "Entered %s", __func__); switch ( geom->type ) { case POINTTYPE: { LWDEBUGF(4,"Type found is Point, %d", geom->type); return lwpoint_to_twkb_buf((LWPOINT*) geom, globals, ts); } case LINETYPE: { LWDEBUGF(4,"Type found is Linestring, %d", geom->type); return lwline_to_twkb_buf((LWLINE*) geom, globals, ts); } /* Polygon has 'nrings' and 'rings' elements */ case POLYGONTYPE: { LWDEBUGF(4,"Type found is Polygon, %d", geom->type); return lwpoly_to_twkb_buf((LWPOLY*)geom, globals, ts); } /* All these Collection types have 'ngeoms' and 'geoms' elements */ case MULTIPOINTTYPE: case MULTILINETYPE: case MULTIPOLYGONTYPE: { LWDEBUGF(4,"Type found is Multi, %d", geom->type); return lwmulti_to_twkb_buf((LWCOLLECTION*)geom, globals, ts); } case COLLECTIONTYPE: { LWDEBUGF(4,"Type found is collection, %d", geom->type); return lwcollection_to_twkb_buf((LWCOLLECTION*) geom, globals, ts); } /* Unknown type! */ default: lwerror("Unsupported geometry type: %s [%d]", lwtype_name((geom)->type), (geom)->type); } return 0; }
Datum ST_MakeValid(PG_FUNCTION_ARGS) { #if POSTGIS_GEOS_VERSION < 33 elog(ERROR, "You need GEOS-3.3.0 or up for ST_MakeValid"); 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); switch ( lwgeom_in->type ) { case POINTTYPE: case MULTIPOINTTYPE: case LINETYPE: case POLYGONTYPE: case MULTILINETYPE: case MULTIPOLYGONTYPE: case COLLECTIONTYPE: break; default: lwerror("ST_MakeValid: unsupported geometry type %s", lwtype_name(lwgeom_in->type)); PG_RETURN_NULL(); break; } lwgeom_out = lwgeom_make_valid(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 */ }
void lwgeom_set_geodetic(LWGEOM *geom, int value) { LWPOINT *pt; LWLINE *ln; LWPOLY *ply; LWCOLLECTION *col; int i; FLAGS_SET_GEODETIC(geom->flags, value); if ( geom->bbox ) FLAGS_SET_GEODETIC(geom->bbox->flags, value); switch(geom->type) { case POINTTYPE: pt = (LWPOINT*)geom; if ( pt->point ) FLAGS_SET_GEODETIC(pt->point->flags, value); break; case LINETYPE: ln = (LWLINE*)geom; if ( ln->points ) FLAGS_SET_GEODETIC(ln->points->flags, value); break; case POLYGONTYPE: ply = (LWPOLY*)geom; for ( i = 0; i < ply->nrings; i++ ) FLAGS_SET_GEODETIC(ply->rings[i]->flags, value); break; case MULTIPOINTTYPE: case MULTILINETYPE: case MULTIPOLYGONTYPE: case COLLECTIONTYPE: col = (LWCOLLECTION*)geom; for ( i = 0; i < col->ngeoms; i++ ) lwgeom_set_geodetic(col->geoms[i], value); break; default: lwerror("lwgeom_set_geodetic: unsupported geom type: %s", lwtype_name(geom->type)); return; } }
LWGEOM* lwgeom_simplify(const LWGEOM *igeom, double dist) { switch (igeom->type) { case POINTTYPE: case MULTIPOINTTYPE: return lwgeom_clone(igeom); case LINETYPE: return (LWGEOM*)lwline_simplify((LWLINE*)igeom, dist); case POLYGONTYPE: return (LWGEOM*)lwpoly_simplify((LWPOLY*)igeom, dist); case MULTILINETYPE: case MULTIPOLYGONTYPE: case COLLECTIONTYPE: return (LWGEOM*)lwcollection_simplify((LWCOLLECTION *)igeom, dist); default: lwerror("lwgeom_simplify: unsupported geometry type: %s",lwtype_name(igeom->type)); } return NULL; }
/* * Multi-curves provide type information for their curved sub-geometries * but not their linear sub-geometries. * MULTICURVE((0 0, 1 1), CURVESTRING(0 0, 1 1, 2 2)) */ static void lwmcurve_to_wkt_sb(const LWMCURVE *mcurv, stringbuffer_t *sb, int precision, uint8_t variant) { int i = 0; if ( ! (variant & WKT_NO_TYPE) ) { stringbuffer_append(sb, "MULTICURVE"); /* "MULTICURVE" */ dimension_qualifiers_to_wkt_sb((LWGEOM*)mcurv, sb, variant); } if ( mcurv->ngeoms < 1 ) { empty_to_wkt_sb(sb); return; } stringbuffer_append(sb, "("); variant = variant | WKT_IS_CHILD; /* Inform the sub-geometries they are childre */ for ( i = 0; i < mcurv->ngeoms; i++ ) { int type = mcurv->geoms[i]->type; if ( i > 0 ) stringbuffer_append(sb, ","); switch (type) { case LINETYPE: /* Linestring subgeoms don't get type identifiers */ lwline_to_wkt_sb((LWLINE*)mcurv->geoms[i], sb, precision, variant | WKT_NO_TYPE ); break; case CIRCSTRINGTYPE: /* But circstring subgeoms *do* get type identifiers */ lwcircstring_to_wkt_sb((LWCIRCSTRING*)mcurv->geoms[i], sb, precision, variant ); break; case COMPOUNDTYPE: /* And compoundcurve subgeoms *do* get type identifiers */ lwcompound_to_wkt_sb((LWCOMPOUND*)mcurv->geoms[i], sb, precision, variant ); break; default: lwerror("lwmcurve_to_wkt_sb: Unknown type recieved %d - %s", type, lwtype_name(type)); } } stringbuffer_append(sb, ")"); }
/** * Takes a GEOMETRY and returns a GeoJson representation */ char * lwgeom_to_geojson(const LWGEOM *geom, char *srs, int precision, int has_bbox) { int type = geom->type; GBOX *bbox = NULL; GBOX tmp; if ( precision > OUT_MAX_DOUBLE_PRECISION ) precision = OUT_MAX_DOUBLE_PRECISION; if (has_bbox) { /* Whether these are geography or geometry, the GeoJSON expects a cartesian bounding box */ lwgeom_calculate_gbox_cartesian(geom, &tmp); bbox = &tmp; } switch (type) { case POINTTYPE: return asgeojson_point((LWPOINT*)geom, srs, bbox, precision); case LINETYPE: return asgeojson_line((LWLINE*)geom, srs, bbox, precision); case POLYGONTYPE: return asgeojson_poly((LWPOLY*)geom, srs, bbox, precision); case MULTIPOINTTYPE: return asgeojson_multipoint((LWMPOINT*)geom, srs, bbox, precision); case MULTILINETYPE: return asgeojson_multiline((LWMLINE*)geom, srs, bbox, precision); case MULTIPOLYGONTYPE: return asgeojson_multipolygon((LWMPOLY*)geom, srs, bbox, precision); case COLLECTIONTYPE: return asgeojson_collection((LWCOLLECTION*)geom, srs, bbox, precision); default: lwerror("lwgeom_to_geojson: '%s' geometry type not supported", lwtype_name(type)); } /* Never get here */ return NULL; }
LWGEOM* lwgeom_set_effective_area(const LWGEOM *igeom,int set_area, double trshld) { LWDEBUG(2, "Entered lwgeom_set_effective_area"); switch (igeom->type) { case POINTTYPE: case MULTIPOINTTYPE: return lwgeom_clone(igeom); case LINETYPE: return (LWGEOM*)lwline_set_effective_area((LWLINE*)igeom,set_area, trshld); case POLYGONTYPE: return (LWGEOM*)lwpoly_set_effective_area((LWPOLY*)igeom,set_area, trshld); case MULTILINETYPE: case MULTIPOLYGONTYPE: case COLLECTIONTYPE: return (LWGEOM*)lwcollection_set_effective_area((LWCOLLECTION *)igeom,set_area, trshld); default: lwerror("lwgeom_simplify: unsupported geometry type: %s",lwtype_name(igeom->type)); } return NULL; }
static size_t assvg_geom_buf(const LWGEOM *geom, char *output, int relative, int precision) { int type = geom->type; char *ptr=output; switch (type) { case POINTTYPE: ptr += assvg_point_buf((LWPOINT*)geom, ptr, relative, precision); break; case LINETYPE: ptr += assvg_line_buf((LWLINE*)geom, ptr, relative, precision); break; case POLYGONTYPE: ptr += assvg_polygon_buf((LWPOLY*)geom, ptr, relative, precision); break; case MULTIPOINTTYPE: ptr += assvg_multipoint_buf((LWMPOINT*)geom, ptr, relative, precision); break; case MULTILINETYPE: ptr += assvg_multiline_buf((LWMLINE*)geom, ptr, relative, precision); break; case MULTIPOLYGONTYPE: ptr += assvg_multipolygon_buf((LWMPOLY*)geom, ptr, relative, precision); break; default: lwerror("assvg_geom_buf: '%s' geometry type not supported.", lwtype_name(type)); } return (ptr-output); }
/* * Compound curves provide type information for their curved sub-geometries * but not their linestring sub-geometries. * COMPOUNDCURVE((0 0, 1 1), CURVESTRING(1 1, 2 2, 3 3)) */ static void lwcompound_to_wkt_sb(const LWCOMPOUND *comp, stringbuffer_t *sb, int precision, uint8_t variant) { int i = 0; if ( ! (variant & WKT_NO_TYPE) ) { stringbuffer_append(sb, "COMPOUNDCURVE"); /* "COMPOUNDCURVE" */ dimension_qualifiers_to_wkt_sb((LWGEOM*)comp, sb, variant); } if ( comp->ngeoms < 1 ) { empty_to_wkt_sb(sb); return; } stringbuffer_append(sb, "("); variant = variant | WKT_IS_CHILD; /* Inform the sub-geometries they are childre */ for ( i = 0; i < comp->ngeoms; i++ ) { int type = comp->geoms[i]->type; if ( i > 0 ) stringbuffer_append(sb, ","); /* Linestring subgeoms don't get type identifiers */ if ( type == LINETYPE ) { lwline_to_wkt_sb((LWLINE*)comp->geoms[i], sb, precision, variant | WKT_NO_TYPE ); } /* But circstring subgeoms *do* get type identifiers */ else if ( type == CIRCSTRINGTYPE ) { lwcircstring_to_wkt_sb((LWCIRCSTRING*)comp->geoms[i], sb, precision, variant ); } else { lwerror("lwcompound_to_wkt_sb: Unknown type recieved %d - %s", type, lwtype_name(type)); } } stringbuffer_append(sb, ")"); }
static size_t assvg_geom_size(const LWGEOM *geom, int relative, int precision) { int type = geom->type; size_t size = 0; switch (type) { case POINTTYPE: size = assvg_point_size((LWPOINT*)geom, relative, precision); break; case LINETYPE: size = assvg_line_size((LWLINE*)geom, relative, precision); break; case POLYGONTYPE: size = assvg_polygon_size((LWPOLY*)geom, relative, precision); break; case MULTIPOINTTYPE: size = assvg_multipoint_size((LWMPOINT*)geom, relative, precision); break; case MULTILINETYPE: size = assvg_multiline_size((LWMLINE*)geom, relative, precision); break; case MULTIPOLYGONTYPE: size = assvg_multipolygon_size((LWMPOLY*)geom, relative, precision); break; default: lwerror("assvg_geom_size: '%s' geometry type not supported.", lwtype_name(type)); } return size; }
Datum geometry_geometrytype(PG_FUNCTION_ARGS) { GSERIALIZED *lwgeom; text *type_text; char *type_str = palloc(32); lwgeom = (GSERIALIZED*)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, lwtype_name(gserialized_get_type(lwgeom)), 32); /* Build a text type to store things in */ type_text = cstring2text(type_str); pfree(type_str); PG_FREE_IF_COPY(lwgeom, 0); PG_RETURN_TEXT_P(type_text); }
/* exported */ LWGEOM* lwgeom_split(const LWGEOM* lwgeom_in, const LWGEOM* blade_in) { switch (lwgeom_in->type) { case LINETYPE: return lwline_split((const LWLINE*)lwgeom_in, blade_in); case POLYGONTYPE: return lwpoly_split((const LWPOLY*)lwgeom_in, blade_in); case MULTIPOLYGONTYPE: case MULTILINETYPE: case COLLECTIONTYPE: return lwcollection_split((const LWCOLLECTION*)lwgeom_in, blade_in); default: lwerror("Splitting of %s geometries is unsupported", lwtype_name(lwgeom_in->type)); return NULL; } }
Datum geometry_geometrytype(PG_FUNCTION_ARGS) { GSERIALIZED *gser; text *type_text; static int type_str_len = 32; char type_str[type_str_len]; /* Read just the header from the toasted tuple */ gser = PG_GETARG_GSERIALIZED_P_SLICE(0, 0, gserialized_max_header_size()); /* Make it empty string to start */ type_str[0] = 0; /* Build up the output string */ strncat(type_str, "ST_", type_str_len); strncat(type_str, lwtype_name(gserialized_get_type(gser)), type_str_len - 3); /* Build a text type to store things in */ type_text = cstring2text(type_str); PG_FREE_IF_COPY(gser, 0); PG_RETURN_TEXT_P(type_text); }
/* * Multi-surfaces provide type information for their curved sub-geometries * but not their linear sub-geometries. * MULTISURFACE(((0 0, 1 1, 1 0, 0 0)), CURVEPOLYGON(CURVESTRING(0 0, 1 1, 2 2, 0 1, 0 0))) */ static void lwmsurface_to_wkt_sb(const LWMSURFACE *msurf, stringbuffer_t *sb, int precision, uint8_t variant) { int i = 0; if ( ! (variant & WKT_NO_TYPE) ) { stringbuffer_append(sb, "MULTISURFACE"); /* "MULTISURFACE" */ dimension_qualifiers_to_wkt_sb((LWGEOM*)msurf, sb, variant); } if ( msurf->ngeoms < 1 ) { empty_to_wkt_sb(sb); return; } stringbuffer_append(sb, "("); variant = variant | WKT_IS_CHILD; /* Inform the sub-geometries they are childre */ for ( i = 0; i < msurf->ngeoms; i++ ) { int type = msurf->geoms[i]->type; if ( i > 0 ) stringbuffer_append(sb, ","); switch (type) { case POLYGONTYPE: /* Linestring subgeoms don't get type identifiers */ lwpoly_to_wkt_sb((LWPOLY*)msurf->geoms[i], sb, precision, variant | WKT_NO_TYPE ); break; case CURVEPOLYTYPE: /* But circstring subgeoms *do* get type identifiers */ lwcurvepoly_to_wkt_sb((LWCURVEPOLY*)msurf->geoms[i], sb, precision, variant); break; default: lwerror("lwmsurface_to_wkt_sb: Unknown type recieved %d - %s", type, lwtype_name(type)); } } stringbuffer_append(sb, ")"); }