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 */ }
Datum LWGEOM_simplify2d(PG_FUNCTION_ARGS) { GSERIALIZED *geom = PG_GETARG_GSERIALIZED_P(0); double dist = PG_GETARG_FLOAT8(1); GSERIALIZED *result; int type = gserialized_get_type(geom); LWGEOM *in, *out; bool preserve_collapsed = false; /* Handle optional argument to preserve collapsed features */ if ( PG_NARGS() > 2 && ! PG_ARGISNULL(2) ) preserve_collapsed = true; /* Can't simplify points! */ if ( type == POINTTYPE || type == MULTIPOINTTYPE ) PG_RETURN_POINTER(geom); in = lwgeom_from_gserialized(geom); out = lwgeom_simplify(in, dist, preserve_collapsed); if ( ! out ) PG_RETURN_NULL(); /* COMPUTE_BBOX TAINTING */ if ( in->bbox ) lwgeom_add_bbox(out); result = geometry_serialize(out); lwgeom_free(out); PG_FREE_IF_COPY(geom, 0); PG_RETURN_POINTER(result); }
Datum LWGEOM_SetEffectiveArea(PG_FUNCTION_ARGS) { GSERIALIZED *geom = PG_GETARG_GSERIALIZED_P(0); GSERIALIZED *result; int type = gserialized_get_type(geom); LWGEOM *in; LWGEOM *out; double area=0; int set_area=0; if ( type == POINTTYPE || type == MULTIPOINTTYPE ) PG_RETURN_POINTER(geom); if ( (PG_NARGS()>1) && (!PG_ARGISNULL(1)) ) area = PG_GETARG_FLOAT8(1); if ( (PG_NARGS()>2) && (!PG_ARGISNULL(2)) ) set_area = PG_GETARG_INT32(2); in = lwgeom_from_gserialized(geom); out = lwgeom_set_effective_area(in,set_area, area); if ( ! out ) PG_RETURN_NULL(); /* COMPUTE_BBOX TAINTING */ if ( in->bbox ) lwgeom_add_bbox(out); result = geometry_serialize(out); lwgeom_free(out); PG_FREE_IF_COPY(geom, 0); PG_RETURN_POINTER(result); }
Datum ST_LocateBetween(PG_FUNCTION_ARGS) { GSERIALIZED *geom_in = PG_GETARG_GSERIALIZED_P(0); double from = PG_GETARG_FLOAT8(1); double to = PG_GETARG_FLOAT8(2); double offset = PG_GETARG_FLOAT8(3); LWCOLLECTION *geom_out = NULL; LWGEOM *line_in = NULL; static char ordinate = 'M'; /* M */ if ( ! gserialized_has_m(geom_in) ) { elog(ERROR,"This function only accepts geometries that have an M dimension."); PG_RETURN_NULL(); } /* This should be a call to ST_LocateAlong! */ if ( to == from ) { PG_RETURN_DATUM(DirectFunctionCall3(ST_LocateAlong, PG_GETARG_DATUM(0), PG_GETARG_DATUM(1), PG_GETARG_DATUM(3))); } line_in = lwgeom_from_gserialized(geom_in); geom_out = lwgeom_clip_to_ordinate_range(line_in, ordinate, from, to, offset); lwgeom_free(line_in); PG_FREE_IF_COPY(geom_in, 0); if ( ! geom_out ) { elog(ERROR,"lwline_clip_to_ordinate_range returned null"); PG_RETURN_NULL(); } PG_RETURN_POINTER(geometry_serialize((LWGEOM*)geom_out)); }
Datum LWGEOM_curve_segmentize(PG_FUNCTION_ARGS) { GSERIALIZED *geom = PG_GETARG_GSERIALIZED_P(0); int32 perQuad = PG_GETARG_INT32(1); GSERIALIZED *ret; LWGEOM *igeom = NULL, *ogeom = NULL; POSTGIS_DEBUG(2, "LWGEOM_curve_segmentize called."); if (perQuad < 0) { elog(ERROR, "2nd argument must be positive."); PG_RETURN_NULL(); } POSTGIS_DEBUGF(3, "perQuad = %d", perQuad); igeom = lwgeom_from_gserialized(geom); ogeom = lwgeom_stroke(igeom, perQuad); lwgeom_free(igeom); if (ogeom == NULL) PG_RETURN_NULL(); ret = geometry_serialize(ogeom); lwgeom_free(ogeom); PG_FREE_IF_COPY(geom, 0); PG_RETURN_POINTER(ret); }
Datum ST_LocateBetweenElevations(PG_FUNCTION_ARGS) { GSERIALIZED *geom_in = PG_GETARG_GSERIALIZED_P(0); double from = PG_GETARG_FLOAT8(1); double to = PG_GETARG_FLOAT8(2); LWCOLLECTION *geom_out = NULL; LWGEOM *line_in = NULL; static char ordinate = 'Z'; /* Z */ static double offset = 0.0; if ( ! gserialized_has_z(geom_in) ) { elog(ERROR,"This function only accepts LINESTRING or MULTILINESTRING with Z dimensions."); PG_RETURN_NULL(); } line_in = lwgeom_from_gserialized(geom_in); geom_out = lwgeom_clip_to_ordinate_range(line_in, ordinate, from, to, offset); lwgeom_free(line_in); PG_FREE_IF_COPY(geom_in, 0); if ( ! geom_out ) { elog(ERROR,"lwline_clip_to_ordinate_range returned null"); PG_RETURN_NULL(); } PG_RETURN_POINTER(geometry_serialize((LWGEOM*)geom_out)); }
Datum LWGEOM_from_text(PG_FUNCTION_ARGS) { text *wkttext = PG_GETARG_TEXT_P(0); char *wkt = text2cstring(wkttext); LWGEOM_PARSER_RESULT lwg_parser_result; GSERIALIZED *geom_result = NULL; LWGEOM *lwgeom; POSTGIS_DEBUG(2, "LWGEOM_from_text"); POSTGIS_DEBUGF(3, "wkt: [%s]", wkt); if (lwgeom_parse_wkt(&lwg_parser_result, wkt, LW_PARSER_CHECK_ALL) == LW_FAILURE) PG_PARSER_ERROR(lwg_parser_result); lwgeom = lwg_parser_result.geom; if ( lwgeom->srid != SRID_UNKNOWN ) { elog(WARNING, "OGC WKT expected, EWKT provided - use GeomFromEWKT() for this"); } /* read user-requested SRID if any */ if ( PG_NARGS() > 1 ) lwgeom_set_srid(lwgeom, PG_GETARG_INT32(1)); geom_result = geometry_serialize(lwgeom); lwgeom_parser_result_free(&lwg_parser_result); PG_RETURN_POINTER(geom_result); }
Datum LWGEOM_recv(PG_FUNCTION_ARGS) { StringInfo buf = (StringInfo) PG_GETARG_POINTER(0); int32 geom_typmod = -1; GSERIALIZED *geom; LWGEOM *lwgeom; if ( (PG_NARGS()>2) && (!PG_ARGISNULL(2)) ) { geom_typmod = PG_GETARG_INT32(2); } lwgeom = lwgeom_from_wkb((uint8_t*)buf->data, buf->len, LW_PARSER_CHECK_ALL); if ( lwgeom_needs_bbox(lwgeom) ) lwgeom_add_bbox(lwgeom); /* Set cursor to the end of buffer (so the backend is happy) */ buf->cursor = buf->len; geom = geometry_serialize(lwgeom); lwgeom_free(lwgeom); if ( geom_typmod >= 0 ) { postgis_valid_typmod(geom, geom_typmod); POSTGIS_DEBUG(3, "typmod and geometry were consistent"); } else { POSTGIS_DEBUG(3, "typmod was -1"); } PG_RETURN_POINTER(geom); }
Datum LWGEOM_pointn_linestring(PG_FUNCTION_ARGS) { GSERIALIZED *geom = (GSERIALIZED*)PG_DETOAST_DATUM(PG_GETARG_DATUM(0)); int where = PG_GETARG_INT32(1); LWGEOM *lwgeom = lwgeom_from_gserialized(geom); LWPOINT *lwpoint = NULL; int type = lwgeom->type; /* Can't handle crazy index! */ if ( where < 1 ) PG_RETURN_NULL(); if ( type == LINETYPE || type == CIRCSTRINGTYPE ) { /* OGC index starts at one, so we substract first. */ lwpoint = lwline_get_lwpoint((LWLINE*)lwgeom, where - 1); } lwgeom_free(lwgeom); PG_FREE_IF_COPY(geom, 0); if ( ! lwpoint ) PG_RETURN_NULL(); PG_RETURN_POINTER(geometry_serialize(lwpoint_as_lwgeom(lwpoint))); }
Datum point_from_geohash(PG_FUNCTION_ARGS) { GBOX *box = NULL; LWPOINT *point = NULL; GSERIALIZED *result = NULL; text *geohash_input = NULL; char *geohash = NULL; double lon, lat; int precision = -1; if (PG_ARGISNULL(0)) { PG_RETURN_NULL(); } if (!PG_ARGISNULL(1)) { precision = PG_GETARG_INT32(1); } geohash_input = PG_GETARG_TEXT_P(0); geohash = text2cstring(geohash_input); box = parse_geohash(geohash, precision); lon = box->xmin + (box->xmax - box->xmin) / 2; lat = box->ymin + (box->ymax - box->ymin) / 2; point = lwpoint_make2d(SRID_UNKNOWN, lon, lat); result = geometry_serialize((LWGEOM *) point); lwfree(box); PG_RETURN_POINTER(result); }
Datum LWGEOM_from_WKB(PG_FUNCTION_ARGS) { bytea *bytea_wkb = (bytea*)PG_GETARG_BYTEA_P(0); int32 srid = 0; GSERIALIZED *geom; LWGEOM *lwgeom; uint8_t *wkb = (uint8_t*)VARDATA(bytea_wkb); lwgeom = lwgeom_from_wkb(wkb, VARSIZE(bytea_wkb)-VARHDRSZ, LW_PARSER_CHECK_ALL); if ( lwgeom_needs_bbox(lwgeom) ) lwgeom_add_bbox(lwgeom); geom = geometry_serialize(lwgeom); lwgeom_free(lwgeom); PG_FREE_IF_COPY(bytea_wkb, 0); if ( gserialized_get_srid(geom) != SRID_UNKNOWN ) { elog(WARNING, "OGC WKB expected, EWKB provided - use GeometryFromEWKB() for this"); } if ( PG_NARGS() > 1 ) { srid = PG_GETARG_INT32(1); if ( srid != gserialized_get_srid(geom) ) gserialized_set_srid(geom, srid); } PG_RETURN_POINTER(geom); }
Datum ST_AddMeasure(PG_FUNCTION_ARGS) { GSERIALIZED *gin = PG_GETARG_GSERIALIZED_P(0); GSERIALIZED *gout; double start_measure = PG_GETARG_FLOAT8(1); double end_measure = PG_GETARG_FLOAT8(2); LWGEOM *lwin, *lwout; int type = gserialized_get_type(gin); /* Raise an error if input is not a linestring or multilinestring */ if ( type != LINETYPE && type != MULTILINETYPE ) { lwpgerror("Only LINESTRING and MULTILINESTRING are supported"); PG_RETURN_NULL(); } lwin = lwgeom_from_gserialized(gin); if ( type == LINETYPE ) lwout = (LWGEOM*)lwline_measured_from_lwline((LWLINE*)lwin, start_measure, end_measure); else lwout = (LWGEOM*)lwmline_measured_from_lwmline((LWMLINE*)lwin, start_measure, end_measure); lwgeom_free(lwin); if ( lwout == NULL ) PG_RETURN_NULL(); gout = geometry_serialize(lwout); lwgeom_free(lwout); PG_RETURN_POINTER(gout); }
Datum LWGEOM_endpoint_linestring(PG_FUNCTION_ARGS) { GSERIALIZED *geom = PG_GETARG_GSERIALIZED_P(0); LWGEOM *lwgeom = lwgeom_from_gserialized(geom); LWPOINT *lwpoint = NULL; int type = lwgeom->type; if ( type == LINETYPE || type == CIRCSTRINGTYPE ) { LWLINE *line = (LWLINE*)lwgeom; if ( line->points ) lwpoint = lwline_get_lwpoint((LWLINE*)lwgeom, line->points->npoints - 1); } else if ( type == COMPOUNDTYPE ) { lwpoint = lwcompound_get_endpoint((LWCOMPOUND*)lwgeom); } lwgeom_free(lwgeom); PG_FREE_IF_COPY(geom, 0); if ( ! lwpoint ) PG_RETURN_NULL(); PG_RETURN_POINTER(geometry_serialize(lwpoint_as_lwgeom(lwpoint))); }
Datum line_from_encoded_polyline(PG_FUNCTION_ARGS) { GSERIALIZED *geom; LWGEOM *lwgeom; text *encodedpolyline_input; char *encodedpolyline; int precision = 5; if (PG_ARGISNULL(0)) PG_RETURN_NULL(); encodedpolyline_input = PG_GETARG_TEXT_P(0); encodedpolyline = text2cstring(encodedpolyline_input); if (PG_NARGS() >2 && !PG_ARGISNULL(2)) { precision = PG_GETARG_INT32(2); if ( precision < 0 ) precision = 5; } lwgeom = lwgeom_from_encoded_polyline(encodedpolyline, precision); if ( ! lwgeom ) { /* Shouldn't get here */ elog(ERROR, "lwgeom_from_encoded_polyline returned NULL"); PG_RETURN_NULL(); } lwgeom_set_srid(lwgeom, 4326); geom = geometry_serialize(lwgeom); lwgeom_free(lwgeom); PG_RETURN_POINTER(geom); }
Datum LWGEOM_simplify2d(PG_FUNCTION_ARGS) { GSERIALIZED *geom = PG_GETARG_GSERIALIZED_P(0); GSERIALIZED *result; int type = gserialized_get_type(geom); LWGEOM *in; LWGEOM *out; double dist; if ( type == POINTTYPE || type == MULTIPOINTTYPE ) PG_RETURN_POINTER(geom); dist = PG_GETARG_FLOAT8(1); in = lwgeom_from_gserialized(geom); out = lwgeom_simplify(in, dist); if ( ! out ) PG_RETURN_NULL(); /* COMPUTE_BBOX TAINTING */ if ( in->bbox ) lwgeom_add_bbox(out); result = geometry_serialize(out); lwgeom_free(out); PG_FREE_IF_COPY(geom, 0); PG_RETURN_POINTER(result); }
Datum LWGEOM_locate_between_m(PG_FUNCTION_ARGS) { GSERIALIZED *gin = PG_GETARG_GSERIALIZED_P(0); GSERIALIZED *gout; double start_measure = PG_GETARG_FLOAT8(1); double end_measure = PG_GETARG_FLOAT8(2); LWGEOM *lwin, *lwout; int hasz = gserialized_has_z(gin); int hasm = gserialized_has_m(gin); int type; elog(WARNING,"ST_Locate_Between_Measures and ST_Locate_Along_Measure were deprecated in 2.2.0. Please use ST_LocateAlong and ST_LocateBetween"); if ( end_measure < start_measure ) { lwpgerror("locate_between_m: 2nd arg must be bigger then 1st arg"); PG_RETURN_NULL(); } /* * Return error if input doesn't have a measure */ if ( ! hasm ) { lwpgerror("Geometry argument does not have an 'M' ordinate"); PG_RETURN_NULL(); } /* * Raise an error if input is a polygon, a multipolygon * or a collection */ type = gserialized_get_type(gin); if ( type == POLYGONTYPE || type == MULTIPOLYGONTYPE || type == COLLECTIONTYPE ) { lwpgerror("Areal or Collection types are not supported"); PG_RETURN_NULL(); } lwin = lwgeom_from_gserialized(gin); lwout = lwgeom_locate_between_m(lwin, start_measure, end_measure); lwgeom_free(lwin); if ( lwout == NULL ) { lwout = (LWGEOM *)lwcollection_construct_empty(COLLECTIONTYPE, gserialized_get_srid(gin), hasz, hasm); } gout = geometry_serialize(lwout); lwgeom_free(lwout); PG_RETURN_POINTER(gout); }
Datum transform(PG_FUNCTION_ARGS) { GSERIALIZED *geom; GSERIALIZED *result=NULL; LWGEOM *lwgeom; projPJ input_pj, output_pj; int32 output_srid, input_srid; output_srid = PG_GETARG_INT32(1); if (output_srid == SRID_UNKNOWN) { elog(ERROR,"%d is an invalid target SRID",SRID_UNKNOWN); PG_RETURN_NULL(); } geom = (GSERIALIZED *)PG_DETOAST_DATUM_COPY(PG_GETARG_DATUM(0)); input_srid = gserialized_get_srid(geom); if ( input_srid == SRID_UNKNOWN ) { PG_FREE_IF_COPY(geom, 0); elog(ERROR,"Input geometry has unknown (%d) SRID",SRID_UNKNOWN); PG_RETURN_NULL(); } /* * If input SRID and output SRID are equal, return geometry * without transform it */ if ( input_srid == output_srid ) PG_RETURN_POINTER(PG_GETARG_DATUM(0)); if ( GetProjectionsUsingFCInfo(fcinfo, input_srid, output_srid, &input_pj, &output_pj) == LW_FAILURE ) { PG_FREE_IF_COPY(geom, 0); elog(ERROR,"Failure reading projections from spatial_ref_sys."); PG_RETURN_NULL(); } /* now we have a geometry, and input/output PJ structs. */ lwgeom = lwgeom_from_gserialized(geom); lwgeom_transform(lwgeom, input_pj, output_pj); lwgeom->srid = output_srid; /* Re-compute bbox if input had one (COMPUTE_BBOX TAINTING) */ if ( lwgeom->bbox ) { lwgeom_drop_bbox(lwgeom); lwgeom_add_bbox(lwgeom); } result = geometry_serialize(lwgeom); lwgeom_free(lwgeom); PG_FREE_IF_COPY(geom, 0); PG_RETURN_POINTER(result); /* new geometry */ }
Datum LWGEOM_set_srid(PG_FUNCTION_ARGS) { GSERIALIZED *result; GSERIALIZED *geom = (GSERIALIZED *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0)); int srid = PG_GETARG_INT32(1); LWGEOM *lwgeom = lwgeom_from_gserialized(geom); lwgeom_set_srid(lwgeom, srid); result = geometry_serialize(lwgeom); lwgeom_free(lwgeom); PG_FREE_IF_COPY(geom, 0); PG_RETURN_POINTER(result); }
Datum LWGEOM_snaptogrid(PG_FUNCTION_ARGS) { Datum datum; GSERIALIZED *in_geom; LWGEOM *in_lwgeom; GSERIALIZED *out_geom = NULL; LWGEOM *out_lwgeom; gridspec grid; /* BOX3D box3d; */ if ( PG_ARGISNULL(0) ) PG_RETURN_NULL(); datum = PG_GETARG_DATUM(0); in_geom = (GSERIALIZED *)PG_DETOAST_DATUM(datum); if ( PG_ARGISNULL(1) ) PG_RETURN_NULL(); grid.ipx = PG_GETARG_FLOAT8(1); if ( PG_ARGISNULL(2) ) PG_RETURN_NULL(); grid.ipy = PG_GETARG_FLOAT8(2); if ( PG_ARGISNULL(3) ) PG_RETURN_NULL(); grid.xsize = PG_GETARG_FLOAT8(3); if ( PG_ARGISNULL(4) ) PG_RETURN_NULL(); grid.ysize = PG_GETARG_FLOAT8(4); /* Do not support gridding Z and M values for now */ grid.ipz=grid.ipm=grid.zsize=grid.msize=0; /* Return input geometry if grid is null */ if ( grid_isNull(&grid) ) { PG_RETURN_POINTER(in_geom); } in_lwgeom = lwgeom_from_gserialized(in_geom); POSTGIS_DEBUGF(3, "SnapToGrid got a %s", lwtype_name(in_lwgeom->type)); out_lwgeom = lwgeom_grid(in_lwgeom, &grid); if ( out_lwgeom == NULL ) PG_RETURN_NULL(); /* COMPUTE_BBOX TAINTING */ if ( in_lwgeom->bbox ) lwgeom_add_bbox(out_lwgeom); POSTGIS_DEBUGF(3, "SnapToGrid made a %s", lwtype_name(out_lwgeom->type)); out_geom = geometry_serialize(out_lwgeom); PG_RETURN_POINTER(out_geom); }
Datum LWGEOM_addBBOX(PG_FUNCTION_ARGS) { GSERIALIZED *geom = (GSERIALIZED *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0)); GSERIALIZED *result; LWGEOM *lwgeom; lwgeom = lwgeom_from_gserialized(geom); lwgeom_add_bbox(lwgeom); result = geometry_serialize(lwgeom); PG_FREE_IF_COPY(geom, 0); PG_RETURN_POINTER(result); }
/* Conversion from SFCGAL::Geometry to GSERIALIZED */ GSERIALIZED* SFCGALGeometry2POSTGIS(const sfcgal_geometry_t* geom, int force3D, int SRID) { GSERIALIZED *result; LWGEOM* lwgeom = SFCGAL2LWGEOM(geom, force3D, SRID); if (lwgeom_needs_bbox(lwgeom) == LW_TRUE) lwgeom_add_bbox(lwgeom); result = geometry_serialize(lwgeom); lwgeom_free(lwgeom); return result; }
Datum LWGEOM_snaptogrid(PG_FUNCTION_ARGS) { LWGEOM *in_lwgeom; GSERIALIZED *out_geom = NULL; LWGEOM *out_lwgeom; gridspec grid; GSERIALIZED *in_geom = PG_GETARG_GSERIALIZED_P(0); /* Set grid values to zero to start */ memset(&grid, 0, sizeof(gridspec)); grid.ipx = PG_GETARG_FLOAT8(1); grid.ipy = PG_GETARG_FLOAT8(2); grid.xsize = PG_GETARG_FLOAT8(3); grid.ysize = PG_GETARG_FLOAT8(4); /* Return input geometry if input geometry is empty */ if ( gserialized_is_empty(in_geom) ) { PG_RETURN_POINTER(in_geom); } /* Return input geometry if input grid is meaningless */ if ( grid.xsize==0 && grid.ysize==0 && grid.zsize==0 && grid.msize==0 ) { PG_RETURN_POINTER(in_geom); } in_lwgeom = lwgeom_from_gserialized(in_geom); POSTGIS_DEBUGF(3, "SnapToGrid got a %s", lwtype_name(in_lwgeom->type)); out_lwgeom = lwgeom_grid(in_lwgeom, &grid); if ( out_lwgeom == NULL ) PG_RETURN_NULL(); /* COMPUTE_BBOX TAINTING */ if ( in_lwgeom->bbox ) lwgeom_add_bbox(out_lwgeom); POSTGIS_DEBUGF(3, "SnapToGrid made a %s", lwtype_name(out_lwgeom->type)); out_geom = geometry_serialize(out_lwgeom); PG_RETURN_POINTER(out_geom); }
Datum sfcgal_make_solid(PG_FUNCTION_ARGS) { GSERIALIZED *output; GSERIALIZED *input = PG_GETARG_GSERIALIZED_P(0); LWGEOM *lwgeom = lwgeom_from_gserialized(input); PG_FREE_IF_COPY(input, 0); if (! lwgeom) { lwerror("sfcgal_make_solid: Unable to deserialize input"); } FLAGS_SET_SOLID( lwgeom->flags, 1); output = geometry_serialize( lwgeom ); lwgeom_free(lwgeom); PG_RETURN_POINTER(output); }
Datum LWGEOM_geometryn_collection(PG_FUNCTION_ARGS) { GSERIALIZED *geom = (GSERIALIZED *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0)); GSERIALIZED *result; int type = gserialized_get_type(geom); int32 idx; LWCOLLECTION *coll; LWGEOM *subgeom; POSTGIS_DEBUG(2, "LWGEOM_geometryn_collection called."); /* elog(NOTICE, "GeometryN called"); */ idx = PG_GETARG_INT32(1); idx -= 1; /* index is 1-based */ /* call is valid on multi* geoms only */ if (type==POINTTYPE || type==LINETYPE || type==CIRCSTRINGTYPE || type==COMPOUNDTYPE || type==POLYGONTYPE || type==CURVEPOLYTYPE || type==TRIANGLETYPE) { if ( idx == 0 ) PG_RETURN_POINTER(geom); PG_RETURN_NULL(); } coll = lwgeom_as_lwcollection(lwgeom_from_gserialized(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 = geometry_serialize(subgeom); lwcollection_free(coll); PG_FREE_IF_COPY(geom, 0); PG_RETURN_POINTER(result); }
Datum LWGEOM_simplify2d(PG_FUNCTION_ARGS) { GSERIALIZED *geom = (GSERIALIZED *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0)); GSERIALIZED *result; LWGEOM *in = lwgeom_from_gserialized(geom); LWGEOM *out; double dist = PG_GETARG_FLOAT8(1); out = lwgeom_simplify(in, dist); if ( ! out ) PG_RETURN_NULL(); /* COMPUTE_BBOX TAINTING */ if ( in->bbox ) lwgeom_add_bbox(out); result = geometry_serialize(out); lwgeom_free(out); PG_FREE_IF_COPY(geom, 0); PG_RETURN_POINTER(result); }
Datum ST_LocateBetweenElevations(PG_FUNCTION_ARGS) { GSERIALIZED *geom_in = (GSERIALIZED *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0)); double from = PG_GETARG_FLOAT8(1); double to = PG_GETARG_FLOAT8(2); LWCOLLECTION *geom_out = NULL; LWGEOM *line_in = NULL; char geomtype = gserialized_get_type(geom_in); static int ordinate = 2; /* Z */ if ( ! ( geomtype == LINETYPE || geomtype == MULTILINETYPE ) ) { elog(ERROR,"This function only accepts LINESTRING or MULTILINESTRING as arguments."); PG_RETURN_NULL(); } line_in = lwgeom_from_gserialized(geom_in); if ( ! FLAGS_GET_Z(line_in->flags) ) { elog(ERROR,"This function only accepts LINESTRING or MULTILINESTRING with Z values as arguments."); PG_RETURN_NULL(); } if ( geomtype == LINETYPE ) { geom_out = lwline_clip_to_ordinate_range((LWLINE*)line_in, ordinate, from, to); } else if ( geomtype == MULTILINETYPE ) { geom_out = lwmline_clip_to_ordinate_range((LWMLINE*)line_in, ordinate, from, to); } lwgeom_free(line_in); if ( ! geom_out ) { elog(ERROR,"The lwline_clip_to_ordinate_range returned null."); PG_RETURN_NULL(); } PG_FREE_IF_COPY(geom_in, 0); PG_RETURN_POINTER(geometry_serialize((LWGEOM*)geom_out)); }
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 */ }
Datum LWGEOM_startpoint_linestring(PG_FUNCTION_ARGS) { GSERIALIZED *geom = (GSERIALIZED*)PG_DETOAST_DATUM(PG_GETARG_DATUM(0)); LWGEOM *lwgeom = lwgeom_from_gserialized(geom); LWPOINT *lwpoint = NULL; int type = lwgeom->type; if ( type == LINETYPE || type == CIRCSTRINGTYPE ) { lwpoint = lwline_get_lwpoint((LWLINE*)lwgeom, 0); } lwgeom_free(lwgeom); PG_FREE_IF_COPY(geom, 0); if ( ! lwpoint ) PG_RETURN_NULL(); PG_RETURN_POINTER(geometry_serialize(lwpoint_as_lwgeom(lwpoint))); }
Datum ST_LocateAlong(PG_FUNCTION_ARGS) { GSERIALIZED *gin = PG_GETARG_GSERIALIZED_P(0); GSERIALIZED *gout; LWGEOM *lwin = NULL, *lwout = NULL; double measure = PG_GETARG_FLOAT8(1); double offset = PG_GETARG_FLOAT8(2);; lwin = lwgeom_from_gserialized(gin); lwout = lwgeom_locate_along(lwin, measure, offset); lwgeom_free(lwin); PG_FREE_IF_COPY(gin, 0); if ( ! lwout ) PG_RETURN_NULL(); gout = geometry_serialize(lwout); lwgeom_free(lwout); PG_RETURN_POINTER(gout); }
Datum geom_from_geojson(PG_FUNCTION_ARGS) { #ifndef HAVE_LIBJSON elog(ERROR, "You need JSON-C for ST_GeomFromGeoJSON"); PG_RETURN_NULL(); #else /* HAVE_LIBJSON */ GSERIALIZED *geom; LWGEOM *lwgeom; text *geojson_input; char *geojson; char *srs = NULL; /* Get the geojson stream */ if (PG_ARGISNULL(0)) PG_RETURN_NULL(); geojson_input = PG_GETARG_TEXT_P(0); geojson = text2cstring(geojson_input); lwgeom = lwgeom_from_geojson(geojson, &srs); if ( ! lwgeom ) { /* Shouldn't get here */ elog(ERROR, "lwgeom_from_geojson returned NULL"); PG_RETURN_NULL(); } if ( srs ) { lwgeom_set_srid(lwgeom, getSRIDbySRS(srs)); lwfree(srs); } geom = geometry_serialize(lwgeom); lwgeom_free(lwgeom); PG_RETURN_POINTER(geom); #endif }