Take a list of LWGEOMs and a number of clusters and return an integer array indicating which cluster each geometry is in.
245{
246 uint32_t i;
247 uint32_t num_centroids = 0;
248 uint32_t num_non_empty = 0;
253
254
255
257
258
260
261
262 int* clusters;
263
264 assert(k > 0);
265 assert(n > 0);
266 assert(geoms);
267
268 if (n < k)
269 {
270 lwerror(
"%s: number of geometries is less than the number of clusters requested, not all clusters will get data", __func__);
271 k = n;
272 }
273
274
276 memset(centroids, 0,
sizeof(
LWGEOM*) * n);
277
278
279
281 memset(centers_raw, 0,
sizeof(
POINT2D) * k);
282
283
285 clusters =
lwalloc(
sizeof(
int) * n);
287
288
289 memset(objs, 0,
sizeof(
POINT2D*) * n);
290 memset(clusters, 0, sizeof(int) * n);
291 memset(centers, 0,
sizeof(
POINT2D*) * k);
292
293
294 for (i = 0; i < n; i++)
295 {
296 const LWGEOM* geom = geoms[i];
298
299
301
302
303
305 {
309 {
311 continue;
312 }
313 centroids[num_centroids++] =
centroid;
315 }
316 else
318
319
322 num_non_empty++;
323 }
324
325 if (num_non_empty < k)
326 {
327 lwnotice(
"%s: number of non-empty geometries is less than the number of clusters requested, not all clusters will get data", __func__);
328 k = num_non_empty;
329 }
330
331 if (k > 1)
332 {
334 result =
kmeans(objs, clusters, n, centers, k);
335 }
336 else
337 {
338
339
340 for (i = 0; i < n; i++)
341 {
342 if (k == 0 || !objs[i])
344 else
345 clusters[i] = 0;
346 }
348 }
349
350
355
356
357 if (result) return clusters;
358
359
361 return NULL;
362}
void lwgeom_free(LWGEOM *geom)
LWGEOM * lwgeom_centroid(const LWGEOM *geom)
#define POINTTYPE
LWTYPE numbers, used internally by PostGIS.
void * lwalloc(size_t size)
#define LW_TRUE
Return types for functions with status returns.
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.
static uint32_t lwgeom_get_type(const LWGEOM *geom)
Return LWTYPE number.
static LWPOINT * lwgeom_as_lwpoint(const LWGEOM *lwgeom)
static int lwgeom_is_empty(const LWGEOM *geom)
Return true or false depending on whether a geometry is an "empty" geometry (no vertices members)
static const POINT2D * getPoint2d_cp(const POINTARRAY *pa, uint32_t n)
Returns a POINT2D pointer into the POINTARRAY serialized_ptlist, suitable for reading from.
static void kmeans_init(POINT2D **objs, uint32_t n, POINT2D **centers, POINT2D *centers_raw, uint32_t k)
#define KMEANS_NULL_CLUSTER
static int kmeans(POINT2D **objs, int *clusters, uint32_t n, POINT2D **centers, uint32_t k)
Datum centroid(PG_FUNCTION_ARGS)