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

◆ _lwt_AddPoint()

static LWT_ELEMID _lwt_AddPoint ( LWT_TOPOLOGY topo,
LWPOINT point,
double  tol,
int  findFace,
int *  moved,
int *  numSplitEdges 
)
static

Definition at line 6871 of file lwgeom_topo.c.

6873{
6874 uint64_t num, i;
6875 double mindist = FLT_MAX;
6876 LWT_ISO_NODE *nodes, *nodes2;
6877 LWT_ISO_EDGE *edges;
6878 LWGEOM *pt = lwpoint_as_lwgeom(point);
6879 scored_pointer *sorted;
6880 int flds;
6881 LWT_ELEMID id = 0;
6882
6883 /* Get tolerance, if 0 was given */
6884 if ( tol == -1 )
6885 tol = _LWT_MINTOLERANCE(topo, pt);
6886
6887 LWDEBUGG(1, pt, "Adding point");
6888
6889 /*
6890 -- 1. Check if any existing node is closer than the given precision
6891 -- and if so pick the closest
6892 TODO: use WithinBox2D
6893 */
6895 nodes = lwt_be_getNodeWithinDistance2D(topo, point, tol, &num, flds, 0);
6896 if (num == UINT64_MAX)
6897 {
6899 return -1;
6900 }
6901
6902 if ( numSplitEdges ) *numSplitEdges = 0;
6903
6904 if ( num )
6905 {
6906 LWDEBUGF(1, "New point is within %.15g units of %llu nodes", tol, num);
6907 /* Order by distance if there are more than a single return */
6908 if ( num > 1 )
6909 {{
6910 sorted = lwalloc(sizeof(scored_pointer)*num);
6911 for (i=0; i<num; ++i)
6912 {
6913 sorted[i].ptr = nodes+i;
6914 sorted[i].score = lwgeom_mindistance2d(lwpoint_as_lwgeom(nodes[i].geom), pt);
6915 LWDEBUGF(1, "Node %" LWTFMT_ELEMID " distance: %.15g",
6916 ((LWT_ISO_NODE*)(sorted[i].ptr))->node_id, sorted[i].score);
6917 }
6918 qsort(sorted, num, sizeof(scored_pointer), compare_scored_pointer);
6919 nodes2 = lwalloc(sizeof(LWT_ISO_NODE)*num);
6920 for (i=0; i<num; ++i)
6921 {
6922 nodes2[i] = *((LWT_ISO_NODE*)sorted[i].ptr);
6923 }
6924 lwfree(sorted);
6925 lwfree(nodes);
6926 nodes = nodes2;
6927 }}
6928
6929 for ( i=0; i<num; ++i )
6930 {
6931 LWT_ISO_NODE *n = &(nodes[i]);
6932 LWGEOM *g = lwpoint_as_lwgeom(n->geom);
6933 double dist = lwgeom_mindistance2d(g, pt);
6934 /* TODO: move this check in the previous sort scan ... */
6935 /* must be closer than tolerated, unless distance is zero */
6936 if ( dist && dist >= tol ) continue;
6937 if ( ! id || dist < mindist )
6938 {
6939 id = n->node_id;
6940 mindist = dist;
6941 }
6942 }
6943 if ( id )
6944 {
6945 /* found an existing node */
6946 if ( nodes ) _lwt_release_nodes(nodes, num);
6947 if ( moved ) *moved = mindist == 0 ? 0 : 1;
6948 return id;
6949 }
6950 }
6951
6952 initGEOS(lwnotice, lwgeom_geos_error);
6953
6954 /*
6955 -- 2. Check if any existing edge falls within tolerance
6956 -- and if so split it by a point projected on it
6957 TODO: use WithinBox2D
6958 */
6959 flds = LWT_COL_EDGE_ALL; /* EDGE_ID|LWT_COL_EDGE_GEOM;*/
6960 edges = lwt_be_getEdgeWithinDistance2D(topo, point, tol, &num, flds, 0);
6961 if (num == UINT64_MAX)
6962 {
6964 return -1;
6965 }
6966 LWDEBUGF(1, "New point is within %.15g units of %llu edges", tol, num);
6967 if ( num )
6968 {
6969 id = _lwt_SplitAllEdgesToNewNode(topo, edges, num, lwgeom_as_lwpoint(pt), tol, moved);
6970 _lwt_release_edges(edges, num);
6971 if ( numSplitEdges ) *numSplitEdges = num;
6972 }
6973
6974 if ( id == 0 )
6975 {
6976 /* The point is isolated, add it as such */
6977 /* TODO: pass 1 as last argument (skipChecks) ? */
6978 id = _lwt_AddIsoNode(topo, -1, point, 0, findFace);
6979 if ( moved ) *moved = 0;
6980 if ( -1 == id )
6981 {
6982 /* should have invoked lwerror already, leaking memory */
6983 _lwt_release_edges(edges, num);
6984 lwerror("lwt_AddIsoNode failed");
6985 return -1;
6986 }
6987 }
6988
6989 return id;
6990}
void lwgeom_geos_error(const char *fmt,...)
LWGEOM * lwpoint_as_lwgeom(const LWPOINT *obj)
Definition lwgeom.c:372
void * lwalloc(size_t size)
Definition lwutil.c:227
void lwfree(void *mem)
Definition lwutil.c:248
double lwgeom_mindistance2d(const LWGEOM *lw1, const LWGEOM *lw2)
Function initializing min distance calculation.
Definition measures.c:212
LWT_INT64 LWT_ELEMID
Identifier of topology element.
#define LWT_COL_EDGE_ALL
#define LWT_COL_NODE_GEOM
#define LWT_COL_NODE_NODE_ID
Node fields.
#define PGTOPO_BE_ERROR()
#define LWTFMT_ELEMID
#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
LWT_ISO_EDGE * lwt_be_getEdgeWithinDistance2D(LWT_TOPOLOGY *topo, const LWPOINT *pt, double dist, uint64_t *numelems, int fields, int64_t limit)
static LWT_ELEMID _lwt_AddIsoNode(LWT_TOPOLOGY *topo, LWT_ELEMID face, LWPOINT *pt, int skipISOChecks, int checkFace)
LWT_ISO_NODE * lwt_be_getNodeWithinDistance2D(LWT_TOPOLOGY *topo, const LWPOINT *pt, double dist, uint64_t *numelems, int fields, int64_t limit)
static void _lwt_release_nodes(LWT_ISO_NODE *nodes, int num_nodes)
static int compare_scored_pointer(const void *si1, const void *si2)
void _lwt_release_edges(LWT_ISO_EDGE *edges, int num_edges)
#define _LWT_MINTOLERANCE(topo, geom)
static LWT_ELEMID _lwt_SplitAllEdgesToNewNode(LWT_TOPOLOGY *topo, LWT_ISO_EDGE *edges, uint64_t num, LWPOINT *point, double tol, int *moved)
static LWPOINT * lwgeom_as_lwpoint(const LWGEOM *lwgeom)
Definition lwinline.h:127
LWT_ELEMID node_id
LWPOINT * geom

References _lwt_AddIsoNode(), _LWT_MINTOLERANCE, _lwt_release_edges(), _lwt_release_nodes(), _lwt_SplitAllEdgesToNewNode(), compare_scored_pointer(), LWT_ISO_NODE::geom, lwalloc(), LWDEBUGF, LWDEBUGG, lwerror(), lwfree(), lwgeom_as_lwpoint(), lwgeom_geos_error(), lwgeom_mindistance2d(), lwnotice(), lwpoint_as_lwgeom(), lwt_be_getEdgeWithinDistance2D(), lwt_be_getNodeWithinDistance2D(), LWT_COL_EDGE_ALL, LWT_COL_NODE_GEOM, LWT_COL_NODE_NODE_ID, LWTFMT_ELEMID, LWT_ISO_NODE::node_id, PGTOPO_BE_ERROR, scored_pointer_t::ptr, and scored_pointer_t::score.

Referenced by _lwt_AddLineEdge(), lwt_AddPoint(), and lwt_LoadPoint().

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