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

◆ _lwt_FindFaceContainingRing()

static LWT_ELEMID _lwt_FindFaceContainingRing ( LWT_TOPOLOGY topo,
LWT_EDGERING ring,
LWT_EDGERING_ARRAY shells 
)
static

Definition at line 639 of file lwgeom_topo_polygonizer.c.

641{
642 LWT_ELEMID foundInFace = -1;
643 int i;
644 const GBOX *minenv = NULL;
645 POINT2D pt;
646 const GBOX *testbox;
647 GEOSGeometry *ghole;
648
649 getPoint2d_p( ring->elems[0]->edge->geom->points, 0, &pt );
650
651 testbox = _lwt_EdgeRingGetBbox(ring);
652
653 /* Create a GEOS Point from a vertex of the hole ring */
654 {
655 LWPOINT *point = lwpoint_make2d(topo->srid, pt.x, pt.y);
656 ghole = LWGEOM2GEOS( lwpoint_as_lwgeom(point), 1 );
657 lwpoint_free(point);
658 if ( ! ghole ) {
659 lwerror("Could not convert edge geometry to GEOS: %s", lwgeom_geos_errmsg);
660 return -1;
661 }
662 }
663
664 /* Build STRtree of shell envelopes */
665 if ( ! shells->tree )
666 {
667 static const int STRTREE_NODE_CAPACITY = 10;
668 LWDEBUG(1, "Building STRtree");
669 shells->tree = GEOSSTRtree_create(STRTREE_NODE_CAPACITY);
670 if (shells->tree == NULL)
671 {
672 lwerror("Could not create GEOS STRTree: %s", lwgeom_geos_errmsg);
673 return -1;
674 }
675 for (i=0; i<shells->size; ++i)
676 {
677 LWT_EDGERING *sring = shells->rings[i];
678 const GBOX* shellbox = _lwt_EdgeRingGetBbox(sring);
679 LWDEBUGF(2, "GBOX of shell %p for edge %lld is %g %g,%g %g",
680 sring, sring->elems[0]->edge->edge_id, shellbox->xmin,
681 shellbox->ymin, shellbox->xmax, shellbox->ymax);
682 POINTARRAY *pa = ptarray_construct(0, 0, 2);
683 POINT4D pt;
684 LWLINE *diag;
685 pt.x = shellbox->xmin;
686 pt.y = shellbox->ymin;
687 ptarray_set_point4d(pa, 0, &pt);
688 pt.x = shellbox->xmax;
689 pt.y = shellbox->ymax;
690 ptarray_set_point4d(pa, 1, &pt);
691 diag = lwline_construct(topo->srid, NULL, pa);
692 /* Record just envelope in ggeom */
693 /* making valid, probably not needed */
694 sring->genv = LWGEOM2GEOS( lwline_as_lwgeom(diag), 1 );
695 lwline_free(diag);
696 GEOSSTRtree_insert(shells->tree, sring->genv, sring);
697 }
698 LWDEBUG(1, "STRtree build completed");
699 }
700
701 LWT_EDGERING_ARRAY candidates;
702 LWT_EDGERING_ARRAY_INIT(&candidates);
703 GEOSSTRtree_query(shells->tree, ghole, &_lwt_AccumulateCanditates, &candidates);
704 LWDEBUGF(1, "Found %d candidate shells containing first point of ring's originating edge %lld",
705 candidates.size, ring->elems[0]->edge->edge_id * ( ring->elems[0]->left ? 1 : -1 ) );
706
707 /* TODO: sort candidates by bounding box size */
708
709 for (i=0; i<candidates.size; ++i)
710 {
711 LWT_EDGERING *sring = candidates.rings[i];
712 const GBOX* shellbox = _lwt_EdgeRingGetBbox(sring);
713 int contains = 0;
714
715 if ( sring->elems[0]->edge->edge_id == ring->elems[0]->edge->edge_id )
716 {
717 LWDEBUGF(1, "Shell %lld is on other side of ring",
718 _lwt_EdgeRingGetFace(sring));
719 continue;
720 }
721
722 /* The hole envelope cannot equal the shell envelope */
723 if ( gbox_same(shellbox, testbox) )
724 {
725 LWDEBUGF(1, "Bbox of shell %lld equals that of hole ring",
726 _lwt_EdgeRingGetFace(sring));
727 continue;
728 }
729
730 /* Skip if ring box is not in shell box */
731 if ( ! gbox_contains_2d(shellbox, testbox) )
732 {
733 LWDEBUGF(1, "Bbox of shell %lld does not contain bbox of ring point",
734 _lwt_EdgeRingGetFace(sring));
735 continue;
736 }
737
738 /* Skip test if a containing shell was already found
739 * and this shell's bbox is not contained in the other */
740 if ( minenv && ! gbox_contains_2d(minenv, shellbox) )
741 {
742 LWDEBUGF(2, "Bbox of shell %d (face %lld) not contained by bbox "
743 "of last shell found to contain the point",
744 i, _lwt_EdgeRingGetFace(sring));
745 continue;
746 }
747
749 if ( contains )
750 {
751 /* Continue until all shells are tested, as we want to
752 * use the one with the smallest bounding box */
753 /* IDEA: sort shells by bbox size, stopping on first match */
754 LWDEBUGF(1, "Shell %lld contains hole of edge %lld",
756 ring->elems[0]->edge->edge_id);
757 minenv = shellbox;
758 foundInFace = _lwt_EdgeRingGetFace(sring);
759 }
760 }
761 if ( foundInFace == -1 ) foundInFace = 0;
762
763 candidates.size = 0; /* Avoid destroying the actual shell rings */
764 LWT_EDGERING_ARRAY_CLEAN(&candidates);
765
766 GEOSGeom_destroy(ghole);
767
768 return foundInFace;
769}
int gbox_same(const GBOX *g1, const GBOX *g2)
Check if 2 given Gbox are the same.
Definition gbox.c:164
int gbox_contains_2d(const GBOX *g1, const GBOX *g2)
Return LW_TRUE if the first GBOX contains the second on the 2d plane, LW_FALSE otherwise.
Definition gbox.c:339
char lwgeom_geos_errmsg[LWGEOM_GEOS_ERRMSG_MAXSIZE]
GEOSGeometry * LWGEOM2GEOS(const LWGEOM *lwgeom, uint8_t autofix)
LWGEOM * lwpoint_as_lwgeom(const LWPOINT *obj)
Definition lwgeom.c:372
void lwpoint_free(LWPOINT *pt)
Definition lwpoint.c:213
int getPoint2d_p(const POINTARRAY *pa, uint32_t n, POINT2D *point)
Definition lwgeom_api.c:342
LWLINE * lwline_construct(int32_t srid, GBOX *bbox, POINTARRAY *points)
Definition lwline.c:42
LWPOINT * lwpoint_make2d(int32_t srid, double x, double y)
Definition lwpoint.c:163
LWGEOM * lwline_as_lwgeom(const LWLINE *obj)
Definition lwgeom.c:367
void ptarray_set_point4d(POINTARRAY *pa, uint32_t n, const POINT4D *p4d)
Definition lwgeom_api.c:369
void lwline_free(LWLINE *line)
Definition lwline.c:67
POINTARRAY * ptarray_construct(char hasz, char hasm, uint32_t npoints)
Construct an empty pointarray, allocating storage and setting the npoints, but not filling in any inf...
Definition ptarray.c:51
LWT_INT64 LWT_ELEMID
Identifier of topology element.
static const int STRTREE_NODE_CAPACITY
Datum contains(PG_FUNCTION_ARGS)
#define LWDEBUG(level, msg)
Definition lwgeom_log.h:101
#define LWDEBUGF(level, msg,...)
Definition lwgeom_log.h:106
void void lwerror(const char *fmt,...) __attribute__((format(printf
Write a notice out to the error handler.
static int _lwt_EdgeRingContainsPoint(LWT_EDGERING *ring, POINT2D *p)
static GBOX * _lwt_EdgeRingGetBbox(LWT_EDGERING *ring)
static LWT_ELEMID _lwt_EdgeRingGetFace(LWT_EDGERING *ring)
#define LWT_EDGERING_ARRAY_INIT(a)
static void _lwt_AccumulateCanditates(void *item, void *userdata)
#define LWT_EDGERING_ARRAY_CLEAN(a)
double ymax
Definition liblwgeom.h:357
double xmax
Definition liblwgeom.h:355
double ymin
Definition liblwgeom.h:356
double xmin
Definition liblwgeom.h:354
POINTARRAY * points
Definition liblwgeom.h:483
LWT_EDGERING_ELEM ** elems
LWT_ELEMID edge_id
double y
Definition liblwgeom.h:390
double x
Definition liblwgeom.h:390
double x
Definition liblwgeom.h:414
double y
Definition liblwgeom.h:414

References _lwt_AccumulateCanditates(), _lwt_EdgeRingContainsPoint(), _lwt_EdgeRingGetBbox(), _lwt_EdgeRingGetFace(), contains(), LWT_EDGERING_ELEM_T::edge, LWT_ISO_EDGE::edge_id, LWT_EDGERING_T::elems, gbox_contains_2d(), gbox_same(), LWT_EDGERING_T::genv, LWT_ISO_EDGE::geom, getPoint2d_p(), LWT_EDGERING_ELEM_T::left, LWDEBUG, LWDEBUGF, lwerror(), LWGEOM2GEOS(), lwgeom_geos_errmsg, lwline_as_lwgeom(), lwline_construct(), lwline_free(), lwpoint_as_lwgeom(), lwpoint_free(), lwpoint_make2d(), LWT_EDGERING_ARRAY_CLEAN, LWT_EDGERING_ARRAY_INIT, LWLINE::points, ptarray_construct(), ptarray_set_point4d(), LWT_EDGERING_ARRAY_T::rings, LWT_EDGERING_ARRAY_T::size, LWT_TOPOLOGY_T::srid, STRTREE_NODE_CAPACITY, LWT_EDGERING_ARRAY_T::tree, POINT2D::x, POINT4D::x, GBOX::xmax, GBOX::xmin, POINT2D::y, POINT4D::y, GBOX::ymax, and GBOX::ymin.

Referenced by lwt_Polygonize().

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