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

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

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_STRICT, LWPOINT::point, LWLINE::points, and LWT_ISO_EDGE::start_node.

Here is the call graph for this function: