PostGIS 3.0.6dev-r@@SVN_REVISION@@
Loading...
Searching...
No Matches

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

1175{
1176 LWT_ISO_NODE node;
1177 LWT_ISO_EDGE* oldedge = NULL;
1178 LWCOLLECTION *split_col;
1179 const LWGEOM *oldedge_geom;
1180 const LWGEOM *newedge_geom;
1181 LWT_ISO_EDGE newedges[2];
1182 LWT_ISO_EDGE seledge, updedge;
1183 int ret;
1184
1185 split_col = _lwt_EdgeSplit( topo, edge, pt, skipISOChecks, &oldedge );
1186 if ( ! split_col ) return -1; /* should have raised an exception */
1187 oldedge_geom = split_col->geoms[0];
1188 newedge_geom = split_col->geoms[1];
1189 /* Make sure the SRID is set on the subgeom */
1190 ((LWGEOM*)oldedge_geom)->srid = split_col->srid;
1191 ((LWGEOM*)newedge_geom)->srid = split_col->srid;
1192
1193 /* Add new node, getting new id back */
1194 node.node_id = -1;
1195 node.containing_face = -1; /* means not-isolated */
1196 node.geom = pt;
1197 if ( ! lwt_be_insertNodes(topo, &node, 1) )
1198 {
1199 _lwt_release_edges(oldedge, 1);
1200 lwcollection_free(split_col);
1201 lwerror("Backend error: %s", lwt_be_lastErrorMessage(topo->be_iface));
1202 return -1;
1203 }
1204 if (node.node_id == -1) {
1205 _lwt_release_edges(oldedge, 1);
1206 lwcollection_free(split_col);
1207 /* should have been set by backend */
1208 lwerror("Backend coding error: "
1209 "insertNodes callback did not return node_id");
1210 return -1;
1211 }
1212
1213 /* Delete the old edge */
1214 seledge.edge_id = edge;
1215 ret = lwt_be_deleteEdges(topo, &seledge, LWT_COL_EDGE_EDGE_ID);
1216 if ( ret == -1 ) {
1217 _lwt_release_edges(oldedge, 1);
1218 lwcollection_free(split_col);
1219 lwerror("Backend error: %s", lwt_be_lastErrorMessage(topo->be_iface));
1220 return -1;
1221 }
1222
1223 /* Get new edges identifiers */
1224 newedges[0].edge_id = lwt_be_getNextEdgeId(topo);
1225 if ( newedges[0].edge_id == -1 ) {
1226 _lwt_release_edges(oldedge, 1);
1227 lwcollection_free(split_col);
1228 lwerror("Backend error: %s", lwt_be_lastErrorMessage(topo->be_iface));
1229 return -1;
1230 }
1231 newedges[1].edge_id = lwt_be_getNextEdgeId(topo);
1232 if ( newedges[1].edge_id == -1 ) {
1233 _lwt_release_edges(oldedge, 1);
1234 lwcollection_free(split_col);
1235 lwerror("Backend error: %s", lwt_be_lastErrorMessage(topo->be_iface));
1236 return -1;
1237 }
1238
1239 /* Define the first new edge (to new node) */
1240 newedges[0].start_node = oldedge->start_node;
1241 newedges[0].end_node = node.node_id;
1242 newedges[0].face_left = oldedge->face_left;
1243 newedges[0].face_right = oldedge->face_right;
1244 newedges[0].next_left = newedges[1].edge_id;
1245 if ( oldedge->next_right == edge )
1246 newedges[0].next_right = newedges[0].edge_id;
1247 else if ( oldedge->next_right == -edge )
1248 newedges[0].next_right = -newedges[1].edge_id;
1249 else
1250 newedges[0].next_right = oldedge->next_right;
1251 newedges[0].geom = lwgeom_as_lwline(oldedge_geom);
1252 /* lwgeom_split of a line should only return lines ... */
1253 if ( ! newedges[0].geom ) {
1254 _lwt_release_edges(oldedge, 1);
1255 lwcollection_free(split_col);
1256 lwerror("first geometry in lwgeom_split output is not a line");
1257 return -1;
1258 }
1259
1260 /* Define the second new edge (from new node) */
1261 newedges[1].start_node = node.node_id;
1262 newedges[1].end_node = oldedge->end_node;
1263 newedges[1].face_left = oldedge->face_left;
1264 newedges[1].face_right = oldedge->face_right;
1265 newedges[1].next_right = -newedges[0].edge_id;
1266 if ( oldedge->next_left == -edge )
1267 newedges[1].next_left = -newedges[1].edge_id;
1268 else if ( oldedge->next_left == edge )
1269 newedges[1].next_left = newedges[0].edge_id;
1270 else
1271 newedges[1].next_left = oldedge->next_left;
1272 newedges[1].geom = lwgeom_as_lwline(newedge_geom);
1273 /* lwgeom_split of a line should only return lines ... */
1274 if ( ! newedges[1].geom ) {
1275 _lwt_release_edges(oldedge, 1);
1276 lwcollection_free(split_col);
1277 lwerror("second geometry in lwgeom_split output is not a line");
1278 return -1;
1279 }
1280
1281 /* Insert both new edges */
1282 ret = lwt_be_insertEdges(topo, newedges, 2);
1283 if ( ret == -1 ) {
1284 _lwt_release_edges(oldedge, 1);
1285 lwerror("Backend error: %s", lwt_be_lastErrorMessage(topo->be_iface));
1286 return -1;
1287 } else if ( ret == 0 ) {
1288 _lwt_release_edges(oldedge, 1);
1289 lwcollection_free(split_col);
1290 lwerror("Insertion of split edge failed (no reason)");
1291 return -1;
1292 }
1293
1294 /* Update all next edge references pointing to old edge id */
1295
1296 updedge.next_right = newedges[0].edge_id;
1297 seledge.next_right = edge;
1298 seledge.start_node = oldedge->start_node;
1299 ret = lwt_be_updateEdges(topo,
1301 &updedge, LWT_COL_EDGE_NEXT_RIGHT,
1302 NULL, 0);
1303 if ( ret == -1 ) {
1304 _lwt_release_edges(oldedge, 1);
1305 lwcollection_free(split_col);
1306 lwerror("Backend error: %s", lwt_be_lastErrorMessage(topo->be_iface));
1307 return -1;
1308 }
1309
1310 updedge.next_right = -newedges[1].edge_id;
1311 seledge.next_right = -edge;
1312 seledge.start_node = oldedge->end_node;
1313 ret = lwt_be_updateEdges(topo,
1315 &updedge, LWT_COL_EDGE_NEXT_RIGHT,
1316 NULL, 0);
1317 if ( ret == -1 ) {
1318 _lwt_release_edges(oldedge, 1);
1319 lwcollection_free(split_col);
1320 lwerror("Backend error: %s", lwt_be_lastErrorMessage(topo->be_iface));
1321 return -1;
1322 }
1323
1324 updedge.next_left = newedges[0].edge_id;
1325 seledge.next_left = edge;
1326 seledge.end_node = oldedge->start_node;
1327 ret = lwt_be_updateEdges(topo,
1329 &updedge, LWT_COL_EDGE_NEXT_LEFT,
1330 NULL, 0);
1331 if ( ret == -1 ) {
1332 _lwt_release_edges(oldedge, 1);
1333 lwcollection_free(split_col);
1334 lwerror("Backend error: %s", lwt_be_lastErrorMessage(topo->be_iface));
1335 return -1;
1336 }
1337
1338 updedge.next_left = -newedges[1].edge_id;
1339 seledge.next_left = -edge;
1340 seledge.end_node = oldedge->end_node;
1341 ret = lwt_be_updateEdges(topo,
1343 &updedge, LWT_COL_EDGE_NEXT_LEFT,
1344 NULL, 0);
1345 if ( ret == -1 ) {
1346 _lwt_release_edges(oldedge, 1);
1347 lwcollection_release(split_col);
1348 lwerror("Backend error: %s", lwt_be_lastErrorMessage(topo->be_iface));
1349 return -1;
1350 }
1351
1352 /* Update TopoGeometries composition */
1353 ret = lwt_be_updateTopoGeomEdgeSplit(topo, oldedge->edge_id, newedges[0].edge_id, newedges[1].edge_id);
1354 if ( ! ret ) {
1355 _lwt_release_edges(oldedge, 1);
1356 lwcollection_free(split_col);
1357 lwerror("Backend error: %s", lwt_be_lastErrorMessage(topo->be_iface));
1358 return -1;
1359 }
1360
1361 _lwt_release_edges(oldedge, 1);
1362 lwcollection_free(split_col);
1363
1364 /* return new node id */
1365 return node.node_id;
1366}
void lwcollection_release(LWCOLLECTION *lwcollection)
void lwcollection_free(LWCOLLECTION *col)
LWLINE * lwgeom_as_lwline(const LWGEOM *lwgeom)
Definition lwgeom.c:161
#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
LWT_ELEMID lwt_be_getNextEdgeId(LWT_TOPOLOGY *topo)
int lwt_be_updateTopoGeomEdgeSplit(LWT_TOPOLOGY *topo, LWT_ELEMID split_edge, LWT_ELEMID new_edge1, LWT_ELEMID new_edge2)
int lwt_be_insertNodes(LWT_TOPOLOGY *topo, LWT_ISO_NODE *node, uint64_t numelems)
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)
int lwt_be_deleteEdges(LWT_TOPOLOGY *topo, const LWT_ISO_EDGE *sel_edge, int sel_fields)
int lwt_be_insertEdges(LWT_TOPOLOGY *topo, LWT_ISO_EDGE *edge, uint64_t numelems)
const char * lwt_be_lastErrorMessage(const LWT_BE_IFACE *be)
static void _lwt_release_edges(LWT_ISO_EDGE *edges, int num_edges)
static LWCOLLECTION * _lwt_EdgeSplit(LWT_TOPOLOGY *topo, LWT_ELEMID edge, LWPOINT *pt, int skipISOChecks, LWT_ISO_EDGE **oldedge)
LWGEOM ** geoms
Definition liblwgeom.h:561
int32_t srid
Definition liblwgeom.h:562
int32_t srid
Definition liblwgeom.h:446
LWT_ELEMID face_right
LWT_ELEMID next_right
LWT_ELEMID end_node
LWT_ELEMID face_left
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: