PostGIS  3.2.2dev-r@@SVN_REVISION@@

◆ lwt_NewEdgesSplit()

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 1214 of file lwgeom_topo.c.

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

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.

Here is the call graph for this function: