PostGIS  3.7.0dev-r@@SVN_REVISION@@

◆ ST_LargestEmptyCircle()

Datum ST_LargestEmptyCircle ( PG_FUNCTION_ARGS  )

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

392 {
393 #if POSTGIS_GEOS_VERSION < 30900
394 
395  lwpgerror("The GEOS version this PostGIS binary "
396  "was compiled against (%d) doesn't support "
397  "'GEOSMaximumInscribedCircle' function (3.9.0+ required)",
399  PG_RETURN_NULL();
400 
401 #else /* POSTGIS_GEOS_VERSION >= 30900 */
402  GSERIALIZED* geom;
404  GSERIALIZED* center;
405  GSERIALIZED* nearest;
406  TupleDesc resultTupleDesc;
407  HeapTuple resultTuple;
408  Datum result;
409  Datum result_values[3];
410  bool result_is_null[3];
411  double radius = 0.0, tolerance = 0.0;
412  int32 srid = SRID_UNKNOWN;
413  bool is3d = false, hasBoundary = false;
414 
415  if (PG_ARGISNULL(0))
416  PG_RETURN_NULL();
417 
418  geom = PG_GETARG_GSERIALIZED_P(0);
419  tolerance = PG_GETARG_FLOAT8(1);
420  boundary = PG_GETARG_GSERIALIZED_P(2);
421  srid = gserialized_get_srid(geom);
422  is3d = gserialized_has_z(geom);
423 
425  hasBoundary = true;
426 
427  /* Empty geometry? Return POINT EMPTY with zero radius */
428  if (gserialized_is_empty(geom))
429  {
432  center = geometry_serialize(lwcenter);
433  nearest = geometry_serialize(lwnearest);
434  radius = 0.0;
435  }
436  else
437  {
438  GEOSGeometry *ginput, *gcircle, *gcenter, *gnearest;
439  GEOSGeometry *gboundary = NULL;
440  double width, height, size;
441  GBOX gbox;
442  LWGEOM *lwg;
443  lwg = lwgeom_from_gserialized(geom);
444  if (!lwgeom_isfinite(lwg))
445  {
446  lwpgerror("Geometry contains invalid coordinates");
447  PG_RETURN_NULL();
448  }
449  lwgeom_free(lwg);
450 
451 
452  if (!gserialized_get_gbox_p(geom, &gbox))
453  PG_RETURN_NULL();
454 
455  if (tolerance <= 0)
456  {
457  width = gbox.xmax - gbox.xmin;
458  height = gbox.ymax - gbox.ymin;
459  size = width > height ? width : height;
460  tolerance = size / 1000.0;
461  }
462 
463  initGEOS(lwpgnotice, lwgeom_geos_error);
464 
465  ginput = POSTGIS2GEOS(geom);
466  if (!ginput)
467  HANDLE_GEOS_ERROR("Geometry could not be converted to GEOS");
468 
469  if (hasBoundary)
470  {
471  gboundary = POSTGIS2GEOS(boundary);
472  if (!gboundary)
473  HANDLE_GEOS_ERROR("Boundary could not be converted to GEOS");
474  }
475 
476  gcircle = GEOSLargestEmptyCircle(ginput, gboundary, tolerance);
477  if (!gcircle)
478  {
479  lwpgerror("Error calculating GEOSLargestEmptyCircle.");
480  GEOSGeom_destroy(ginput);
481  PG_RETURN_NULL();
482  }
483 
484  gcenter = GEOSGeomGetStartPoint(gcircle);
485  gnearest = GEOSGeomGetEndPoint(gcircle);
486  GEOSDistance(gcenter, gnearest, &radius);
487  GEOSSetSRID(gcenter, srid);
488  GEOSSetSRID(gnearest, srid);
489 
490  center = GEOS2POSTGIS(gcenter, is3d);
491  nearest = GEOS2POSTGIS(gnearest, is3d);
492  GEOSGeom_destroy(gcenter);
493  GEOSGeom_destroy(gnearest);
494  GEOSGeom_destroy(gcircle);
495  GEOSGeom_destroy(ginput);
496  if (gboundary) GEOSGeom_destroy(gboundary);
497  }
498 
499  get_call_result_type(fcinfo, NULL, &resultTupleDesc);
500  BlessTupleDesc(resultTupleDesc);
501 
502  result_values[0] = PointerGetDatum(center);
503  result_is_null[0] = false;
504  result_values[1] = PointerGetDatum(nearest);
505  result_is_null[1] = false;
506  result_values[2] = Float8GetDatum(radius);
507  result_is_null[2] = false;
508  resultTuple = heap_form_tuple(resultTupleDesc, result_values, result_is_null);
509 
510  result = HeapTupleGetDatum(resultTuple);
511 
512  PG_RETURN_DATUM(result);
513 
514 #endif /* POSTGIS_GEOS_VERSION >= 30900 */
515 }
char result[OUT_DOUBLE_BUFFER_SIZE]
Definition: cu_print.c:267
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:155
int gserialized_get_gbox_p(const GSERIALIZED *g, GBOX *gbox)
Read the box from the GSERIALIZED or calculate it if necessary.
Definition: gserialized.c:94
LWGEOM * lwgeom_from_gserialized(const GSERIALIZED *g)
Allocate a new LWGEOM from a GSERIALIZED.
Definition: gserialized.c:268
int gserialized_is_empty(const GSERIALIZED *g)
Check if a GSERIALIZED is empty without deserializing first.
Definition: gserialized.c:181
int gserialized_has_z(const GSERIALIZED *g)
Check if a GSERIALIZED has a Z ordinate.
Definition: gserialized.c:203
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:1218
int lwgeom_isfinite(const LWGEOM *lwgeom)
Check if a LWGEOM has any non-finite (NaN or Inf) coordinates.
Definition: lwgeom.c:2807
#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: