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

◆ _lwt_CheckEdgeCrossing()

static int _lwt_CheckEdgeCrossing ( LWT_TOPOLOGY topo,
LWT_ELEMID  start_node,
LWT_ELEMID  end_node,
const LWLINE geom,
LWT_ELEMID  myself 
)
static

Definition at line 595 of file lwgeom_topo.c.

598{
599 uint64_t i, num_nodes, num_edges;
600 LWT_ISO_EDGE *edges;
601 LWT_ISO_NODE *nodes;
602 const GBOX *edgebox;
603 GEOSGeometry *edgegg;
604
605 initGEOS(lwnotice, lwgeom_geos_error);
606
607 edgegg = LWGEOM2GEOS(lwline_as_lwgeom(geom), 0);
608 if (!edgegg)
609 {
610 lwerror("Could not convert edge geometry to GEOS: %s", lwgeom_geos_errmsg);
611 return -1;
612 }
613 edgebox = lwgeom_get_bbox( lwline_as_lwgeom(geom) );
614
615 /* loop over each node within the edge's gbox */
616 nodes = lwt_be_getNodeWithinBox2D( topo, edgebox, &num_nodes,
617 LWT_COL_NODE_ALL, 0 );
618 LWDEBUGF(1, "lwt_be_getNodeWithinBox2D returned %d nodes", num_nodes);
619 if (num_nodes == UINT64_MAX)
620 {
621 lwerror("Backend error: %s", lwt_be_lastErrorMessage(topo->be_iface));
622 return -1;
623 }
624 for ( i=0; i<num_nodes; ++i )
625 {
626 const POINT2D *pt;
627 LWT_ISO_NODE* node = &(nodes[i]);
628 if ( node->node_id == start_node ) continue;
629 if ( node->node_id == end_node ) continue;
630 /* check if the edge contains this node (not on boundary) */
631 /* ST_RelateMatch(rec.relate, 'T********') */
632 pt = getPoint2d_cp(node->geom->point, 0);
634 if ( contains )
635 {
636 GEOSGeom_destroy(edgegg);
637 _lwt_release_nodes(nodes, num_nodes);
638 lwerror("SQL/MM Spatial exception - geometry crosses a node");
639 return -1;
640 }
641 }
642 if ( nodes ) _lwt_release_nodes(nodes, num_nodes);
643 /* may be NULL if num_nodes == 0 */
644
645 /* loop over each edge within the edge's gbox */
646 edges = lwt_be_getEdgeWithinBox2D( topo, edgebox, &num_edges, LWT_COL_EDGE_ALL, 0 );
647 LWDEBUGF(1, "lwt_be_getEdgeWithinBox2D returned %d edges", num_edges);
648 if (num_edges == UINT64_MAX)
649 {
650 GEOSGeom_destroy(edgegg);
651 lwerror("Backend error: %s", lwt_be_lastErrorMessage(topo->be_iface));
652 return -1;
653 }
654 for ( i=0; i<num_edges; ++i )
655 {
656 LWT_ISO_EDGE* edge = &(edges[i]);
657 LWT_ELEMID edge_id = edge->edge_id;
658 GEOSGeometry *eegg;
659 char *relate;
660 int match;
661
662 if ( edge_id == myself ) continue;
663
664 if ( ! edge->geom ) {
665 _lwt_release_edges(edges, num_edges);
666 lwerror("Edge %d has NULL geometry!", edge_id);
667 return -1;
668 }
669
670 eegg = LWGEOM2GEOS( lwline_as_lwgeom(edge->geom), 0 );
671 if ( ! eegg ) {
672 GEOSGeom_destroy(edgegg);
673 _lwt_release_edges(edges, num_edges);
674 lwerror("Could not convert edge geometry to GEOS: %s", lwgeom_geos_errmsg);
675 return -1;
676 }
677
678 LWDEBUGF(2, "Edge %d converted to GEOS", edge_id);
679
680 /* check if the edge crosses our edge (not boundary-boundary) */
681
682 relate = GEOSRelateBoundaryNodeRule(eegg, edgegg, 2);
683 if ( ! relate ) {
684 GEOSGeom_destroy(eegg);
685 GEOSGeom_destroy(edgegg);
686 _lwt_release_edges(edges, num_edges);
687 lwerror("GEOSRelateBoundaryNodeRule error: %s", lwgeom_geos_errmsg);
688 return -1;
689 }
690
691 LWDEBUGF(2, "Edge %d relate pattern is %s", edge_id, relate);
692
693 match = GEOSRelatePatternMatch(relate, "F********");
694 if ( match ) {
695 /* error or no interior intersection */
696 GEOSGeom_destroy(eegg);
697 GEOSFree(relate);
698 if ( match == 2 ) {
699 _lwt_release_edges(edges, num_edges);
700 GEOSGeom_destroy(edgegg);
701 lwerror("GEOSRelatePatternMatch error: %s", lwgeom_geos_errmsg);
702 return -1;
703 }
704 else continue; /* no interior intersection */
705 }
706
707 match = GEOSRelatePatternMatch(relate, "1FFF*FFF2");
708 if ( match ) {
709 _lwt_release_edges(edges, num_edges);
710 GEOSGeom_destroy(edgegg);
711 GEOSGeom_destroy(eegg);
712 GEOSFree(relate);
713 if ( match == 2 ) {
714 lwerror("GEOSRelatePatternMatch error: %s", lwgeom_geos_errmsg);
715 } else {
716 lwerror("SQL/MM Spatial exception - coincident edge %" LWTFMT_ELEMID,
717 edge_id);
718 }
719 return -1;
720 }
721
722 match = GEOSRelatePatternMatch(relate, "1********");
723 if ( match ) {
724 _lwt_release_edges(edges, num_edges);
725 GEOSGeom_destroy(edgegg);
726 GEOSGeom_destroy(eegg);
727 GEOSFree(relate);
728 if ( match == 2 ) {
729 lwerror("GEOSRelatePatternMatch error: %s", lwgeom_geos_errmsg);
730 } else {
731 lwerror("Spatial exception - geometry intersects edge %"
732 LWTFMT_ELEMID, edge_id);
733 }
734 return -1;
735 }
736
737 match = GEOSRelatePatternMatch(relate, "T********");
738 if ( match ) {
739 _lwt_release_edges(edges, num_edges);
740 GEOSGeom_destroy(edgegg);
741 GEOSGeom_destroy(eegg);
742 GEOSFree(relate);
743 if ( match == 2 ) {
744 lwerror("GEOSRelatePatternMatch error: %s", lwgeom_geos_errmsg);
745 } else {
746 lwerror("SQL/MM Spatial exception - geometry crosses edge %"
747 LWTFMT_ELEMID, edge_id);
748 }
749 return -1;
750 }
751
752 LWDEBUGF(2, "Edge %d analisys completed, it does no harm", edge_id);
753
754 GEOSFree(relate);
755 GEOSGeom_destroy(eegg);
756 }
757 if ( edges ) _lwt_release_edges(edges, num_edges);
758 /* would be NULL if num_edges was 0 */
759
760 GEOSGeom_destroy(edgegg);
761
762 return 0;
763}
char lwgeom_geos_errmsg[LWGEOM_GEOS_ERRMSG_MAXSIZE]
GEOSGeometry * LWGEOM2GEOS(const LWGEOM *lwgeom, uint8_t autofix)
void lwgeom_geos_error(const char *fmt,...)
#define LW_FALSE
Definition liblwgeom.h:108
LWGEOM * lwline_as_lwgeom(const LWLINE *obj)
Definition lwgeom.c:321
const GBOX * lwgeom_get_bbox(const LWGEOM *lwgeom)
Get a non-empty geometry bounding box, computing and caching it if not already there.
Definition lwgeom.c:725
int ptarray_contains_point_partial(const POINTARRAY *pa, const POINT2D *pt, int check_closed, int *winding_number)
Definition ptarray.c:746
#define LW_BOUNDARY
LWT_INT64 LWT_ELEMID
Identifier of topology element.
#define LWT_COL_EDGE_ALL
#define LWT_COL_NODE_ALL
#define LWDEBUGF(level, msg,...)
Definition lwgeom_log.h:88
void lwerror(const char *fmt,...)
Write a notice out to the error handler.
Definition lwutil.c:190
void lwnotice(const char *fmt,...)
Write a notice out to the notice handler.
Definition lwutil.c:177
static LWT_ISO_EDGE * lwt_be_getEdgeWithinBox2D(const LWT_TOPOLOGY *topo, const GBOX *box, uint64_t *numelems, int fields, uint64_t limit)
static void _lwt_release_nodes(LWT_ISO_NODE *nodes, int num_nodes)
const char * lwt_be_lastErrorMessage(const LWT_BE_IFACE *be)
static LWT_ISO_NODE * lwt_be_getNodeWithinBox2D(const LWT_TOPOLOGY *topo, const GBOX *box, uint64_t *numelems, int fields, uint64_t limit)
#define LWTFMT_ELEMID
Definition lwgeom_topo.c:43
static void _lwt_release_edges(LWT_ISO_EDGE *edges, int num_edges)
static const POINT2D * getPoint2d_cp(const POINTARRAY *pa, uint32_t n)
Returns a POINT2D pointer into the POINTARRAY serialized_ptlist, suitable for reading from.
Definition lwinline.h:91
Datum contains(PG_FUNCTION_ARGS)
POINTARRAY * points
Definition liblwgeom.h:469
POINTARRAY * point
Definition liblwgeom.h:457
LWT_ELEMID edge_id
LWT_ELEMID node_id
LWPOINT * geom
const LWT_BE_IFACE * be_iface

References _lwt_release_edges(), _lwt_release_nodes(), LWT_TOPOLOGY_T::be_iface, contains(), LWT_ISO_EDGE::edge_id, LWT_ISO_NODE::geom, LWT_ISO_EDGE::geom, getPoint2d_cp(), LW_BOUNDARY, LW_FALSE, LWDEBUGF, lwerror(), LWGEOM2GEOS(), lwgeom_geos_errmsg, lwgeom_geos_error(), lwgeom_get_bbox(), lwline_as_lwgeom(), lwnotice(), lwt_be_getEdgeWithinBox2D(), lwt_be_getNodeWithinBox2D(), lwt_be_lastErrorMessage(), LWT_COL_EDGE_ALL, LWT_COL_NODE_ALL, LWTFMT_ELEMID, LWT_ISO_NODE::node_id, LWPOINT::point, LWLINE::points, and ptarray_contains_point_partial().

Referenced by _lwt_AddEdge(), lwt_AddIsoEdge(), and lwt_ChangeEdgeGeom().

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