PostGIS 3.7.0dev-r@@SVN_REVISION@@
Loading...
Searching...
No Matches

◆ _lwt_AddLineEdge()

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

Definition at line 7020 of file lwgeom_topo.c.

7022{
7023 LWCOLLECTION *col;
7024 LWPOINT *start_point, *end_point;
7025 LWGEOM *tmp = 0, *tmp2;
7026 LWT_ISO_NODE *node;
7027 LWT_ELEMID nid[2]; /* start_node, end_node */
7028 LWT_ELEMID id; /* edge id */
7029 POINT4D p4d;
7030 uint64_t nn, i;
7031 int moved=0, mm;
7032 int pointSplitEdges = -666;
7033
7034 if ( numNewEdges ) *numNewEdges = 0;
7035
7036 LWDEBUGG(1, lwline_as_lwgeom(edge), "_lwtAddLineEdge");
7037 LWDEBUGF(1, "_lwtAddLineEdge with tolerance %g", tol);
7038
7039 start_point = lwline_get_lwpoint(edge, 0);
7040 if ( ! start_point )
7041 {
7042 lwnotice("Empty component of noded line");
7043 return 0; /* must be empty */
7044 }
7045 nid[0] = _lwt_AddPoint( topo, start_point,
7047 handleFaceSplit, &mm, &pointSplitEdges );
7048 lwpoint_free(start_point); /* too late if lwt_AddPoint calls lwerror */
7049 if ( nid[0] == -1 ) return -1; /* lwerror should have been called */
7050 if ( numNewEdges ) *numNewEdges += pointSplitEdges;
7051 moved += mm;
7052 LWDEBUGF(1, "node for start point added or found to be %" LWTFMT_ELEMID " (moved ? %d; split %d edges)", nid[0], mm, pointSplitEdges);
7053
7054
7055 end_point = lwline_get_lwpoint(edge, edge->points->npoints-1);
7056 if ( ! end_point )
7057 {
7058 lwerror("could not get last point of line "
7059 "after successfully getting first point !?");
7060 return -1;
7061 }
7062 nid[1] = _lwt_AddPoint( topo, end_point,
7064 handleFaceSplit, &mm, &pointSplitEdges );
7065 lwpoint_free(end_point); /* too late if lwt_AddPoint calls lwerror */
7066 if ( nid[1] == -1 ) return -1; /* lwerror should have been called */
7067 if ( numNewEdges ) *numNewEdges += pointSplitEdges;
7068 moved += mm;
7069 LWDEBUGF(1, "node for end point added or found to be %" LWTFMT_ELEMID " (moved ? %d; split %d edges)", nid[1], mm, pointSplitEdges);
7070
7071 /*
7072 -- Added endpoints may have drifted due to tolerance, so
7073 -- we need to re-snap the edge to the new nodes before adding it
7074 */
7075 if ( moved )
7076 {
7077
7078 LWDEBUG(1, "One or both line endpoints moved by snap, updating line");
7079
7080 nn = nid[0] == nid[1] ? 1 : 2;
7081 node = lwt_be_getNodeById( topo, nid, &nn,
7083 if (nn == UINT64_MAX)
7084 {
7086 return -1;
7087 }
7088 start_point = NULL; end_point = NULL;
7089 for (i=0; i<nn; ++i)
7090 {
7091 if ( node[i].node_id == nid[0] ) start_point = node[i].geom;
7092 if ( node[i].node_id == nid[1] ) end_point = node[i].geom;
7093 }
7094 if ( ! start_point || ! end_point )
7095 {
7096 if ( nn ) _lwt_release_nodes(node, nn);
7097 lwerror("Could not find just-added nodes % " LWTFMT_ELEMID
7098 " and %" LWTFMT_ELEMID, nid[0], nid[1]);
7099 return -1;
7100 }
7101
7102 /* snap */
7103
7104 getPoint4d_p( start_point->point, 0, &p4d );
7105 lwline_setPoint4d(edge, 0, &p4d);
7106
7107 getPoint4d_p( end_point->point, 0, &p4d );
7108 lwline_setPoint4d(edge, edge->points->npoints-1, &p4d);
7109
7110 if ( nn ) _lwt_release_nodes(node, nn);
7111
7112 LWDEBUGG(2, lwline_as_lwgeom(edge), "Snapped after drifted endpoints snap");
7113
7114 /* make valid, after snap (to handle collapses) */
7116
7117 LWDEBUGG(2, tmp, "Made-valid after snap to drifted endpoints");
7118
7119 col = lwgeom_as_lwcollection(tmp);
7120 if ( col )
7121 {{
7122
7124
7125 /* Check if the so-snapped edge collapsed (see #1650) */
7126 if ( colex->ngeoms == 0 )
7127 {
7128 lwcollection_free(colex);
7129 lwgeom_free(tmp);
7130 LWDEBUG(1, "Made-valid snapped edge collapsed");
7131 return 0;
7132 }
7133
7134 tmp2 = lwgeom_clone_deep(colex->geoms[0]);
7135 lwgeom_free(tmp);
7136 tmp = tmp2;
7137 edge = lwgeom_as_lwline(tmp);
7138 lwcollection_free(colex);
7139 if ( ! edge )
7140 {
7141 /* should never happen */
7142 lwerror("lwcollection_extract(LINETYPE) returned a non-line?");
7143 return -1;
7144 }
7145 }}
7146 else
7147 {
7148 edge = lwgeom_as_lwline(tmp);
7149 if ( ! edge )
7150 {
7151 LWDEBUGF(1, "Made-valid snapped edge collapsed to %s",
7153 lwgeom_free(tmp);
7154 return 0;
7155 }
7156 }
7157
7158 }
7159
7160 /* check if the so-snapped edge _now_ exists */
7161 id = _lwt_GetEqualEdge ( topo, edge, forward );
7162 LWDEBUGF(1, "_lwt_GetEqualEdge returned %" LWTFMT_ELEMID, id);
7163 if ( id == -1 )
7164 {
7165 if ( tmp ) lwgeom_free(tmp); /* probably too late, due to internal lwerror */
7166 return -1;
7167 }
7168 if ( id )
7169 {
7170 if ( tmp ) lwgeom_free(tmp); /* possibly takes "edge" down with it */
7171 return id;
7172 }
7173
7174 /* No previously existing edge was found, we'll check after
7175 * decimating, if a tolerance was given */
7176
7177 /* Remove consecutive vertices below given tolerance
7178 * on edge addition */
7179 if ( tol )
7180 {{
7181 tmp2 = lwline_remove_repeated_points(edge, tol);
7182 LWDEBUGG(2, tmp2, "Repeated-point removed");
7183 edge = lwgeom_as_lwline(tmp2);
7184 if ( tmp ) lwgeom_free(tmp);
7185 tmp = tmp2;
7186
7187 /* check if the so-decimated edge collapsed to single-point */
7188 if ( nid[0] == nid[1] && edge->points->npoints == 2 )
7189 {
7190 lwgeom_free(tmp);
7191 LWDEBUG(1, "Repeated-point removed edge collapsed");
7192 return 0;
7193 }
7194
7195 /* check if the so-decimated edge _now_ exists */
7196 id = _lwt_GetEqualEdge ( topo, edge, forward );
7197 LWDEBUGF(1, "_lwt_GetEqualEdge returned %" LWTFMT_ELEMID, id);
7198 if ( id == -1 )
7199 {
7200 lwgeom_free(tmp); /* probably too late, due to internal lwerror */
7201 return -1;
7202 }
7203 if ( id )
7204 {
7205 lwgeom_free(tmp); /* takes "edge" down with it */
7206 return id;
7207 }
7208 }}
7209
7210 /* No previously existing edge was found, we'll add one */
7211
7212 /* TODO: skip checks ? */
7213 id = _lwt_AddEdge( topo, nid[0], nid[1], edge, 0, handleFaceSplit ? 1 : -1 );
7214 LWDEBUGF(1, "lwt_AddEdgeModFace returned %" LWTFMT_ELEMID, id);
7215 if ( id == -1 )
7216 {
7217 lwgeom_free(tmp); /* probably too late, due to internal lwerror */
7218 return -1;
7219 }
7220 lwgeom_free(tmp); /* possibly takes "edge" down with it */
7221
7222 if ( numNewEdges ) ++*numNewEdges;
7223 *forward = 1;
7224
7225 return id;
7226}
const char * lwtype_name(uint8_t type)
Return the type name string associated with a type number (e.g.
Definition lwutil.c:216
LWGEOM * lwpoint_as_lwgeom(const LWPOINT *obj)
Definition lwgeom.c:372
void lwpoint_free(LWPOINT *pt)
Definition lwpoint.c:213
void lwgeom_free(LWGEOM *geom)
Definition lwgeom.c:1246
LWPOINT * lwline_get_lwpoint(const LWLINE *line, uint32_t where)
Returns freshly allocated LWPOINT that corresponds to the index where.
Definition lwline.c:319
#define LINETYPE
Definition liblwgeom.h:103
LWCOLLECTION * lwgeom_as_lwcollection(const LWGEOM *lwgeom)
Definition lwgeom.c:261
LWGEOM * lwline_as_lwgeom(const LWLINE *obj)
Definition lwgeom.c:367
void lwcollection_free(LWCOLLECTION *col)
int getPoint4d_p(const POINTARRAY *pa, uint32_t n, POINT4D *point)
Definition lwgeom_api.c:125
LWLINE * lwgeom_as_lwline(const LWGEOM *lwgeom)
Definition lwgeom.c:207
void lwline_setPoint4d(LWLINE *line, uint32_t which, POINT4D *newpoint)
Definition lwline.c:374
LWCOLLECTION * lwcollection_extract(const LWCOLLECTION *col, uint32_t type)
LWGEOM * lwgeom_make_valid(LWGEOM *geom)
Attempts to make an invalid geometries valid w/out losing points.
LWGEOM * lwgeom_clone_deep(const LWGEOM *lwgeom)
Deep clone an LWGEOM, everything is copied.
Definition lwgeom.c:557
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)
static void _lwt_release_nodes(LWT_ISO_NODE *nodes, int num_nodes)
static double _lwt_minTolerance(LWGEOM *g)
static LWT_ELEMID _lwt_AddPoint(LWT_TOPOLOGY *topo, LWPOINT *point, double tol, int findFace, int *moved, int *numSplitEdges)
static LWT_ELEMID _lwt_GetEqualEdge(LWT_TOPOLOGY *topo, LWLINE *edge, int *forward)
LWT_ISO_NODE * lwt_be_getNodeById(LWT_TOPOLOGY *topo, const LWT_ELEMID *ids, uint64_t *numelems, int fields)
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: