31 #include "lwgeom_pg.h"
35 #include "access/htup_details.h"
60 GSERIALIZED *geom = PG_GETARG_GSERIALIZED_P_COPY(0);
61 double dist = PG_GETARG_FLOAT8(1);
65 bool preserve_collapsed =
false;
70 PG_RETURN_POINTER(geom);
73 if ((PG_NARGS() > 2) && (!PG_ARGISNULL(2)))
74 preserve_collapsed = PG_GETARG_BOOL(2);
80 PG_RETURN_POINTER(geom);
85 result = geometry_serialize(in);
101 PG_RETURN_POINTER(geom);
103 if ( (PG_NARGS()>1) && (!PG_ARGISNULL(1)) )
104 area = PG_GETARG_FLOAT8(1);
106 if ( (PG_NARGS()>2) && (!PG_ARGISNULL(2)) )
107 set_area = PG_GETARG_INT32(2);
112 if ( ! out ) PG_RETURN_NULL();
117 result = geometry_serialize(out);
119 PG_FREE_IF_COPY(geom, 0);
120 PG_RETURN_POINTER(
result);
131 int preserve_endpoints=1;
135 PG_RETURN_POINTER(geom);
137 if ( (PG_NARGS()>1) && (!PG_ARGISNULL(1)) )
138 n_iterations = PG_GETARG_INT32(1);
140 if (n_iterations< 1 || n_iterations>5)
141 elog(ERROR,
"Number of iterations must be between 1 and 5 : %s", __func__);
143 if ( (PG_NARGS()>2) && (!PG_ARGISNULL(2)) )
145 if(PG_GETARG_BOOL(2))
146 preserve_endpoints = 1;
148 preserve_endpoints = 0;
154 if ( ! out ) PG_RETURN_NULL();
159 result = geometry_serialize(out);
161 PG_FREE_IF_COPY(geom, 0);
162 PG_RETURN_POINTER(
result);
180 double distance_fraction = PG_GETARG_FLOAT8(1);
181 int repeat = PG_NARGS() > 2 && PG_GETARG_BOOL(2);
187 if ( distance_fraction < 0 || distance_fraction > 1 )
189 elog(ERROR,
"line_interpolate_point: 2nd arg isn't within [0,1]");
190 PG_FREE_IF_COPY(gser, 0);
196 elog(ERROR,
"line_interpolate_point: 1st arg isn't a line");
197 PG_FREE_IF_COPY(gser, 0);
205 PG_FREE_IF_COPY(gser, 0);
214 result = geometry_serialize(lwresult);
217 PG_RETURN_POINTER(
result);
232 double distance = PG_GETARG_FLOAT8(1);
237 if (distance < 0 || distance > 1)
239 elog(ERROR,
"line_interpolate_point: 2nd arg isn't within [0,1]");
245 elog(ERROR,
"line_interpolate_point: 1st arg isn't a line");
255 PG_FREE_IF_COPY(gser, 0);
260 PG_RETURN_POINTER(
result);
320 #define CHECK_RING_IS_CLOSE
321 #define SAMEPOINT(a,b) ((a)->x==(b)->x&&(a)->y==(b)->y)
344 grid.
ipx = PG_GETARG_FLOAT8(1);
345 grid.
ipy = PG_GETARG_FLOAT8(2);
346 grid.
xsize = PG_GETARG_FLOAT8(3);
347 grid.
ysize = PG_GETARG_FLOAT8(4);
352 PG_RETURN_POINTER(in_geom);
358 PG_RETURN_POINTER(in_geom);
363 POSTGIS_DEBUGF(3,
"SnapToGrid got a %s",
lwtype_name(in_lwgeom->
type));
366 if ( out_lwgeom == NULL ) PG_RETURN_NULL();
369 if ( in_lwgeom->
bbox )
372 POSTGIS_DEBUGF(3,
"SnapToGrid made a %s",
lwtype_name(out_lwgeom->
type));
374 out_geom = geometry_serialize(out_lwgeom);
376 PG_RETURN_POINTER(out_geom);
380 #if POSTGIS_DEBUG_LEVEL >= 4
385 lwpgnotice(
"GRID(%g %g %g %g, %g %g %g %g)",
404 in_geom = PG_GETARG_GSERIALIZED_P(0);
409 PG_RETURN_POINTER(in_geom);
412 in_point = PG_GETARG_GSERIALIZED_P(1);
414 if ( in_lwpoint == NULL )
416 lwpgerror(
"Offset geometry must be a point");
419 grid.
xsize = PG_GETARG_FLOAT8(2);
420 grid.
ysize = PG_GETARG_FLOAT8(3);
421 grid.
zsize = PG_GETARG_FLOAT8(4);
422 grid.
msize = PG_GETARG_FLOAT8(5);
426 grid.
ipx = offsetpoint.
x;
427 grid.
ipy = offsetpoint.
y;
431 #if POSTGIS_DEBUG_LEVEL >= 4
438 PG_RETURN_POINTER(in_geom);
443 POSTGIS_DEBUGF(3,
"SnapToGrid got a %s",
lwtype_name(in_lwgeom->
type));
446 if ( out_lwgeom == NULL ) PG_RETURN_NULL();
454 POSTGIS_DEBUGF(3,
"SnapToGrid made a %s",
lwtype_name(out_lwgeom->
type));
456 out_geom = geometry_serialize(out_lwgeom);
458 PG_RETURN_POINTER(out_geom);
471 int type1, type2, rv;
484 elog(ERROR,
"This function only accepts LINESTRING as arguments.");
493 PG_FREE_IF_COPY(geom1, 0);
494 PG_FREE_IF_COPY(geom2, 1);
512 double from = PG_GETARG_FLOAT8(1);
513 double to = PG_GETARG_FLOAT8(2);
519 if ( from < 0 || from > 1 )
521 elog(ERROR,
"line_interpolate_point: 2nd arg isn't within [0,1]");
525 if ( to < 0 || to > 1 )
527 elog(ERROR,
"line_interpolate_point: 3rd arg isn't within [0,1]");
533 elog(ERROR,
"2nd arg must be smaller then 3rd arg");
545 PG_FREE_IF_COPY(geom, 0);
562 uint32_t i = 0, g = 0;
565 double length = 0.0, sublength = 0.0, minprop = 0.0, maxprop = 0.0;
573 PG_FREE_IF_COPY(geom, 0);
578 for ( i = 0; i < iline->
ngeoms; i++ )
588 for ( i = 0; i < iline->
ngeoms; i++ )
591 double subfrom = 0.0, subto = 0.0;
598 maxprop = sublength / length;
602 if ( from > maxprop || to < minprop )
605 if ( from <= minprop )
610 if ( from > minprop && from <= maxprop )
611 subfrom = (from - minprop) / (maxprop - minprop);
613 if ( to < maxprop && to >= minprop )
614 subto = (to - minprop) / (maxprop - minprop);
643 elog(ERROR,
"line_substring: 1st arg isn't a line");
647 ret = geometry_serialize(olwgeom);
649 PG_FREE_IF_COPY(geom, 0);
650 PG_RETURN_POINTER(ret);
669 TupleDesc resultTupleDesc;
670 HeapTuple resultTuple;
672 Datum result_values[2];
673 bool result_is_null[2];
679 geom = PG_GETARG_GSERIALIZED_P(0);
691 if (!(mbc && mbc->
center))
693 lwpgerror(
"Error calculating minimum bounding circle.");
705 center = geometry_serialize(lwcenter);
708 get_call_result_type(fcinfo, NULL, &resultTupleDesc);
709 BlessTupleDesc(resultTupleDesc);
711 result_values[0] = PointerGetDatum(center);
712 result_is_null[0] =
false;
713 result_values[1] = Float8GetDatum(radius);
714 result_is_null[1] =
false;
716 resultTuple = heap_form_tuple(resultTupleDesc, result_values, result_is_null);
718 result = HeapTupleGetDatum(resultTuple);
737 int segs_per_quarter;
742 geom = PG_GETARG_GSERIALIZED_P(0);
743 segs_per_quarter = PG_GETARG_INT32(1);
755 if (!(mbc && mbc->
center))
757 lwpgerror(
"Error calculating minimum bounding circle.");
772 center = geometry_serialize(lwcircle);
775 PG_RETURN_POINTER(center);
791 static const double min_default_tolerance = 1e-8;
792 double tolerance = min_default_tolerance;
793 bool compute_tolerance_from_box;
794 bool fail_if_not_converged;
801 compute_tolerance_from_box = PG_ARGISNULL(1);
803 if (!compute_tolerance_from_box)
805 tolerance = PG_GETARG_FLOAT8(1);
808 lwpgerror(
"Tolerance must be positive.");
813 max_iter = PG_ARGISNULL(2) ? -1 : PG_GETARG_INT32(2);
814 fail_if_not_converged = PG_ARGISNULL(3) ?
LW_FALSE : PG_GETARG_BOOL(3);
818 lwpgerror(
"Maximum iterations must be positive.");
823 geom = PG_GETARG_GSERIALIZED_P(0);
826 if (compute_tolerance_from_box)
831 static const double tolerance_coefficient = 1e-6;
844 tolerance =
FP_MAX(min_default_tolerance, tolerance_coefficient * min_dim);
848 lwresult =
lwgeom_median(input, tolerance, max_iter, fail_if_not_converged);
853 lwpgerror(
"Error computing geometric median.");
859 PG_RETURN_POINTER(
result);
878 geom = PG_GETARG_GSERIALIZED_P(0);
884 PG_FREE_IF_COPY(geom, 0);
905 geom = PG_GETARG_GSERIALIZED_P_COPY(0);
910 PG_FREE_IF_COPY(geom, 0);
912 PG_RETURN_BOOL(is_ccw);
char result[OUT_DOUBLE_BUFFER_SIZE]
LWGEOM * lwgeom_set_effective_area(const LWGEOM *igeom, int set_area, double trshld)
void gserialized_error_if_srid_mismatch(const GSERIALIZED *g1, const GSERIALIZED *g2, const char *funcname)
int32_t gserialized_get_srid(const GSERIALIZED *g)
Extract the SRID from the serialized form (it is packed into three bytes so this is a handy function)...
LWGEOM * lwgeom_from_gserialized(const GSERIALIZED *g)
Allocate a new LWGEOM from a GSERIALIZED.
int gserialized_is_empty(const GSERIALIZED *g)
Check if a GSERIALIZED is empty without deserializing first.
uint32_t gserialized_get_type(const GSERIALIZED *g)
Extract the geometry type from the serialized form (it hides in the anonymous data area,...
LWPOINT * lwpoint_construct_empty(int32_t srid, char hasz, char hasm)
LWPOLY * lwpoly_construct_circle(int32_t srid, double x, double y, double radius, uint32_t segments_per_quarter, char exterior)
void lwgeom_refresh_bbox(LWGEOM *lwgeom)
Drop current bbox and calculate a fresh one.
LWLINE * lwgeom_as_lwline(const LWGEOM *lwgeom)
LWPOINT * lwline_interpolate_point_3d(const LWLINE *line, double distance)
Interpolate one point along a line in 3D.
LWGEOM * lwgeom_grid(const LWGEOM *lwgeom, gridspec *grid)
LWGEOM * lwline_as_lwgeom(const LWLINE *obj)
int lwgeom_simplify_in_place(LWGEOM *igeom, double dist, int preserve_collapsed)
LWPOINT * lwpoint_make2d(int32_t srid, double x, double y)
void lwpoint_free(LWPOINT *pt)
POINTARRAY * ptarray_substring(POINTARRAY *pa, double d1, double d2, double tolerance)
@d1 start location (distance from start / total distance) @d2 end location (distance from start / tot...
void lwgeom_free(LWGEOM *geom)
LWGEOM * lwmpoint_as_lwgeom(const LWMPOINT *obj)
LWGEOM * lwpoly_as_lwgeom(const LWPOLY *obj)
void lwline_release(LWLINE *lwline)
int lwline_crossing_direction(const LWLINE *l1, const LWLINE *l2)
Given two lines, characterize how (and if) they cross each other.
double ptarray_length_2d(const POINTARRAY *pts)
Find the 2d length of the given POINTARRAY (even if it's 3d)
int lwgeom_has_z(const LWGEOM *geom)
Return LW_TRUE if geometry has Z ordinates.
#define POINTTYPE
LWTYPE numbers, used internally by PostGIS.
LWLINE * lwline_construct(int32_t srid, GBOX *bbox, POINTARRAY *points)
void lwmline_release(LWMLINE *lwline)
LWBOUNDINGCIRCLE * lwgeom_calculate_mbc(const LWGEOM *g)
LWMLINE * lwgeom_as_lwmline(const LWGEOM *lwgeom)
POINTARRAY * lwline_interpolate_points(const LWLINE *line, double length_fraction, char repeat)
Interpolate one or more points along a line.
LWGEOM * lwgeom_chaikin(const LWGEOM *igeom, int n_iterations, int preserve_endpoint)
LWGEOM * lwpoint_as_lwgeom(const LWPOINT *obj)
LWPOINT * lwpoint_construct(int32_t srid, GBOX *bbox, POINTARRAY *point)
void lwboundingcircle_destroy(LWBOUNDINGCIRCLE *c)
const char * lwtype_name(uint8_t type)
Return the type name string associated with a type number (e.g.
int getPoint4d_p(const POINTARRAY *pa, uint32_t n, POINT4D *point)
const GBOX * lwgeom_get_bbox(const LWGEOM *lwgeom)
Get a non-empty geometry bounding box, computing and caching it if not already there.
void * lwalloc(size_t size)
LWCOLLECTION * lwcollection_construct(uint8_t type, int32_t srid, GBOX *bbox, uint32_t ngeoms, LWGEOM **geoms)
LWPOINT * lwgeom_median(const LWGEOM *g, double tol, uint32_t maxiter, char fail_if_not_converged)
#define LW_TRUE
Return types for functions with status returns.
#define SRID_UNKNOWN
Unknown SRID value.
int lwgeom_has_m(const LWGEOM *geom)
Return LW_TRUE if geometry has M ordinates.
int lwgeom_is_clockwise(LWGEOM *lwgeom)
Ensure the outer ring is clockwise oriented and all inner rings are counter-clockwise.
LWMPOINT * lwmpoint_construct(int32_t srid, const POINTARRAY *pa)
void lwgeom_add_bbox(LWGEOM *lwgeom)
Compute a bbox if not already computed.
void lwgeom_reverse_in_place(LWGEOM *lwgeom)
Reverse vertex order of LWGEOM.
This library is the generic geometry handling section of PostGIS.
Datum LWGEOM_simplify2d(PG_FUNCTION_ARGS)
Datum ST_MinimumBoundingCircle(PG_FUNCTION_ARGS)
Datum LWGEOM_ChaikinSmoothing(PG_FUNCTION_ARGS)
Datum ST_GeometricMedian(PG_FUNCTION_ARGS)
PG_FUNCTION_INFO_V1(LWGEOM_simplify2d)
Datum LWGEOM_snaptogrid(PG_FUNCTION_ARGS)
Datum ST_IsPolygonCW(PG_FUNCTION_ARGS)
Datum LWGEOM_snaptogrid_pointoff(PG_FUNCTION_ARGS)
Datum ST_IsPolygonCCW(PG_FUNCTION_ARGS)
Datum ST_MinimumBoundingRadius(PG_FUNCTION_ARGS)
Datum ST_LineCrossingDirection(PG_FUNCTION_ARGS)
Datum LWGEOM_line_interpolate_point(PG_FUNCTION_ARGS)
Datum ST_3DLineInterpolatePoint(PG_FUNCTION_ARGS)
Datum LWGEOM_line_substring(PG_FUNCTION_ARGS)
Datum LWGEOM_SetEffectiveArea(PG_FUNCTION_ARGS)
static int lwgeom_is_empty(const LWGEOM *geom)
Return true or false depending on whether a geometry is an "empty" geometry (no vertices members)
static LWPOINT * lwgeom_as_lwpoint(const LWGEOM *lwgeom)
static double distance(double x1, double y1, double x2, double y2)
static int is_clockwise(int num_points, double *x, double *y, double *z)