PostGIS  2.5.1dev-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 601 of file lwgeom_topo.c.

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().

604 {
605  int i, num_nodes, num_edges;
606  LWT_ISO_EDGE *edges;
607  LWT_ISO_NODE *nodes;
608  const GBOX *edgebox;
609  GEOSGeometry *edgegg;
610 
611  initGEOS(lwnotice, lwgeom_geos_error);
612 
613  edgegg = LWGEOM2GEOS( lwline_as_lwgeom(geom), 0);
614  if ( ! edgegg ) {
615  lwerror("Could not convert edge geometry to GEOS: %s", lwgeom_geos_errmsg);
616  return -1;
617  }
618  edgebox = lwgeom_get_bbox( lwline_as_lwgeom(geom) );
619 
620  /* loop over each node within the edge's gbox */
621  nodes = lwt_be_getNodeWithinBox2D( topo, edgebox, &num_nodes,
622  LWT_COL_NODE_ALL, 0 );
623  LWDEBUGF(1, "lwt_be_getNodeWithinBox2D returned %d nodes", num_nodes);
624  if ( num_nodes == -1 ) {
625  lwerror("Backend error: %s", lwt_be_lastErrorMessage(topo->be_iface));
626  return -1;
627  }
628  for ( i=0; i<num_nodes; ++i )
629  {
630  const POINT2D *pt;
631  LWT_ISO_NODE* node = &(nodes[i]);
632  if ( node->node_id == start_node ) continue;
633  if ( node->node_id == end_node ) continue;
634  /* check if the edge contains this node (not on boundary) */
635  /* ST_RelateMatch(rec.relate, 'T********') */
636  pt = getPoint2d_cp(node->geom->point, 0);
638  if ( contains )
639  {
640  GEOSGeom_destroy(edgegg);
641  _lwt_release_nodes(nodes, num_nodes);
642  lwerror("SQL/MM Spatial exception - geometry crosses a node");
643  return -1;
644  }
645  }
646  if ( nodes ) _lwt_release_nodes(nodes, num_nodes);
647  /* may be NULL if num_nodes == 0 */
648 
649  /* loop over each edge within the edge's gbox */
650  edges = lwt_be_getEdgeWithinBox2D( topo, edgebox, &num_edges, LWT_COL_EDGE_ALL, 0 );
651  LWDEBUGF(1, "lwt_be_getEdgeWithinBox2D returned %d edges", num_edges);
652  if ( num_edges == -1 ) {
653  GEOSGeom_destroy(edgegg);
654  lwerror("Backend error: %s", lwt_be_lastErrorMessage(topo->be_iface));
655  return -1;
656  }
657  for ( i=0; i<num_edges; ++i )
658  {
659  LWT_ISO_EDGE* edge = &(edges[i]);
660  LWT_ELEMID edge_id = edge->edge_id;
661  GEOSGeometry *eegg;
662  char *relate;
663  int match;
664 
665  if ( edge_id == myself ) continue;
666 
667  if ( ! edge->geom ) {
668  _lwt_release_edges(edges, num_edges);
669  lwerror("Edge %d has NULL geometry!", edge_id);
670  return -1;
671  }
672 
673  eegg = LWGEOM2GEOS( lwline_as_lwgeom(edge->geom), 0 );
674  if ( ! eegg ) {
675  GEOSGeom_destroy(edgegg);
676  _lwt_release_edges(edges, num_edges);
677  lwerror("Could not convert edge geometry to GEOS: %s", lwgeom_geos_errmsg);
678  return -1;
679  }
680 
681  LWDEBUGF(2, "Edge %d converted to GEOS", edge_id);
682 
683  /* check if the edge crosses our edge (not boundary-boundary) */
684 
685  relate = GEOSRelateBoundaryNodeRule(eegg, edgegg, 2);
686  if ( ! relate ) {
687  GEOSGeom_destroy(eegg);
688  GEOSGeom_destroy(edgegg);
689  _lwt_release_edges(edges, num_edges);
690  lwerror("GEOSRelateBoundaryNodeRule error: %s", lwgeom_geos_errmsg);
691  return -1;
692  }
693 
694  LWDEBUGF(2, "Edge %d relate pattern is %s", edge_id, relate);
695 
696  match = GEOSRelatePatternMatch(relate, "F********");
697  if ( match ) {
698  /* error or no interior intersection */
699  GEOSGeom_destroy(eegg);
700  GEOSFree(relate);
701  if ( match == 2 ) {
702  _lwt_release_edges(edges, num_edges);
703  GEOSGeom_destroy(edgegg);
704  lwerror("GEOSRelatePatternMatch error: %s", lwgeom_geos_errmsg);
705  return -1;
706  }
707  else continue; /* no interior intersection */
708  }
709 
710  match = GEOSRelatePatternMatch(relate, "1FFF*FFF2");
711  if ( match ) {
712  _lwt_release_edges(edges, num_edges);
713  GEOSGeom_destroy(edgegg);
714  GEOSGeom_destroy(eegg);
715  GEOSFree(relate);
716  if ( match == 2 ) {
717  lwerror("GEOSRelatePatternMatch error: %s", lwgeom_geos_errmsg);
718  } else {
719  lwerror("SQL/MM Spatial exception - coincident edge %" LWTFMT_ELEMID,
720  edge_id);
721  }
722  return -1;
723  }
724 
725  match = GEOSRelatePatternMatch(relate, "1********");
726  if ( match ) {
727  _lwt_release_edges(edges, num_edges);
728  GEOSGeom_destroy(edgegg);
729  GEOSGeom_destroy(eegg);
730  GEOSFree(relate);
731  if ( match == 2 ) {
732  lwerror("GEOSRelatePatternMatch error: %s", lwgeom_geos_errmsg);
733  } else {
734  lwerror("Spatial exception - geometry intersects edge %"
735  LWTFMT_ELEMID, edge_id);
736  }
737  return -1;
738  }
739 
740  match = GEOSRelatePatternMatch(relate, "T********");
741  if ( match ) {
742  _lwt_release_edges(edges, num_edges);
743  GEOSGeom_destroy(edgegg);
744  GEOSGeom_destroy(eegg);
745  GEOSFree(relate);
746  if ( match == 2 ) {
747  lwerror("GEOSRelatePatternMatch error: %s", lwgeom_geos_errmsg);
748  } else {
749  lwerror("SQL/MM Spatial exception - geometry crosses edge %"
750  LWTFMT_ELEMID, edge_id);
751  }
752  return -1;
753  }
754 
755  LWDEBUGF(2, "Edge %d analisys completed, it does no harm", edge_id);
756 
757  GEOSFree(relate);
758  GEOSGeom_destroy(eegg);
759  }
760  if ( edges ) _lwt_release_edges(edges, num_edges);
761  /* would be NULL if num_edges was 0 */
762 
763  GEOSGeom_destroy(edgegg);
764 
765  return 0;
766 }
static void _lwt_release_nodes(LWT_ISO_NODE *nodes, int num_nodes)
Definition: lwgeom_topo.c:467
LWPOINT * geom
void lwnotice(const char *fmt,...)
Write a notice out to the notice handler.
Definition: lwutil.c:177
Datum contains(PG_FUNCTION_ARGS)
char lwgeom_geos_errmsg[LWGEOM_GEOS_ERRMSG_MAXSIZE]
LWLINE * geom
POINTARRAY * point
Definition: liblwgeom.h:413
LWGEOM * lwline_as_lwgeom(const LWLINE *obj)
Definition: lwgeom.c:330
void lwgeom_geos_error(const char *fmt,...)
#define LW_FALSE
Definition: liblwgeom.h:76
const LWT_BE_IFACE * be_iface
int ptarray_contains_point_partial(const POINTARRAY *pa, const POINT2D *pt, int check_closed, int *winding_number)
Definition: ptarray.c:740
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:734
#define LWT_COL_EDGE_ALL
LWT_ELEMID node_id
LWT_ELEMID edge_id
GEOSGeometry * LWGEOM2GEOS(const LWGEOM *lwgeom, uint8_t autofix)
#define LW_BOUNDARY
#define LWT_COL_NODE_ALL
static void _lwt_release_edges(LWT_ISO_EDGE *edges, int num_edges)
Definition: lwgeom_topo.c:457
LWT_INT64 LWT_ELEMID
Identifier of topology element.
#define LWDEBUGF(level, msg,...)
Definition: lwgeom_log.h:88
static LWT_ISO_EDGE * lwt_be_getEdgeWithinBox2D(const LWT_TOPOLOGY *topo, const GBOX *box, int *numelems, int fields, int limit)
Definition: lwgeom_topo.c:179
static LWT_ISO_NODE * lwt_be_getNodeWithinBox2D(const LWT_TOPOLOGY *topo, const GBOX *box, int *numelems, int fields, int limit)
Definition: lwgeom_topo.c:171
const char * lwt_be_lastErrorMessage(const LWT_BE_IFACE *be)
Definition: lwgeom_topo.c:120
void lwerror(const char *fmt,...)
Write a notice out to the error handler.
Definition: lwutil.c:190
#define LWTFMT_ELEMID
Definition: lwgeom_topo.c:44
POINTARRAY * points
Definition: liblwgeom.h:424
const POINT2D * getPoint2d_cp(const POINTARRAY *pa, uint32_t n)
Returns a POINT2D pointer into the POINTARRAY serialized_ptlist, suitable for reading from...
Definition: lwgeom_api.c:364
Here is the call graph for this function:
Here is the caller graph for this function: