PostGIS 3.7.0dev-r@@SVN_REVISION@@
Loading...
Searching...
No Matches

◆ 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)
void lwcollection_free(LWCOLLECTION *col)
@ 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: