PostGIS  3.4.0dev-r@@SVN_REVISION@@

◆ coverage_window_calculation()

static Datum coverage_window_calculation ( PG_FUNCTION_ARGS  ,
int  mode 
)
static

Definition at line 627 of file lwgeom_window.c.

628 {
629  WindowObject winobj = PG_WINDOW_OBJECT();
630  int64 curpos = WinGetCurrentPosition(winobj);
631  int64 rowcount = WinGetPartitionRowCount(winobj);
632  coverage_context *context = coverage_context_fetch(winobj, rowcount);
634  MemoryContext uppercontext = fcinfo->flinfo->fn_mcxt;
635  MemoryContext oldcontext;
636  const LWGEOM* subgeom;
637 
638  if (!context->isdone)
639  {
640  bool isnull;
641  Datum d;
642  double tolerance = 0.0;
643  bool simplifyBoundary = true;
644  GEOSGeometry *output = NULL;
645  GEOSGeometry *input = NULL;
646 
647  if (!fcinfo->flinfo)
648  elog(ERROR, "%s: Could not find upper context", __func__);
649 
650  if (rowcount == 0)
651  {
652  context->isdone = true;
653  context->isnull = true;
654  PG_RETURN_NULL();
655  }
656 
657  /* Get the tolerance argument from second postition */
658  d = WinGetFuncArgCurrent(winobj, 1, &isnull);
659  if (!isnull)
660  tolerance = DatumGetFloat8(d);
661 
662  /* The third position "preserve boundary" argument */
663  /* is only for the simplify mode */
664  if (mode == COVERAGE_SIMPLIFY)
665  {
666  d = WinGetFuncArgCurrent(winobj, 2, &isnull);
667  if (!isnull)
668  simplifyBoundary = DatumGetBool(d);
669  }
670 
671  initGEOS(lwnotice, lwgeom_geos_error);
672 
673  input = coverage_read_partition_into_collection(winobj, context);
674  if (!input)
675  HANDLE_GEOS_ERROR("Failed to create collection");
676 
677  /* Run the correct GEOS function for the calling mode */
678  if (mode == COVERAGE_SIMPLIFY)
679  {
680  /* GEOSCoverageSimplifyVW is "preserveBoundary" so we invert simplifyBoundary */
681  output = GEOSCoverageSimplifyVW(input, tolerance, !simplifyBoundary);
682  }
683  else if (mode == COVERAGE_ISVALID)
684  {
685  GEOSCoverageIsValid(input, tolerance, &output);
686  }
687  else
688  {
689  elog(ERROR, "Unknown mode, never get here");
690  }
691 
692  GEOSGeom_destroy(input);
693 
694  if (!output)
695  {
696  HANDLE_GEOS_ERROR("Failed to process collection");
697  }
698 
699  oldcontext = MemoryContextSwitchTo(uppercontext);
700  context->geom = (LWCOLLECTION *) GEOS2LWGEOM(output, GEOSHasZ(output));
701  MemoryContextSwitchTo(oldcontext);
702  GEOSGeom_destroy(output);
703 
704  context->isdone = true;
705  }
706 
707  /* Bomb out of any errors */
708  if (context->isnull)
709  PG_RETURN_NULL();
710 
711  /* Propogate the null entries */
712  if (context->idx[curpos] < 0)
713  PG_RETURN_NULL();
714 
715  /*
716  * Geometry serialization is not const-safe! (we
717  * calculate bounding boxes on demand) so we need
718  * to make sure we have a persistent context when
719  * we call the serialization, lest we create dangling
720  * pointers in the object. It's possible we could
721  * ignore them, skip the manual lwcollection_free
722  * and let the aggcontext deletion take
723  * care of the memory.
724  */
725  oldcontext = MemoryContextSwitchTo(uppercontext);
726  subgeom = lwcollection_getsubgeom(context->geom, context->idx[curpos]);
727  if (mode == COVERAGE_ISVALID && lwgeom_is_empty(subgeom))
728  {
729  result = NULL;
730  }
731  else
732  {
733  result = geometry_serialize((LWGEOM*)subgeom);
734  }
735  MemoryContextSwitchTo(oldcontext);
736 
737  /* When at the end of the partition, release the */
738  /* simplified collection we have been reading. */
739  if (curpos == rowcount - 1)
740  lwcollection_free(context->geom);
741 
742  if (!result) PG_RETURN_NULL();
743 
744  PG_RETURN_POINTER(result);
745 
746 }
char result[OUT_DOUBLE_BUFFER_SIZE]
Definition: cu_print.c:262
LWGEOM * GEOS2LWGEOM(const GEOSGeometry *geom, uint8_t want3d)
void lwgeom_geos_error(const char *fmt,...)
LWGEOM * lwcollection_getsubgeom(LWCOLLECTION *col, int gnum)
Definition: lwcollection.c:114
void lwcollection_free(LWCOLLECTION *col)
Definition: lwcollection.c:357
void lwnotice(const char *fmt,...)
Write a notice out to the notice handler.
Definition: lwutil.c:177
@ COVERAGE_ISVALID
@ COVERAGE_SIMPLIFY
static coverage_context * coverage_context_fetch(WindowObject winobj, int64 rowcount)
static GEOSGeometry * coverage_read_partition_into_collection(WindowObject winobj, coverage_context *context)
static int lwgeom_is_empty(const LWGEOM *geom)
Return true or false depending on whether a geometry is an "empty" geometry (no vertices members)
Definition: lwinline.h:203
#define HANDLE_GEOS_ERROR(label)
LWCOLLECTION * geom

References coverage_context_fetch(), COVERAGE_ISVALID, coverage_read_partition_into_collection(), COVERAGE_SIMPLIFY, coverage_context::geom, GEOS2LWGEOM(), HANDLE_GEOS_ERROR, coverage_context::idx, coverage_context::isdone, coverage_context::isnull, lwcollection_free(), lwcollection_getsubgeom(), lwgeom_geos_error(), lwgeom_is_empty(), lwnotice(), and result.

Referenced by ST_CoverageInvalidEdges(), and ST_CoverageSimplify().

Here is the call graph for this function:
Here is the caller graph for this function: