PostGIS  3.7.0dev-r@@SVN_REVISION@@

◆ ST_GeometricMedian()

Datum ST_GeometricMedian ( PG_FUNCTION_ARGS  )

Definition at line 785 of file lwgeom_functions_analytic.c.

786 {
787  GSERIALIZED* geom;
789  LWGEOM* input;
790  LWPOINT* lwresult;
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;
795  int max_iter;
796 
797  /* Read and validate our input arguments */
798  if (PG_ARGISNULL(0))
799  PG_RETURN_NULL();
800 
801  compute_tolerance_from_box = PG_ARGISNULL(1);
802 
803  if (!compute_tolerance_from_box)
804  {
805  tolerance = PG_GETARG_FLOAT8(1);
806  if (tolerance < 0)
807  {
808  lwpgerror("Tolerance must be positive.");
809  PG_RETURN_NULL();
810  }
811  }
812 
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);
815 
816  if (max_iter < 0)
817  {
818  lwpgerror("Maximum iterations must be positive.");
819  PG_RETURN_NULL();
820  }
821 
822  /* OK, inputs are valid. */
823  geom = PG_GETARG_GSERIALIZED_P(0);
824  input = lwgeom_from_gserialized(geom);
825 
826  if (compute_tolerance_from_box)
827  {
828  /* Compute a default tolerance based on the smallest dimension
829  * of the geometry's bounding box.
830  */
831  static const double tolerance_coefficient = 1e-6;
832  const GBOX* box = lwgeom_get_bbox(input);
833 
834  if (box)
835  {
836  double min_dim = FP_MIN(box->xmax - box->xmin, box->ymax - box->ymin);
837  if (lwgeom_has_z(input))
838  min_dim = FP_MIN(min_dim, box->zmax - box->zmin);
839 
840  /* Apply a lower bound to the computed default tolerance to
841  * avoid a tolerance of zero in the case of collinear
842  * points.
843  */
844  tolerance = FP_MAX(min_default_tolerance, tolerance_coefficient * min_dim);
845  }
846  }
847 
848  lwresult = lwgeom_median(input, tolerance, max_iter, fail_if_not_converged);
849  lwgeom_free(input);
850 
851  if(!lwresult)
852  {
853  lwpgerror("Error computing geometric median.");
854  PG_RETURN_NULL();
855  }
856 
857  result = geometry_serialize(lwpoint_as_lwgeom(lwresult));
858 
859  PG_RETURN_POINTER(result);
860 }
char result[OUT_DOUBLE_BUFFER_SIZE]
Definition: cu_print.c:267
LWGEOM * lwgeom_from_gserialized(const GSERIALIZED *g)
Allocate a new LWGEOM from a GSERIALIZED.
Definition: gserialized.c:268
#define LW_FALSE
Definition: liblwgeom.h:94
void lwgeom_free(LWGEOM *geom)
Definition: lwgeom.c:1218
int lwgeom_has_z(const LWGEOM *geom)
Return LW_TRUE if geometry has Z ordinates.
Definition: lwgeom.c:934
LWGEOM * lwpoint_as_lwgeom(const LWPOINT *obj)
Definition: lwgeom.c:344
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:743
LWPOINT * lwgeom_median(const LWGEOM *g, double tol, uint32_t maxiter, char fail_if_not_converged)
#define FP_MAX(A, B)
#define FP_MIN(A, B)
double ymax
Definition: liblwgeom.h:357
double zmax
Definition: liblwgeom.h:359
double xmax
Definition: liblwgeom.h:355
double zmin
Definition: liblwgeom.h:358
double ymin
Definition: liblwgeom.h:356
double xmin
Definition: liblwgeom.h:354

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

Here is the call graph for this function: