PostGIS  3.7.0dev-r@@SVN_REVISION@@

◆ lwt_ModEdgeSplit()

LWT_ELEMID lwt_ModEdgeSplit ( LWT_TOPOLOGY topo,
LWT_ELEMID  edge,
LWPOINT pt,
int  skipChecks 
)

Split an edge by a node, modifying the original edge and adding a new one.

For ST_ModEdgeSplit

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, or -1 on error (liblwgeom error handler will be invoked with error message)

Definition at line 1052 of file lwgeom_topo.c.

1054 {
1055  LWT_ISO_NODE node;
1056  LWT_ISO_EDGE* oldedge = NULL;
1057  LWCOLLECTION *split_col;
1058  const LWGEOM *oldedge_geom;
1059  const LWGEOM *newedge_geom;
1060  LWT_ISO_EDGE newedge1;
1061  LWT_ISO_EDGE seledge, updedge, excedge;
1062  int ret;
1063 
1064  split_col = _lwt_EdgeSplit( topo, edge, pt, skipISOChecks, &oldedge );
1065  if ( ! split_col ) return -1; /* should have raised an exception */
1066  oldedge_geom = split_col->geoms[0];
1067  newedge_geom = split_col->geoms[1];
1068  /* Make sure the SRID is set on the subgeom */
1069  ((LWGEOM*)oldedge_geom)->srid = split_col->srid;
1070  ((LWGEOM*)newedge_geom)->srid = split_col->srid;
1071 
1072  /* Add new node, getting new id back */
1073  node.node_id = -1;
1074  node.containing_face = -1; /* means not-isolated */
1075  node.geom = pt;
1076  if ( ! lwt_be_insertNodes(topo, &node, 1) )
1077  {
1078  _lwt_release_edges(oldedge, 1);
1079  lwcollection_free(split_col);
1080  PGTOPO_BE_ERROR();
1081  return -1;
1082  }
1083  if (node.node_id == -1) {
1084  /* should have been set by backend */
1085  _lwt_release_edges(oldedge, 1);
1086  lwcollection_free(split_col);
1087  lwerror("Backend coding error: "
1088  "insertNodes callback did not return node_id");
1089  return -1;
1090  }
1091 
1092  /* Insert the new edge */
1093  newedge1.edge_id = lwt_be_getNextEdgeId(topo);
1094  if ( newedge1.edge_id == -1 ) {
1095  _lwt_release_edges(oldedge, 1);
1096  lwcollection_free(split_col);
1097  PGTOPO_BE_ERROR();
1098  return -1;
1099  }
1100  newedge1.start_node = node.node_id;
1101  newedge1.end_node = oldedge->end_node;
1102  newedge1.face_left = oldedge->face_left;
1103  newedge1.face_right = oldedge->face_right;
1104  newedge1.next_left = oldedge->next_left == -oldedge->edge_id ?
1105  -newedge1.edge_id : oldedge->next_left;
1106  newedge1.next_right = -oldedge->edge_id;
1107  newedge1.geom = lwgeom_as_lwline(newedge_geom);
1108  /* lwgeom_split of a line should only return lines ... */
1109  if ( ! newedge1.geom ) {
1110  _lwt_release_edges(oldedge, 1);
1111  lwcollection_free(split_col);
1112  lwerror("first geometry in lwgeom_split output is not a line");
1113  return -1;
1114  }
1115  ret = lwt_be_insertEdges(topo, &newedge1, 1);
1116  if ( ret == -1 ) {
1117  _lwt_release_edges(oldedge, 1);
1118  lwcollection_free(split_col);
1119  PGTOPO_BE_ERROR();
1120  return -1;
1121  } else if ( ret == 0 ) {
1122  _lwt_release_edges(oldedge, 1);
1123  lwcollection_free(split_col);
1124  lwerror("Insertion of split edge failed (no reason)");
1125  return -1;
1126  }
1127 
1128  /* Update the old edge */
1129  updedge.geom = lwgeom_as_lwline(oldedge_geom);
1130  /* lwgeom_split of a line should only return lines ... */
1131  if ( ! updedge.geom ) {
1132  _lwt_release_edges(oldedge, 1);
1133  lwcollection_free(split_col);
1134  lwerror("second geometry in lwgeom_split output is not a line");
1135  return -1;
1136  }
1137  updedge.next_left = newedge1.edge_id;
1138  updedge.end_node = node.node_id;
1139  ret = lwt_be_updateEdges(topo,
1140  oldedge, LWT_COL_EDGE_EDGE_ID,
1142  NULL, 0);
1143  if ( ret == -1 ) {
1144  _lwt_release_edges(oldedge, 1);
1145  lwcollection_free(split_col);
1146  PGTOPO_BE_ERROR();
1147  return -1;
1148  } else if ( ret == 0 ) {
1149  _lwt_release_edges(oldedge, 1);
1150  lwcollection_free(split_col);
1151  lwerror("Edge being split (%" LWTFMT_ELEMID ") disappeared during operations?", oldedge->edge_id);
1152  return -1;
1153  } else if ( ret > 1 ) {
1154  _lwt_release_edges(oldedge, 1);
1155  lwcollection_free(split_col);
1156  lwerror("More than a single edge found with id %" LWTFMT_ELEMID " !", oldedge->edge_id);
1157  return -1;
1158  }
1159 
1160  /* Update all next edge references to match new layout (ST_ModEdgeSplit) */
1161 
1162  updedge.next_right = -newedge1.edge_id;
1163  excedge.edge_id = newedge1.edge_id;
1164  seledge.next_right = -oldedge->edge_id;
1165  seledge.start_node = oldedge->end_node;
1166  ret = lwt_be_updateEdges(topo,
1168  &updedge, LWT_COL_EDGE_NEXT_RIGHT,
1169  &excedge, LWT_COL_EDGE_EDGE_ID);
1170  if ( ret == -1 ) {
1171  _lwt_release_edges(oldedge, 1);
1172  lwcollection_free(split_col);
1173  PGTOPO_BE_ERROR();
1174  return -1;
1175  }
1176 
1177  updedge.next_left = -newedge1.edge_id;
1178  excedge.edge_id = newedge1.edge_id;
1179  seledge.next_left = -oldedge->edge_id;
1180  seledge.end_node = oldedge->end_node;
1181  ret = lwt_be_updateEdges(topo,
1183  &updedge, LWT_COL_EDGE_NEXT_LEFT,
1184  &excedge, LWT_COL_EDGE_EDGE_ID);
1185  if ( ret == -1 ) {
1186  _lwt_release_edges(oldedge, 1);
1187  lwcollection_free(split_col);
1188  PGTOPO_BE_ERROR();
1189  return -1;
1190  }
1191 
1192  /* Update TopoGeometries composition */
1193  ret = lwt_be_updateTopoGeomEdgeSplit(topo, oldedge->edge_id, newedge1.edge_id, -1);
1194  if ( ! ret ) {
1195  _lwt_release_edges(oldedge, 1);
1196  lwcollection_free(split_col);
1197  PGTOPO_BE_ERROR();
1198  return -1;
1199  }
1200 
1201  _lwt_release_edges(oldedge, 1);
1202  lwcollection_free(split_col);
1203 
1204  /* return new node id */
1205  return node.node_id;
1206 }
LWLINE * lwgeom_as_lwline(const LWGEOM *lwgeom)
Definition: lwgeom.c:179
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 LWT_COL_EDGE_GEOM
#define PGTOPO_BE_ERROR()
#define LWTFMT_ELEMID
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
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(), lwerror(), lwgeom_as_lwline(), 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_GEOM, LWT_COL_EDGE_NEXT_LEFT, LWT_COL_EDGE_NEXT_RIGHT, LWT_COL_EDGE_START_NODE, LWTFMT_ELEMID, 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.

Referenced by _lwt_SplitAllEdgesToNewNode().

Here is the call graph for this function:
Here is the caller graph for this function: