PostGIS 3.0.6dev-r@@SVN_REVISION@@
Loading...
Searching...
No Matches

◆ ST_GeometricMedian()

Datum ST_GeometricMedian ( PG_FUNCTION_ARGS  )

Definition at line 1241 of file lwgeom_functions_analytic.c.

1242{
1243 GSERIALIZED* geom;
1244 GSERIALIZED* result;
1245 LWGEOM* input;
1246 LWPOINT* lwresult;
1247 static const double min_default_tolerance = 1e-8;
1248 double tolerance = min_default_tolerance;
1249 bool compute_tolerance_from_box;
1250 bool fail_if_not_converged;
1251 int max_iter;
1252
1253 /* Read and validate our input arguments */
1254 if (PG_ARGISNULL(0))
1255 PG_RETURN_NULL();
1256
1257 compute_tolerance_from_box = PG_ARGISNULL(1);
1258
1259 if (!compute_tolerance_from_box)
1260 {
1261 tolerance = PG_GETARG_FLOAT8(1);
1262 if (tolerance < 0)
1263 {
1264 lwpgerror("Tolerance must be positive.");
1265 PG_RETURN_NULL();
1266 }
1267 }
1268
1269 max_iter = PG_ARGISNULL(2) ? -1 : PG_GETARG_INT32(2);
1270 fail_if_not_converged = PG_ARGISNULL(3) ? LW_FALSE : PG_GETARG_BOOL(3);
1271
1272 if (max_iter < 0)
1273 {
1274 lwpgerror("Maximum iterations must be positive.");
1275 PG_RETURN_NULL();
1276 }
1277
1278 /* OK, inputs are valid. */
1279 geom = PG_GETARG_GSERIALIZED_P(0);
1280 input = lwgeom_from_gserialized(geom);
1281
1282 if (compute_tolerance_from_box)
1283 {
1284 /* Compute a default tolerance based on the smallest dimension
1285 * of the geometry's bounding box.
1286 */
1287 static const double tolerance_coefficient = 1e-6;
1288 const GBOX* box = lwgeom_get_bbox(input);
1289
1290 if (box)
1291 {
1292 double min_dim = FP_MIN(box->xmax - box->xmin, box->ymax - box->ymin);
1293 if (lwgeom_has_z(input))
1294 min_dim = FP_MIN(min_dim, box->zmax - box->zmin);
1295
1296 /* Apply a lower bound to the computed default tolerance to
1297 * avoid a tolerance of zero in the case of collinear
1298 * points.
1299 */
1300 tolerance = FP_MAX(min_default_tolerance, tolerance_coefficient * min_dim);
1301 }
1302 }
1303
1304 lwresult = lwgeom_median(input, tolerance, max_iter, fail_if_not_converged);
1305 lwgeom_free(input);
1306
1307 if(!lwresult)
1308 {
1309 lwpgerror("Error computing geometric median.");
1310 PG_RETURN_NULL();
1311 }
1312
1313 result = geometry_serialize(lwpoint_as_lwgeom(lwresult));
1314
1315 PG_RETURN_POINTER(result);
1316}
LWGEOM * lwgeom_from_gserialized(const GSERIALIZED *g)
Allocate a new LWGEOM from a GSERIALIZED.
LWGEOM * lwpoint_as_lwgeom(const LWPOINT *obj)
Definition lwgeom.c:326
#define LW_FALSE
Definition liblwgeom.h:108
void lwgeom_free(LWGEOM *geom)
Definition lwgeom.c:1138
int lwgeom_has_z(const LWGEOM *geom)
Return LW_TRUE if geometry has Z ordinates.
Definition lwgeom.c:916
LWPOINT * lwgeom_median(const LWGEOM *g, double tol, uint32_t maxiter, char fail_if_not_converged)
const GBOX * lwgeom_get_bbox(const LWGEOM *lwgeom)
Get a non-empty geometry bounding box, computing and caching it if not already there.
Definition lwgeom.c:725
#define FP_MAX(A, B)
#define FP_MIN(A, B)
GSERIALIZED * geometry_serialize(LWGEOM *lwgeom)
double ymax
Definition liblwgeom.h:343
double zmax
Definition liblwgeom.h:345
double xmax
Definition liblwgeom.h:341
double zmin
Definition liblwgeom.h:344
double ymin
Definition liblwgeom.h:342
double xmin
Definition liblwgeom.h:340

References FP_MAX, FP_MIN, geometry_serialize(), LW_FALSE, lwgeom_free(), lwgeom_from_gserialized(), lwgeom_get_bbox(), lwgeom_has_z(), lwgeom_median(), lwpoint_as_lwgeom(), GBOX::xmax, GBOX::xmin, GBOX::ymax, GBOX::ymin, GBOX::zmax, and GBOX::zmin.

Here is the call graph for this function: