PostGIS  3.7.0dev-r@@SVN_REVISION@@

◆ _lwt_RemEdge()

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

Definition at line 3976 of file lwgeom_topo.c.

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

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, PGTOPO_BE_ERROR, result, and LWT_ISO_EDGE::start_node.

Referenced by lwt_RemEdgeModFace(), and lwt_RemEdgeNewFace().

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