PostGIS  2.5.0beta2dev-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 1019 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(), lwerror(), lwgeom_as_lwline(), 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_GEOM, 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.

Referenced by _lwt_AddPoint().

1021 {
1022  LWT_ISO_NODE node;
1023  LWT_ISO_EDGE* oldedge = NULL;
1024  LWCOLLECTION *split_col;
1025  const LWGEOM *oldedge_geom;
1026  const LWGEOM *newedge_geom;
1027  LWT_ISO_EDGE newedge1;
1028  LWT_ISO_EDGE seledge, updedge, excedge;
1029  int ret;
1030 
1031  split_col = _lwt_EdgeSplit( topo, edge, pt, skipISOChecks, &oldedge );
1032  if ( ! split_col ) return -1; /* should have raised an exception */
1033  oldedge_geom = split_col->geoms[0];
1034  newedge_geom = split_col->geoms[1];
1035  /* Make sure the SRID is set on the subgeom */
1036  ((LWGEOM*)oldedge_geom)->srid = split_col->srid;
1037  ((LWGEOM*)newedge_geom)->srid = split_col->srid;
1038 
1039  /* Add new node, getting new id back */
1040  node.node_id = -1;
1041  node.containing_face = -1; /* means not-isolated */
1042  node.geom = pt;
1043  if ( ! lwt_be_insertNodes(topo, &node, 1) )
1044  {
1045  _lwt_release_edges(oldedge, 1);
1046  lwcollection_free(split_col);
1047  lwerror("Backend error: %s", lwt_be_lastErrorMessage(topo->be_iface));
1048  return -1;
1049  }
1050  if (node.node_id == -1) {
1051  /* should have been set by backend */
1052  _lwt_release_edges(oldedge, 1);
1053  lwcollection_free(split_col);
1054  lwerror("Backend coding error: "
1055  "insertNodes callback did not return node_id");
1056  return -1;
1057  }
1058 
1059  /* Insert the new edge */
1060  newedge1.edge_id = lwt_be_getNextEdgeId(topo);
1061  if ( newedge1.edge_id == -1 ) {
1062  _lwt_release_edges(oldedge, 1);
1063  lwcollection_free(split_col);
1064  lwerror("Backend error: %s", lwt_be_lastErrorMessage(topo->be_iface));
1065  return -1;
1066  }
1067  newedge1.start_node = node.node_id;
1068  newedge1.end_node = oldedge->end_node;
1069  newedge1.face_left = oldedge->face_left;
1070  newedge1.face_right = oldedge->face_right;
1071  newedge1.next_left = oldedge->next_left == -oldedge->edge_id ?
1072  -newedge1.edge_id : oldedge->next_left;
1073  newedge1.next_right = -oldedge->edge_id;
1074  newedge1.geom = lwgeom_as_lwline(newedge_geom);
1075  /* lwgeom_split of a line should only return lines ... */
1076  if ( ! newedge1.geom ) {
1077  _lwt_release_edges(oldedge, 1);
1078  lwcollection_free(split_col);
1079  lwerror("first geometry in lwgeom_split output is not a line");
1080  return -1;
1081  }
1082  ret = lwt_be_insertEdges(topo, &newedge1, 1);
1083  if ( ret == -1 ) {
1084  _lwt_release_edges(oldedge, 1);
1085  lwcollection_free(split_col);
1086  lwerror("Backend error: %s", lwt_be_lastErrorMessage(topo->be_iface));
1087  return -1;
1088  } else if ( ret == 0 ) {
1089  _lwt_release_edges(oldedge, 1);
1090  lwcollection_free(split_col);
1091  lwerror("Insertion of split edge failed (no reason)");
1092  return -1;
1093  }
1094 
1095  /* Update the old edge */
1096  updedge.geom = lwgeom_as_lwline(oldedge_geom);
1097  /* lwgeom_split of a line should only return lines ... */
1098  if ( ! updedge.geom ) {
1099  _lwt_release_edges(oldedge, 1);
1100  lwcollection_free(split_col);
1101  lwerror("second geometry in lwgeom_split output is not a line");
1102  return -1;
1103  }
1104  updedge.next_left = newedge1.edge_id;
1105  updedge.end_node = node.node_id;
1106  ret = lwt_be_updateEdges(topo,
1107  oldedge, LWT_COL_EDGE_EDGE_ID,
1109  NULL, 0);
1110  if ( ret == -1 ) {
1111  _lwt_release_edges(oldedge, 1);
1112  lwcollection_free(split_col);
1113  lwerror("Backend error: %s", lwt_be_lastErrorMessage(topo->be_iface));
1114  return -1;
1115  } else if ( ret == 0 ) {
1116  _lwt_release_edges(oldedge, 1);
1117  lwcollection_free(split_col);
1118  lwerror("Edge being split (%d) disappeared during operations?", oldedge->edge_id);
1119  return -1;
1120  } else if ( ret > 1 ) {
1121  _lwt_release_edges(oldedge, 1);
1122  lwcollection_free(split_col);
1123  lwerror("More than a single edge found with id %d !", oldedge->edge_id);
1124  return -1;
1125  }
1126 
1127  /* Update all next edge references to match new layout (ST_ModEdgeSplit) */
1128 
1129  updedge.next_right = -newedge1.edge_id;
1130  excedge.edge_id = newedge1.edge_id;
1131  seledge.next_right = -oldedge->edge_id;
1132  seledge.start_node = oldedge->end_node;
1133  ret = lwt_be_updateEdges(topo,
1135  &updedge, LWT_COL_EDGE_NEXT_RIGHT,
1136  &excedge, LWT_COL_EDGE_EDGE_ID);
1137  if ( ret == -1 ) {
1138  _lwt_release_edges(oldedge, 1);
1139  lwcollection_free(split_col);
1140  lwerror("Backend error: %s", lwt_be_lastErrorMessage(topo->be_iface));
1141  return -1;
1142  }
1143 
1144  updedge.next_left = -newedge1.edge_id;
1145  excedge.edge_id = newedge1.edge_id;
1146  seledge.next_left = -oldedge->edge_id;
1147  seledge.end_node = oldedge->end_node;
1148  ret = lwt_be_updateEdges(topo,
1150  &updedge, LWT_COL_EDGE_NEXT_LEFT,
1151  &excedge, LWT_COL_EDGE_EDGE_ID);
1152  if ( ret == -1 ) {
1153  _lwt_release_edges(oldedge, 1);
1154  lwcollection_free(split_col);
1155  lwerror("Backend error: %s", lwt_be_lastErrorMessage(topo->be_iface));
1156  return -1;
1157  }
1158 
1159  /* Update TopoGeometries composition */
1160  ret = lwt_be_updateTopoGeomEdgeSplit(topo, oldedge->edge_id, newedge1.edge_id, -1);
1161  if ( ! ret ) {
1162  _lwt_release_edges(oldedge, 1);
1163  lwcollection_free(split_col);
1164  lwerror("Backend error: %s", lwt_be_lastErrorMessage(topo->be_iface));
1165  return -1;
1166  }
1167 
1168  _lwt_release_edges(oldedge, 1);
1169  lwcollection_free(split_col);
1170 
1171  /* return new node id */
1172  return node.node_id;
1173 }
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
#define LWT_COL_EDGE_START_NODE
LWLINE * geom
int32_t srid
Definition: liblwgeom.h:401
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:935
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:511
#define LWT_COL_EDGE_END_NODE
LWT_ELEMID face_right
int32_t srid
Definition: liblwgeom.h:508
LWT_ELEMID node_id
LWT_ELEMID edge_id
LWLINE * lwgeom_as_lwline(const LWGEOM *lwgeom)
Definition: lwgeom.c:170
LWT_ELEMID lwt_be_getNextEdgeId(LWT_TOPOLOGY *topo)
Definition: lwgeom_topo.c:219
#define LWT_COL_EDGE_EDGE_ID
Edge fields.
#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:356
#define LWT_COL_EDGE_GEOM
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:
Here is the caller graph for this function: