PostGIS  2.2.7dev-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 593 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().

596 {
597  int i, num_nodes, num_edges;
598  LWT_ISO_EDGE *edges;
599  LWT_ISO_NODE *nodes;
600  const GBOX *edgebox;
601  GEOSGeometry *edgegg;
602  const GEOSPreparedGeometry* prepared_edge;
603 
604  initGEOS(lwnotice, lwgeom_geos_error);
605 
606  edgegg = LWGEOM2GEOS( lwline_as_lwgeom(geom), 0);
607  if ( ! edgegg ) {
608  lwerror("Could not convert edge geometry to GEOS: %s", lwgeom_geos_errmsg);
609  return -1;
610  }
611  prepared_edge = GEOSPrepare( edgegg );
612  if ( ! prepared_edge ) {
613  lwerror("Could not prepare edge geometry: %s", lwgeom_geos_errmsg);
614  return -1;
615  }
616  edgebox = lwgeom_get_bbox( lwline_as_lwgeom(geom) );
617 
618  /* loop over each node within the edge's gbox */
619  nodes = lwt_be_getNodeWithinBox2D( topo, edgebox, &num_nodes,
620  LWT_COL_NODE_ALL, 0 );
621  LWDEBUGF(1, "lwt_be_getNodeWithinBox2D returned %d nodes", num_nodes);
622  if ( num_nodes == -1 ) {
623  GEOSPreparedGeom_destroy(prepared_edge);
624  GEOSGeom_destroy(edgegg);
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  LWT_ISO_NODE* node = &(nodes[i]);
631  GEOSGeometry *nodegg;
632  int contains;
633  if ( node->node_id == start_node ) continue;
634  if ( node->node_id == end_node ) continue;
635  /* check if the edge contains this node (not on boundary) */
636  nodegg = LWGEOM2GEOS( lwpoint_as_lwgeom(node->geom) , 0);
637  /* ST_RelateMatch(rec.relate, 'T********') */
638  contains = GEOSPreparedContains( prepared_edge, nodegg );
639  GEOSGeom_destroy(nodegg);
640  if (contains == 2)
641  {
642  GEOSPreparedGeom_destroy(prepared_edge);
643  GEOSGeom_destroy(edgegg);
644  _lwt_release_nodes(nodes, num_nodes);
645  lwerror("GEOS exception on PreparedContains: %s", lwgeom_geos_errmsg);
646  return -1;
647  }
648  if ( contains )
649  {
650  GEOSPreparedGeom_destroy(prepared_edge);
651  GEOSGeom_destroy(edgegg);
652  _lwt_release_nodes(nodes, num_nodes);
653  lwerror("SQL/MM Spatial exception - geometry crosses a node");
654  return -1;
655  }
656  }
657  if ( nodes ) _lwt_release_nodes(nodes, num_nodes);
658  /* may be NULL if num_nodes == 0 */
659 
660  /* loop over each edge within the edge's gbox */
661  edges = lwt_be_getEdgeWithinBox2D( topo, edgebox, &num_edges, LWT_COL_EDGE_ALL, 0 );
662  LWDEBUGF(1, "lwt_be_getEdgeWithinBox2D returned %d edges", num_edges);
663  if ( num_edges == -1 ) {
664  GEOSPreparedGeom_destroy(prepared_edge);
665  GEOSGeom_destroy(edgegg);
666  lwerror("Backend error: %s", lwt_be_lastErrorMessage(topo->be_iface));
667  return -1;
668  }
669  for ( i=0; i<num_edges; ++i )
670  {
671  LWT_ISO_EDGE* edge = &(edges[i]);
672  LWT_ELEMID edge_id = edge->edge_id;
673  GEOSGeometry *eegg;
674  char *relate;
675  int match;
676 
677  if ( edge_id == myself ) continue;
678 
679  if ( ! edge->geom ) {
680  _lwt_release_edges(edges, num_edges);
681  lwerror("Edge %d has NULL geometry!", edge_id);
682  return -1;
683  }
684 
685  eegg = LWGEOM2GEOS( lwline_as_lwgeom(edge->geom), 0 );
686  if ( ! eegg ) {
687  GEOSPreparedGeom_destroy(prepared_edge);
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 crosses our edge (not boundary-boundary) */
697 
698  relate = GEOSRelateBoundaryNodeRule(eegg, edgegg, 2);
699  if ( ! relate ) {
700  GEOSGeom_destroy(eegg);
701  GEOSPreparedGeom_destroy(prepared_edge);
702  GEOSGeom_destroy(edgegg);
703  _lwt_release_edges(edges, num_edges);
704  lwerror("GEOSRelateBoundaryNodeRule error: %s", lwgeom_geos_errmsg);
705  return -1;
706  }
707 
708  LWDEBUGF(2, "Edge %d relate pattern is %s", edge_id, relate);
709 
710  match = GEOSRelatePatternMatch(relate, "F********");
711  if ( match ) {
712  /* error or no interior intersection */
713  GEOSGeom_destroy(eegg);
714  GEOSFree(relate);
715  if ( match == 2 ) {
716  _lwt_release_edges(edges, num_edges);
717  GEOSPreparedGeom_destroy(prepared_edge);
718  GEOSGeom_destroy(edgegg);
719  lwerror("GEOSRelatePatternMatch error: %s", lwgeom_geos_errmsg);
720  return -1;
721  }
722  else continue; /* no interior intersection */
723  }
724 
725  match = GEOSRelatePatternMatch(relate, "1FFF*FFF2");
726  if ( match ) {
727  _lwt_release_edges(edges, num_edges);
728  GEOSPreparedGeom_destroy(prepared_edge);
729  GEOSGeom_destroy(edgegg);
730  GEOSGeom_destroy(eegg);
731  GEOSFree(relate);
732  if ( match == 2 ) {
733  lwerror("GEOSRelatePatternMatch error: %s", lwgeom_geos_errmsg);
734  } else {
735  lwerror("SQL/MM Spatial exception - coincident edge %" LWTFMT_ELEMID,
736  edge_id);
737  }
738  return -1;
739  }
740 
741  match = GEOSRelatePatternMatch(relate, "1********");
742  if ( match ) {
743  _lwt_release_edges(edges, num_edges);
744  GEOSPreparedGeom_destroy(prepared_edge);
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  GEOSPreparedGeom_destroy(prepared_edge);
761  GEOSGeom_destroy(edgegg);
762  GEOSGeom_destroy(eegg);
763  GEOSFree(relate);
764  if ( match == 2 ) {
765  lwerror("GEOSRelatePatternMatch error: %s", lwgeom_geos_errmsg);
766  } else {
767  lwerror("SQL/MM Spatial exception - geometry crosses edge %"
768  LWTFMT_ELEMID, edge_id);
769  }
770  return -1;
771  }
772 
773  LWDEBUGF(2, "Edge %d analisys completed, it does no harm", edge_id);
774 
775  GEOSFree(relate);
776  GEOSGeom_destroy(eegg);
777  }
778  if ( edges ) _lwt_release_edges(edges, num_edges);
779  /* would be NULL if num_edges was 0 */
780 
781  GEOSPreparedGeom_destroy(prepared_edge);
782  GEOSGeom_destroy(edgegg);
783 
784  return 0;
785 }
static void _lwt_release_nodes(LWT_ISO_NODE *nodes, int num_nodes)
Definition: lwgeom_topo.c:481
LWPOINT * geom
void lwnotice(const char *fmt,...)
Write a notice out to the notice handler.
Definition: lwutil.c:61
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:249
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:640
#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:471
LWGEOM * lwpoint_as_lwgeom(const LWPOINT *obj)
Definition: lwgeom.c:254
LWT_INT64 LWT_ELEMID
Identifier of topology element.
#define LWDEBUGF(level, msg,...)
Definition: lwgeom_log.h:55
static LWT_ISO_EDGE * lwt_be_getEdgeWithinBox2D(const LWT_TOPOLOGY *topo, const GBOX *box, int *numelems, int fields, int limit)
Definition: lwgeom_topo.c:183
static LWT_ISO_NODE * lwt_be_getNodeWithinBox2D(const LWT_TOPOLOGY *topo, const GBOX *box, int *numelems, int fields, int limit)
Definition: lwgeom_topo.c:175
const char * lwt_be_lastErrorMessage(const LWT_BE_IFACE *be)
Definition: lwgeom_topo.c:124
void lwerror(const char *fmt,...)
Write a notice out to the error handler.
Definition: lwutil.c:74
#define LWTFMT_ELEMID
Definition: lwgeom_topo.c:36

Here is the call graph for this function:

Here is the caller graph for this function: