PostGIS  3.3.9dev-r@@SVN_REVISION@@

◆ _lwt_RemEdge()

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

Definition at line 3979 of file lwgeom_topo.c.

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