PostGIS  3.3.9dev-r@@SVN_REVISION@@

◆ _lwt_AddLineEdge()

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

Definition at line 5535 of file lwgeom_topo.c.

5537 {
5538  LWCOLLECTION *col;
5539  LWPOINT *start_point, *end_point;
5540  LWGEOM *tmp = 0, *tmp2;
5541  LWT_ISO_NODE *node;
5542  LWT_ELEMID nid[2]; /* start_node, end_node */
5543  LWT_ELEMID id; /* edge id */
5544  POINT4D p4d;
5545  uint64_t nn, i;
5546  int moved=0, mm;
5547 
5548  LWDEBUGG(1, lwline_as_lwgeom(edge), "_lwtAddLineEdge");
5549  LWDEBUGF(1, "_lwtAddLineEdge with tolerance %g", tol);
5550 
5551  start_point = lwline_get_lwpoint(edge, 0);
5552  if ( ! start_point )
5553  {
5554  lwnotice("Empty component of noded line");
5555  return 0; /* must be empty */
5556  }
5557  nid[0] = _lwt_AddPoint( topo, start_point,
5558  _lwt_minTolerance(lwpoint_as_lwgeom(start_point)),
5559  handleFaceSplit, &mm );
5560  lwpoint_free(start_point); /* too late if lwt_AddPoint calls lwerror */
5561  if ( nid[0] == -1 ) return -1; /* lwerror should have been called */
5562  moved += mm;
5563 
5564 
5565  end_point = lwline_get_lwpoint(edge, edge->points->npoints-1);
5566  if ( ! end_point )
5567  {
5568  lwerror("could not get last point of line "
5569  "after successfully getting first point !?");
5570  return -1;
5571  }
5572  nid[1] = _lwt_AddPoint( topo, end_point,
5574  handleFaceSplit, &mm );
5575  moved += mm;
5576  lwpoint_free(end_point); /* too late if lwt_AddPoint calls lwerror */
5577  if ( nid[1] == -1 ) return -1; /* lwerror should have been called */
5578 
5579  /*
5580  -- Added endpoints may have drifted due to tolerance, so
5581  -- we need to re-snap the edge to the new nodes before adding it
5582  */
5583  if ( moved )
5584  {
5585 
5586  nn = nid[0] == nid[1] ? 1 : 2;
5587  node = lwt_be_getNodeById( topo, nid, &nn,
5589  if (nn == UINT64_MAX)
5590  {
5591  lwerror("Backend error: %s", lwt_be_lastErrorMessage(topo->be_iface));
5592  return -1;
5593  }
5594  start_point = NULL; end_point = NULL;
5595  for (i=0; i<nn; ++i)
5596  {
5597  if ( node[i].node_id == nid[0] ) start_point = node[i].geom;
5598  if ( node[i].node_id == nid[1] ) end_point = node[i].geom;
5599  }
5600  if ( ! start_point || ! end_point )
5601  {
5602  if ( nn ) _lwt_release_nodes(node, nn);
5603  lwerror("Could not find just-added nodes % " LWTFMT_ELEMID
5604  " and %" LWTFMT_ELEMID, nid[0], nid[1]);
5605  return -1;
5606  }
5607 
5608  /* snap */
5609 
5610  getPoint4d_p( start_point->point, 0, &p4d );
5611  lwline_setPoint4d(edge, 0, &p4d);
5612 
5613  getPoint4d_p( end_point->point, 0, &p4d );
5614  lwline_setPoint4d(edge, edge->points->npoints-1, &p4d);
5615 
5616  if ( nn ) _lwt_release_nodes(node, nn);
5617 
5618  /* make valid, after snap (to handle collapses) */
5619  tmp = lwgeom_make_valid(lwline_as_lwgeom(edge));
5620 
5621  col = lwgeom_as_lwcollection(tmp);
5622  if ( col )
5623  {{
5624 
5626 
5627  /* Check if the so-snapped edge collapsed (see #1650) */
5628  if ( colex->ngeoms == 0 )
5629  {
5630  lwcollection_free(colex);
5631  lwgeom_free(tmp);
5632  LWDEBUG(1, "Made-valid snapped edge collapsed");
5633  return 0;
5634  }
5635 
5636  tmp2 = lwgeom_clone_deep(colex->geoms[0]);
5637  lwgeom_free(tmp);
5638  tmp = tmp2;
5639  edge = lwgeom_as_lwline(tmp);
5640  lwcollection_free(colex);
5641  if ( ! edge )
5642  {
5643  /* should never happen */
5644  lwerror("lwcollection_extract(LINETYPE) returned a non-line?");
5645  return -1;
5646  }
5647  }}
5648  else
5649  {
5650  edge = lwgeom_as_lwline(tmp);
5651  if ( ! edge )
5652  {
5653  LWDEBUGF(1, "Made-valid snapped edge collapsed to %s",
5655  lwgeom_free(tmp);
5656  return 0;
5657  }
5658  }
5659  }
5660 
5661  /* check if the so-snapped edge _now_ exists */
5662  id = _lwt_GetEqualEdge ( topo, edge, forward );
5663  LWDEBUGF(1, "_lwt_GetEqualEdge returned %" LWTFMT_ELEMID, id);
5664  if ( id == -1 )
5665  {
5666  if ( tmp ) lwgeom_free(tmp); /* probably too late, due to internal lwerror */
5667  return -1;
5668  }
5669  if ( id )
5670  {
5671  if ( tmp ) lwgeom_free(tmp); /* possibly takes "edge" down with it */
5672  return id;
5673  }
5674 
5675  /* No previously existing edge was found, we'll add one */
5676 
5677  /* Remove consecutive vertices below given tolerance
5678  * on edge addition */
5679  if ( tol )
5680  {{
5681  tmp2 = lwline_remove_repeated_points(edge, tol);
5682  LWDEBUGG(1, tmp2, "Repeated-point removed");
5683  edge = lwgeom_as_lwline(tmp2);
5684  if ( tmp ) lwgeom_free(tmp);
5685  tmp = tmp2;
5686 
5687  /* check if the so-decimated edge collapsed to single-point */
5688  if ( nid[0] == nid[1] && edge->points->npoints == 2 )
5689  {
5690  lwgeom_free(tmp);
5691  LWDEBUG(1, "Repeated-point removed edge collapsed");
5692  return 0;
5693  }
5694 
5695  /* check if the so-decimated edge _now_ exists */
5696  id = _lwt_GetEqualEdge ( topo, edge, forward );
5697  LWDEBUGF(1, "_lwt_GetEqualEdge returned %" LWTFMT_ELEMID, id);
5698  if ( id == -1 )
5699  {
5700  lwgeom_free(tmp); /* probably too late, due to internal lwerror */
5701  return -1;
5702  }
5703  if ( id )
5704  {
5705  lwgeom_free(tmp); /* takes "edge" down with it */
5706  return id;
5707  }
5708  }}
5709 
5710 
5711  /* TODO: skip checks ? */
5712  id = _lwt_AddEdge( topo, nid[0], nid[1], edge, 0, handleFaceSplit ? 1 : -1 );
5713  LWDEBUGF(1, "lwt_AddEdgeModFace returned %" LWTFMT_ELEMID, id);
5714  if ( id == -1 )
5715  {
5716  lwgeom_free(tmp); /* probably too late, due to internal lwerror */
5717  return -1;
5718  }
5719  lwgeom_free(tmp); /* possibly takes "edge" down with it */
5720 
5721  *forward = 1;
5722  return id;
5723 }
LWLINE * lwgeom_as_lwline(const LWGEOM *lwgeom)
Definition: lwgeom.c:179
LWGEOM * lwline_as_lwgeom(const LWLINE *obj)
Definition: lwgeom.c:339
void lwpoint_free(LWPOINT *pt)
Definition: lwpoint.c:213
void lwgeom_free(LWGEOM *geom)
Definition: lwgeom.c:1155
#define LINETYPE
Definition: liblwgeom.h:118
LWGEOM * lwgeom_clone_deep(const LWGEOM *lwgeom)
Deep clone an LWGEOM, everything is copied.
Definition: lwgeom.c:529
LWGEOM * lwpoint_as_lwgeom(const LWPOINT *obj)
Definition: lwgeom.c:344
LWCOLLECTION * lwcollection_extract(const LWCOLLECTION *col, uint32_t type)
Definition: lwcollection.c:432
const char * lwtype_name(uint8_t type)
Return the type name string associated with a type number (e.g.
Definition: lwutil.c:216
void lwcollection_free(LWCOLLECTION *col)
Definition: lwcollection.c:357
int getPoint4d_p(const POINTARRAY *pa, uint32_t n, POINT4D *point)
Definition: lwgeom_api.c:126
void lwline_setPoint4d(LWLINE *line, uint32_t which, POINT4D *newpoint)
Definition: lwline.c:364
LWCOLLECTION * lwgeom_as_lwcollection(const LWGEOM *lwgeom)
Definition: lwgeom.c:233
LWGEOM * lwgeom_make_valid(LWGEOM *geom)
Attempts to make an invalid geometries valid w/out losing points.
LWPOINT * lwline_get_lwpoint(const LWLINE *line, uint32_t where)
Returns freshly allocated LWPOINT that corresponds to the index where.
Definition: lwline.c:309
LWGEOM * lwline_remove_repeated_points(const LWLINE *in, double tolerance)
Definition: lwline.c:439
LWT_INT64 LWT_ELEMID
Identifier of topology element.
#define LWT_COL_NODE_GEOM
#define LWT_COL_NODE_NODE_ID
Node fields.
#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
void lwnotice(const char *fmt,...)
Write a notice out to the notice handler.
Definition: lwutil.c:177
#define LWDEBUGG(level, geom, msg)
Definition: lwgeom_log.h:93
const char * lwt_be_lastErrorMessage(const LWT_BE_IFACE *be)
Definition: lwgeom_topo.c:119
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:2314
static void _lwt_release_nodes(LWT_ISO_NODE *nodes, int num_nodes)
Definition: lwgeom_topo.c:475
static double _lwt_minTolerance(LWGEOM *g)
Definition: lwgeom_topo.c:5046
static LWT_ELEMID _lwt_GetEqualEdge(LWT_TOPOLOGY *topo, LWLINE *edge, int *forward)
Definition: lwgeom_topo.c:5421
LWT_ISO_NODE * lwt_be_getNodeById(LWT_TOPOLOGY *topo, const LWT_ELEMID *ids, uint64_t *numelems, int fields)
Definition: lwgeom_topo.c:155
#define LWTFMT_ELEMID
Definition: lwgeom_topo.c:43
static LWT_ELEMID _lwt_AddPoint(LWT_TOPOLOGY *topo, LWPOINT *point, double tol, int findFace, int *moved)
Definition: lwgeom_topo.c:5093
static uint32_t lwgeom_get_type(const LWGEOM *geom)
Return LWTYPE number.
Definition: lwinline.h:145
uint32_t ngeoms
Definition: liblwgeom.h:595
LWGEOM ** geoms
Definition: liblwgeom.h:590
POINTARRAY * points
Definition: liblwgeom.h:498
POINTARRAY * point
Definition: liblwgeom.h:486
LWPOINT * geom
const LWT_BE_IFACE * be_iface
uint32_t npoints
Definition: liblwgeom.h:442

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().

Here is the call graph for this function:
Here is the caller graph for this function: