609{
610 uint64_t i, num_nodes, num_edges;
614 GEOSGeometry *edgegg;
615
617
619 if (!edgegg)
620 {
622 return -1;
623 }
625
626
629 LWDEBUGF(1,
"lwt_be_getNodeWithinBox2D returned %llu nodes", num_nodes);
630 if (num_nodes == UINT64_MAX)
631 {
633 return -1;
634 }
635 for ( i=0; i<num_nodes; ++i )
636 {
639 if ( node->
node_id == start_node )
continue;
640 if ( node->
node_id == end_node )
continue;
641
642
646 {
647 GEOSGeom_destroy(edgegg);
649 lwerror(
"SQL/MM Spatial exception - geometry crosses a node");
650 return -1;
651 }
652 }
654
655
656
658 LWDEBUGF(1,
"lwt_be_getEdgeWithinBox2D returned %llu edges", num_edges);
659 if (num_edges == UINT64_MAX)
660 {
661 GEOSGeom_destroy(edgegg);
663 return -1;
664 }
665 for ( i=0; i<num_edges; ++i )
666 {
669 GEOSGeometry *eegg;
670 char *relate;
671 int match;
672
673 if ( edge_id == myself ) continue;
674
675 if ( ! edge->
geom ) {
678 return -1;
679 }
680
682 if ( ! eegg ) {
683 GEOSGeom_destroy(edgegg);
686 return -1;
687 }
688
690
691
692
693 relate = GEOSRelateBoundaryNodeRule(eegg, edgegg, 2);
694 GEOSGeom_destroy(eegg);
695 if ( ! relate ) {
696 GEOSGeom_destroy(edgegg);
699 return -1;
700 }
701
703
704 match = GEOSRelatePatternMatch(relate, "FF*F*****");
705 if ( match ) {
706
707 GEOSFree(relate);
708 if ( match == 2 ) {
710 GEOSGeom_destroy(edgegg);
712 return -1;
713 }
714 else continue;
715 }
716
717 match = GEOSRelatePatternMatch(relate, "1FFF*FFF2");
718 if ( match ) {
720 GEOSGeom_destroy(edgegg);
721 GEOSFree(relate);
722 if ( match == 2 ) {
724 } else {
726 edge_id);
727 }
728 return -1;
729 }
730
731 match = GEOSRelatePatternMatch(relate, "1********");
732 if ( match ) {
734 GEOSGeom_destroy(edgegg);
735 GEOSFree(relate);
736 if ( match == 2 ) {
738 } else {
739 lwerror(
"Spatial exception - geometry intersects edge %"
741 }
742 return -1;
743 }
744
745 match = GEOSRelatePatternMatch(relate, "T********");
746 if ( match ) {
748 GEOSGeom_destroy(edgegg);
749 GEOSFree(relate);
750 if ( match == 2 ) {
752 } else {
753 lwerror(
"SQL/MM Spatial exception - geometry crosses edge %"
755 }
756 return -1;
757 }
758
759 match = GEOSRelatePatternMatch(relate, "*T*******");
760 if ( match ) {
762 GEOSGeom_destroy(edgegg);
763 GEOSFree(relate);
764 if ( match == 2 ) {
766 } else {
767 lwerror(
"Spatial exception - geometry boundary touches interior of edge %"
769 }
770 return -1;
771 }
772
773 match = GEOSRelatePatternMatch(relate, "***T*****");
774 if ( match ) {
776 GEOSGeom_destroy(edgegg);
777 GEOSFree(relate);
778 if ( match == 2 ) {
780 } else {
781 lwerror(
"Spatial exception - boundary of edge %" LWTFMT_ELEMID" touches interior of geometry", edge_id);
782 }
783 return -1;
784 }
785
787
788 GEOSFree(relate);
789 }
790 LWDEBUGF(1,
"No edge crossing detected among the %llu candidate edges", num_edges);
792
793
794 GEOSGeom_destroy(edgegg);
795
796 return 0;
797}
char lwgeom_geos_errmsg[LWGEOM_GEOS_ERRMSG_MAXSIZE]
GEOSGeometry * LWGEOM2GEOS(const LWGEOM *lwgeom, uint8_t autofix)
void lwgeom_geos_error(const char *fmt,...)
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)
LWT_ISO_EDGE * lwt_be_getEdgeWithinBox2D(const LWT_TOPOLOGY *topo, const GBOX *box, uint64_t *numelems, int fields, uint64_t limit)
static const POINT2D * getPoint2d_cp(const POINTARRAY *pa, uint32_t n)
Returns a POINT2D pointer into the POINTARRAY serialized_ptlist, suitable for reading from.