671{
672 uint64_t i, num_nodes, num_edges;
676 GEOSGeometry *edgegg;
677
679
681 if (!edgegg)
682 {
684 return -1;
685 }
687
688
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 {
701 if (node->
node_id == start_node)
702 continue;
704 continue;
705
706
708 {
709 GEOSGeom_destroy(edgegg);
711 lwerror(
"SQL/MM Spatial exception - geometry crosses a node");
712 return -1;
713 }
714
718 {
719 char locinfo[128] = "";
720 snprintf(locinfo,
sizeof(locinfo),
" at POINT(%.15g %.15g)", p.
x, p.
y);
721 GEOSGeom_destroy(edgegg);
723 lwerror(
"SQL/MM Spatial exception - geometry crosses a node%s", locinfo);
724 return -1;
725 }
726 }
728
729
730
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 {
743 GEOSGeometry *eegg;
744 char *relate;
745 int match;
746
747 if ( edge_id == myself ) continue;
748
749 if ( ! edge->
geom ) {
752 return -1;
753 }
754
756 if ( ! eegg ) {
757 GEOSGeom_destroy(edgegg);
760 return -1;
761 }
762
764
765
766
767 relate = GEOSRelateBoundaryNodeRule(eegg, edgegg, 2);
768 if ( ! relate ) {
769 GEOSGeom_destroy(eegg);
770 GEOSGeom_destroy(edgegg);
773 return -1;
774 }
775
777
778 match = GEOSRelatePatternMatch(relate, "FF*F*****");
779 if ( match ) {
780
781 GEOSFree(relate);
782 GEOSGeom_destroy(eegg);
783 if ( match == 2 ) {
785 GEOSGeom_destroy(edgegg);
787 return -1;
788 }
789 continue;
790 }
791
792 match = GEOSRelatePatternMatch(relate, "1FFF*FFF2");
793 if ( match ) {
794 char locinfo[128] = "";
795 const char *locsuffix = match == 2 ? ""
797 : "";
798 GEOSGeom_destroy(eegg);
799 GEOSGeom_destroy(edgegg);
801 GEOSFree(relate);
802 if (match == 2)
803 {
805 }
806 else
807 {
809 }
810 return -1;
811 }
812
813 match = GEOSRelatePatternMatch(relate, "1********");
814 if ( match ) {
815 char locinfo[128] = "";
816 const char *locsuffix = match == 2 ? ""
818 : "";
819 GEOSGeom_destroy(eegg);
820 GEOSGeom_destroy(edgegg);
822 GEOSFree(relate);
823 if (match == 2)
824 {
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 ? ""
839 : "";
840 GEOSGeom_destroy(eegg);
841 GEOSGeom_destroy(edgegg);
843 GEOSFree(relate);
844 if (match == 2)
845 {
847 }
848 else
849 {
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 ? ""
861 : "";
862 GEOSGeom_destroy(eegg);
863 GEOSGeom_destroy(edgegg);
865 GEOSFree(relate);
866 if (match == 2)
867 {
869 }
870 else
871 {
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 ? ""
884 : "";
885 GEOSGeom_destroy(eegg);
886 GEOSGeom_destroy(edgegg);
888 GEOSFree(relate);
889 if (match == 2)
890 {
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
903
904 GEOSFree(relate);
905 GEOSGeom_destroy(eegg);
906 }
907 LWDEBUGF(1,
"No edge crossing detected among the %llu candidate edges", num_edges);
909
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,...)
int getPoint2d_p(const POINTARRAY *pa, uint32_t n, POINT2D *point)
LWGEOM * lwline_as_lwgeom(const LWLINE *obj)
const GBOX * lwgeom_get_bbox(const LWGEOM *lwgeom)
Get a non-empty geometry bounding box, computing and caching it if not already there.
int ptarray_contains_point_partial(const POINTARRAY *pa, const POINT2D *pt, int check_closed, int *winding_number)
LWT_INT64 LWT_ELEMID
Identifier of topology element.
#define PGTOPO_BE_ERROR()
Datum contains(PG_FUNCTION_ARGS)
#define LWDEBUGF(level, msg,...)
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)
LWT_ISO_EDGE * lwt_be_getEdgeWithinBox2D(const LWT_TOPOLOGY *topo, const GBOX *box, uint64_t *numelems, int fields, uint64_t limit)