PostGIS  2.5.0dev-r@@SVN_REVISION@@
LWT_ELEMID lwt_NewEdgesSplit ( LWT_TOPOLOGY topo,
LWT_ELEMID  edge,
LWPOINT pt,
int  skipChecks 
)

Split an edge by a node, replacing it with two new edges.

For ST_NewEdgesSplit

Parameters
topothe topology to operate on
edgeidentifier of the edge to be split
ptgeometry of the new node
skipChecksif non-zero skips consistency checks (coincident node, point not on edge...)
Returns
the id of newly created node

Definition at line 1203 of file lwgeom_topo.c.

References _lwt_EdgeSplit(), _lwt_release_edges(), 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, LWCOLLECTION::geoms, lwcollection_free(), lwcollection_release(), lwerror(), lwgeom_as_lwline(), lwt_be_deleteEdges(), lwt_be_getNextEdgeId(), lwt_be_insertEdges(), lwt_be_insertNodes(), lwt_be_lastErrorMessage(), lwt_be_updateEdges(), lwt_be_updateTopoGeomEdgeSplit(), LWT_COL_EDGE_EDGE_ID, LWT_COL_EDGE_END_NODE, LWT_COL_EDGE_NEXT_LEFT, LWT_COL_EDGE_NEXT_RIGHT, LWT_COL_EDGE_START_NODE, LWT_ISO_EDGE::next_left, LWT_ISO_EDGE::next_right, LWT_ISO_NODE::node_id, LWGEOM::srid, LWCOLLECTION::srid, and LWT_ISO_EDGE::start_node.

