4921{
4922 uint64_t num, i;
4923 double mindist = FLT_MAX;
4927 int flds;
4930
4931
4932 if (!tol)
4934
4936
4937
4938
4939
4940
4941
4944 if (num == UINT64_MAX)
4945 {
4947 return -1;
4948 }
4949 if ( num )
4950 {
4951 LWDEBUGF(1,
"New point is within %.15g units of %d nodes", tol, num);
4952
4953 if ( num > 1 )
4954 {{
4956 for (i=0; i<num; ++i)
4957 {
4958 sorted[i].
ptr = nodes+i;
4961 ((
LWT_ISO_NODE*)(sorted[i].ptr))->node_id, sorted[i].score);
4962 }
4965 for (i=0; i<num; ++i)
4966 {
4968 }
4971 nodes = nodes2;
4972 }}
4973
4974 for ( i=0; i<num; ++i )
4975 {
4979
4980
4981 if ( dist && dist >= tol ) continue;
4982 if ( ! id || dist < mindist )
4983 {
4985 mindist = dist;
4986 }
4987 }
4988 if ( id )
4989 {
4990
4992 if ( moved ) *moved = mindist == 0 ? 0 : 1;
4993 return id;
4994 }
4995 }
4996
4998
4999
5000
5001
5002
5003
5006 if (num == UINT64_MAX)
5007 {
5009 return -1;
5010 }
5011 if ( num )
5012 {
5013 LWDEBUGF(1,
"New point is within %.15g units of %d edges", tol, num);
5014
5015
5016 if ( num > 1 )
5017 {{
5018 int j;
5020 for (i=0; i<num; ++i)
5021 {
5022 sorted[i].
ptr = edges+i;
5025 ((
LWT_ISO_EDGE*)(sorted[i].ptr))->edge_id, sorted[i].score);
5026 }
5029 for (j=0, i=0; i<num; ++i)
5030 {
5031 if ( sorted[i].score == sorted[0].score )
5032 {
5034 }
5035 else
5036 {
5038 }
5039 }
5040 num = j;
5043 edges = edges2;
5044 }}
5045
5046 for (i=0; i<num; ++i)
5047 {
5048
5054
5056
5057
5059 if ( moved ) *moved =
lwgeom_same(prj,pt) ? 0 : 1;
5061 {{
5062
5063
5064
5065
5067 double z;
5070
5079 prj = tmp;
5080 }}
5084 {{
5085 double snaptol;
5089
5091 " does not contain projected point to it",
5092 edge_id);
5093
5094
5095
5096 if ( i+1 < num )
5097 {
5098 LWDEBUG(1,
"But there's another to check");
5100 continue;
5101 }
5102
5103
5104
5105
5106
5107
5108
5112
5113 LWDEBUGF(1,
"Edge snapped with tolerance %g", snaptol);
5114
5115
5116#if POSTGIS_DEBUG_LEVEL > 0
5117 {
5118 size_t sz;
5121 LWDEBUGF(1,
"Edge %s snapped became %s", wkt1, wkt2);
5124 }
5125#endif
5126
5127
5128
5129
5130
5131
5134 LWDEBUGF(1,
"Edge first point is %g %g, "
5135 "snapline first point is %g %g",
5136 p1.
x, p1.
y, p2.
x, p2.
y);
5137 if ( p1.
x != p2.
x || p1.
y != p2.
y )
5138 {
5139 LWDEBUG(1,
"Snapping moved first point, re-adding it");
5141 {
5146 return -1;
5147 }
5148#if POSTGIS_DEBUG_LEVEL > 0
5149 {
5150 size_t sz;
5152 LWDEBUGF(1,
"Tweaked snapline became %s", wkt1);
5154 }
5155#endif
5156 }
5157#if POSTGIS_DEBUG_LEVEL > 0
5158 else {
5159 LWDEBUG(1,
"Snapping did not move first point");
5160 }
5161#endif
5162
5164 {
5165
5169 lwerror(
"lwt_ChangeEdgeGeom failed");
5170 return -1;
5171 }
5173 }}
5174#if POSTGIS_DEBUG_LEVEL > 0
5175 else
5176 {{
5177 size_t sz;
5180 LWDEBUGF(1,
"Edge %s contains projected point %s", wkt1, wkt2);
5183 }}
5184#endif
5185
5186
5188 if ( -1 == id )
5189 {
5190
5193 lwerror(
"lwt_ModEdgeSplit failed");
5194 return -1;
5195 }
5196
5198
5199
5200
5201
5202
5203
5204
5205
5206
5207
5208
5209
5210
5211
5212 break;
5213 }
5215 }
5216 else
5217 {
5218
5219
5221 if ( moved ) *moved = 0;
5222 if ( -1 == id )
5223 {
5224
5225 lwerror(
"lwt_AddIsoNode failed");
5226 return -1;
5227 }
5228 }
5229
5230 return id;
5231}
char lwgeom_geos_errmsg[LWGEOM_GEOS_ERRMSG_MAXSIZE]
void lwgeom_geos_error(const char *fmt,...)
LWGEOM * lwpoint_as_lwgeom(const LWPOINT *obj)
char lwgeom_same(const LWGEOM *lwgeom1, const LWGEOM *lwgeom2)
geom1 same as geom2 iff
LWGEOM * lwgeom_closest_point(const LWGEOM *lw1, const LWGEOM *lw2)
void lwgeom_free(LWGEOM *geom)
char * lwgeom_to_wkt(const LWGEOM *geom, uint8_t variant, int precision, size_t *size_out)
WKT emitter function.
int lwgeom_has_z(const LWGEOM *geom)
Return LW_TRUE if geometry has Z ordinates.
void * lwalloc(size_t size)
int ptarray_insert_point(POINTARRAY *pa, const POINT4D *p, uint32_t where)
Insert a point into an existing POINTARRAY.
LWGEOM * lwgeom_force_3dz(const LWGEOM *geom)
LWGEOM * lwline_as_lwgeom(const LWLINE *obj)
double lwgeom_mindistance2d(const LWGEOM *lw1, const LWGEOM *lw2)
Function initializing min distance calculation.
int getPoint4d_p(const POINTARRAY *pa, uint32_t n, POINT4D *point)
LWLINE * lwgeom_as_lwline(const LWGEOM *lwgeom)
void ptarray_set_point4d(POINTARRAY *pa, uint32_t n, const POINT4D *p4d)
void lwline_free(LWLINE *line)
int ptarray_contains_point_partial(const POINTARRAY *pa, const POINT2D *pt, int check_closed, int *winding_number)
LWT_INT64 LWT_ELEMID
Identifier of topology element.
#define LWT_COL_EDGE_EDGE_ID
Edge fields.
#define LWT_COL_NODE_GEOM
#define LWT_COL_NODE_NODE_ID
Node fields.
#define LWT_COL_EDGE_GEOM
#define LWDEBUG(level, msg)
#define LWDEBUGF(level, msg,...)
void lwerror(const char *fmt,...)
Write a notice out to the error handler.
void lwnotice(const char *fmt,...)
Write a notice out to the notice handler.
#define LWDEBUGG(level, geom, msg)
static LWGEOM * _lwt_toposnap(LWGEOM *src, LWGEOM *tgt, double tol)
LWT_ISO_NODE * lwt_be_getNodeWithinDistance2D(LWT_TOPOLOGY *topo, LWPOINT *pt, double dist, uint64_t *numelems, int fields, int64_t limit)
LWT_ELEMID lwt_ModEdgeSplit(LWT_TOPOLOGY *topo, LWT_ELEMID edge, LWPOINT *pt, int skipISOChecks)
Split an edge by a node, modifying the original edge and adding a new one.
static LWT_ELEMID _lwt_AddIsoNode(LWT_TOPOLOGY *topo, LWT_ELEMID face, LWPOINT *pt, int skipISOChecks, int checkFace)
static void _lwt_release_nodes(LWT_ISO_NODE *nodes, int num_nodes)
static double _lwt_minTolerance(LWGEOM *g)
static int compare_scored_pointer(const void *si1, const void *si2)
#define _LWT_MINTOLERANCE(topo, geom)
const char * lwt_be_lastErrorMessage(const LWT_BE_IFACE *be)
LWT_ISO_EDGE * lwt_be_getEdgeWithinDistance2D(LWT_TOPOLOGY *topo, LWPOINT *pt, double dist, uint64_t *numelems, int fields, int64_t limit)
static void _lwt_release_edges(LWT_ISO_EDGE *edges, int num_edges)
int lwt_ChangeEdgeGeom(LWT_TOPOLOGY *topo, LWT_ELEMID edge_id, LWLINE *geom)
Changes the shape of an edge without affecting the topology structure.
static LWPOINT * lwgeom_as_lwpoint(const LWGEOM *lwgeom)
static const POINT2D * getPoint2d_cp(const POINTARRAY *pa, uint32_t n)
Returns a POINT2D pointer into the POINTARRAY serialized_ptlist, suitable for reading from.
Datum contains(PG_FUNCTION_ARGS)
const LWT_BE_IFACE * be_iface