PostGIS  2.2.7dev-r@@SVN_REVISION@@
static LWT_ELEMID _lwt_RemEdge ( LWT_TOPOLOGY topo,
LWT_ELEMID  edge_id,
int  modFace 
)
static

Definition at line 3910 of file lwgeom_topo.c.

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

Referenced by lwt_RemEdgeModFace(), and lwt_RemEdgeNewFace().

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

Here is the call graph for this function:

Here is the caller graph for this function: