PostGIS  3.1.6dev-r@@SVN_REVISION@@

◆ _lwt_RemEdge()

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

Definition at line 3862 of file lwgeom_topo.c.

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