37 for (i = 0; i < npoints; i++)
40 distances[i] = dist / points[i].
m;
41 weight += dist * points[i].
m;
52 double sum_curr = 0, sum_next = 0;
54 double *distances =
lwalloc(npoints *
sizeof(
double));
58 for (iter = 0; iter < max_iter; iter++)
64 for (i = 0; i < npoints; i++)
67 if (distances[i] > DBL_EPSILON)
69 next.
x += points[i].
x / distances[i];
70 next.
y += points[i].
y / distances[i];
71 next.
z += points[i].
z / distances[i];
72 denom += 1.0 / distances[i];
80 if (denom < DBL_EPSILON)
107 double dx = 0, dy = 0, dz = 0;
111 for (i = 0; i < npoints; i++)
113 if (distances[i] > DBL_EPSILON)
115 dx += (points[i].
x - curr->
x) / distances[i];
116 dy += (points[i].
y - curr->
y) / distances[i];
117 dz += (points[i].
z - curr->
z) / distances[i];
121 d_sqr = sqrt(dx*dx + dy*dy + dz*dz);
122 if (d_sqr > DBL_EPSILON)
124 double r_inv =
FP_MAX(0, 1.0 / d_sqr);
125 next.
x = (1.0 - r_inv)*next.
x + r_inv*curr->
x;
126 next.
y = (1.0 - r_inv)*next.
y + r_inv*curr->
y;
127 next.
z = (1.0 - r_inv)*next.
z + r_inv*curr->
z;
133 delta = sum_curr - sum_next;
158 for (i = 0; i < npoints; i++)
160 guess.
x += points[i].
x * points[i].
m;
161 guess.
y += points[i].
y * points[i].
m;
162 guess.
z += points[i].
z * points[i].
m;
179 for (i = 0; i < g->
ngeoms; i++)
187 lwerror(
"Geometric median: getPoint4d_p reported failure on point (POINT(%g %g %g %g), number %d of %d in input).", points[n].
x, points[n].
y, points[n].z, points[n].m, i, g->
ngeoms);
204 lwerror(
"Geometric median input contains points with negative weights (POINT(%g %g %g %g), number %d of %d in input). Implementation can't guarantee global minimum convergence.", points[n].
x, points[n].
y, points[n].z, points[n].m, i, g->
ngeoms);
210 if (points[n].m > DBL_EPSILON) n++;
220 #if PARANOIA_LEVEL > 0
241 if (points == NULL)
return NULL;
252 lwerror(
"Median failed to find non-empty input points with positive weight.");
259 i =
iterate_4d(&median, points, npoints, max_iter, tol);
263 if (fail_if_not_converged && i >= max_iter)
265 lwerror(
"Median failed to converge within %g after %d iterations.", tol, max_iter);
289 lwerror(
"Unsupported geometry type in lwgeom_median");
LWPOINT * lwpoint_make2d(int srid, double x, double y)
LWMPOINT * lwgeom_as_lwmpoint(const LWGEOM *lwgeom)
LWGEOM * lwcollection_getsubgeom(LWCOLLECTION *col, int gnum)
uint32_t lwgeom_get_type(const LWGEOM *geom)
Return LWTYPE number.
int lwgeom_has_z(const LWGEOM *geom)
Return LW_TRUE if geometry has Z ordinates.
#define POINTTYPE
LWTYPE numbers, used internally by PostGIS.
LWPOINT * lwgeom_as_lwpoint(const LWGEOM *lwgeom)
double distance3d_pt_pt(const POINT3D *p1, const POINT3D *p2)
int lwgeom_is_empty(const LWGEOM *geom)
Return true or false depending on whether a geometry is an "empty" geometry (no vertices members)
int getPoint4d_p(const POINTARRAY *pa, uint32_t n, POINT4D *point)
void * lwalloc(size_t size)
LWPOINT * lwpoint_make3dz(int srid, double x, double y, double z)
#define LW_TRUE
Return types for functions with status returns.
LWPOINT * lwpoint_construct_empty(int srid, char hasz, char hasm)
int lwgeom_has_m(const LWGEOM *geom)
Return LW_TRUE if geometry has M ordinates.
LWPOINT * lwpoint_clone(const LWPOINT *lwgeom)
void lwerror(const char *fmt,...)
Write a notice out to the error handler.