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 3808 of file lwgeom_topo.c.

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