PostGIS 3.7.0dev-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 668 of file lwgeom_topo.c.

671{
672 uint64_t i, num_nodes, num_edges;
673 LWT_ISO_EDGE *edges;
674 LWT_ISO_NODE *nodes;
675 const GBOX *edgebox;
676 GEOSGeometry *edgegg;
677
678 initGEOS(lwnotice, lwgeom_geos_error);
679
680 edgegg = LWGEOM2GEOS(lwline_as_lwgeom(geom), 0);
681 if (!edgegg)
682 {
683 lwerror("Could not convert edge geometry to GEOS: %s", lwgeom_geos_errmsg);
684 return -1;
685 }
686 edgebox = lwgeom_get_bbox( lwline_as_lwgeom(geom) );
687
688 /* loop over each node within the edge's gbox */
689 nodes = lwt_be_getNodeWithinBox2D( topo, edgebox, &num_nodes,
690 LWT_COL_NODE_ALL, 0 );
691 LWDEBUGF(1, "lwt_be_getNodeWithinBox2D returned %llu nodes", num_nodes);
692 if (num_nodes == UINT64_MAX)
693 {
695 return -1;
696 }
697 for ( i=0; i<num_nodes; ++i )
698 {
699 POINT2D p;
700 LWT_ISO_NODE *node = &(nodes[i]);
701 if (node->node_id == start_node)
702 continue;
703 if (node->node_id == end_node)
704 continue;
705 /* check if the edge contains this node (not on boundary) */
706 /* ST_RelateMatch(rec.relate, 'T********') */
707 if (!node->geom || !node->geom->point || !node->geom->point->npoints)
708 {
709 GEOSGeom_destroy(edgegg);
710 _lwt_release_nodes(nodes, num_nodes);
711 lwerror("SQL/MM Spatial exception - geometry crosses a node");
712 return -1;
713 }
714
715 getPoint2d_p(node->geom->point, 0, &p);
717 if (contains)
718 {
719 char locinfo[128] = "";
720 snprintf(locinfo, sizeof(locinfo), " at POINT(%.15g %.15g)", p.x, p.y);
721 GEOSGeom_destroy(edgegg);
722 _lwt_release_nodes(nodes, num_nodes);
723 lwerror("SQL/MM Spatial exception - geometry crosses a node%s", locinfo);
724 return -1;
725 }
726 }
727 if ( nodes ) _lwt_release_nodes(nodes, num_nodes);
728 /* may be NULL if num_nodes == 0 */
729
730 /* loop over each edge within the edge's gbox */
731 edges = lwt_be_getEdgeWithinBox2D( topo, edgebox, &num_edges, LWT_COL_EDGE_ALL, 0 );
732 LWDEBUGF(1, "lwt_be_getEdgeWithinBox2D returned %llu edges", num_edges);
733 if (num_edges == UINT64_MAX)
734 {
735 GEOSGeom_destroy(edgegg);
737 return -1;
738 }
739 for ( i=0; i<num_edges; ++i )
740 {
741 LWT_ISO_EDGE* edge = &(edges[i]);
742 LWT_ELEMID edge_id = edge->edge_id;
743 GEOSGeometry *eegg;
744 char *relate;
745 int match;
746
747 if ( edge_id == myself ) continue;
748
749 if ( ! edge->geom ) {
750 _lwt_release_edges(edges, num_edges);
751 lwerror("Edge %" LWTFMT_ELEMID " has NULL geometry!", edge_id);
752 return -1;
753 }
754
755 eegg = LWGEOM2GEOS( lwline_as_lwgeom(edge->geom), 0 );
756 if ( ! eegg ) {
757 GEOSGeom_destroy(edgegg);
758 _lwt_release_edges(edges, num_edges);
759 lwerror("Could not convert edge geometry to GEOS: %s", lwgeom_geos_errmsg);
760 return -1;
761 }
762
763 LWDEBUGF(2, "Edge %" LWTFMT_ELEMID " converted to GEOS", edge_id);
764
765 /* check if the edge has a non-boundary-boundary intersection with our edge */
766
767 relate = GEOSRelateBoundaryNodeRule(eegg, edgegg, 2);
768 if ( ! relate ) {
769 GEOSGeom_destroy(eegg);
770 GEOSGeom_destroy(edgegg);
771 _lwt_release_edges(edges, num_edges);
772 lwerror("GEOSRelateBoundaryNodeRule error: %s", lwgeom_geos_errmsg);
773 return -1;
774 }
775
776 LWDEBUGF(2, "Edge %" LWTFMT_ELEMID " relate pattern is %s", edge_id, relate);
777
778 match = GEOSRelatePatternMatch(relate, "FF*F*****");
779 if ( match ) {
780 /* error or no interior intersection */
781 GEOSFree(relate);
782 GEOSGeom_destroy(eegg);
783 if ( match == 2 ) {
784 _lwt_release_edges(edges, num_edges);
785 GEOSGeom_destroy(edgegg);
786 lwerror("GEOSRelatePatternMatch error: %s", lwgeom_geos_errmsg);
787 return -1;
788 }
789 continue; /* no interior intersection */
790 }
791
792 match = GEOSRelatePatternMatch(relate, "1FFF*FFF2");
793 if ( match ) {
794 char locinfo[128] = "";
795 const char *locsuffix = match == 2 ? ""
796 : _lwt_describe_intersection_point(edgegg, eegg, locinfo, sizeof(locinfo)) ? locinfo
797 : "";
798 GEOSGeom_destroy(eegg);
799 GEOSGeom_destroy(edgegg);
800 _lwt_release_edges(edges, num_edges);
801 GEOSFree(relate);
802 if (match == 2)
803 {
804 lwerror("GEOSRelatePatternMatch error: %s", lwgeom_geos_errmsg);
805 }
806 else
807 {
808 lwerror("SQL/MM Spatial exception - coincident edge %" LWTFMT_ELEMID "%s", edge_id, locsuffix);
809 }
810 return -1;
811 }
812
813 match = GEOSRelatePatternMatch(relate, "1********");
814 if ( match ) {
815 char locinfo[128] = "";
816 const char *locsuffix = match == 2 ? ""
817 : _lwt_describe_intersection_point(edgegg, eegg, locinfo, sizeof(locinfo)) ? locinfo
818 : "";
819 GEOSGeom_destroy(eegg);
820 GEOSGeom_destroy(edgegg);
821 _lwt_release_edges(edges, num_edges);
822 GEOSFree(relate);
823 if (match == 2)
824 {
825 lwerror("GEOSRelatePatternMatch error: %s", lwgeom_geos_errmsg);
826 }
827 else
828 {
829 lwerror("Spatial exception - geometry intersects edge %" LWTFMT_ELEMID "%s", edge_id, locsuffix);
830 }
831 return -1;
832 }
833
834 match = GEOSRelatePatternMatch(relate, "T********");
835 if ( match ) {
836 char locinfo[128] = "";
837 const char *locsuffix = match == 2 ? ""
838 : _lwt_describe_intersection_point(edgegg, eegg, locinfo, sizeof(locinfo)) ? locinfo
839 : "";
840 GEOSGeom_destroy(eegg);
841 GEOSGeom_destroy(edgegg);
842 _lwt_release_edges(edges, num_edges);
843 GEOSFree(relate);
844 if (match == 2)
845 {
846 lwerror("GEOSRelatePatternMatch error: %s", lwgeom_geos_errmsg);
847 }
848 else
849 {
850 lwerror(
851 "SQL/MM Spatial exception - geometry crosses edge %" LWTFMT_ELEMID "%s", edge_id, locsuffix);
852 }
853 return -1;
854 }
855
856 match = GEOSRelatePatternMatch(relate, "*T*******");
857 if ( match ) {
858 char locinfo[128] = "";
859 const char *locsuffix = match == 2 ? ""
860 : _lwt_describe_intersection_point(edgegg, eegg, locinfo, sizeof(locinfo)) ? locinfo
861 : "";
862 GEOSGeom_destroy(eegg);
863 GEOSGeom_destroy(edgegg);
864 _lwt_release_edges(edges, num_edges);
865 GEOSFree(relate);
866 if (match == 2)
867 {
868 lwerror("GEOSRelatePatternMatch error: %s", lwgeom_geos_errmsg);
869 }
870 else
871 {
872 lwerror("Spatial exception - geometry boundary touches interior of edge %" LWTFMT_ELEMID "%s",
873 edge_id,
874 locsuffix);
875 }
876 return -1;
877 }
878
879 match = GEOSRelatePatternMatch(relate, "***T*****");
880 if ( match ) {
881 char locinfo[128] = "";
882 const char *locsuffix = match == 2 ? ""
883 : _lwt_describe_intersection_point(edgegg, eegg, locinfo, sizeof(locinfo)) ? locinfo
884 : "";
885 GEOSGeom_destroy(eegg);
886 GEOSGeom_destroy(edgegg);
887 _lwt_release_edges(edges, num_edges);
888 GEOSFree(relate);
889 if (match == 2)
890 {
891 lwerror("GEOSRelatePatternMatch error: %s", lwgeom_geos_errmsg);
892 }
893 else
894 {
895 lwerror("Spatial exception - boundary of edge %" LWTFMT_ELEMID " touches interior of geometry%s",
896 edge_id,
897 locsuffix);
898 }
899 return -1;
900 }
901
902 LWDEBUGF(2, "Edge %" LWTFMT_ELEMID " analysis completed, it does no harm", edge_id);
903
904 GEOSFree(relate);
905 GEOSGeom_destroy(eegg);
906 }
907 LWDEBUGF(1, "No edge crossing detected among the %llu candidate edges", num_edges);
908 if ( edges ) _lwt_release_edges(edges, num_edges);
909 /* would be NULL if num_edges was 0 */
910
911 GEOSGeom_destroy(edgegg);
912
913 return 0;
914}
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:94
int getPoint2d_p(const POINTARRAY *pa, uint32_t n, POINT2D *point)
Definition lwgeom_api.c:342
LWGEOM * lwline_as_lwgeom(const LWLINE *obj)
Definition lwgeom.c:367
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:771
int ptarray_contains_point_partial(const POINTARRAY *pa, const POINT2D *pt, int check_closed, int *winding_number)
Definition ptarray.c:1031
#define LW_BOUNDARY
LWT_INT64 LWT_ELEMID
Identifier of topology element.
#define LWT_COL_EDGE_ALL
#define LWT_COL_NODE_ALL
#define PGTOPO_BE_ERROR()
#define LWTFMT_ELEMID
Datum contains(PG_FUNCTION_ARGS)
#define LWDEBUGF(level, msg,...)
Definition lwgeom_log.h:106
void lwnotice(const char *fmt,...) __attribute__((format(printf
Write a notice out to the notice handler.
void void lwerror(const char *fmt,...) __attribute__((format(printf
Write a notice out to the error handler.
static void _lwt_release_nodes(LWT_ISO_NODE *nodes, int num_nodes)
void _lwt_release_edges(LWT_ISO_EDGE *edges, int num_edges)
static LWT_ISO_NODE * lwt_be_getNodeWithinBox2D(const LWT_TOPOLOGY *topo, const GBOX *box, uint64_t *numelems, int fields, uint64_t limit)
static bool _lwt_describe_intersection_point(const GEOSGeometry *g1, const GEOSGeometry *g2, char *buf, size_t bufsize)
Definition lwgeom_topo.c:47
LWT_ISO_EDGE * lwt_be_getEdgeWithinBox2D(const LWT_TOPOLOGY *topo, const GBOX *box, uint64_t *numelems, int fields, uint64_t limit)
POINTARRAY * points
Definition liblwgeom.h:483
POINTARRAY * point
Definition liblwgeom.h:471
LWT_ELEMID edge_id
LWT_ELEMID node_id
LWPOINT * geom
double y
Definition liblwgeom.h:390
double x
Definition liblwgeom.h:390
uint32_t npoints
Definition liblwgeom.h:427

References _lwt_describe_intersection_point(), _lwt_release_edges(), _lwt_release_nodes(), contains(), LWT_ISO_EDGE::edge_id, LWT_ISO_NODE::geom, LWT_ISO_EDGE::geom, getPoint2d_p(), 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_COL_EDGE_ALL, LWT_COL_NODE_ALL, LWTFMT_ELEMID, LWT_ISO_NODE::node_id, POINTARRAY::npoints, PGTOPO_BE_ERROR, LWPOINT::point, LWLINE::points, ptarray_contains_point_partial(), POINT2D::x, and POINT2D::y.

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: