PostGIS  2.5.1dev-r@@SVN_REVISION@@

◆ _lwt_AddLineEdge()

static LWT_ELEMID _lwt_AddLineEdge ( LWT_TOPOLOGY topo,
LWLINE edge,
double  tol,
int  handleFaceSplit 
)
static

Definition at line 5283 of file lwgeom_topo.c.

References _lwt_AddEdge(), _lwt_AddPoint(), _lwt_GetEqualEdge(), _lwt_minTolerance(), _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_as_lwgeom(), lwpoint_free(), 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().

5285 {
5286  LWCOLLECTION *col;
5287  LWPOINT *start_point, *end_point;
5288  LWGEOM *tmp = 0, *tmp2;
5289  LWT_ISO_NODE *node;
5290  LWT_ELEMID nid[2]; /* start_node, end_node */
5291  LWT_ELEMID id; /* edge id */
5292  POINT4D p4d;
5293  int nn, i;
5294  int moved=0, mm;
5295 
5296  LWDEBUGG(1, lwline_as_lwgeom(edge), "_lwtAddLineEdge");
5297  LWDEBUGF(1, "_lwtAddLineEdge with tolerance %g", tol);
5298 
5299  start_point = lwline_get_lwpoint(edge, 0);
5300  if ( ! start_point )
5301  {
5302  lwnotice("Empty component of noded line");
5303  return 0; /* must be empty */
5304  }
5305  nid[0] = _lwt_AddPoint( topo, start_point,
5306  _lwt_minTolerance(lwpoint_as_lwgeom(start_point)),
5307  handleFaceSplit, &mm );
5308  lwpoint_free(start_point); /* too late if lwt_AddPoint calls lwerror */
5309  if ( nid[0] == -1 ) return -1; /* lwerror should have been called */
5310  moved += mm;
5311 
5312 
5313  end_point = lwline_get_lwpoint(edge, edge->points->npoints-1);
5314  if ( ! end_point )
5315  {
5316  lwerror("could not get last point of line "
5317  "after successfully getting first point !?");
5318  return -1;
5319  }
5320  nid[1] = _lwt_AddPoint( topo, end_point,
5322  handleFaceSplit, &mm );
5323  moved += mm;
5324  lwpoint_free(end_point); /* too late if lwt_AddPoint calls lwerror */
5325  if ( nid[1] == -1 ) return -1; /* lwerror should have been called */
5326 
5327  /*
5328  -- Added endpoints may have drifted due to tolerance, so
5329  -- we need to re-snap the edge to the new nodes before adding it
5330  */
5331  if ( moved )
5332  {
5333 
5334  nn = nid[0] == nid[1] ? 1 : 2;
5335  node = lwt_be_getNodeById( topo, nid, &nn,
5337  if ( nn == -1 )
5338  {
5339  lwerror("Backend error: %s", lwt_be_lastErrorMessage(topo->be_iface));
5340  return -1;
5341  }
5342  start_point = NULL; end_point = NULL;
5343  for (i=0; i<nn; ++i)
5344  {
5345  if ( node[i].node_id == nid[0] ) start_point = node[i].geom;
5346  if ( node[i].node_id == nid[1] ) end_point = node[i].geom;
5347  }
5348  if ( ! start_point || ! end_point )
5349  {
5350  if ( nn ) _lwt_release_nodes(node, nn);
5351  lwerror("Could not find just-added nodes % " LWTFMT_ELEMID
5352  " and %" LWTFMT_ELEMID, nid[0], nid[1]);
5353  return -1;
5354  }
5355 
5356  /* snap */
5357 
5358  getPoint4d_p( start_point->point, 0, &p4d );
5359  lwline_setPoint4d(edge, 0, &p4d);
5360 
5361  getPoint4d_p( end_point->point, 0, &p4d );
5362  lwline_setPoint4d(edge, edge->points->npoints-1, &p4d);
5363 
5364  if ( nn ) _lwt_release_nodes(node, nn);
5365 
5366  /* make valid, after snap (to handle collapses) */
5367  tmp = lwgeom_make_valid(lwline_as_lwgeom(edge));
5368 
5369  col = lwgeom_as_lwcollection(tmp);
5370  if ( col )
5371  {{
5372 
5373  col = lwcollection_extract(col, LINETYPE);
5374 
5375  /* Check if the so-snapped edge collapsed (see #1650) */
5376  if ( col->ngeoms == 0 )
5377  {
5378  lwcollection_free(col);
5379  lwgeom_free(tmp);
5380  LWDEBUG(1, "Made-valid snapped edge collapsed");
5381  return 0;
5382  }
5383 
5384  tmp2 = lwgeom_clone_deep( col->geoms[0] );
5385  lwgeom_free(tmp);
5386  tmp = tmp2;
5387  edge = lwgeom_as_lwline(tmp);
5388  lwcollection_free(col);
5389  if ( ! edge )
5390  {
5391  /* should never happen */
5392  lwerror("lwcollection_extract(LINETYPE) returned a non-line?");
5393  return -1;
5394  }
5395  }}
5396  else
5397  {
5398  edge = lwgeom_as_lwline(tmp);
5399  if ( ! edge )
5400  {
5401  LWDEBUGF(1, "Made-valid snapped edge collapsed to %s",
5403  lwgeom_free(tmp);
5404  return 0;
5405  }
5406  }
5407  }
5408 
5409  /* check if the so-snapped edge _now_ exists */
5410  id = _lwt_GetEqualEdge ( topo, edge );
5411  LWDEBUGF(1, "_lwt_GetEqualEdge returned %" LWTFMT_ELEMID, id);
5412  if ( id == -1 )
5413  {
5414  if ( tmp ) lwgeom_free(tmp); /* probably too late, due to internal lwerror */
5415  return -1;
5416  }
5417  if ( id )
5418  {
5419  if ( tmp ) lwgeom_free(tmp); /* possibly takes "edge" down with it */
5420  return id;
5421  }
5422 
5423  /* No previously existing edge was found, we'll add one */
5424 
5425  /* Remove consecutive vertices below given tolerance
5426  * on edge addition */
5427  if ( tol )
5428  {{
5429  tmp2 = lwline_remove_repeated_points(edge, tol);
5430  LWDEBUGG(1, tmp2, "Repeated-point removed");
5431  edge = lwgeom_as_lwline(tmp2);
5432  if ( tmp ) lwgeom_free(tmp);
5433  tmp = tmp2;
5434 
5435  /* check if the so-decimated edge _now_ exists */
5436  id = _lwt_GetEqualEdge ( topo, edge );
5437  LWDEBUGF(1, "_lwt_GetEqualEdge returned %" LWTFMT_ELEMID, id);
5438  if ( id == -1 )
5439  {
5440  lwgeom_free(tmp); /* probably too late, due to internal lwerror */
5441  return -1;
5442  }
5443  if ( id )
5444  {
5445  lwgeom_free(tmp); /* takes "edge" down with it */
5446  return id;
5447  }
5448  }}
5449 
5450 
5451  /* TODO: skip checks ? */
5452  id = _lwt_AddEdge( topo, nid[0], nid[1], edge, 0, handleFaceSplit ? 1 : -1 );
5453  LWDEBUGF(1, "lwt_AddEdgeModFace returned %" LWTFMT_ELEMID, id);
5454  if ( id == -1 )
5455  {
5456  lwgeom_free(tmp); /* probably too late, due to internal lwerror */
5457  return -1;
5458  }
5459  lwgeom_free(tmp); /* possibly takes "edge" down with it */
5460 
5461  return id;
5462 }
static LWT_ELEMID _lwt_GetEqualEdge(LWT_TOPOLOGY *topo, LWLINE *edge)
Definition: lwgeom_topo.c:5209
#define LINETYPE
Definition: liblwgeom.h:85
static void _lwt_release_nodes(LWT_ISO_NODE *nodes, int num_nodes)
Definition: lwgeom_topo.c:467
LWCOLLECTION * lwcollection_extract(LWCOLLECTION *col, int type)
Takes a potentially heterogeneous collection and returns a homogeneous collection consisting only of ...
Definition: lwcollection.c:386
LWPOINT * geom
void lwnotice(const char *fmt,...)
Write a notice out to the notice handler.
Definition: lwutil.c:177
uint32_t lwgeom_get_type(const LWGEOM *geom)
Return LWTYPE number.
Definition: lwgeom.c:923
void lwpoint_free(LWPOINT *pt)
Definition: lwpoint.c:213
void lwgeom_free(LWGEOM *geom)
Definition: lwgeom.c:1144
static LWT_ELEMID _lwt_AddPoint(LWT_TOPOLOGY *topo, LWPOINT *point, double tol, int findFace, int *moved)
Definition: lwgeom_topo.c:4886
#define LWDEBUG(level, msg)
Definition: lwgeom_log.h:83
LWGEOM * lwgeom_clone_deep(const LWGEOM *lwgeom)
Deep clone an LWGEOM, everything is copied.
Definition: lwgeom.c:520
uint32_t ngeoms
Definition: liblwgeom.h:509
POINTARRAY * point
Definition: liblwgeom.h:413
void lwline_setPoint4d(LWLINE *line, uint32_t which, POINT4D *newpoint)
Definition: lwline.c:373
const char * lwtype_name(uint8_t type)
Return the type name string associated with a type number (e.g.
Definition: lwutil.c:218
LWGEOM * lwline_as_lwgeom(const LWLINE *obj)
Definition: lwgeom.c:330
LWGEOM * lwgeom_make_valid(LWGEOM *geom)
Attempts to make an invalid geometries valid w/out losing points.
static LWT_ELEMID _lwt_AddEdge(LWT_TOPOLOGY *topo, LWT_ELEMID start_node, LWT_ELEMID end_node, LWLINE *geom, int skipChecks, int modFace)
Definition: lwgeom_topo.c:2255
const LWT_BE_IFACE * be_iface
LWGEOM ** geoms
Definition: liblwgeom.h:511
static double _lwt_minTolerance(LWGEOM *g)
Definition: lwgeom_topo.c:4839
LWLINE * lwgeom_as_lwline(const LWGEOM *lwgeom)
Definition: lwgeom.c:170
#define LWDEBUGG(level, geom, msg)
Definition: lwgeom_log.h:93
int getPoint4d_p(const POINTARRAY *pa, uint32_t n, POINT4D *point)
Definition: lwgeom_api.c:113
#define LWT_COL_NODE_NODE_ID
Node fields.
LWGEOM * lwline_remove_repeated_points(const LWLINE *in, double tolerance)
Definition: lwline.c:448
LWCOLLECTION * lwgeom_as_lwcollection(const LWGEOM *lwgeom)
Definition: lwgeom.c:224
#define LWT_COL_NODE_GEOM
void lwcollection_free(LWCOLLECTION *col)
Definition: lwcollection.c:356
LWGEOM * lwpoint_as_lwgeom(const LWPOINT *obj)
Definition: lwgeom.c:335
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:156
#define LWDEBUGF(level, msg,...)
Definition: lwgeom_log.h:88
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
#define LWTFMT_ELEMID
Definition: lwgeom_topo.c:44
LWPOINT * lwline_get_lwpoint(const LWLINE *line, uint32_t where)
Returns freshly allocated LWPOINT that corresponds to the index where.
Definition: lwline.c:318
POINTARRAY * points
Definition: liblwgeom.h:424
uint32_t npoints
Definition: liblwgeom.h:373
Here is the call graph for this function:
Here is the caller graph for this function: