PostGIS  3.2.2dev-r@@SVN_REVISION@@

◆ _lwt_RemEdge()

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

Definition at line 3898 of file lwgeom_topo.c.

3899 {
3900  uint64_t i, nedges, nfaces, fields;
3901  LWT_ISO_EDGE *edge = NULL;
3902  LWT_ISO_EDGE *upd_edge = NULL;
3903  LWT_ISO_EDGE upd_edge_left[2];
3904  int nedge_left = 0;
3905  LWT_ISO_EDGE upd_edge_right[2];
3906  int nedge_right = 0;
3907  LWT_ISO_NODE upd_node[2];
3908  int nnode = 0;
3909  LWT_ISO_FACE *faces = NULL;
3910  LWT_ISO_FACE newface;
3911  LWT_ELEMID node_ids[2];
3912  LWT_ELEMID face_ids[2];
3913  int fnode_edges = 0; /* number of edges on the first node (excluded
3914  * the one being removed ) */
3915  int lnode_edges = 0; /* number of edges on the last node (excluded
3916  * the one being removed ) */
3917 
3918  newface.face_id = 0;
3919 
3920  i = 1;
3921  edge = lwt_be_getEdgeById(topo, &edge_id, &i, LWT_COL_EDGE_ALL);
3922  if (!edge)
3923  {
3924  LWDEBUGF(1, "lwt_be_getEdgeById returned NULL and set i=%d", i);
3925  if (i == UINT64_MAX)
3926  {
3927  lwerror("Backend error: %s", lwt_be_lastErrorMessage(topo->be_iface));
3928  return -1;
3929  }
3930  else if (i == 0)
3931  {
3932  lwerror("SQL/MM Spatial exception - non-existent edge %" LWTFMT_ELEMID, edge_id);
3933  return -1;
3934  }
3935  else
3936  {
3937  lwerror(
3938  "Backend coding error: getEdgeById callback returned NULL "
3939  "but numelements output parameter has value %d "
3940  "(expected 0 or 1)",
3941  i);
3942  return -1;
3943  }
3944  }
3945 
3946  if ( ! lwt_be_checkTopoGeomRemEdge(topo, edge_id,
3947  edge->face_left, edge->face_right) )
3948  {
3950  return -1;
3951  }
3952 
3953  LWDEBUG(1, "Updating next_{right,left}_face of ring edges...");
3954 
3955  /* Update edge linking */
3956 
3957  nedges = 0;
3958  node_ids[nedges++] = edge->start_node;
3959  if ( edge->end_node != edge->start_node )
3960  {
3961  node_ids[nedges++] = edge->end_node;
3962  }
3966  upd_edge = lwt_be_getEdgeByNode( topo, &(node_ids[0]), &nedges, fields );
3967  if (nedges == UINT64_MAX)
3968  {
3969  lwerror("Backend error: %s", lwt_be_lastErrorMessage(topo->be_iface));
3970  return -1;
3971  }
3972  nedge_left = nedge_right = 0;
3973  for ( i=0; i<nedges; ++i )
3974  {
3975  LWT_ISO_EDGE *e = &(upd_edge[i]);
3976  if ( e->edge_id == edge_id ) continue;
3977  if ( e->start_node == edge->start_node || e->end_node == edge->start_node )
3978  {
3979  ++fnode_edges;
3980  }
3981  if ( e->start_node == edge->end_node || e->end_node == edge->end_node )
3982  {
3983  ++lnode_edges;
3984  }
3985  if ( e->next_left == -edge_id )
3986  {
3987  upd_edge_left[nedge_left].edge_id = e->edge_id;
3988  upd_edge_left[nedge_left++].next_left =
3989  edge->next_left != edge_id ? edge->next_left : edge->next_right;
3990  }
3991  else if ( e->next_left == edge_id )
3992  {
3993  upd_edge_left[nedge_left].edge_id = e->edge_id;
3994  upd_edge_left[nedge_left++].next_left =
3995  edge->next_right != -edge_id ? edge->next_right : edge->next_left;
3996  }
3997 
3998  if ( e->next_right == -edge_id )
3999  {
4000  upd_edge_right[nedge_right].edge_id = e->edge_id;
4001  upd_edge_right[nedge_right++].next_right =
4002  edge->next_left != edge_id ? edge->next_left : edge->next_right;
4003  }
4004  else if ( e->next_right == edge_id )
4005  {
4006  upd_edge_right[nedge_right].edge_id = e->edge_id;
4007  upd_edge_right[nedge_right++].next_right =
4008  edge->next_right != -edge_id ? edge->next_right : edge->next_left;
4009  }
4010  }
4011 
4012  if ( nedge_left )
4013  {
4014  LWDEBUGF(1, "updating %d 'next_left' edges", nedge_left);
4015  /* update edges in upd_edge_left set next_left */
4016  int result = lwt_be_updateEdgesById(topo, &(upd_edge_left[0]), nedge_left, LWT_COL_EDGE_NEXT_LEFT);
4017  if (result == -1)
4018  {
4019  _lwt_release_edges(edge, 1);
4020  lwfree(upd_edge);
4021  lwerror("Backend error: %s", lwt_be_lastErrorMessage(topo->be_iface));
4022  return -1;
4023  }
4024  }
4025  if ( nedge_right )
4026  {
4027  LWDEBUGF(1, "updating %d 'next_right' edges", nedge_right);
4028  /* update edges in upd_edge_right set next_right */
4029  int result = lwt_be_updateEdgesById(topo, &(upd_edge_right[0]), nedge_right, LWT_COL_EDGE_NEXT_RIGHT);
4030  if (result == -1)
4031  {
4032  _lwt_release_edges(edge, 1);
4033  lwfree(upd_edge);
4034  lwerror("Backend error: %s", lwt_be_lastErrorMessage(topo->be_iface));
4035  return -1;
4036  }
4037  }
4038  LWDEBUGF(1, "releasing %d updateable edges in %p", nedges, upd_edge);
4039  lwfree(upd_edge);
4040 
4041  /* Id of face that will take up all the space previously
4042  * taken by left and right faces of the edge */
4043  LWT_ELEMID floodface;
4044 
4045  /* Find floodface, and update its mbr if != 0 */
4046  if ( edge->face_left == edge->face_right )
4047  {
4048  floodface = edge->face_right;
4049  }
4050  else
4051  {
4052  /* Two faces healed */
4053  if ( edge->face_left == 0 || edge->face_right == 0 )
4054  {
4055  floodface = 0;
4056  LWDEBUG(1, "floodface is universe");
4057  }
4058  else
4059  {
4060  /* we choose right face as the face that will remain
4061  * to be symmetric with ST_AddEdgeModFace */
4062  floodface = edge->face_right;
4063  LWDEBUGF(1, "floodface is %" LWTFMT_ELEMID, floodface);
4064  /* update mbr of floodface as union of mbr of both faces */
4065  face_ids[0] = edge->face_left;
4066  face_ids[1] = edge->face_right;
4067  nfaces = 2;
4068  fields = LWT_COL_FACE_ALL;
4069  faces = lwt_be_getFaceById(topo, face_ids, &nfaces, fields);
4070  if (nfaces == UINT64_MAX)
4071  {
4072  lwerror("Backend error: %s", lwt_be_lastErrorMessage(topo->be_iface));
4073  return -1;
4074  }
4075  GBOX *box1=NULL;
4076  GBOX *box2=NULL;
4077  for ( i=0; i<nfaces; ++i )
4078  {
4079  if ( faces[i].face_id == edge->face_left )
4080  {
4081  if ( ! box1 ) box1 = faces[i].mbr;
4082  else
4083  {
4084  i = edge->face_left;
4085  _lwt_release_edges(edge, 1);
4086  _lwt_release_faces(faces, nfaces);
4087  lwerror("corrupted topology: more than 1 face have face_id=%"
4088  LWTFMT_ELEMID, i);
4089  return -1;
4090  }
4091  }
4092  else if ( faces[i].face_id == edge->face_right )
4093  {
4094  if ( ! box2 ) box2 = faces[i].mbr;
4095  else
4096  {
4097  i = edge->face_right;
4098  _lwt_release_edges(edge, 1);
4099  _lwt_release_faces(faces, nfaces);
4100  lwerror("corrupted topology: more than 1 face have face_id=%"
4101  LWTFMT_ELEMID, i);
4102  return -1;
4103  }
4104  }
4105  else
4106  {
4107  i = faces[i].face_id;
4108  _lwt_release_edges(edge, 1);
4109  _lwt_release_faces(faces, nfaces);
4110  lwerror("Backend coding error: getFaceById returned face "
4111  "with non-requested id %" LWTFMT_ELEMID, i);
4112  return -1;
4113  }
4114  }
4115  if ( ! box1 ) {
4116  i = edge->face_left;
4117  _lwt_release_edges(edge, 1);
4118  if ( nfaces ) _lwt_release_faces(faces, nfaces);
4119  lwerror("corrupted topology: no face have face_id=%"
4120  LWTFMT_ELEMID " (left face for edge %"
4121  LWTFMT_ELEMID ")", i, edge_id);
4122  return -1;
4123  }
4124  if ( ! box2 ) {
4125  i = edge->face_right;
4126  _lwt_release_edges(edge, 1);
4127  if ( nfaces ) _lwt_release_faces(faces, nfaces);
4128  lwerror("corrupted topology: no face have face_id=%"
4129  LWTFMT_ELEMID " (right face for edge %"
4130  LWTFMT_ELEMID ")", i, edge_id);
4131  return -1;
4132  }
4133  gbox_merge(box2, box1); /* box1 is now the union of the two */
4134  newface.mbr = box1;
4135  if ( modFace )
4136  {
4137  newface.face_id = floodface;
4138  int result = lwt_be_updateFacesById(topo, &newface, 1);
4139  _lwt_release_faces(faces, 2);
4140  if (result == -1)
4141  {
4142  _lwt_release_edges(edge, 1);
4143  lwerror("Backend error: %s", lwt_be_lastErrorMessage(topo->be_iface));
4144  return -1;
4145  }
4146  if (result != 1)
4147  {
4148  _lwt_release_edges(edge, 1);
4149  lwerror("Unexpected error: %d faces updated when expecting 1", i);
4150  return -1;
4151  }
4152  }
4153  else
4154  {
4155  /* New face replaces the old two faces */
4156  newface.face_id = -1;
4157  int result = lwt_be_insertFaces(topo, &newface, 1);
4158  _lwt_release_faces(faces, 2);
4159  if (result == -1)
4160  {
4161  _lwt_release_edges(edge, 1);
4162  lwerror("Backend error: %s", lwt_be_lastErrorMessage(topo->be_iface));
4163  return -1;
4164  }
4165  if (result != 1)
4166  {
4167  _lwt_release_edges(edge, 1);
4168  lwerror("Unexpected error: %d faces inserted when expecting 1", result);
4169  return -1;
4170  }
4171  floodface = newface.face_id;
4172  }
4173  }
4174 
4175  /* Update face references for edges and nodes still referencing
4176  * the removed face(s) */
4177 
4178  if ( edge->face_left != floodface )
4179  {
4180  if ( -1 == _lwt_UpdateEdgeFaceRef(topo, edge->face_left, floodface) )
4181  {
4182  _lwt_release_edges(edge, 1);
4183  lwerror("Backend error: %s", lwt_be_lastErrorMessage(topo->be_iface));
4184  return -1;
4185  }
4186  if ( -1 == _lwt_UpdateNodeFaceRef(topo, edge->face_left, floodface) )
4187  {
4188  _lwt_release_edges(edge, 1);
4189  lwerror("Backend error: %s", lwt_be_lastErrorMessage(topo->be_iface));
4190  return -1;
4191  }
4192  }
4193 
4194  if ( edge->face_right != floodface )
4195  {
4196  if ( -1 == _lwt_UpdateEdgeFaceRef(topo, edge->face_right, floodface) )
4197  {
4198  _lwt_release_edges(edge, 1);
4199  lwerror("Backend error: %s", lwt_be_lastErrorMessage(topo->be_iface));
4200  return -1;
4201  }
4202  if ( -1 == _lwt_UpdateNodeFaceRef(topo, edge->face_right, floodface) )
4203  {
4204  _lwt_release_edges(edge, 1);
4205  lwerror("Backend error: %s", lwt_be_lastErrorMessage(topo->be_iface));
4206  return -1;
4207  }
4208  }
4209 
4210  /* Update topogeoms on heal */
4211  if ( ! lwt_be_updateTopoGeomFaceHeal(topo,
4212  edge->face_right, edge->face_left,
4213  floodface) )
4214  {
4215  _lwt_release_edges(edge, 1);
4217  return -1;
4218  }
4219  } /* two faces healed */
4220 
4221  /* Delete the edge */
4222  int result = lwt_be_deleteEdges(topo, edge, LWT_COL_EDGE_EDGE_ID);
4223  if (result == -1)
4224  {
4225  _lwt_release_edges(edge, 1);
4226  lwerror("Backend error: %s", lwt_be_lastErrorMessage(topo->be_iface));
4227  return -1;
4228  }
4229 
4230  /* If any of the edge nodes remained isolated, set
4231  * containing_face = floodface
4232  */
4233  if ( ! fnode_edges )
4234  {
4235  upd_node[nnode].node_id = edge->start_node;
4236  upd_node[nnode].containing_face = floodface;
4237  ++nnode;
4238  }
4239  if ( edge->end_node != edge->start_node && ! lnode_edges )
4240  {
4241  upd_node[nnode].node_id = edge->end_node;
4242  upd_node[nnode].containing_face = floodface;
4243  ++nnode;
4244  }
4245  if ( nnode )
4246  {
4247  int result = lwt_be_updateNodesById(topo, upd_node, nnode, LWT_COL_NODE_CONTAINING_FACE);
4248  if (result == -1)
4249  {
4250  _lwt_release_edges(edge, 1);
4251  lwerror("Backend error: %s", lwt_be_lastErrorMessage(topo->be_iface));
4252  return -1;
4253  }
4254  }
4255 
4256  if ( edge->face_left != edge->face_right )
4257  /* or there'd be no face to remove */
4258  {
4259  LWT_ELEMID ids[2];
4260  int nids = 0;
4261  if ( edge->face_right != floodface )
4262  ids[nids++] = edge->face_right;
4263  if ( edge->face_left != floodface )
4264  ids[nids++] = edge->face_left;
4265  int result = lwt_be_deleteFacesById(topo, ids, nids);
4266  if (result == -1)
4267  {
4268  _lwt_release_edges(edge, 1);
4269  lwerror("Backend error: %s", lwt_be_lastErrorMessage(topo->be_iface));
4270  return -1;
4271  }
4272  }
4273 
4274  _lwt_release_edges(edge, 1);
4275  return modFace ? floodface : newface.face_id;
4276 }
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:3840
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:3873
static void _lwt_release_faces(LWT_ISO_FACE *faces, int num_faces)
Definition: lwgeom_topo.c:449
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:459
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: