PostGIS  3.4.0dev-r@@SVN_REVISION@@

◆ _lwt_RemEdge()

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

Definition at line 3838 of file lwgeom_topo.c.

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