PostGIS  2.5.0beta2dev-r@@SVN_REVISION@@

◆ _lwt_RemEdge()

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

Definition at line 3776 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().

3777 {
3778  int i, nedges, nfaces, fields;
3779  LWT_ISO_EDGE *edge = NULL;
3780  LWT_ISO_EDGE *upd_edge = NULL;
3781  LWT_ISO_EDGE upd_edge_left[2];
3782  int nedge_left = 0;
3783  LWT_ISO_EDGE upd_edge_right[2];
3784  int nedge_right = 0;
3785  LWT_ISO_NODE upd_node[2];
3786  int nnode = 0;
3787  LWT_ISO_FACE *faces = NULL;
3788  LWT_ISO_FACE newface;
3789  LWT_ELEMID node_ids[2];
3790  LWT_ELEMID face_ids[2];
3791  int fnode_edges = 0; /* number of edges on the first node (excluded
3792  * the one being removed ) */
3793  int lnode_edges = 0; /* number of edges on the last node (excluded
3794  * the one being removed ) */
3795 
3796  newface.face_id = 0;
3797 
3798  i = 1;
3799  edge = lwt_be_getEdgeById(topo, &edge_id, &i, LWT_COL_EDGE_ALL);
3800  if ( ! edge )
3801  {
3802  LWDEBUGF(1, "lwt_be_getEdgeById returned NULL and set i=%d", i);
3803  if ( i == -1 )
3804  {
3805  lwerror("Backend error: %s", lwt_be_lastErrorMessage(topo->be_iface));
3806  return -1;
3807  }
3808  else if ( i == 0 )
3809  {
3810  lwerror("SQL/MM Spatial exception - non-existent edge %"
3811  LWTFMT_ELEMID, edge_id);
3812  return -1;
3813  }
3814  else
3815  {
3816  lwerror("Backend coding error: getEdgeById callback returned NULL "
3817  "but numelements output parameter has value %d "
3818  "(expected 0 or 1)", i);
3819  return -1;
3820  }
3821  }
3822 
3823  if ( ! lwt_be_checkTopoGeomRemEdge(topo, edge_id,
3824  edge->face_left, edge->face_right) )
3825  {
3827  return -1;
3828  }
3829 
3830  LWDEBUG(1, "Updating next_{right,left}_face of ring edges...");
3831 
3832  /* Update edge linking */
3833 
3834  nedges = 0;
3835  node_ids[nedges++] = edge->start_node;
3836  if ( edge->end_node != edge->start_node )
3837  {
3838  node_ids[nedges++] = edge->end_node;
3839  }
3843  upd_edge = lwt_be_getEdgeByNode( topo, &(node_ids[0]), &nedges, fields );
3844  if ( nedges == -1 ) {
3845  lwerror("Backend error: %s", lwt_be_lastErrorMessage(topo->be_iface));
3846  return -1;
3847  }
3848  nedge_left = nedge_right = 0;
3849  for ( i=0; i<nedges; ++i )
3850  {
3851  LWT_ISO_EDGE *e = &(upd_edge[i]);
3852  if ( e->edge_id == edge_id ) continue;
3853  if ( e->start_node == edge->start_node || e->end_node == edge->start_node )
3854  {
3855  ++fnode_edges;
3856  }
3857  if ( e->start_node == edge->end_node || e->end_node == edge->end_node )
3858  {
3859  ++lnode_edges;
3860  }
3861  if ( e->next_left == -edge_id )
3862  {
3863  upd_edge_left[nedge_left].edge_id = e->edge_id;
3864  upd_edge_left[nedge_left++].next_left =
3865  edge->next_left != edge_id ? edge->next_left : edge->next_right;
3866  }
3867  else if ( e->next_left == edge_id )
3868  {
3869  upd_edge_left[nedge_left].edge_id = e->edge_id;
3870  upd_edge_left[nedge_left++].next_left =
3871  edge->next_right != -edge_id ? edge->next_right : edge->next_left;
3872  }
3873 
3874  if ( e->next_right == -edge_id )
3875  {
3876  upd_edge_right[nedge_right].edge_id = e->edge_id;
3877  upd_edge_right[nedge_right++].next_right =
3878  edge->next_left != edge_id ? edge->next_left : edge->next_right;
3879  }
3880  else if ( e->next_right == edge_id )
3881  {
3882  upd_edge_right[nedge_right].edge_id = e->edge_id;
3883  upd_edge_right[nedge_right++].next_right =
3884  edge->next_right != -edge_id ? edge->next_right : edge->next_left;
3885  }
3886  }
3887 
3888  if ( nedge_left )
3889  {
3890  LWDEBUGF(1, "updating %d 'next_left' edges", nedge_left);
3891  /* update edges in upd_edge_left set next_left */
3892  i = lwt_be_updateEdgesById(topo, &(upd_edge_left[0]), nedge_left,
3894  if ( i == -1 )
3895  {
3896  _lwt_release_edges(edge, 1);
3897  lwfree(upd_edge);
3898  lwerror("Backend error: %s", lwt_be_lastErrorMessage(topo->be_iface));
3899  return -1;
3900  }
3901  }
3902  if ( nedge_right )
3903  {
3904  LWDEBUGF(1, "updating %d 'next_right' edges", nedge_right);
3905  /* update edges in upd_edge_right set next_right */
3906  i = lwt_be_updateEdgesById(topo, &(upd_edge_right[0]), nedge_right,
3908  if ( i == -1 )
3909  {
3910  _lwt_release_edges(edge, 1);
3911  lwfree(upd_edge);
3912  lwerror("Backend error: %s", lwt_be_lastErrorMessage(topo->be_iface));
3913  return -1;
3914  }
3915  }
3916  LWDEBUGF(1, "releasing %d updateable edges in %p", nedges, upd_edge);
3917  lwfree(upd_edge);
3918 
3919  /* Id of face that will take up all the space previously
3920  * taken by left and right faces of the edge */
3921  LWT_ELEMID floodface;
3922 
3923  /* Find floodface, and update its mbr if != 0 */
3924  if ( edge->face_left == edge->face_right )
3925  {
3926  floodface = edge->face_right;
3927  }
3928  else
3929  {
3930  /* Two faces healed */
3931  if ( edge->face_left == 0 || edge->face_right == 0 )
3932  {
3933  floodface = 0;
3934  LWDEBUG(1, "floodface is universe");
3935  }
3936  else
3937  {
3938  /* we choose right face as the face that will remain
3939  * to be symmetric with ST_AddEdgeModFace */
3940  floodface = edge->face_right;
3941  LWDEBUGF(1, "floodface is %" LWTFMT_ELEMID, floodface);
3942  /* update mbr of floodface as union of mbr of both faces */
3943  face_ids[0] = edge->face_left;
3944  face_ids[1] = edge->face_right;
3945  nfaces = 2;
3946  fields = LWT_COL_FACE_ALL;
3947  faces = lwt_be_getFaceById(topo, face_ids, &nfaces, fields);
3948  if ( nfaces == -1 ) {
3949  lwerror("Backend error: %s", lwt_be_lastErrorMessage(topo->be_iface));
3950  return -1;
3951  }
3952  GBOX *box1=NULL;
3953  GBOX *box2=NULL;
3954  for ( i=0; i<nfaces; ++i )
3955  {
3956  if ( faces[i].face_id == edge->face_left )
3957  {
3958  if ( ! box1 ) box1 = faces[i].mbr;
3959  else
3960  {
3961  i = edge->face_left;
3962  _lwt_release_edges(edge, 1);
3963  _lwt_release_faces(faces, nfaces);
3964  lwerror("corrupted topology: more than 1 face have face_id=%"
3965  LWTFMT_ELEMID, i);
3966  return -1;
3967  }
3968  }
3969  else if ( faces[i].face_id == edge->face_right )
3970  {
3971  if ( ! box2 ) box2 = faces[i].mbr;
3972  else
3973  {
3974  i = edge->face_right;
3975  _lwt_release_edges(edge, 1);
3976  _lwt_release_faces(faces, nfaces);
3977  lwerror("corrupted topology: more than 1 face have face_id=%"
3978  LWTFMT_ELEMID, i);
3979  return -1;
3980  }
3981  }
3982  else
3983  {
3984  i = faces[i].face_id;
3985  _lwt_release_edges(edge, 1);
3986  _lwt_release_faces(faces, nfaces);
3987  lwerror("Backend coding error: getFaceById returned face "
3988  "with non-requested id %" LWTFMT_ELEMID, i);
3989  return -1;
3990  }
3991  }
3992  if ( ! box1 ) {
3993  i = edge->face_left;
3994  _lwt_release_edges(edge, 1);
3995  _lwt_release_faces(faces, nfaces);
3996  lwerror("corrupted topology: no face have face_id=%"
3997  LWTFMT_ELEMID " (left face for edge %"
3998  LWTFMT_ELEMID ")", i, edge_id);
3999  return -1;
4000  }
4001  if ( ! box2 ) {
4002  i = edge->face_right;
4003  _lwt_release_edges(edge, 1);
4004  _lwt_release_faces(faces, nfaces);
4005  lwerror("corrupted topology: no face have face_id=%"
4006  LWTFMT_ELEMID " (right face for edge %"
4007  LWTFMT_ELEMID ")", i, edge_id);
4008  return -1;
4009  }
4010  gbox_merge(box2, box1); /* box1 is now the union of the two */
4011  newface.mbr = box1;
4012  if ( modFace )
4013  {
4014  newface.face_id = floodface;
4015  i = lwt_be_updateFacesById( topo, &newface, 1 );
4016  _lwt_release_faces(faces, 2);
4017  if ( i == -1 )
4018  {
4019  _lwt_release_edges(edge, 1);
4020  lwerror("Backend error: %s", lwt_be_lastErrorMessage(topo->be_iface));
4021  return -1;
4022  }
4023  if ( i != 1 )
4024  {
4025  _lwt_release_edges(edge, 1);
4026  lwerror("Unexpected error: %d faces updated when expecting 1", i);
4027  return -1;
4028  }
4029  }
4030  else
4031  {
4032  /* New face replaces the old two faces */
4033  newface.face_id = -1;
4034  i = lwt_be_insertFaces( topo, &newface, 1 );
4035  _lwt_release_faces(faces, 2);
4036  if ( i == -1 )
4037  {
4038  _lwt_release_edges(edge, 1);
4039  lwerror("Backend error: %s", lwt_be_lastErrorMessage(topo->be_iface));
4040  return -1;
4041  }
4042  if ( i != 1 )
4043  {
4044  _lwt_release_edges(edge, 1);
4045  lwerror("Unexpected error: %d faces inserted when expecting 1", i);
4046  return -1;
4047  }
4048  floodface = newface.face_id;
4049  }
4050  }
4051 
4052  /* Update face references for edges and nodes still referencing
4053  * the removed face(s) */
4054 
4055  if ( edge->face_left != floodface )
4056  {
4057  if ( -1 == _lwt_UpdateEdgeFaceRef(topo, edge->face_left, floodface) )
4058  {
4059  _lwt_release_edges(edge, 1);
4060  lwerror("Backend error: %s", lwt_be_lastErrorMessage(topo->be_iface));
4061  return -1;
4062  }
4063  if ( -1 == _lwt_UpdateNodeFaceRef(topo, edge->face_left, floodface) )
4064  {
4065  _lwt_release_edges(edge, 1);
4066  lwerror("Backend error: %s", lwt_be_lastErrorMessage(topo->be_iface));
4067  return -1;
4068  }
4069  }
4070 
4071  if ( edge->face_right != floodface )
4072  {
4073  if ( -1 == _lwt_UpdateEdgeFaceRef(topo, edge->face_right, floodface) )
4074  {
4075  _lwt_release_edges(edge, 1);
4076  lwerror("Backend error: %s", lwt_be_lastErrorMessage(topo->be_iface));
4077  return -1;
4078  }
4079  if ( -1 == _lwt_UpdateNodeFaceRef(topo, edge->face_right, floodface) )
4080  {
4081  _lwt_release_edges(edge, 1);
4082  lwerror("Backend error: %s", lwt_be_lastErrorMessage(topo->be_iface));
4083  return -1;
4084  }
4085  }
4086 
4087  /* Update topogeoms on heal */
4088  if ( ! lwt_be_updateTopoGeomFaceHeal(topo,
4089  edge->face_right, edge->face_left,
4090  floodface) )
4091  {
4092  _lwt_release_edges(edge, 1);
4094  return -1;
4095  }
4096  } /* two faces healed */
4097 
4098  /* Delete the edge */
4099  i = lwt_be_deleteEdges(topo, edge, LWT_COL_EDGE_EDGE_ID);
4100  if ( i == -1 ) {
4101  _lwt_release_edges(edge, 1);
4102  lwerror("Backend error: %s", lwt_be_lastErrorMessage(topo->be_iface));
4103  return -1;
4104  }
4105 
4106  /* If any of the edge nodes remained isolated, set
4107  * containing_face = floodface
4108  */
4109  if ( ! fnode_edges )
4110  {
4111  upd_node[nnode].node_id = edge->start_node;
4112  upd_node[nnode].containing_face = floodface;
4113  ++nnode;
4114  }
4115  if ( edge->end_node != edge->start_node && ! lnode_edges )
4116  {
4117  upd_node[nnode].node_id = edge->end_node;
4118  upd_node[nnode].containing_face = floodface;
4119  ++nnode;
4120  }
4121  if ( nnode )
4122  {
4123  i = lwt_be_updateNodesById(topo, upd_node, nnode,
4125  if ( i == -1 ) {
4126  _lwt_release_edges(edge, 1);
4127  lwerror("Backend error: %s", lwt_be_lastErrorMessage(topo->be_iface));
4128  return -1;
4129  }
4130  }
4131 
4132  if ( edge->face_left != edge->face_right )
4133  /* or there'd be no face to remove */
4134  {
4135  LWT_ELEMID ids[2];
4136  int nids = 0;
4137  if ( edge->face_right != floodface )
4138  ids[nids++] = edge->face_right;
4139  if ( edge->face_left != floodface )
4140  ids[nids++] = edge->face_left;
4141  i = lwt_be_deleteFacesById(topo, ids, nids);
4142  if ( i == -1 ) {
4143  _lwt_release_edges(edge, 1);
4144  lwerror("Backend error: %s", lwt_be_lastErrorMessage(topo->be_iface));
4145  return -1;
4146  }
4147  }
4148 
4149  _lwt_release_edges(edge, 1);
4150  return modFace ? floodface : newface.face_id;
4151 }
static LWT_ISO_FACE * lwt_be_getFaceById(LWT_TOPOLOGY *topo, const LWT_ELEMID *ids, int *numelems, int fields)
Definition: lwgeom_topo.c:232
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:201
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:306
void lwfree(void *mem)
Definition: lwutil.c:244
static int _lwt_UpdateNodeFaceRef(LWT_TOPOLOGY *topo, LWT_ELEMID of, LWT_ELEMID nf)
Definition: lwgeom_topo.c:3751
int lwt_be_deleteEdges(LWT_TOPOLOGY *topo, const LWT_ISO_EDGE *sel_edge, int sel_fields)
Definition: lwgeom_topo.c:322
#define LWT_COL_EDGE_START_NODE
#define LWDEBUG(level, msg)
Definition: lwgeom_log.h:83
LWT_ISO_EDGE * lwt_be_getEdgeById(LWT_TOPOLOGY *topo, const LWT_ELEMID *ids, int *numelems, int fields)
Definition: lwgeom_topo.c:225
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:264
static int lwt_be_updateFacesById(LWT_TOPOLOGY *topo, const LWT_ISO_FACE *faces, int numfaces)
Definition: lwgeom_topo.c:298
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:364
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:207
static int lwt_be_updateNodesById(LWT_TOPOLOGY *topo, const LWT_ISO_NODE *nodes, int numnodes, int upd_fields)
Definition: lwgeom_topo.c:314
#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:3718
#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:457
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:239
static void _lwt_release_faces(LWT_ISO_FACE *faces, int num_faces)
Definition: lwgeom_topo.c:447
LWT_ELEMID end_node
#define LWDEBUGF(level, msg,...)
Definition: lwgeom_log.h:88
uint32_t e
Definition: geobuf.h:57
const char * lwt_be_lastErrorMessage(const LWT_BE_IFACE *be)
Definition: lwgeom_topo.c:120
void lwerror(const char *fmt,...)
Write a notice out to the error handler.
Definition: lwutil.c:190
static int lwt_be_checkTopoGeomRemEdge(LWT_TOPOLOGY *topo, LWT_ELEMID edge_id, LWT_ELEMID face_left, LWT_ELEMID face_right)
Definition: lwgeom_topo.c:350
#define LWTFMT_ELEMID
Definition: lwgeom_topo.c:44
Here is the call graph for this function:
Here is the caller graph for this function: