PostGIS  3.7.0dev-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 1209 of file lwgeom_topo.c.

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

References _lwt_EdgeSplit(), _lwt_release_edges(), 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_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, PGTOPO_BE_ERROR, LWGEOM::srid, LWCOLLECTION::srid, and LWT_ISO_EDGE::start_node.

Here is the call graph for this function: