PostGIS  2.5.0dev-r@@SVN_REVISION@@
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, LWDEBUGF, lwerror(), LWGEOM2GEOS(), lwgeom_geos_errmsg, lwgeom_geos_error(), lwgeom_get_bbox(), lwline_as_lwgeom(), lwnotice(), lwpoint_as_lwgeom(), lwt_be_getEdgeWithinBox2D(), lwt_be_getNodeWithinBox2D(), lwt_be_lastErrorMessage(), LWT_COL_EDGE_ALL, LWT_COL_NODE_ALL, LWTFMT_ELEMID, and LWT_ISO_NODE::node_id.

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

Here is the call graph for this function:

Here is the caller graph for this function: