PostGIS  2.5.0beta1dev-r@@SVN_REVISION@@

◆ lwt_AddIsoEdge()

LWT_ELEMID lwt_AddIsoEdge ( LWT_TOPOLOGY topo,
LWT_ELEMID  startNode,
LWT_ELEMID  endNode,
const LWLINE geom 
)

Add an isolated edge connecting two existing isolated nodes.

For ST_AddIsoEdge

Parameters
topothe topology to operate on
start_nodeidentifier of the starting node
end_nodeidentifier of the ending node
geomthe edge geometry
Returns
ID of the newly added edge, or -1 on error (liblwgeom error handler will be invoked with error message)

Definition at line 770 of file lwgeom_topo.c.

References _lwt_CheckEdgeCrossing(), _lwt_release_nodes(), LWT_TOPOLOGY_T::be_iface, LWT_ISO_NODE::containing_face, LWT_ISO_EDGE::edge_id, LWT_ISO_EDGE::end_node, LWT_ISO_EDGE::face_left, LWT_ISO_EDGE::face_right, LWT_ISO_NODE::geom, LWT_ISO_EDGE::geom, getPoint2d_p(), lwerror(), lwgeom_is_simple(), lwline_as_lwgeom(), lwt_be_getNextEdgeId(), lwt_be_getNodeById(), lwt_be_insertEdges(), lwt_be_lastErrorMessage(), lwt_be_updateNodesById(), LWT_COL_NODE_ALL, LWT_COL_NODE_CONTAINING_FACE, LWT_ISO_EDGE::next_left, LWT_ISO_EDGE::next_right, LWT_ISO_NODE::node_id, POINTARRAY::npoints, p2d_same(), LWPOINT::point, LWLINE::points, and LWT_ISO_EDGE::start_node.

772 {
773  int num_nodes;
774  int i;
775  LWT_ISO_EDGE newedge;
776  LWT_ISO_NODE *endpoints;
777  LWT_ELEMID containing_face = -1;
778  LWT_ELEMID node_ids[2];
779  LWT_ISO_NODE updated_nodes[2];
780  int skipISOChecks = 0;
781  POINT2D p1, p2;
782 
783  /* NOT IN THE SPECS:
784  * A closed edge is never isolated (as it forms a face)
785  */
786  if ( startNode == endNode )
787  {
788  lwerror("Closed edges would not be isolated, try lwt_AddEdgeNewFaces");
789  return -1;
790  }
791 
792  if ( ! skipISOChecks )
793  {
794  /* Acurve must be simple */
795  if ( ! lwgeom_is_simple(lwline_as_lwgeom(geom)) )
796  {
797  lwerror("SQL/MM Spatial exception - curve not simple");
798  return -1;
799  }
800  }
801 
802  /*
803  * Check for:
804  * existence of nodes
805  * nodes faces match
806  * Extract:
807  * nodes face id
808  * nodes geoms
809  */
810  num_nodes = 2;
811  node_ids[0] = startNode;
812  node_ids[1] = endNode;
813  endpoints = lwt_be_getNodeById( topo, node_ids, &num_nodes,
815  if ( num_nodes < 0 )
816  {
817  lwerror("Backend error: %s", lwt_be_lastErrorMessage(topo->be_iface));
818  return -1;
819  }
820  else if ( num_nodes < 2 )
821  {
822  if ( num_nodes ) _lwt_release_nodes(endpoints, num_nodes);
823  lwerror("SQL/MM Spatial exception - non-existent node");
824  return -1;
825  }
826  for ( i=0; i<num_nodes; ++i )
827  {
828  const LWT_ISO_NODE *n = &(endpoints[i]);
829  if ( n->containing_face == -1 )
830  {
831  _lwt_release_nodes(endpoints, num_nodes);
832  lwerror("SQL/MM Spatial exception - not isolated node");
833  return -1;
834  }
835  if ( containing_face == -1 ) containing_face = n->containing_face;
836  else if ( containing_face != n->containing_face )
837  {
838  _lwt_release_nodes(endpoints, num_nodes);
839  lwerror("SQL/MM Spatial exception - nodes in different faces");
840  return -1;
841  }
842 
843  if ( ! skipISOChecks )
844  {
845  if ( n->node_id == startNode )
846  {
847  /* l) Check that start point of acurve match start node geoms. */
848  getPoint2d_p(geom->points, 0, &p1);
849  getPoint2d_p(n->geom->point, 0, &p2);
850  if ( ! p2d_same(&p1, &p2) )
851  {
852  _lwt_release_nodes(endpoints, num_nodes);
853  lwerror("SQL/MM Spatial exception - "
854  "start node not geometry start point.");
855  return -1;
856  }
857  }
858  else
859  {
860  /* m) Check that end point of acurve match end node geoms. */
861  getPoint2d_p(geom->points, geom->points->npoints-1, &p1);
862  getPoint2d_p(n->geom->point, 0, &p2);
863  if ( ! p2d_same(&p1, &p2) )
864  {
865  _lwt_release_nodes(endpoints, num_nodes);
866  lwerror("SQL/MM Spatial exception - "
867  "end node not geometry end point.");
868  return -1;
869  }
870  }
871  }
872  }
873 
874  if ( num_nodes ) _lwt_release_nodes(endpoints, num_nodes);
875 
876  if ( ! skipISOChecks )
877  {
878  if ( _lwt_CheckEdgeCrossing( topo, startNode, endNode, geom, 0 ) )
879  {
880  /* would have called lwerror already, leaking :( */
881  return -1;
882  }
883  }
884 
885  /*
886  * All checks passed, time to prepare the new edge
887  */
888 
889  newedge.edge_id = lwt_be_getNextEdgeId( topo );
890  if ( newedge.edge_id == -1 ) {
891  lwerror("Backend error: %s", lwt_be_lastErrorMessage(topo->be_iface));
892  return -1;
893  }
894 
895  /* TODO: this should likely be an exception instead ! */
896  if ( containing_face == -1 ) containing_face = 0;
897 
898  newedge.start_node = startNode;
899  newedge.end_node = endNode;
900  newedge.face_left = newedge.face_right = containing_face;
901  newedge.next_left = -newedge.edge_id;
902  newedge.next_right = newedge.edge_id;
903  newedge.geom = (LWLINE *)geom; /* const cast.. */
904 
905  int ret = lwt_be_insertEdges(topo, &newedge, 1);
906  if ( ret == -1 ) {
907  lwerror("Backend error: %s", lwt_be_lastErrorMessage(topo->be_iface));
908  return -1;
909  } else if ( ret == 0 ) {
910  lwerror("Insertion of split edge failed (no reason)");
911  return -1;
912  }
913 
914  /*
915  * Update Node containing_face values
916  *
917  * the nodes anode and anothernode are no more isolated
918  * because now there is an edge connecting them
919  */
920  updated_nodes[0].node_id = startNode;
921  updated_nodes[0].containing_face = -1;
922  updated_nodes[1].node_id = endNode;
923  updated_nodes[1].containing_face = -1;
924  ret = lwt_be_updateNodesById(topo, updated_nodes, 2,
926  if ( ret == -1 ) {
927  lwerror("Backend error: %s", lwt_be_lastErrorMessage(topo->be_iface));
928  return -1;
929  }
930 
931  return newedge.edge_id;
932 }
static int _lwt_CheckEdgeCrossing(LWT_TOPOLOGY *topo, LWT_ELEMID start_node, LWT_ELEMID end_node, const LWLINE *geom, LWT_ELEMID myself)
Definition: lwgeom_topo.c:601
static void _lwt_release_nodes(LWT_ISO_NODE *nodes, int num_nodes)
Definition: lwgeom_topo.c:467
LWT_ELEMID face_left
#define LWT_COL_NODE_CONTAINING_FACE
LWT_ELEMID containing_face
LWPOINT * geom
LWLINE * geom
POINTARRAY * point
Definition: liblwgeom.h:413
LWT_ELEMID next_left
int p2d_same(const POINT2D *p1, const POINT2D *p2)
Definition: lwalgorithm.c:49
LWGEOM * lwline_as_lwgeom(const LWLINE *obj)
Definition: lwgeom.c:330
const LWT_BE_IFACE * be_iface
LWT_ELEMID face_right
LWT_ELEMID node_id
LWT_ELEMID edge_id
static int lwt_be_updateNodesById(LWT_TOPOLOGY *topo, const LWT_ISO_NODE *nodes, int numnodes, int upd_fields)
Definition: lwgeom_topo.c:314
LWT_ELEMID lwt_be_getNextEdgeId(LWT_TOPOLOGY *topo)
Definition: lwgeom_topo.c:219
int getPoint2d_p(const POINTARRAY *pa, uint32_t n, POINT2D *point)
Definition: lwgeom_api.c:338
int lwt_be_insertEdges(LWT_TOPOLOGY *topo, LWT_ISO_EDGE *edge, int numelems)
Definition: lwgeom_topo.c:268
#define LWT_COL_NODE_ALL
LWT_ELEMID start_node
int lwgeom_is_simple(const LWGEOM *lwgeom)
LWT_ELEMID next_right
LWT_INT64 LWT_ELEMID
Identifier of topology element.
LWT_ISO_NODE * lwt_be_getNodeById(LWT_TOPOLOGY *topo, const LWT_ELEMID *ids, int *numelems, int fields)
Definition: lwgeom_topo.c:156
LWT_ELEMID end_node
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
POINTARRAY * points
Definition: liblwgeom.h:424
uint32_t npoints
Definition: liblwgeom.h:373
Here is the call graph for this function: