PostGIS  3.7.0dev-r@@SVN_REVISION@@

◆ coverage_window_calculation()

static Datum coverage_window_calculation ( PG_FUNCTION_ARGS  ,
int  mode 
)
static

Definition at line 659 of file lwgeom_window.c.

660 {
661  WindowObject winobj = PG_WINDOW_OBJECT();
662  int64 curpos = WinGetCurrentPosition(winobj);
663  int64 rowcount = WinGetPartitionRowCount(winobj);
664  coverage_context *context = coverage_context_fetch(winobj, rowcount);
666  MemoryContext uppercontext = fcinfo->flinfo->fn_mcxt;
667  MemoryContext oldcontext;
668  const LWGEOM* subgeom;
669 
670  if (!context->isdone)
671  {
672  bool isnull;
673  GEOSGeometry *output = NULL;
674  GEOSGeometry *input = NULL;
675  Datum d;
676 
677  if (!fcinfo->flinfo)
678  elog(ERROR, "%s: Could not find upper context", __func__);
679 
680  if (rowcount == 0)
681  {
682  context->isdone = true;
683  context->isnull = true;
684  PG_RETURN_NULL();
685  }
686 
687  initGEOS(lwpgnotice, lwgeom_geos_error);
688 
689  input = coverage_read_partition_into_collection(winobj, context);
690  if (!input)
691  HANDLE_GEOS_ERROR("Failed to create collection");
692 
693  /* Run the correct GEOS function for the calling mode */
694  if (mode == COVERAGE_SIMPLIFY)
695  {
696  bool simplifyBoundary = true;
697  double tolerance = 0.0;
698 
699  d = WinGetFuncArgCurrent(winobj, 1, &isnull);
700  if (!isnull) tolerance = DatumGetFloat8(d);
701 
702  d = WinGetFuncArgCurrent(winobj, 2, &isnull);
703  if (!isnull) simplifyBoundary = DatumGetFloat8(d);
704 
705  /* GEOSCoverageSimplifyVW is "preserveBoundary" so we invert simplifyBoundary */
706  output = GEOSCoverageSimplifyVW(input, tolerance, !simplifyBoundary);
707  }
708  else if (mode == COVERAGE_ISVALID)
709  {
710  double tolerance = 0.0;
711  d = WinGetFuncArgCurrent(winobj, 1, &isnull);
712  if (!isnull) tolerance = DatumGetFloat8(d);
713  GEOSCoverageIsValid(input, tolerance, &output);
714  }
715 
716 #if POSTGIS_GEOS_VERSION >= 31400
717 
718  else if (mode == COVERAGE_CLEAN)
719  {
720  double snappingDistance = 0.0;
721  double gapMaximumWidth = 0.0;
722  text *overlapMergeStrategyText;
723  int overlapMergeStrategy;
724  GEOSCoverageCleanParams *params = NULL;
725 
726  d = WinGetFuncArgCurrent(winobj, 1, &isnull);
727  if (!isnull) gapMaximumWidth = DatumGetFloat8(d);
728 
729  d = WinGetFuncArgCurrent(winobj, 2, &isnull);
730  if (!isnull) snappingDistance = DatumGetFloat8(d);
731 
732  d = WinGetFuncArgCurrent(winobj, 3, &isnull);
733  if (!isnull)
734  {
735  overlapMergeStrategyText = DatumGetTextP(d);
736  overlapMergeStrategy = coverage_merge_strategy(text_to_cstring(overlapMergeStrategyText));
737  }
738  else
739  {
740  overlapMergeStrategy = 0; /* Default to MERGE_LONGEST_BORDER */
741  }
742  if (overlapMergeStrategy < 0)
743  {
744  HANDLE_GEOS_ERROR("Invalid OverlapMergeStrategy");
745  }
746 
747  params = GEOSCoverageCleanParams_create();
748  GEOSCoverageCleanParams_setGapMaximumWidth(params, gapMaximumWidth);
749  GEOSCoverageCleanParams_setSnappingDistance(params, snappingDistance);
750  if (!GEOSCoverageCleanParams_setOverlapMergeStrategy(params, overlapMergeStrategy))
751  {
752  GEOSCoverageCleanParams_destroy(params);
753  HANDLE_GEOS_ERROR("Invalid OverlapMergeStrategy");
754  }
755 
756  output = GEOSCoverageCleanWithParams(input, params);
757  GEOSCoverageCleanParams_destroy(params);
758  }
759 #endif
760  else
761  {
762  elog(ERROR, "Unknown mode, never get here");
763  }
764 
765  GEOSGeom_destroy(input);
766 
767  if (!output)
768  {
769  HANDLE_GEOS_ERROR("Failed to process collection");
770  }
771 
772  oldcontext = MemoryContextSwitchTo(uppercontext);
773  context->geom = (LWCOLLECTION *) GEOS2LWGEOM(output, GEOSHasZ(output));
774  MemoryContextSwitchTo(oldcontext);
775  GEOSGeom_destroy(output);
776 
777  context->isdone = true;
778  }
779 
780  /* Bomb out of any errors */
781  if (context->isnull)
782  PG_RETURN_NULL();
783 
784  /* Propagate the null entries */
785  if (context->idx[curpos] < 0)
786  PG_RETURN_NULL();
787 
788  /*
789  * Geometry serialization is not const-safe! (we
790  * calculate bounding boxes on demand) so we need
791  * to make sure we have a persistent context when
792  * we call the serialization, lest we create dangling
793  * pointers in the object. It's possible we could
794  * ignore them, skip the manual lwcollection_free
795  * and let the aggcontext deletion take
796  * care of the memory.
797  */
798  oldcontext = MemoryContextSwitchTo(uppercontext);
799  subgeom = lwcollection_getsubgeom(context->geom, context->idx[curpos]);
800  if (mode == COVERAGE_ISVALID && lwgeom_is_empty(subgeom))
801  {
802  result = NULL;
803  }
804  else
805  {
806  result = geometry_serialize((LWGEOM*)subgeom);
807  }
808  MemoryContextSwitchTo(oldcontext);
809 
810  /* When at the end of the partition, release the */
811  /* simplified collection we have been reading. */
812  if (curpos == rowcount - 1)
813  lwcollection_free(context->geom);
814 
815  if (!result) PG_RETURN_NULL();
816 
817  PG_RETURN_POINTER(result);
818 
819 }
char result[OUT_DOUBLE_BUFFER_SIZE]
Definition: cu_print.c:267
void lwgeom_geos_error(const char *fmt,...)
void(*) LWGEOM GEOS2LWGEOM)(const GEOSGeometry *geom, uint8_t want3d)
const LWGEOM * lwcollection_getsubgeom(LWCOLLECTION *col, uint32_t gnum)
Definition: lwcollection.c:115
void lwcollection_free(LWCOLLECTION *col)
Definition: lwcollection.c:357
@ 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:199
#define HANDLE_GEOS_ERROR(label)
LWCOLLECTION * geom

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

Referenced by ST_CoverageClean(), ST_CoverageInvalidEdges(), and ST_CoverageSimplify().

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