1205 {
1206  LWT_ISO_NODE node;
1207  LWT_ISO_EDGE* oldedge = NULL;
1208  LWCOLLECTION *split_col;
1209  const LWGEOM *oldedge_geom;
1210  const LWGEOM *newedge_geom;
1211  LWT_ISO_EDGE newedges[2];
1212  LWT_ISO_EDGE seledge, updedge;
1213  int ret;
1214 
1215  split_col = _lwt_EdgeSplit( topo, edge, pt, skipISOChecks, &oldedge );
1216  if ( ! split_col ) return -1; /* should have raised an exception */
1217  oldedge_geom = split_col->geoms[0];
1218  newedge_geom = split_col->geoms[1];
1219  /* Make sure the SRID is set on the subgeom */
1220  ((LWGEOM*)oldedge_geom)->srid = split_col->srid;
1221  ((LWGEOM*)newedge_geom)->srid = split_col->srid;
1222 
1223  /* Add new node, getting new id back */
1224  node.node_id = -1;
1225  node.containing_face = -1; /* means not-isolated */
1226  node.geom = pt;
1227  if ( ! lwt_be_insertNodes(topo, &node, 1) )
1228  {
1229  _lwt_release_edges(oldedge, 1);
1230  lwcollection_free(split_col);
1231  lwerror("Backend error: %s", lwt_be_lastErrorMessage(topo->be_iface));
1232  return -1;
1233  }
1234  if (node.node_id == -1) {
1235  _lwt_release_edges(oldedge, 1);
1236  lwcollection_free(split_col);
1237  /* should have been set by backend */
1238  lwerror("Backend coding error: "
1239  "insertNodes callback did not return node_id");
1240  return -1;
1241  }
1242 
1243  /* Delete the old edge */
1244  seledge.edge_id = edge;
1245  ret = lwt_be_deleteEdges(topo, &seledge, LWT_COL_EDGE_EDGE_ID);
1246  if ( ret == -1 ) {
1247  _lwt_release_edges(oldedge, 1);
1248  lwcollection_free(split_col);
1249  lwerror("Backend error: %s", lwt_be_lastErrorMessage(topo->be_iface));
1250  return -1;
1251  }
1252 
1253  /* Get new edges identifiers */
1254  newedges[0].edge_id = lwt_be_getNextEdgeId(topo);
1255  if ( newedges[0].edge_id == -1 ) {
1256  _lwt_release_edges(oldedge, 1);
1257  lwcollection_free(split_col);
1258  lwerror("Backend error: %s", lwt_be_lastErrorMessage(topo->be_iface));
1259  return -1;
1260  }
1261  newedges[1].edge_id = lwt_be_getNextEdgeId(topo);
1262  if ( newedges[1].edge_id == -1 ) {
1263  _lwt_release_edges(oldedge, 1);
1264  lwcollection_free(split_col);
1265  lwerror("Backend error: %s", lwt_be_lastErrorMessage(topo->be_iface));
1266  return -1;
1267  }
1268 
1269  /* Define the first new edge (to new node) */
1270  newedges[0].start_node = oldedge->start_node;
1271  newedges[0].end_node = node.node_id;
1272  newedges[0].face_left = oldedge->face_left;
1273  newedges[0].face_right = oldedge->face_right;
1274  newedges[0].next_left = newedges[1].edge_id;
1275  if ( oldedge->next_right == edge )
1276  newedges[0].next_right = newedges[0].edge_id;
1277  else if ( oldedge->next_right == -edge )
1278  newedges[0].next_right = -newedges[1].edge_id;
1279  else
1280  newedges[0].next_right = oldedge->next_right;
1281  newedges[0].geom = lwgeom_as_lwline(oldedge_geom);
1282  /* lwgeom_split of a line should only return lines ... */
1283  if ( ! newedges[0].geom ) {
1284  _lwt_release_edges(oldedge, 1);
1285  lwcollection_free(split_col);
1286  lwerror("first geometry in lwgeom_split output is not a line");
1287  return -1;
1288  }
1289 
1290  /* Define the second new edge (from new node) */
1291  newedges[1].start_node = node.node_id;
1292  newedges[1].end_node = oldedge->end_node;
1293  newedges[1].face_left = oldedge->face_left;
1294  newedges[1].face_right = oldedge->face_right;
1295  newedges[1].next_right = -newedges[0].edge_id;
1296  if ( oldedge->next_left == -edge )
1297  newedges[1].next_left = -newedges[1].edge_id;
1298  else if ( oldedge->next_left == edge )
1299  newedges[1].next_left = newedges[0].edge_id;
1300  else
1301  newedges[1].next_left = oldedge->next_left;
1302  newedges[1].geom = lwgeom_as_lwline(newedge_geom);
1303  /* lwgeom_split of a line should only return lines ... */
1304  if ( ! newedges[1].geom ) {
1305  _lwt_release_edges(oldedge, 1);
1306  lwcollection_free(split_col);
1307  lwerror("second geometry in lwgeom_split output is not a line");
1308  return -1;
1309  }
1310 
1311  /* Insert both new edges */
1312  ret = lwt_be_insertEdges(topo, newedges, 2);
1313  if ( ret == -1 ) {
1314  _lwt_release_edges(oldedge, 1);
1315  lwerror("Backend error: %s", lwt_be_lastErrorMessage(topo->be_iface));
1316  return -1;
1317  } else if ( ret == 0 ) {
1318  _lwt_release_edges(oldedge, 1);
1319  lwcollection_free(split_col);
1320  lwerror("Insertion of split edge failed (no reason)");
1321  return -1;
1322  }
1323 
1324  /* Update all next edge references pointing to old edge id */
1325 
1326  updedge.next_right = newedges[1].edge_id;
1327  seledge.next_right = edge;
1328  seledge.start_node = oldedge->start_node;
1329  ret = lwt_be_updateEdges(topo,
1331  &updedge, LWT_COL_EDGE_NEXT_RIGHT,
1332  NULL, 0);
1333  if ( ret == -1 ) {
1334  _lwt_release_edges(oldedge, 1);
1335  lwcollection_free(split_col);
1336  lwerror("Backend error: %s", lwt_be_lastErrorMessage(topo->be_iface));
1337  return -1;
1338  }
1339 
1340  updedge.next_right = -newedges[0].edge_id;
1341  seledge.next_right = -edge;
1342  seledge.start_node = oldedge->end_node;
1343  ret = lwt_be_updateEdges(topo,
1345  &updedge, LWT_COL_EDGE_NEXT_RIGHT,
1346  NULL, 0);
1347  if ( ret == -1 ) {
1348  _lwt_release_edges(oldedge, 1);
1349  lwcollection_free(split_col);
1350  lwerror("Backend error: %s", lwt_be_lastErrorMessage(topo->be_iface));
1351  return -1;
1352  }
1353 
1354  updedge.next_left = newedges[0].edge_id;
1355  seledge.next_left = edge;
1356  seledge.end_node = oldedge->start_node;
1357  ret = lwt_be_updateEdges(topo,
1359  &updedge, LWT_COL_EDGE_NEXT_LEFT,
1360  NULL, 0);
1361  if ( ret == -1 ) {
1362  _lwt_release_edges(oldedge, 1);
1363  lwcollection_free(split_col);
1364  lwerror("Backend error: %s", lwt_be_lastErrorMessage(topo->be_iface));
1365  return -1;
1366  }
1367 
1368  updedge.next_left = -newedges[1].edge_id;
1369  seledge.next_left = -edge;
1370  seledge.end_node = oldedge->end_node;
1371  ret = lwt_be_updateEdges(topo,
1373  &updedge, LWT_COL_EDGE_NEXT_LEFT,
1374  NULL, 0);
1375  if ( ret == -1 ) {
1376  _lwt_release_edges(oldedge, 1);
1377  lwcollection_release(split_col);
1378  lwerror("Backend error: %s", lwt_be_lastErrorMessage(topo->be_iface));
1379  return -1;
1380  }
1381 
1382  /* Update TopoGeometries composition */
1383  ret = lwt_be_updateTopoGeomEdgeSplit(topo, oldedge->edge_id, newedges[0].edge_id, newedges[1].edge_id);
1384  if ( ! ret ) {
1385  _lwt_release_edges(oldedge, 1);
1386  lwcollection_free(split_col);
1387  lwerror("Backend error: %s", lwt_be_lastErrorMessage(topo->be_iface));
1388  return -1;
1389  }
1390 
1391  _lwt_release_edges(oldedge, 1);
1392  lwcollection_free(split_col);
1393 
1394  /* return new node id */
1395  return node.node_id;
1396 }
LWT_ELEMID face_left
LWT_ELEMID containing_face
LWPOINT * geom
int lwt_be_insertNodes(LWT_TOPOLOGY *topo, LWT_ISO_NODE *node, int numelems)
Definition: lwgeom_topo.c:195
int lwt_be_deleteEdges(LWT_TOPOLOGY *topo, const LWT_ISO_EDGE *sel_edge, int sel_fields)
Definition: lwgeom_topo.c:322
#define LWT_COL_EDGE_START_NODE
LWLINE * geom
int32_t srid
Definition: liblwgeom.h:398
LWT_ELEMID next_left
static LWCOLLECTION * _lwt_EdgeSplit(LWT_TOPOLOGY *topo, LWT_ELEMID edge, LWPOINT *pt, int skipISOChecks, LWT_ISO_EDGE **oldedge)
Definition: lwgeom_topo.c:962
int lwt_be_updateEdges(LWT_TOPOLOGY *topo, const LWT_ISO_EDGE *sel_edge, int sel_fields, const LWT_ISO_EDGE *upd_edge, int upd_fields, const LWT_ISO_EDGE *exc_edge, int exc_fields)
Definition: lwgeom_topo.c:274
const LWT_BE_IFACE * be_iface
LWGEOM ** geoms
Definition: liblwgeom.h:508
#define LWT_COL_EDGE_END_NODE
LWT_ELEMID face_right
int32_t srid
Definition: liblwgeom.h:505
LWT_ELEMID node_id
LWT_ELEMID edge_id
LWLINE * lwgeom_as_lwline(const LWGEOM *lwgeom)
Definition: lwgeom.c:169
LWT_ELEMID lwt_be_getNextEdgeId(LWT_TOPOLOGY *topo)
Definition: lwgeom_topo.c:219
#define LWT_COL_EDGE_EDGE_ID
Edge fields.
void lwcollection_release(LWCOLLECTION *lwcollection)
Definition: lwcollection.c:36
#define LWT_COL_EDGE_NEXT_LEFT
int lwt_be_insertEdges(LWT_TOPOLOGY *topo, LWT_ISO_EDGE *edge, int numelems)
Definition: lwgeom_topo.c:268
#define LWT_COL_EDGE_NEXT_RIGHT
LWT_ELEMID start_node
static void _lwt_release_edges(LWT_ISO_EDGE *edges, int num_edges)
Definition: lwgeom_topo.c:457
LWT_ELEMID next_right
void lwcollection_free(LWCOLLECTION *col)
Definition: lwcollection.c:341
LWT_ELEMID end_node
int lwt_be_updateTopoGeomEdgeSplit(LWT_TOPOLOGY *topo, LWT_ELEMID split_edge, LWT_ELEMID new_edge1, LWT_ELEMID new_edge2)
Definition: lwgeom_topo.c:337
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

Here is the call graph for this function: