PostGIS  3.3.9dev-r@@SVN_REVISION@@

◆ _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 611 of file lwgeom_topo.c.

614 {
615  uint64_t i, num_nodes, num_edges;
616  LWT_ISO_EDGE *edges;
617  LWT_ISO_NODE *nodes;
618  const GBOX *edgebox;
619  GEOSGeometry *edgegg;
620 
621  initGEOS(lwnotice, lwgeom_geos_error);
622 
623  edgegg = LWGEOM2GEOS(lwline_as_lwgeom(geom), 0);
624  if (!edgegg)
625  {
626  lwerror("Could not convert edge geometry to GEOS: %s", lwgeom_geos_errmsg);
627  return -1;
628  }
629  edgebox = lwgeom_get_bbox( lwline_as_lwgeom(geom) );
630 
631  /* loop over each node within the edge's gbox */
632  nodes = lwt_be_getNodeWithinBox2D( topo, edgebox, &num_nodes,
633  LWT_COL_NODE_ALL, 0 );
634  LWDEBUGF(1, "lwt_be_getNodeWithinBox2D returned %d nodes", num_nodes);
635  if (num_nodes == UINT64_MAX)
636  {
637  lwerror("Backend error: %s", lwt_be_lastErrorMessage(topo->be_iface));
638  return -1;
639  }
640  for ( i=0; i<num_nodes; ++i )
641  {
642  const POINT2D *pt;
643  LWT_ISO_NODE* node = &(nodes[i]);
644  if ( node->node_id == start_node ) continue;
645  if ( node->node_id == end_node ) continue;
646  /* check if the edge contains this node (not on boundary) */
647  /* ST_RelateMatch(rec.relate, 'T********') */
648  pt = getPoint2d_cp(node->geom->point, 0);
650  if ( contains )
651  {
652  GEOSGeom_destroy(edgegg);
653  _lwt_release_nodes(nodes, num_nodes);
654  lwerror("SQL/MM Spatial exception - geometry crosses a node");
655  return -1;
656  }
657  }
658  if ( nodes ) _lwt_release_nodes(nodes, num_nodes);
659  /* may be NULL if num_nodes == 0 */
660 
661  /* loop over each edge within the edge's gbox */
662  edges = lwt_be_getEdgeWithinBox2D( topo, edgebox, &num_edges, LWT_COL_EDGE_ALL, 0 );
663  LWDEBUGF(1, "lwt_be_getEdgeWithinBox2D returned %d edges", num_edges);
664  if (num_edges == UINT64_MAX)
665  {
666  GEOSGeom_destroy(edgegg);
667  lwerror("Backend error: %s", lwt_be_lastErrorMessage(topo->be_iface));
668  return -1;
669  }
670  for ( i=0; i<num_edges; ++i )
671  {
672  LWT_ISO_EDGE* edge = &(edges[i]);
673  LWT_ELEMID edge_id = edge->edge_id;
674  GEOSGeometry *eegg;
675  char *relate;
676  int match;
677 
678  if ( edge_id == myself ) continue;
679 
680  if ( ! edge->geom ) {
681  _lwt_release_edges(edges, num_edges);
682  lwerror("Edge %d has NULL geometry!", edge_id);
683  return -1;
684  }
685 
686  eegg = LWGEOM2GEOS( lwline_as_lwgeom(edge->geom), 0 );
687  if ( ! eegg ) {
688  GEOSGeom_destroy(edgegg);
689  _lwt_release_edges(edges, num_edges);
690  lwerror("Could not convert edge geometry to GEOS: %s", lwgeom_geos_errmsg);
691  return -1;
692  }
693 
694  LWDEBUGF(2, "Edge %d converted to GEOS", edge_id);
695 
696  /* check if the edge has a non-boundary-boundary intersection with our edge */
697 
698  relate = GEOSRelateBoundaryNodeRule(eegg, edgegg, 2);
699  if ( ! relate ) {
700  GEOSGeom_destroy(eegg);
701  GEOSGeom_destroy(edgegg);
702  _lwt_release_edges(edges, num_edges);
703  lwerror("GEOSRelateBoundaryNodeRule error: %s", lwgeom_geos_errmsg);
704  return -1;
705  }
706 
707  LWDEBUGF(2, "Edge %d relate pattern is %s", edge_id, relate);
708 
709  match = GEOSRelatePatternMatch(relate, "FF*F*****");
710  if ( match ) {
711  /* error or no interior intersection */
712  GEOSGeom_destroy(eegg);
713  GEOSFree(relate);
714  if ( match == 2 ) {
715  _lwt_release_edges(edges, num_edges);
716  GEOSGeom_destroy(edgegg);
717  lwerror("GEOSRelatePatternMatch error: %s", lwgeom_geos_errmsg);
718  return -1;
719  }
720  else continue; /* no interior intersection */
721  }
722 
723  match = GEOSRelatePatternMatch(relate, "1FFF*FFF2");
724  if ( match ) {
725  _lwt_release_edges(edges, num_edges);
726  GEOSGeom_destroy(edgegg);
727  GEOSGeom_destroy(eegg);
728  GEOSFree(relate);
729  if ( match == 2 ) {
730  lwerror("GEOSRelatePatternMatch error: %s", lwgeom_geos_errmsg);
731  } else {
732  lwerror("SQL/MM Spatial exception - coincident edge %" LWTFMT_ELEMID,
733  edge_id);
734  }
735  return -1;
736  }
737 
738  match = GEOSRelatePatternMatch(relate, "1********");
739  if ( match ) {
740  _lwt_release_edges(edges, num_edges);
741  GEOSGeom_destroy(edgegg);
742  GEOSGeom_destroy(eegg);
743  GEOSFree(relate);
744  if ( match == 2 ) {
745  lwerror("GEOSRelatePatternMatch error: %s", lwgeom_geos_errmsg);
746  } else {
747  lwerror("Spatial exception - geometry intersects edge %"
748  LWTFMT_ELEMID, edge_id);
749  }
750  return -1;
751  }
752 
753  match = GEOSRelatePatternMatch(relate, "T********");
754  if ( match ) {
755  _lwt_release_edges(edges, num_edges);
756  GEOSGeom_destroy(edgegg);
757  GEOSGeom_destroy(eegg);
758  GEOSFree(relate);
759  if ( match == 2 ) {
760  lwerror("GEOSRelatePatternMatch error: %s", lwgeom_geos_errmsg);
761  } else {
762  lwerror("SQL/MM Spatial exception - geometry crosses edge %"
763  LWTFMT_ELEMID, edge_id);
764  }
765  return -1;
766  }
767 
768  match = GEOSRelatePatternMatch(relate, "*T*******");
769  if ( match ) {
770  _lwt_release_edges(edges, num_edges);
771  GEOSGeom_destroy(edgegg);
772  GEOSGeom_destroy(eegg);
773  GEOSFree(relate);
774  if ( match == 2 ) {
775  lwerror("GEOSRelatePatternMatch error: %s", lwgeom_geos_errmsg);
776  } else {
777  lwerror("Spatial exception - geometry boundary touches interior of edge %"
778  LWTFMT_ELEMID, edge_id);
779  }
780  return -1;
781  }
782 
783  match = GEOSRelatePatternMatch(relate, "***T*****");
784  if ( match ) {
785  _lwt_release_edges(edges, num_edges);
786  GEOSGeom_destroy(edgegg);
787  GEOSGeom_destroy(eegg);
788  GEOSFree(relate);
789  if ( match == 2 ) {
790  lwerror("GEOSRelatePatternMatch error: %s", lwgeom_geos_errmsg);
791  } else {
792  lwerror("Spatial exception - boundary of edge % touches interior of geometry"
793  LWTFMT_ELEMID, edge_id);
794  }
795  return -1;
796  }
797 
798  LWDEBUGF(2, "Edge %d analisys completed, it does no harm", edge_id);
799 
800  GEOSFree(relate);
801  GEOSGeom_destroy(eegg);
802  }
803  LWDEBUGF(1, "No edge crossing detected among the %d candidate edges", num_edges);
804  if ( edges ) _lwt_release_edges(edges, num_edges);
805  /* would be NULL if num_edges was 0 */
806 
807  GEOSGeom_destroy(edgegg);
808 
809  return 0;
810 }
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)
Definition: lwgeom.c:339
#define LW_FALSE
Definition: liblwgeom.h:109
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:743
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
const char * lwt_be_lastErrorMessage(const LWT_BE_IFACE *be)
Definition: lwgeom_topo.c:119
static void _lwt_release_nodes(LWT_ISO_NODE *nodes, int num_nodes)
Definition: lwgeom_topo.c:475
static LWT_ISO_NODE * lwt_be_getNodeWithinBox2D(const LWT_TOPOLOGY *topo, const GBOX *box, uint64_t *numelems, int fields, uint64_t limit)
Definition: lwgeom_topo.c:172
static LWT_ISO_EDGE * lwt_be_getEdgeWithinBox2D(const LWT_TOPOLOGY *topo, const GBOX *box, uint64_t *numelems, int fields, uint64_t limit)
Definition: lwgeom_topo.c:178
#define LWTFMT_ELEMID
Definition: lwgeom_topo.c:43
static void _lwt_release_edges(LWT_ISO_EDGE *edges, int num_edges)
Definition: lwgeom_topo.c:465
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:101
Datum contains(PG_FUNCTION_ARGS)
POINTARRAY * points
Definition: liblwgeom.h:498
POINTARRAY * point
Definition: liblwgeom.h:486
LWLINE * geom
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: