PostGIS  2.2.7dev-r@@SVN_REVISION@@
static LWT_ELEMID _lwt_AddLineEdge ( LWT_TOPOLOGY topo,
LWLINE edge,
double  tol 
)
static

Definition at line 5396 of file lwgeom_topo.c.

References _lwt_GetEqualEdge(), _lwt_release_nodes(), LWT_TOPOLOGY_T::be_iface, LWT_ISO_NODE::geom, LWCOLLECTION::geoms, getPoint4d_p(), LINETYPE, lwcollection_extract(), lwcollection_free(), LWDEBUG, LWDEBUGF, LWDEBUGG, lwerror(), lwgeom_as_lwcollection(), lwgeom_as_lwline(), lwgeom_clone_deep(), lwgeom_free(), lwgeom_get_type(), lwgeom_make_valid(), lwline_as_lwgeom(), lwline_get_lwpoint(), lwline_remove_repeated_points(), lwline_setPoint4d(), lwnotice(), lwpoint_free(), lwt_AddEdgeModFace(), lwt_AddPoint(), lwt_be_getNodeById(), lwt_be_lastErrorMessage(), LWT_COL_NODE_GEOM, LWT_COL_NODE_NODE_ID, LWTFMT_ELEMID, lwtype_name(), LWCOLLECTION::ngeoms, POINTARRAY::npoints, LWPOINT::point, and LWLINE::points.

Referenced by lwt_AddLine().

5397 {
5398  LWCOLLECTION *col;
5399  LWPOINT *start_point, *end_point;
5400  LWGEOM *tmp, *tmp2;
5401  LWT_ISO_NODE *node;
5402  LWT_ELEMID nid[2]; /* start_node, end_node */
5403  LWT_ELEMID id; /* edge id */
5404  POINT4D p4d;
5405  int nn, i;
5406 
5407  LWDEBUGG(1, lwline_as_lwgeom(edge), "_lwtAddLineEdge");
5408  LWDEBUGF(1, "_lwtAddLineEdge with tolerance %g", tol);
5409 
5410  start_point = lwline_get_lwpoint(edge, 0);
5411  if ( ! start_point )
5412  {
5413  lwnotice("Empty component of noded line");
5414  return 0; /* must be empty */
5415  }
5416  nid[0] = lwt_AddPoint( topo, start_point, tol );
5417  lwpoint_free(start_point); /* too late if lwt_AddPoint calls lwerror */
5418  if ( nid[0] == -1 ) return -1; /* lwerror should have been called */
5419 
5420  end_point = lwline_get_lwpoint(edge, edge->points->npoints-1);
5421  if ( ! end_point )
5422  {
5423  lwerror("could not get last point of line "
5424  "after successfully getting first point !?");
5425  return -1;
5426  }
5427  nid[1] = lwt_AddPoint( topo, end_point, tol );
5428  lwpoint_free(end_point); /* too late if lwt_AddPoint calls lwerror */
5429  if ( nid[1] == -1 ) return -1; /* lwerror should have been called */
5430 
5431  /*
5432  -- Added endpoints may have drifted due to tolerance, so
5433  -- we need to re-snap the edge to the new nodes before adding it
5434  */
5435 
5436  nn = nid[0] == nid[1] ? 1 : 2;
5437  node = lwt_be_getNodeById( topo, nid, &nn,
5439  if ( nn == -1 )
5440  {
5441  lwerror("Backend error: %s", lwt_be_lastErrorMessage(topo->be_iface));
5442  return -1;
5443  }
5444  start_point = NULL; end_point = NULL;
5445  for (i=0; i<nn; ++i)
5446  {
5447  if ( node[i].node_id == nid[0] ) start_point = node[i].geom;
5448  if ( node[i].node_id == nid[1] ) end_point = node[i].geom;
5449  }
5450  if ( ! start_point || ! end_point )
5451  {
5452  if ( nn ) _lwt_release_nodes(node, nn);
5453  lwerror("Could not find just-added nodes % " LWTFMT_ELEMID
5454  " and %" LWTFMT_ELEMID, nid[0], nid[1]);
5455  return -1;
5456  }
5457 
5458  /* snap */
5459 
5460  getPoint4d_p( start_point->point, 0, &p4d );
5461  lwline_setPoint4d(edge, 0, &p4d);
5462 
5463  getPoint4d_p( end_point->point, 0, &p4d );
5464  lwline_setPoint4d(edge, edge->points->npoints-1, &p4d);
5465 
5466  if ( nn ) _lwt_release_nodes(node, nn);
5467 
5468  /* make valid, after snap (to handle collapses) */
5469  tmp = lwgeom_make_valid(lwline_as_lwgeom(edge));
5470 
5471  col = lwgeom_as_lwcollection(tmp);
5472  if ( col )
5473  {{
5474 
5475  col = lwcollection_extract(col, LINETYPE);
5476 
5477  /* Check if the so-snapped edge collapsed (see #1650) */
5478  if ( col->ngeoms == 0 )
5479  {
5480  lwcollection_free(col);
5481  lwgeom_free(tmp);
5482  LWDEBUG(1, "Made-valid snapped edge collapsed");
5483  return 0;
5484  }
5485 
5486  tmp2 = lwgeom_clone_deep( col->geoms[0] );
5487  lwgeom_free(tmp);
5488  tmp = tmp2;
5489  edge = lwgeom_as_lwline(tmp);
5490  lwcollection_free(col);
5491  if ( ! edge )
5492  {
5493  /* should never happen */
5494  lwerror("lwcollection_extract(LINETYPE) returned a non-line?");
5495  return -1;
5496  }
5497  }}
5498  else
5499  {
5500  edge = lwgeom_as_lwline(tmp);
5501  if ( ! edge )
5502  {
5503  LWDEBUGF(1, "Made-valid snapped edge collapsed to %s",
5505  lwgeom_free(tmp);
5506  return 0;
5507  }
5508  }
5509 
5510  /* check if the so-snapped edge _now_ exists */
5511  id = _lwt_GetEqualEdge ( topo, edge );
5512  LWDEBUGF(1, "_lwt_GetEqualEdge returned %" LWTFMT_ELEMID, id);
5513  if ( id == -1 )
5514  {
5515  lwgeom_free(tmp); /* probably too late, due to internal lwerror */
5516  return -1;
5517  }
5518  if ( id )
5519  {
5520  lwgeom_free(tmp); /* possibly takes "edge" down with it */
5521  return id;
5522  }
5523 
5524  /* No previously existing edge was found, we'll add one */
5525 
5526  /* Remove consecutive vertices below given tolerance
5527  * on edge addition */
5528  if ( tol )
5529  {{
5530  tmp2 = lwline_remove_repeated_points(edge, tol);
5531  LWDEBUGG(1, tmp2, "Repeated-point removed");
5532  edge = lwgeom_as_lwline(tmp2);
5533  lwgeom_free(tmp);
5534  tmp = tmp2;
5535 
5536  /* check if the so-decimated edge _now_ exists */
5537  id = _lwt_GetEqualEdge ( topo, edge );
5538  LWDEBUGF(1, "_lwt_GetEqualEdge returned %" LWTFMT_ELEMID, id);
5539  if ( id == -1 )
5540  {
5541  lwgeom_free(tmp); /* probably too late, due to internal lwerror */
5542  return -1;
5543  }
5544  if ( id )
5545  {
5546  lwgeom_free(tmp); /* takes "edge" down with it */
5547  return id;
5548  }
5549  }}
5550 
5551 
5552  /* TODO: skip checks ? */
5553  id = lwt_AddEdgeModFace( topo, nid[0], nid[1], edge, 0 );
5554  LWDEBUGF(1, "lwt_AddEdgeModFace returned %" LWTFMT_ELEMID, id);
5555  if ( id == -1 )
5556  {
5557  lwgeom_free(tmp); /* probably too late, due to internal lwerror */
5558  return -1;
5559  }
5560  lwgeom_free(tmp); /* possibly takes "edge" down with it */
5561 
5562  return id;
5563 }
static LWT_ELEMID _lwt_GetEqualEdge(LWT_TOPOLOGY *topo, LWLINE *edge)
Definition: lwgeom_topo.c:5327
#define LINETYPE
Definition: liblwgeom.h:71
static void _lwt_release_nodes(LWT_ISO_NODE *nodes, int num_nodes)
Definition: lwgeom_topo.c:481
LWT_ELEMID lwt_AddPoint(LWT_TOPOLOGY *topo, LWPOINT *point, double tol)
Adds a point to the topology.
Definition: lwgeom_topo.c:4991
#define LWDEBUGG(level, geom, msg)
Definition: lwgeom_topo.c:40
LWCOLLECTION * lwcollection_extract(LWCOLLECTION *col, int type)
Takes a potentially heterogeneous collection and returns a homogeneous collection consisting only of ...
Definition: lwcollection.c:353
LWPOINT * geom
void lwnotice(const char *fmt,...)
Write a notice out to the notice handler.
Definition: lwutil.c:61
int npoints
Definition: liblwgeom.h:355
uint32_t lwgeom_get_type(const LWGEOM *geom)
Return LWTYPE number.
Definition: lwgeom.c:829
void lwpoint_free(LWPOINT *pt)
Definition: lwpoint.c:182
void lwgeom_free(LWGEOM *geom)
Definition: lwgeom.c:1050
#define LWDEBUG(level, msg)
Definition: lwgeom_log.h:50
LWGEOM * lwgeom_clone_deep(const LWGEOM *lwgeom)
Deep clone an LWGEOM, everything is copied.
Definition: lwgeom.c:433
POINTARRAY * point
Definition: liblwgeom.h:395
void lwline_setPoint4d(LWLINE *line, uint32_t which, POINT4D *newpoint)
Definition: lwline.c:351
const char * lwtype_name(uint8_t type)
Return the type name string associated with a type number (e.g.
Definition: lwutil.c:188
LWGEOM * lwline_remove_repeated_points(LWLINE *in, double tolerance)
Definition: lwline.c:427
LWGEOM * lwline_as_lwgeom(const LWLINE *obj)
Definition: lwgeom.c:249
LWGEOM * lwgeom_make_valid(LWGEOM *geom)
Attempts to make an invalid geometries valid w/out losing points.
const LWT_BE_IFACE * be_iface
LWGEOM ** geoms
Definition: liblwgeom.h:493
LWLINE * lwgeom_as_lwline(const LWGEOM *lwgeom)
Definition: lwgeom.c:89
#define LWT_COL_NODE_NODE_ID
Node fields.
LWCOLLECTION * lwgeom_as_lwcollection(const LWGEOM *lwgeom)
Definition: lwgeom.c:143
LWT_ELEMID lwt_AddEdgeModFace(LWT_TOPOLOGY *topo, LWT_ELEMID start_node, LWT_ELEMID end_node, LWLINE *geom, int skipChecks)
Add a new edge possibly splitting a face (modifying it)
Definition: lwgeom_topo.c:2765
LWPOINT * lwline_get_lwpoint(const LWLINE *line, int where)
Returns freshly allocated LWPOINT that corresponds to the index where.
Definition: lwline.c:295
#define LWT_COL_NODE_GEOM
void lwcollection_free(LWCOLLECTION *col)
Definition: lwcollection.c:326
LWT_INT64 LWT_ELEMID
Identifier of topology element.
LWT_ISO_NODE * lwt_be_getNodeById(LWT_TOPOLOGY *topo, const LWT_ELEMID *ids, int *numelems, int fields)
Definition: lwgeom_topo.c:160
#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
int getPoint4d_p(const POINTARRAY *pa, int n, POINT4D *point)
Definition: lwgeom_api.c:231
#define LWTFMT_ELEMID
Definition: lwgeom_topo.c:36
POINTARRAY * points
Definition: liblwgeom.h:406

Here is the call graph for this function:

Here is the caller graph for this function: