Take a list of LWGEOMs and a number of clusters and return an integer array indicating which cluster each geometry is in.
- Parameters
-
geoms | the input array of LWGEOM pointers |
ngeoms | the number of elements in the array |
k | the number of clusters to calculate |
Definition at line 77 of file lwkmeans.c.
References kmeans_config::centers, centroid(), kmeans_config::centroid_method, kmeans_config::clusters, kmeans_config::distance_method, getPoint2d_cp(), if(), kmeans_config::k, kmeans(), KMEANS_EXCEEDED_MAX_ITERATIONS, KMEANS_OK, lwalloc(), lwerror(), lwfree(), lwgeom_as_lwpoint(), lwgeom_centroid(), lwgeom_get_type(), lwgeom_is_empty(), lwkmeans_pt_centroid(), lwkmeans_pt_closest(), lwkmeans_pt_distance(), kmeans_config::max_iterations, kmeans_config::num_objs, kmeans_config::objs, LWPOINT::point, POINTTYPE, POINT2D::x, and POINT2D::y.
Referenced by ST_ClusterKMeans(), and test_kmeans().
80 int num_centroids = 0;
84 POINT2D min = { DBL_MAX, DBL_MAX };
85 POINT2D max = { -DBL_MAX, -DBL_MAX };
102 lwerror(
"%s: number of geometries is less than the number of clusters requested", __func__);
107 memset(centroids, 0,
sizeof(
LWGEOM*) * ngeoms);
113 memset(centers_raw, 0,
sizeof(
POINT2D) * k);
127 memset(config.
clusters, 0,
sizeof(
int) * ngeoms);
131 for (i = 0; i < ngeoms; i++)
133 const LWGEOM *geom = geoms[i];
139 config.
objs[i] = NULL;
150 config.
objs[i] = NULL;
153 centroids[num_centroids++] =
centroid;
166 if (cp->
x < min.
x) min.
x = cp->
x;
167 if (cp->
y < min.
y) min.
y = cp->
y;
168 if (cp->
x > max.
x) max.
x = cp->
x;
169 if (cp->
y > max.
y) max.
y = cp->
y;
176 dx = (max.
x - min.
x)/k;
177 dy = (max.
y - min.
y)/k;
178 seen =
lwalloc(
sizeof(
int)*config.
k);
179 memset(seen, 0,
sizeof(
int)*config.
k);
180 for (i = 0; i < k; i++)
187 p.
x = min.
x + dx * (i + 0.5);
188 p.y = min.
y + dy * (i + 0.5);
195 lwerror(
"unable to calculate cluster seed points, too many NULLs or empties?");
201 if (seen[j] == closest)
204 for (k = 1; k < config.
num_objs; k++)
206 t = (closest + k) % config.
num_objs;
220 seen[sidx++] = closest;
225 centers_raw[i] = *((
POINT2D*)config.
objs[closest]);
226 config.
centers[i] = &(centers_raw[i]);
uint32_t lwgeom_get_type(const LWGEOM *geom)
Return LWTYPE number.
kmeans_result kmeans(kmeans_config *config)
Datum centroid(PG_FUNCTION_ARGS)
LWGEOM * lwgeom_centroid(const LWGEOM *geom)
LWPOINT * lwgeom_as_lwpoint(const LWGEOM *lwgeom)
static double lwkmeans_pt_distance(const Pointer a, const Pointer b)
const POINT2D * getPoint2d_cp(const POINTARRAY *pa, int n)
Returns a POINT2D pointer into the POINTARRAY serialized_ptlist, suitable for reading from...
static void lwkmeans_pt_centroid(const Pointer *objs, const int *clusters, size_t num_objs, int cluster, Pointer centroid)
unsigned int max_iterations
static int lwkmeans_pt_closest(const Pointer *objs, size_t num_objs, const Pointer a)
#define POINTTYPE
LWTYPE numbers, used internally by PostGIS.
void * lwalloc(size_t size)
int lwgeom_is_empty(const LWGEOM *geom)
Return true or false depending on whether a geometry is an "empty" geometry (no vertices members) ...
kmeans_distance_method distance_method
kmeans_centroid_method centroid_method
void lwerror(const char *fmt,...)
Write a notice out to the error handler.