PostGIS  3.4.0dev-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 615 of file lwgeom_topo.c.

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