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

Definition at line 6752 of file lwgeom_topo.c.

6754{
6755 uint64_t num, i;
6756 double mindist = FLT_MAX;
6757 LWT_ISO_NODE *nodes, *nodes2;
6758 LWT_ISO_EDGE *edges;
6759 LWGEOM *pt = lwpoint_as_lwgeom(point);
6760 scored_pointer *sorted;
6761 int flds;
6762 LWT_ELEMID id = 0;
6763
6764 /* Get tolerance, if 0 was given */
6765 if (!tol)
6766 tol = _LWT_MINTOLERANCE(topo, pt);
6767
6768 LWDEBUGG(1, pt, "Adding point");
6769
6770 /*
6771 -- 1. Check if any existing node is closer than the given precision
6772 -- and if so pick the closest
6773 TODO: use WithinBox2D
6774 */
6776 nodes = lwt_be_getNodeWithinDistance2D(topo, point, tol, &num, flds, 0);
6777 if (num == UINT64_MAX)
6778 {
6780 return -1;
6781 }
6782 if ( num )
6783 {
6784 LWDEBUGF(1, "New point is within %.15g units of %llu nodes", tol, num);
6785 /* Order by distance if there are more than a single return */
6786 if ( num > 1 )
6787 {{
6788 sorted = lwalloc(sizeof(scored_pointer)*num);
6789 for (i=0; i<num; ++i)
6790 {
6791 sorted[i].ptr = nodes+i;
6792 sorted[i].score = lwgeom_mindistance2d(lwpoint_as_lwgeom(nodes[i].geom), pt);
6793 LWDEBUGF(1, "Node %" LWTFMT_ELEMID " distance: %.15g",
6794 ((LWT_ISO_NODE*)(sorted[i].ptr))->node_id, sorted[i].score);
6795 }
6796 qsort(sorted, num, sizeof(scored_pointer), compare_scored_pointer);
6797 nodes2 = lwalloc(sizeof(LWT_ISO_NODE)*num);
6798 for (i=0; i<num; ++i)
6799 {
6800 nodes2[i] = *((LWT_ISO_NODE*)sorted[i].ptr);
6801 }
6802 lwfree(sorted);
6803 lwfree(nodes);
6804 nodes = nodes2;
6805 }}
6806
6807 for ( i=0; i<num; ++i )
6808 {
6809 LWT_ISO_NODE *n = &(nodes[i]);
6810 LWGEOM *g = lwpoint_as_lwgeom(n->geom);
6811 double dist = lwgeom_mindistance2d(g, pt);
6812 /* TODO: move this check in the previous sort scan ... */
6813 /* must be closer than tolerated, unless distance is zero */
6814 if ( dist && dist >= tol ) continue;
6815 if ( ! id || dist < mindist )
6816 {
6817 id = n->node_id;
6818 mindist = dist;
6819 }
6820 }
6821 if ( id )
6822 {
6823 /* found an existing node */
6824 if ( nodes ) _lwt_release_nodes(nodes, num);
6825 if ( moved ) *moved = mindist == 0 ? 0 : 1;
6826 return id;
6827 }
6828 }
6829
6830 initGEOS(lwnotice, lwgeom_geos_error);
6831
6832 /*
6833 -- 2. Check if any existing edge falls within tolerance
6834 -- and if so split it by a point projected on it
6835 TODO: use WithinBox2D
6836 */
6837 flds = LWT_COL_EDGE_ALL; /* EDGE_ID|LWT_COL_EDGE_GEOM;*/
6838 edges = lwt_be_getEdgeWithinDistance2D(topo, point, tol, &num, flds, 0);
6839 if (num == UINT64_MAX)
6840 {
6842 return -1;
6843 }
6844 LWDEBUGF(1, "New point is within %.15g units of %llu edges", tol, num);
6845 if ( num )
6846 {
6847 id = _lwt_SplitAllEdgesToNewNode(topo, edges, num, lwgeom_as_lwpoint(pt), tol, moved);
6848 _lwt_release_edges(edges, num);
6849 }
6850
6851 if ( id == 0 )
6852 {
6853 /* The point is isolated, add it as such */
6854 /* TODO: pass 1 as last argument (skipChecks) ? */
6855 id = _lwt_AddIsoNode(topo, -1, point, 0, findFace);
6856 if ( moved ) *moved = 0;
6857 if ( -1 == id )
6858 {
6859 /* should have invoked lwerror already, leaking memory */
6860 _lwt_release_edges(edges, num);
6861 lwerror("lwt_AddIsoNode failed");
6862 return -1;
6863 }
6864 }
6865
6866 return id;
6867}
void lwgeom_geos_error(const char *fmt,...)
LWGEOM * lwpoint_as_lwgeom(const LWPOINT *obj)
Definition lwgeom.c:344
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: