PostGIS 3.6.2dev-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 
)
static

Definition at line 6891 of file lwgeom_topo.c.

6893{
6894 LWCOLLECTION *col;
6895 LWPOINT *start_point, *end_point;
6896 LWGEOM *tmp = 0, *tmp2;
6897 LWT_ISO_NODE *node;
6898 LWT_ELEMID nid[2]; /* start_node, end_node */
6899 LWT_ELEMID id; /* edge id */
6900 POINT4D p4d;
6901 uint64_t nn, i;
6902 int moved=0, mm;
6903
6904 LWDEBUGG(1, lwline_as_lwgeom(edge), "_lwtAddLineEdge");
6905 LWDEBUGF(1, "_lwtAddLineEdge with tolerance %g", tol);
6906
6907 start_point = lwline_get_lwpoint(edge, 0);
6908 if ( ! start_point )
6909 {
6910 lwnotice("Empty component of noded line");
6911 return 0; /* must be empty */
6912 }
6913 nid[0] = _lwt_AddPoint( topo, start_point,
6915 handleFaceSplit, &mm );
6916 lwpoint_free(start_point); /* too late if lwt_AddPoint calls lwerror */
6917 if ( nid[0] == -1 ) return -1; /* lwerror should have been called */
6918 moved += mm;
6919 LWDEBUGF(1, "node for start point added or found to be %" LWTFMT_ELEMID " (moved ? %d)", nid[0], mm);
6920
6921
6922 end_point = lwline_get_lwpoint(edge, edge->points->npoints-1);
6923 if ( ! end_point )
6924 {
6925 lwerror("could not get last point of line "
6926 "after successfully getting first point !?");
6927 return -1;
6928 }
6929 nid[1] = _lwt_AddPoint( topo, end_point,
6931 handleFaceSplit, &mm );
6932 lwpoint_free(end_point); /* too late if lwt_AddPoint calls lwerror */
6933 if ( nid[1] == -1 ) return -1; /* lwerror should have been called */
6934 moved += mm;
6935 LWDEBUGF(1, "node for end point added or found to be %" LWTFMT_ELEMID " (moved ? %d)", nid[1], mm);
6936
6937 /*
6938 -- Added endpoints may have drifted due to tolerance, so
6939 -- we need to re-snap the edge to the new nodes before adding it
6940 */
6941 if ( moved )
6942 {
6943
6944 LWDEBUG(1, "One or both line endpoints moved by snap, updating line");
6945
6946 nn = nid[0] == nid[1] ? 1 : 2;
6947 node = lwt_be_getNodeById( topo, nid, &nn,
6949 if (nn == UINT64_MAX)
6950 {
6952 return -1;
6953 }
6954 start_point = NULL; end_point = NULL;
6955 for (i=0; i<nn; ++i)
6956 {
6957 if ( node[i].node_id == nid[0] ) start_point = node[i].geom;
6958 if ( node[i].node_id == nid[1] ) end_point = node[i].geom;
6959 }
6960 if ( ! start_point || ! end_point )
6961 {
6962 if ( nn ) _lwt_release_nodes(node, nn);
6963 lwerror("Could not find just-added nodes % " LWTFMT_ELEMID
6964 " and %" LWTFMT_ELEMID, nid[0], nid[1]);
6965 return -1;
6966 }
6967
6968 /* snap */
6969
6970 getPoint4d_p( start_point->point, 0, &p4d );
6971 lwline_setPoint4d(edge, 0, &p4d);
6972
6973 getPoint4d_p( end_point->point, 0, &p4d );
6974 lwline_setPoint4d(edge, edge->points->npoints-1, &p4d);
6975
6976 if ( nn ) _lwt_release_nodes(node, nn);
6977
6978 LWDEBUGG(2, lwline_as_lwgeom(edge), "Snapped after drifted endpoints snap");
6979
6980 /* make valid, after snap (to handle collapses) */
6982
6983 LWDEBUGG(2, tmp, "Made-valid after snap to drifted endpoints");
6984
6985 col = lwgeom_as_lwcollection(tmp);
6986 if ( col )
6987 {{
6988
6990
6991 /* Check if the so-snapped edge collapsed (see #1650) */
6992 if ( colex->ngeoms == 0 )
6993 {
6994 lwcollection_free(colex);
6995 lwgeom_free(tmp);
6996 LWDEBUG(1, "Made-valid snapped edge collapsed");
6997 return 0;
6998 }
6999
7000 tmp2 = lwgeom_clone_deep(colex->geoms[0]);
7001 lwgeom_free(tmp);
7002 tmp = tmp2;
7003 edge = lwgeom_as_lwline(tmp);
7004 lwcollection_free(colex);
7005 if ( ! edge )
7006 {
7007 /* should never happen */
7008 lwerror("lwcollection_extract(LINETYPE) returned a non-line?");
7009 return -1;
7010 }
7011 }}
7012 else
7013 {
7014 edge = lwgeom_as_lwline(tmp);
7015 if ( ! edge )
7016 {
7017 LWDEBUGF(1, "Made-valid snapped edge collapsed to %s",
7019 lwgeom_free(tmp);
7020 return 0;
7021 }
7022 }
7023
7024 }
7025
7026 /* check if the so-snapped edge _now_ exists */
7027 id = _lwt_GetEqualEdge ( topo, edge, forward );
7028 LWDEBUGF(1, "_lwt_GetEqualEdge returned %" LWTFMT_ELEMID, id);
7029 if ( id == -1 )
7030 {
7031 if ( tmp ) lwgeom_free(tmp); /* probably too late, due to internal lwerror */
7032 return -1;
7033 }
7034 if ( id )
7035 {
7036 if ( tmp ) lwgeom_free(tmp); /* possibly takes "edge" down with it */
7037 return id;
7038 }
7039
7040 /* No previously existing edge was found, we'll add one */
7041
7042 /* Remove consecutive vertices below given tolerance
7043 * on edge addition */
7044 if ( tol )
7045 {{
7046 tmp2 = lwline_remove_repeated_points(edge, tol);
7047 LWDEBUGG(2, tmp2, "Repeated-point removed");
7048 edge = lwgeom_as_lwline(tmp2);
7049 if ( tmp ) lwgeom_free(tmp);
7050 tmp = tmp2;
7051
7052 /* check if the so-decimated edge collapsed to single-point */
7053 if ( nid[0] == nid[1] && edge->points->npoints == 2 )
7054 {
7055 lwgeom_free(tmp);
7056 LWDEBUG(1, "Repeated-point removed edge collapsed");
7057 return 0;
7058 }
7059
7060 /* check if the so-decimated edge _now_ exists */
7061 id = _lwt_GetEqualEdge ( topo, edge, forward );
7062 LWDEBUGF(1, "_lwt_GetEqualEdge returned %" LWTFMT_ELEMID, id);
7063 if ( id == -1 )
7064 {
7065 lwgeom_free(tmp); /* probably too late, due to internal lwerror */
7066 return -1;
7067 }
7068 if ( id )
7069 {
7070 lwgeom_free(tmp); /* takes "edge" down with it */
7071 return id;
7072 }
7073 }}
7074
7075
7076 /* TODO: skip checks ? */
7077 id = _lwt_AddEdge( topo, nid[0], nid[1], edge, 0, handleFaceSplit ? 1 : -1 );
7078 LWDEBUGF(1, "lwt_AddEdgeModFace returned %" LWTFMT_ELEMID, id);
7079 if ( id == -1 )
7080 {
7081 lwgeom_free(tmp); /* probably too late, due to internal lwerror */
7082 return -1;
7083 }
7084 lwgeom_free(tmp); /* possibly takes "edge" down with it */
7085
7086 *forward = 1;
7087 return id;
7088}
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:344
void lwpoint_free(LWPOINT *pt)
Definition lwpoint.c:213
void lwgeom_free(LWGEOM *geom)
Definition lwgeom.c:1218
LWPOINT * lwline_get_lwpoint(const LWLINE *line, uint32_t where)
Returns freshly allocated LWPOINT that corresponds to the index where.
Definition lwline.c:309
#define LINETYPE
Definition liblwgeom.h:103
LWCOLLECTION * lwgeom_as_lwcollection(const LWGEOM *lwgeom)
Definition lwgeom.c:233
LWGEOM * lwline_as_lwgeom(const LWLINE *obj)
Definition lwgeom.c:339
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:179
void lwline_setPoint4d(LWLINE *line, uint32_t which, POINT4D *newpoint)
Definition lwline.c:364
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:529
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 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_GetEqualEdge(LWT_TOPOLOGY *topo, LWLINE *edge, int *forward)
static LWT_ELEMID _lwt_AddPoint(LWT_TOPOLOGY *topo, LWPOINT *point, double tol, int findFace, int *moved)
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: