PostGIS  3.2.2dev-r@@SVN_REVISION@@

◆ ST_MaximumInscribedCircle()

Datum ST_MaximumInscribedCircle ( PG_FUNCTION_ARGS  )

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

345 {
346 #if POSTGIS_GEOS_VERSION < 30900
347 
348  lwpgerror("The GEOS version this PostGIS binary "
349  "was compiled against (%d) doesn't support "
350  "'GEOSMaximumInscribedCircle' function (3.9.0+ required)",
352  PG_RETURN_NULL();
353 
354 #else /* POSTGIS_GEOS_VERSION >= 30900 */
355  GSERIALIZED* geom;
356  GSERIALIZED* center;
357  GSERIALIZED* nearest;
358  TupleDesc resultTupleDesc;
359  HeapTuple resultTuple;
360  Datum result;
361  Datum result_values[3];
362  bool result_is_null[3];
363  double radius = 0.0;
364  int32 srid = SRID_UNKNOWN;
365  bool is3d;
366 
367  if (PG_ARGISNULL(0))
368  PG_RETURN_NULL();
369 
370  geom = PG_GETARG_GSERIALIZED_P(0);
371  srid = gserialized_get_srid(geom);
372  is3d = gserialized_has_z(geom);
373 
374  /* Empty geometry? Return POINT EMPTY with zero radius */
375  if (gserialized_is_empty(geom))
376  {
379  center = geometry_serialize(lwcenter);
380  nearest = geometry_serialize(lwnearest);
381  radius = 0.0;
382  }
383  else
384  {
385  GEOSGeometry *ginput, *gcircle, *gcenter, *gnearest;
386  double width, height, size, tolerance;
387  GBOX gbox;
388  int gtype;
389  LWGEOM *lwg;
390  lwg = lwgeom_from_gserialized(geom);
391  if (!lwgeom_isfinite(lwg))
392  {
393  lwpgerror("Geometry contains invalid coordinates");
394  PG_RETURN_NULL();
395  }
396  lwgeom_free(lwg);
397 
398  if (!gserialized_get_gbox_p(geom, &gbox))
399  PG_RETURN_NULL();
400 
401  width = gbox.xmax - gbox.xmin;
402  height = gbox.ymax - gbox.ymin;
403  size = width > height ? width : height;
404  tolerance = size / 1000.0;
405 
406  initGEOS(lwpgnotice, lwgeom_geos_error);
407 
408  ginput = POSTGIS2GEOS(geom);
409  if (!ginput)
410  HANDLE_GEOS_ERROR("Geometry could not be converted to GEOS");
411 
412  gtype = gserialized_get_type(geom);
413  if (gtype == POLYGONTYPE || gtype == MULTIPOLYGONTYPE)
414  {
415  gcircle = GEOSMaximumInscribedCircle(ginput, tolerance);
416  if (!gcircle)
417  {
418  lwpgerror("Error calculating GEOSMaximumInscribedCircle.");
419  GEOSGeom_destroy(ginput);
420  PG_RETURN_NULL();
421  }
422  }
423  else
424  {
425  gcircle = GEOSLargestEmptyCircle(ginput, NULL, tolerance);
426  if (!gcircle)
427  {
428  lwpgerror("Error calculating GEOSLargestEmptyCircle.");
429  GEOSGeom_destroy(ginput);
430  PG_RETURN_NULL();
431  }
432  }
433 
434  gcenter = GEOSGeomGetStartPoint(gcircle);
435  gnearest = GEOSGeomGetEndPoint(gcircle);
436  GEOSDistance(gcenter, gnearest, &radius);
437  GEOSSetSRID(gcenter, srid);
438  GEOSSetSRID(gnearest, srid);
439 
440  center = GEOS2POSTGIS(gcenter, is3d);
441  nearest = GEOS2POSTGIS(gnearest, is3d);
442  GEOSGeom_destroy(gcenter);
443  GEOSGeom_destroy(gnearest);
444  GEOSGeom_destroy(gcircle);
445  GEOSGeom_destroy(ginput);
446  }
447 
448  get_call_result_type(fcinfo, NULL, &resultTupleDesc);
449  BlessTupleDesc(resultTupleDesc);
450 
451  result_values[0] = PointerGetDatum(center);
452  result_is_null[0] = false;
453  result_values[1] = PointerGetDatum(nearest);
454  result_is_null[1] = false;
455  result_values[2] = Float8GetDatum(radius);
456  result_is_null[2] = false;
457  resultTuple = heap_form_tuple(resultTupleDesc, result_values, result_is_null);
458 
459  result = HeapTupleGetDatum(resultTuple);
460 
461  PG_RETURN_DATUM(result);
462 
463 #endif /* POSTGIS_GEOS_VERSION >= 30900 */
464 }
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: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
uint32_t gserialized_get_type(const GSERIALIZED *g)
Extract the geometry type from the serialized form (it hides in the anonymous data area,...
Definition: gserialized.c:89
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:108
void lwgeom_free(LWGEOM *geom)
Definition: lwgeom.c:1138
int lwgeom_isfinite(const LWGEOM *lwgeom)
Check if a LWGEOM has any non-finite (NaN or Inf) coordinates.
Definition: lwgeom.c:2690
#define MULTIPOLYGONTYPE
Definition: liblwgeom.h:121
#define POLYGONTYPE
Definition: liblwgeom.h:118
#define SRID_UNKNOWN
Unknown SRID value.
Definition: liblwgeom.h:229
#define HANDLE_GEOS_ERROR(label)
GSERIALIZED * GEOS2POSTGIS(GEOSGeom geom, char want3d)
GEOSGeometry * POSTGIS2GEOS(const GSERIALIZED *pglwgeom)
unsigned int int32
Definition: shpopen.c:54
#define POSTGIS_GEOS_VERSION
Definition: sqldefines.h:11
double ymax
Definition: liblwgeom.h:371
double xmax
Definition: liblwgeom.h:369
double ymin
Definition: liblwgeom.h:370
double xmin
Definition: liblwgeom.h:368

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

Here is the call graph for this function: