PostGIS  3.0.6dev-r@@SVN_REVISION@@

◆ _lwt_RemEdge()

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

Definition at line 3810 of file lwgeom_topo.c.

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