PostGIS  2.5.0dev-r@@SVN_REVISION@@

◆ _lwt_RemEdge()

static LWT_ELEMID _lwt_RemEdge ( LWT_TOPOLOGY topo,
LWT_ELEMID  edge_id,
int  modFace 
)
static

Definition at line 3982 of file lwgeom_topo.c.

References _lwt_release_edges(), _lwt_release_faces(), _lwt_UpdateEdgeFaceRef(), _lwt_UpdateNodeFaceRef(), LWT_TOPOLOGY_T::be_iface, LWT_ISO_NODE::containing_face, LWT_ISO_EDGE::edge_id, LWT_ISO_EDGE::end_node, LWT_ISO_FACE::face_id, LWT_ISO_EDGE::face_left, LWT_ISO_EDGE::face_right, gbox_merge(), LWDEBUG, LWDEBUGF, lwerror(), lwfree(), lwt_be_checkTopoGeomRemEdge(), lwt_be_deleteEdges(), lwt_be_deleteFacesById(), lwt_be_getEdgeById(), lwt_be_getEdgeByNode(), lwt_be_getFaceById(), lwt_be_insertFaces(), lwt_be_lastErrorMessage(), lwt_be_updateEdgesById(), lwt_be_updateFacesById(), lwt_be_updateNodesById(), lwt_be_updateTopoGeomFaceHeal(), LWT_COL_EDGE_ALL, 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_COL_FACE_ALL, LWT_COL_NODE_CONTAINING_FACE, LWTFMT_ELEMID, LWT_ISO_FACE::mbr, LWT_ISO_EDGE::next_left, LWT_ISO_EDGE::next_right, LWT_ISO_NODE::node_id, and LWT_ISO_EDGE::start_node.

Referenced by lwt_RemEdgeModFace(), and lwt_RemEdgeNewFace().

3983 {
3984  int i, nedges, nfaces, fields;
3985  LWT_ISO_EDGE *edge = NULL;
3986  LWT_ISO_EDGE *upd_edge = NULL;
3987  LWT_ISO_EDGE upd_edge_left[2];
3988  int nedge_left = 0;
3989  LWT_ISO_EDGE upd_edge_right[2];
3990  int nedge_right = 0;
3991  LWT_ISO_NODE upd_node[2];
3992  int nnode = 0;
3993  LWT_ISO_FACE *faces = NULL;
3994  LWT_ISO_FACE newface;
3995  LWT_ELEMID node_ids[2];
3996  LWT_ELEMID face_ids[2];
3997  int fnode_edges = 0; /* number of edges on the first node (excluded
3998  * the one being removed ) */
3999  int lnode_edges = 0; /* number of edges on the last node (excluded
4000  * the one being removed ) */
4001 
4002  newface.face_id = 0;
4003 
4004  i = 1;
4005  edge = lwt_be_getEdgeById(topo, &edge_id, &i, LWT_COL_EDGE_ALL);
4006  if ( ! edge )
4007  {
4008  LWDEBUGF(1, "lwt_be_getEdgeById returned NULL and set i=%d", i);
4009  if ( i == -1 )
4010  {
4011  lwerror("Backend error: %s", lwt_be_lastErrorMessage(topo->be_iface));
4012  return -1;
4013  }
4014  else if ( i == 0 )
4015  {
4016  lwerror("SQL/MM Spatial exception - non-existent edge %"
4017  LWTFMT_ELEMID, edge_id);
4018  return -1;
4019  }
4020  else
4021  {
4022  lwerror("Backend coding error: getEdgeById callback returned NULL "
4023  "but numelements output parameter has value %d "
4024  "(expected 0 or 1)", i);
4025  return -1;
4026  }
4027  }
4028 
4029  if ( ! lwt_be_checkTopoGeomRemEdge(topo, edge_id,
4030  edge->face_left, edge->face_right) )
4031  {
4033  return -1;
4034  }
4035 
4036  LWDEBUG(1, "Updating next_{right,left}_face of ring edges...");
4037 
4038  /* Update edge linking */
4039 
4040  nedges = 0;
4041  node_ids[nedges++] = edge->start_node;
4042  if ( edge->end_node != edge->start_node )
4043  {
4044  node_ids[nedges++] = edge->end_node;
4045  }
4049  upd_edge = lwt_be_getEdgeByNode( topo, &(node_ids[0]), &nedges, fields );
4050  if ( nedges == -1 ) {
4051  lwerror("Backend error: %s", lwt_be_lastErrorMessage(topo->be_iface));
4052  return -1;
4053  }
4054  nedge_left = nedge_right = 0;
4055  for ( i=0; i<nedges; ++i )
4056  {
4057  LWT_ISO_EDGE *e = &(upd_edge[i]);
4058  if ( e->edge_id == edge_id ) continue;
4059  if ( e->start_node == edge->start_node || e->end_node == edge->start_node )
4060  {
4061  ++fnode_edges;
4062  }
4063  if ( e->start_node == edge->end_node || e->end_node == edge->end_node )
4064  {
4065  ++lnode_edges;
4066  }
4067  if ( e->next_left == -edge_id )
4068  {
4069  upd_edge_left[nedge_left].edge_id = e->edge_id;
4070  upd_edge_left[nedge_left++].next_left =
4071  edge->next_left != edge_id ? edge->next_left : edge->next_right;
4072  }
4073  else if ( e->next_left == edge_id )
4074  {
4075  upd_edge_left[nedge_left].edge_id = e->edge_id;
4076  upd_edge_left[nedge_left++].next_left =
4077  edge->next_right != -edge_id ? edge->next_right : edge->next_left;
4078  }
4079 
4080  if ( e->next_right == -edge_id )
4081  {
4082  upd_edge_right[nedge_right].edge_id = e->edge_id;
4083  upd_edge_right[nedge_right++].next_right =
4084  edge->next_left != edge_id ? edge->next_left : edge->next_right;
4085  }
4086  else if ( e->next_right == edge_id )
4087  {
4088  upd_edge_right[nedge_right].edge_id = e->edge_id;
4089  upd_edge_right[nedge_right++].next_right =
4090  edge->next_right != -edge_id ? edge->next_right : edge->next_left;
4091  }
4092  }
4093 
4094  if ( nedge_left )
4095  {
4096  LWDEBUGF(1, "updating %d 'next_left' edges", nedge_left);
4097  /* update edges in upd_edge_left set next_left */
4098  i = lwt_be_updateEdgesById(topo, &(upd_edge_left[0]), nedge_left,
4100  if ( i == -1 )
4101  {
4102  _lwt_release_edges(edge, 1);
4103  lwfree(upd_edge);
4104  lwerror("Backend error: %s", lwt_be_lastErrorMessage(topo->be_iface));
4105  return -1;
4106  }
4107  }
4108  if ( nedge_right )
4109  {
4110  LWDEBUGF(1, "updating %d 'next_right' edges", nedge_right);
4111  /* update edges in upd_edge_right set next_right */
4112  i = lwt_be_updateEdgesById(topo, &(upd_edge_right[0]), nedge_right,
4114  if ( i == -1 )
4115  {
4116  _lwt_release_edges(edge, 1);
4117  lwfree(upd_edge);
4118  lwerror("Backend error: %s", lwt_be_lastErrorMessage(topo->be_iface));
4119  return -1;
4120  }
4121  }
4122  LWDEBUGF(1, "releasing %d updateable edges in %p", nedges, upd_edge);
4123  lwfree(upd_edge);
4124 
4125  /* Id of face that will take up all the space previously
4126  * taken by left and right faces of the edge */
4127  LWT_ELEMID floodface;
4128 
4129  /* Find floodface, and update its mbr if != 0 */
4130  if ( edge->face_left == edge->face_right )
4131  {
4132  floodface = edge->face_right;
4133  }
4134  else
4135  {
4136  /* Two faces healed */
4137  if ( edge->face_left == 0 || edge->face_right == 0 )
4138  {
4139  floodface = 0;
4140  LWDEBUG(1, "floodface is universe");
4141  }
4142  else
4143  {
4144  /* we choose right face as the face that will remain
4145  * to be symmetric with ST_AddEdgeModFace */
4146  floodface = edge->face_right;
4147  LWDEBUGF(1, "floodface is %" LWTFMT_ELEMID, floodface);
4148  /* update mbr of floodface as union of mbr of both faces */
4149  face_ids[0] = edge->face_left;
4150  face_ids[1] = edge->face_right;
4151  nfaces = 2;
4152  fields = LWT_COL_FACE_ALL;
4153  faces = lwt_be_getFaceById(topo, face_ids, &nfaces, fields);
4154  if ( nfaces == -1 ) {
4155  lwerror("Backend error: %s", lwt_be_lastErrorMessage(topo->be_iface));
4156  return -1;
4157  }
4158  GBOX *box1=NULL;
4159  GBOX *box2=NULL;
4160  for ( i=0; i<nfaces; ++i )
4161  {
4162  if ( faces[i].face_id == edge->face_left )
4163  {
4164  if ( ! box1 ) box1 = faces[i].mbr;
4165  else
4166  {
4167  i = edge->face_left;
4168  _lwt_release_edges(edge, 1);
4169  _lwt_release_faces(faces, nfaces);
4170  lwerror("corrupted topology: more than 1 face have face_id=%"
4171  LWTFMT_ELEMID, i);
4172  return -1;
4173  }
4174  }
4175  else if ( faces[i].face_id == edge->face_right )
4176  {
4177  if ( ! box2 ) box2 = faces[i].mbr;
4178  else
4179  {
4180  i = edge->face_right;
4181  _lwt_release_edges(edge, 1);
4182  _lwt_release_faces(faces, nfaces);
4183  lwerror("corrupted topology: more than 1 face have face_id=%"
4184  LWTFMT_ELEMID, i);
4185  return -1;
4186  }
4187  }
4188  else
4189  {
4190  i = faces[i].face_id;
4191  _lwt_release_edges(edge, 1);
4192  _lwt_release_faces(faces, nfaces);
4193  lwerror("Backend coding error: getFaceById returned face "
4194  "with non-requested id %" LWTFMT_ELEMID, i);
4195  return -1;
4196  }
4197  }
4198  if ( ! box1 ) {
4199  i = edge->face_left;
4200  _lwt_release_edges(edge, 1);
4201  _lwt_release_faces(faces, nfaces);
4202  lwerror("corrupted topology: no face have face_id=%"
4203  LWTFMT_ELEMID " (left face for edge %"
4204  LWTFMT_ELEMID ")", i, edge_id);
4205  return -1;
4206  }
4207  if ( ! box2 ) {
4208  i = edge->face_right;
4209  _lwt_release_edges(edge, 1);
4210  _lwt_release_faces(faces, nfaces);
4211  lwerror("corrupted topology: no face have face_id=%"
4212  LWTFMT_ELEMID " (right face for edge %"
4213  LWTFMT_ELEMID ")", i, edge_id);
4214  return -1;
4215  }
4216  gbox_merge(box2, box1); /* box1 is now the union of the two */
4217  newface.mbr = box1;
4218  if ( modFace )
4219  {
4220  newface.face_id = floodface;
4221  i = lwt_be_updateFacesById( topo, &newface, 1 );
4222  _lwt_release_faces(faces, 2);
4223  if ( i == -1 )
4224  {
4225  _lwt_release_edges(edge, 1);
4226  lwerror("Backend error: %s", lwt_be_lastErrorMessage(topo->be_iface));
4227  return -1;
4228  }
4229  if ( i != 1 )
4230  {
4231  _lwt_release_edges(edge, 1);
4232  lwerror("Unexpected error: %d faces updated when expecting 1", i);
4233  return -1;
4234  }
4235  }
4236  else
4237  {
4238  /* New face replaces the old two faces */
4239  newface.face_id = -1;
4240  i = lwt_be_insertFaces( topo, &newface, 1 );
4241  _lwt_release_faces(faces, 2);
4242  if ( i == -1 )
4243  {
4244  _lwt_release_edges(edge, 1);
4245  lwerror("Backend error: %s", lwt_be_lastErrorMessage(topo->be_iface));
4246  return -1;
4247  }
4248  if ( i != 1 )
4249  {
4250  _lwt_release_edges(edge, 1);
4251  lwerror("Unexpected error: %d faces inserted when expecting 1", i);
4252  return -1;
4253  }
4254  floodface = newface.face_id;
4255  }
4256  }
4257 
4258  /* Update face references for edges and nodes still referencing
4259  * the removed face(s) */
4260 
4261  if ( edge->face_left != floodface )
4262  {
4263  if ( -1 == _lwt_UpdateEdgeFaceRef(topo, edge->face_left, floodface) )
4264  {
4265  _lwt_release_edges(edge, 1);
4266  lwerror("Backend error: %s", lwt_be_lastErrorMessage(topo->be_iface));
4267  return -1;
4268  }
4269  if ( -1 == _lwt_UpdateNodeFaceRef(topo, edge->face_left, floodface) )
4270  {
4271  _lwt_release_edges(edge, 1);
4272  lwerror("Backend error: %s", lwt_be_lastErrorMessage(topo->be_iface));
4273  return -1;
4274  }
4275  }
4276 
4277  if ( edge->face_right != floodface )
4278  {
4279  if ( -1 == _lwt_UpdateEdgeFaceRef(topo, edge->face_right, floodface) )
4280  {
4281  _lwt_release_edges(edge, 1);
4282  lwerror("Backend error: %s", lwt_be_lastErrorMessage(topo->be_iface));
4283  return -1;
4284  }
4285  if ( -1 == _lwt_UpdateNodeFaceRef(topo, edge->face_right, floodface) )
4286  {
4287  _lwt_release_edges(edge, 1);
4288  lwerror("Backend error: %s", lwt_be_lastErrorMessage(topo->be_iface));
4289  return -1;
4290  }
4291  }
4292 
4293  /* Update topogeoms on heal */
4294  if ( ! lwt_be_updateTopoGeomFaceHeal(topo,
4295  edge->face_right, edge->face_left,
4296  floodface) )
4297  {
4298  _lwt_release_edges(edge, 1);
4300  return -1;
4301  }
4302  } /* two faces healed */
4303 
4304  /* Delete the edge */
4305  i = lwt_be_deleteEdges(topo, edge, LWT_COL_EDGE_EDGE_ID);
4306  if ( i == -1 ) {
4307  _lwt_release_edges(edge, 1);
4308  lwerror("Backend error: %s", lwt_be_lastErrorMessage(topo->be_iface));
4309  return -1;
4310  }
4311 
4312  /* If any of the edge nodes remained isolated, set
4313  * containing_face = floodface
4314  */
4315  if ( ! fnode_edges )
4316  {
4317  upd_node[nnode].node_id = edge->start_node;
4318  upd_node[nnode].containing_face = floodface;
4319  ++nnode;
4320  }
4321  if ( edge->end_node != edge->start_node && ! lnode_edges )
4322  {
4323  upd_node[nnode].node_id = edge->end_node;
4324  upd_node[nnode].containing_face = floodface;
4325  ++nnode;
4326  }
4327  if ( nnode )
4328  {
4329  i = lwt_be_updateNodesById(topo, upd_node, nnode,
4331  if ( i == -1 ) {
4332  _lwt_release_edges(edge, 1);
4333  lwerror("Backend error: %s", lwt_be_lastErrorMessage(topo->be_iface));
4334  return -1;
4335  }
4336  }
4337 
4338  if ( edge->face_left != edge->face_right )
4339  /* or there'd be no face to remove */
4340  {
4341  LWT_ELEMID ids[2];
4342  int nids = 0;
4343  if ( edge->face_right != floodface )
4344  ids[nids++] = edge->face_right;
4345  if ( edge->face_left != floodface )
4346  ids[nids++] = edge->face_left;
4347  i = lwt_be_deleteFacesById(topo, ids, nids);
4348  if ( i == -1 ) {
4349  _lwt_release_edges(edge, 1);
4350  lwerror("Backend error: %s", lwt_be_lastErrorMessage(topo->be_iface));
4351  return -1;
4352  }
4353  }
4354 
4355  _lwt_release_edges(edge, 1);
4356  return modFace ? floodface : newface.face_id;
4357 }
static LWT_ISO_FACE * lwt_be_getFaceById(LWT_TOPOLOGY *topo, const LWT_ELEMID *ids, int *numelems, int fields)
Definition: lwgeom_topo.c:232
LWT_ELEMID face_left
#define LWT_COL_NODE_CONTAINING_FACE
static int lwt_be_insertFaces(LWT_TOPOLOGY *topo, LWT_ISO_FACE *face, int numelems)
Definition: lwgeom_topo.c:201
LWT_ELEMID containing_face
static int lwt_be_updateEdgesById(LWT_TOPOLOGY *topo, const LWT_ISO_EDGE *edges, int numedges, int upd_fields)
Definition: lwgeom_topo.c:306
void lwfree(void *mem)
Definition: lwutil.c:244
static int _lwt_UpdateNodeFaceRef(LWT_TOPOLOGY *topo, LWT_ELEMID of, LWT_ELEMID nf)
Definition: lwgeom_topo.c:3957
int lwt_be_deleteEdges(LWT_TOPOLOGY *topo, const LWT_ISO_EDGE *sel_edge, int sel_fields)
Definition: lwgeom_topo.c:322
#define LWT_COL_EDGE_START_NODE
#define LWDEBUG(level, msg)
Definition: lwgeom_log.h:83
LWT_ISO_EDGE * lwt_be_getEdgeById(LWT_TOPOLOGY *topo, const LWT_ELEMID *ids, int *numelems, int fields)
Definition: lwgeom_topo.c:225
LWT_ELEMID next_left
int gbox_merge(const GBOX *new_box, GBOX *merge_box)
Update the merged GBOX to be large enough to include itself and the new box.
Definition: g_box.c:264
static int lwt_be_updateFacesById(LWT_TOPOLOGY *topo, const LWT_ISO_FACE *faces, int numfaces)
Definition: lwgeom_topo.c:298
const LWT_BE_IFACE * be_iface
#define LWT_COL_EDGE_END_NODE
LWT_ELEMID face_id
static int lwt_be_updateTopoGeomFaceHeal(LWT_TOPOLOGY *topo, LWT_ELEMID face1, LWT_ELEMID face2, LWT_ELEMID newface)
Definition: lwgeom_topo.c:364
LWT_ELEMID face_right
#define LWT_COL_EDGE_ALL
LWT_ELEMID node_id
LWT_ELEMID edge_id
static int lwt_be_deleteFacesById(const LWT_TOPOLOGY *topo, const LWT_ELEMID *ids, int numelems)
Definition: lwgeom_topo.c:207
static int lwt_be_updateNodesById(LWT_TOPOLOGY *topo, const LWT_ISO_NODE *nodes, int numnodes, int upd_fields)
Definition: lwgeom_topo.c:314
#define LWT_COL_EDGE_EDGE_ID
Edge fields.
#define LWT_COL_FACE_ALL
#define LWT_COL_EDGE_NEXT_LEFT
static int _lwt_UpdateEdgeFaceRef(LWT_TOPOLOGY *topo, LWT_ELEMID of, LWT_ELEMID nf)
Definition: lwgeom_topo.c:3924
#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
LWT_INT64 LWT_ELEMID
Identifier of topology element.
static LWT_ISO_EDGE * lwt_be_getEdgeByNode(LWT_TOPOLOGY *topo, const LWT_ELEMID *ids, int *numelems, int fields)
Definition: lwgeom_topo.c:239
static void _lwt_release_faces(LWT_ISO_FACE *faces, int num_faces)
Definition: lwgeom_topo.c:447
LWT_ELEMID end_node
#define LWDEBUGF(level, msg,...)
Definition: lwgeom_log.h:88
uint32_t e
Definition: geobuf.h:57
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
static int lwt_be_checkTopoGeomRemEdge(LWT_TOPOLOGY *topo, LWT_ELEMID edge_id, LWT_ELEMID face_left, LWT_ELEMID face_right)
Definition: lwgeom_topo.c:350
#define LWTFMT_ELEMID
Definition: lwgeom_topo.c:44
Here is the call graph for this function:
Here is the caller graph for this function: