PostGIS  3.7.0dev-r@@SVN_REVISION@@

◆ _lwt_AddLineEdge()

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

Definition at line 6903 of file lwgeom_topo.c.

6905 {
6906  LWCOLLECTION *col;
6907  LWPOINT *start_point, *end_point;
6908  LWGEOM *tmp = 0, *tmp2;
6909  LWT_ISO_NODE *node;
6910  LWT_ELEMID nid[2]; /* start_node, end_node */
6911  LWT_ELEMID id; /* edge id */
6912  POINT4D p4d;
6913  uint64_t nn, i;
6914  int moved=0, mm;
6915  int pointSplitEdges = -666;
6916 
6917  if ( numNewEdges ) *numNewEdges = 0;
6918 
6919  LWDEBUGG(1, lwline_as_lwgeom(edge), "_lwtAddLineEdge");
6920  LWDEBUGF(1, "_lwtAddLineEdge with tolerance %g", tol);
6921 
6922  start_point = lwline_get_lwpoint(edge, 0);
6923  if ( ! start_point )
6924  {
6925  lwnotice("Empty component of noded line");
6926  return 0; /* must be empty */
6927  }
6928  nid[0] = _lwt_AddPoint( topo, start_point,
6929  _lwt_minTolerance(lwpoint_as_lwgeom(start_point)),
6930  handleFaceSplit, &mm, &pointSplitEdges );
6931  lwpoint_free(start_point); /* too late if lwt_AddPoint calls lwerror */
6932  if ( nid[0] == -1 ) return -1; /* lwerror should have been called */
6933  if ( numNewEdges ) *numNewEdges += pointSplitEdges;
6934  moved += mm;
6935  LWDEBUGF(1, "node for start point added or found to be %" LWTFMT_ELEMID " (moved ? %d; split %d edges)", nid[0], mm, pointSplitEdges);
6936 
6937 
6938  end_point = lwline_get_lwpoint(edge, edge->points->npoints-1);
6939  if ( ! end_point )
6940  {
6941  lwerror("could not get last point of line "
6942  "after successfully getting first point !?");
6943  return -1;
6944  }
6945  nid[1] = _lwt_AddPoint( topo, end_point,
6947  handleFaceSplit, &mm, &pointSplitEdges );
6948  lwpoint_free(end_point); /* too late if lwt_AddPoint calls lwerror */
6949  if ( nid[1] == -1 ) return -1; /* lwerror should have been called */
6950  if ( numNewEdges ) *numNewEdges += pointSplitEdges;
6951  moved += mm;
6952  LWDEBUGF(1, "node for end point added or found to be %" LWTFMT_ELEMID " (moved ? %d; split %d edges)", nid[1], mm, pointSplitEdges);
6953 
6954  /*
6955  -- Added endpoints may have drifted due to tolerance, so
6956  -- we need to re-snap the edge to the new nodes before adding it
6957  */
6958  if ( moved )
6959  {
6960 
6961  LWDEBUG(1, "One or both line endpoints moved by snap, updating line");
6962 
6963  nn = nid[0] == nid[1] ? 1 : 2;
6964  node = lwt_be_getNodeById( topo, nid, &nn,
6966  if (nn == UINT64_MAX)
6967  {
6968  PGTOPO_BE_ERROR();
6969  return -1;
6970  }
6971  start_point = NULL; end_point = NULL;
6972  for (i=0; i<nn; ++i)
6973  {
6974  if ( node[i].node_id == nid[0] ) start_point = node[i].geom;
6975  if ( node[i].node_id == nid[1] ) end_point = node[i].geom;
6976  }
6977  if ( ! start_point || ! end_point )
6978  {
6979  if ( nn ) _lwt_release_nodes(node, nn);
6980  lwerror("Could not find just-added nodes % " LWTFMT_ELEMID
6981  " and %" LWTFMT_ELEMID, nid[0], nid[1]);
6982  return -1;
6983  }
6984 
6985  /* snap */
6986 
6987  getPoint4d_p( start_point->point, 0, &p4d );
6988  lwline_setPoint4d(edge, 0, &p4d);
6989 
6990  getPoint4d_p( end_point->point, 0, &p4d );
6991  lwline_setPoint4d(edge, edge->points->npoints-1, &p4d);
6992 
6993  if ( nn ) _lwt_release_nodes(node, nn);
6994 
6995  LWDEBUGG(2, lwline_as_lwgeom(edge), "Snapped after drifted endpoints snap");
6996 
6997  /* make valid, after snap (to handle collapses) */
6998  tmp = lwgeom_make_valid(lwline_as_lwgeom(edge));
6999 
7000  LWDEBUGG(2, tmp, "Made-valid after snap to drifted endpoints");
7001 
7002  col = lwgeom_as_lwcollection(tmp);
7003  if ( col )
7004  {{
7005 
7007 
7008  /* Check if the so-snapped edge collapsed (see #1650) */
7009  if ( colex->ngeoms == 0 )
7010  {
7011  lwcollection_free(colex);
7012  lwgeom_free(tmp);
7013  LWDEBUG(1, "Made-valid snapped edge collapsed");
7014  return 0;
7015  }
7016 
7017  tmp2 = lwgeom_clone_deep(colex->geoms[0]);
7018  lwgeom_free(tmp);
7019  tmp = tmp2;
7020  edge = lwgeom_as_lwline(tmp);
7021  lwcollection_free(colex);
7022  if ( ! edge )
7023  {
7024  /* should never happen */
7025  lwerror("lwcollection_extract(LINETYPE) returned a non-line?");
7026  return -1;
7027  }
7028  }}
7029  else
7030  {
7031  edge = lwgeom_as_lwline(tmp);
7032  if ( ! edge )
7033  {
7034  LWDEBUGF(1, "Made-valid snapped edge collapsed to %s",
7036  lwgeom_free(tmp);
7037  return 0;
7038  }
7039  }
7040 
7041  }
7042 
7043  /* check if the so-snapped edge _now_ exists */
7044  id = _lwt_GetEqualEdge ( topo, edge, forward );
7045  LWDEBUGF(1, "_lwt_GetEqualEdge returned %" LWTFMT_ELEMID, id);
7046  if ( id == -1 )
7047  {
7048  if ( tmp ) lwgeom_free(tmp); /* probably too late, due to internal lwerror */
7049  return -1;
7050  }
7051  if ( id )
7052  {
7053  if ( tmp ) lwgeom_free(tmp); /* possibly takes "edge" down with it */
7054  return id;
7055  }
7056 
7057  /* No previously existing edge was found, we'll check after
7058  * decimating, if a tolerance was given */
7059 
7060  /* Remove consecutive vertices below given tolerance
7061  * on edge addition */
7062  if ( tol )
7063  {{
7064  tmp2 = lwline_remove_repeated_points(edge, tol);
7065  LWDEBUGG(2, tmp2, "Repeated-point removed");
7066  edge = lwgeom_as_lwline(tmp2);
7067  if ( tmp ) lwgeom_free(tmp);
7068  tmp = tmp2;
7069 
7070  /* check if the so-decimated edge collapsed to single-point */
7071  if ( nid[0] == nid[1] && edge->points->npoints == 2 )
7072  {
7073  lwgeom_free(tmp);
7074  LWDEBUG(1, "Repeated-point removed edge collapsed");
7075  return 0;
7076  }
7077 
7078  /* check if the so-decimated edge _now_ exists */
7079  id = _lwt_GetEqualEdge ( topo, edge, forward );
7080  LWDEBUGF(1, "_lwt_GetEqualEdge returned %" LWTFMT_ELEMID, id);
7081  if ( id == -1 )
7082  {
7083  lwgeom_free(tmp); /* probably too late, due to internal lwerror */
7084  return -1;
7085  }
7086  if ( id )
7087  {
7088  lwgeom_free(tmp); /* takes "edge" down with it */
7089  return id;
7090  }
7091  }}
7092 
7093  /* No previously existing edge was found, we'll add one */
7094 
7095  /* TODO: skip checks ? */
7096  id = _lwt_AddEdge( topo, nid[0], nid[1], edge, 0, handleFaceSplit ? 1 : -1 );
7097  LWDEBUGF(1, "lwt_AddEdgeModFace returned %" LWTFMT_ELEMID, id);
7098  if ( id == -1 )
7099  {
7100  lwgeom_free(tmp); /* probably too late, due to internal lwerror */
7101  return -1;
7102  }
7103  lwgeom_free(tmp); /* possibly takes "edge" down with it */
7104 
7105  if ( numNewEdges ) ++*numNewEdges;
7106  *forward = 1;
7107 
7108  return id;
7109 }
LWLINE * lwgeom_as_lwline(const LWGEOM *lwgeom)
Definition: lwgeom.c:207
LWGEOM * lwline_as_lwgeom(const LWLINE *obj)
Definition: lwgeom.c:367
void lwpoint_free(LWPOINT *pt)
Definition: lwpoint.c:213
void lwgeom_free(LWGEOM *geom)
Definition: lwgeom.c:1246
#define LINETYPE
Definition: liblwgeom.h:103
LWGEOM * lwgeom_clone_deep(const LWGEOM *lwgeom)
Deep clone an LWGEOM, everything is copied.
Definition: lwgeom.c:557
LWGEOM * lwpoint_as_lwgeom(const LWPOINT *obj)
Definition: lwgeom.c:372
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:125
void lwline_setPoint4d(LWLINE *line, uint32_t which, POINT4D *newpoint)
Definition: lwline.c:374
LWCOLLECTION * lwgeom_as_lwcollection(const LWGEOM *lwgeom)
Definition: lwgeom.c:261
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:319
LWGEOM * lwline_remove_repeated_points(const LWLINE *in, double tolerance)
Definition: lwline.c:449
LWT_INT64 LWT_ELEMID
Identifier of topology element.
#define LWT_COL_NODE_GEOM
#define LWT_COL_NODE_NODE_ID
Node fields.
#define PGTOPO_BE_ERROR()
#define LWTFMT_ELEMID
#define LWDEBUG(level, msg)
Definition: lwgeom_log.h:101
#define LWDEBUGF(level, msg,...)
Definition: lwgeom_log.h:106
void lwnotice(const char *fmt,...) __attribute__((format(printf
Write a notice out to the notice handler.
void void lwerror(const char *fmt,...) __attribute__((format(printf
Write a notice out to the error handler.
#define LWDEBUGG(level, geom, msg)
Definition: lwgeom_log.h:111
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:2303
static void _lwt_release_nodes(LWT_ISO_NODE *nodes, int num_nodes)
Definition: lwgeom_topo.c:470
static double _lwt_minTolerance(LWGEOM *g)
Definition: lwgeom_topo.c:5044
static LWT_ELEMID _lwt_AddPoint(LWT_TOPOLOGY *topo, LWPOINT *point, double tol, int findFace, int *moved, int *numSplitEdges)
Definition: lwgeom_topo.c:6754
static LWT_ELEMID _lwt_GetEqualEdge(LWT_TOPOLOGY *topo, LWLINE *edge, int *forward)
Definition: lwgeom_topo.c:5091
LWT_ISO_NODE * lwt_be_getNodeById(LWT_TOPOLOGY *topo, const LWT_ELEMID *ids, uint64_t *numelems, int fields)
Definition: lwgeom_topo.c:150
static uint32_t lwgeom_get_type(const LWGEOM *geom)
Return LWTYPE number.
Definition: lwinline.h:141
uint32_t ngeoms
Definition: liblwgeom.h:580
LWGEOM ** geoms
Definition: liblwgeom.h:575
POINTARRAY * points
Definition: liblwgeom.h:483
POINTARRAY * point
Definition: liblwgeom.h:471
LWPOINT * geom
uint32_t npoints
Definition: liblwgeom.h:427

References _lwt_AddEdge(), _lwt_AddPoint(), _lwt_GetEqualEdge(), _lwt_minTolerance(), _lwt_release_nodes(), 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_COL_NODE_GEOM, LWT_COL_NODE_NODE_ID, LWTFMT_ELEMID, lwtype_name(), LWCOLLECTION::ngeoms, POINTARRAY::npoints, PGTOPO_BE_ERROR, 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: