PostGIS  3.4.0dev-r@@SVN_REVISION@@

◆ ST_LargestEmptyCircle()

Datum ST_LargestEmptyCircle ( PG_FUNCTION_ARGS  )

Definition at line 461 of file postgis/lwgeom_geos.c.

462 {
463 #if POSTGIS_GEOS_VERSION < 30900
464 
465  lwpgerror("The GEOS version this PostGIS binary "
466  "was compiled against (%d) doesn't support "
467  "'GEOSMaximumInscribedCircle' function (3.9.0+ required)",
469  PG_RETURN_NULL();
470 
471 #else /* POSTGIS_GEOS_VERSION >= 30900 */
472  GSERIALIZED* geom;
474  GSERIALIZED* center;
475  GSERIALIZED* nearest;
476  TupleDesc resultTupleDesc;
477  HeapTuple resultTuple;
478  Datum result;
479  Datum result_values[3];
480  bool result_is_null[3];
481  double radius = 0.0, tolerance = 0.0;
482  int32 srid = SRID_UNKNOWN;
483  bool is3d = false, hasBoundary = false;
484 
485  if (PG_ARGISNULL(0))
486  PG_RETURN_NULL();
487 
488  geom = PG_GETARG_GSERIALIZED_P(0);
489  tolerance = PG_GETARG_FLOAT8(1);
490  boundary = PG_GETARG_GSERIALIZED_P(2);
491  srid = gserialized_get_srid(geom);
492  is3d = gserialized_has_z(geom);
493 
495  hasBoundary = true;
496 
497  /* Empty geometry? Return POINT EMPTY with zero radius */
498  if (gserialized_is_empty(geom))
499  {
502  center = geometry_serialize(lwcenter);
503  nearest = geometry_serialize(lwnearest);
504  radius = 0.0;
505  }
506  else
507  {
508  GEOSGeometry *ginput, *gcircle, *gcenter, *gnearest;
509  GEOSGeometry *gboundary = NULL;
510  double width, height, size;
511  GBOX gbox;
512  LWGEOM *lwg;
513  lwg = lwgeom_from_gserialized(geom);
514  if (!lwgeom_isfinite(lwg))
515  {
516  lwpgerror("Geometry contains invalid coordinates");
517  PG_RETURN_NULL();
518  }
519  lwgeom_free(lwg);
520 
521 
522  if (!gserialized_get_gbox_p(geom, &gbox))
523  PG_RETURN_NULL();
524 
525  if (tolerance <= 0)
526  {
527  width = gbox.xmax - gbox.xmin;
528  height = gbox.ymax - gbox.ymin;
529  size = width > height ? width : height;
530  tolerance = size / 1000.0;
531  }
532 
533  initGEOS(lwpgnotice, lwgeom_geos_error);
534 
535  ginput = POSTGIS2GEOS(geom);
536  if (!ginput)
537  HANDLE_GEOS_ERROR("Geometry could not be converted to GEOS");
538 
539  if (hasBoundary)
540  {
541  gboundary = POSTGIS2GEOS(boundary);
542  if (!gboundary)
543  HANDLE_GEOS_ERROR("Boundary could not be converted to GEOS");
544  }
545 
546  gcircle = GEOSLargestEmptyCircle(ginput, gboundary, tolerance);
547  if (!gcircle)
548  {
549  lwpgerror("Error calculating GEOSLargestEmptyCircle.");
550  GEOSGeom_destroy(ginput);
551  PG_RETURN_NULL();
552  }
553 
554  gcenter = GEOSGeomGetStartPoint(gcircle);
555  gnearest = GEOSGeomGetEndPoint(gcircle);
556  GEOSDistance(gcenter, gnearest, &radius);
557  GEOSSetSRID(gcenter, srid);
558  GEOSSetSRID(gnearest, srid);
559 
560  center = GEOS2POSTGIS(gcenter, is3d);
561  nearest = GEOS2POSTGIS(gnearest, is3d);
562  GEOSGeom_destroy(gcenter);
563  GEOSGeom_destroy(gnearest);
564  GEOSGeom_destroy(gcircle);
565  GEOSGeom_destroy(ginput);
566  if (gboundary) GEOSGeom_destroy(gboundary);
567  }
568 
569  get_call_result_type(fcinfo, NULL, &resultTupleDesc);
570  BlessTupleDesc(resultTupleDesc);
571 
572  result_values[0] = PointerGetDatum(center);
573  result_is_null[0] = false;
574  result_values[1] = PointerGetDatum(nearest);
575  result_is_null[1] = false;
576  result_values[2] = Float8GetDatum(radius);
577  result_is_null[2] = false;
578  resultTuple = heap_form_tuple(resultTupleDesc, result_values, result_is_null);
579 
580  result = HeapTupleGetDatum(resultTuple);
581 
582  PG_RETURN_DATUM(result);
583 
584 #endif /* POSTGIS_GEOS_VERSION >= 30900 */
585 }
char result[OUT_DOUBLE_BUFFER_SIZE]
Definition: cu_print.c:262
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)...
Definition: gserialized.c:126
int gserialized_get_gbox_p(const GSERIALIZED *g, GBOX *gbox)
Read the box from the GSERIALIZED or calculate it if necessary.
Definition: gserialized.c:65
LWGEOM * lwgeom_from_gserialized(const GSERIALIZED *g)
Allocate a new LWGEOM from a GSERIALIZED.
Definition: gserialized.c:239
int gserialized_is_empty(const GSERIALIZED *g)
Check if a GSERIALIZED is empty without deserializing first.
Definition: gserialized.c:152
int gserialized_has_z(const GSERIALIZED *g)
Check if a GSERIALIZED has a Z ordinate.
Definition: gserialized.c:174
void lwgeom_geos_error(const char *fmt,...)
LWPOINT * lwpoint_construct_empty(int32_t srid, char hasz, char hasm)
Definition: lwpoint.c:151
#define LW_FALSE
Definition: liblwgeom.h:94
void lwgeom_free(LWGEOM *geom)
Definition: lwgeom.c:1155
int lwgeom_isfinite(const LWGEOM *lwgeom)
Check if a LWGEOM has any non-finite (NaN or Inf) coordinates.
Definition: lwgeom.c:2681
#define SRID_UNKNOWN
Unknown SRID value.
Definition: liblwgeom.h:215
GSERIALIZED * GEOS2POSTGIS(GEOSGeom geom, char want3d)
Datum boundary(PG_FUNCTION_ARGS)
GEOSGeometry * POSTGIS2GEOS(const GSERIALIZED *pglwgeom)
#define HANDLE_GEOS_ERROR(label)
unsigned int int32
Definition: shpopen.c:54
#define POSTGIS_GEOS_VERSION
Definition: sqldefines.h:11
double ymax
Definition: liblwgeom.h:357
double xmax
Definition: liblwgeom.h:355
double ymin
Definition: liblwgeom.h:356
double xmin
Definition: liblwgeom.h:354

References boundary(), GEOS2POSTGIS(), gserialized_get_gbox_p(), gserialized_get_srid(), gserialized_has_z(), gserialized_is_empty(), HANDLE_GEOS_ERROR, LW_FALSE, lwgeom_free(), lwgeom_from_gserialized(), lwgeom_geos_error(), lwgeom_isfinite(), lwpoint_construct_empty(), POSTGIS2GEOS(), POSTGIS_GEOS_VERSION, result, SRID_UNKNOWN, GBOX::xmax, GBOX::xmin, GBOX::ymax, and GBOX::ymin.

Here is the call graph for this function: