PostGIS 3.7.0dev-r@@SVN_REVISION@@
Loading...
Searching...
No Matches

◆ ST_ClusterKMeans()

Datum ST_ClusterKMeans ( PG_FUNCTION_ARGS  )
extern

Definition at line 355 of file lwgeom_window.c.

356{
357 WindowObject winobj = PG_WINDOW_OBJECT();
358 kmeans_context *context;
359 int64 curpos, rowcount;
360
361 rowcount = WinGetPartitionRowCount(winobj);
362 context = (kmeans_context *)
363 WinGetPartitionLocalMemory(winobj,
364 sizeof(kmeans_context) + sizeof(int) * rowcount);
365
366 if (!context->isdone)
367 {
368 int i, k, N;
369 bool isnull, isout;
370 double max_radius = 0.0;
371 LWGEOM **geoms;
372 int *r;
373 Datum argdatum;
374
375 /* What is K? If it's NULL or invalid, we can't proceed */
376 argdatum = WinGetFuncArgCurrent(winobj, 1, &isnull);
377 k = DatumGetInt32(argdatum);
378 if (isnull || k <= 0)
379 {
380 context->isdone = true;
381 context->isnull = true;
382 PG_RETURN_NULL();
383 }
384
385 /* We also need a non-zero N */
386 N = (int) WinGetPartitionRowCount(winobj);
387 if (N <= 0)
388 {
389 context->isdone = true;
390 context->isnull = true;
391 PG_RETURN_NULL();
392 }
393
394 /* Maximum cluster radius. 0 if not set*/
395 argdatum = WinGetFuncArgCurrent(winobj, 2, &isnull);
396 if (!isnull)
397 {
398 max_radius = DatumGetFloat8(argdatum);
399 if (max_radius < 0)
400 max_radius = 0.0;
401 }
402
403 /* Error out if N < K */
404 if (N<k)
405 lwpgerror("K (%d) must be smaller than the number of rows in the group (%d)", k, N);
406
407 /* Read all the geometries from the partition window into a list */
408 geoms = palloc(sizeof(LWGEOM*) * N);
409 for (i = 0; i < N; i++)
410 {
411 GSERIALIZED *g;
412 Datum arg = WinGetFuncArgInPartition(winobj, 0, i,
413 WINDOW_SEEK_HEAD, false, &isnull, &isout);
414
415 /* Null geometries are entered as NULL pointers */
416 if (isnull)
417 {
418 geoms[i] = NULL;
419 continue;
420 }
421
422 g = (GSERIALIZED*)PG_DETOAST_DATUM_COPY(arg);
423 geoms[i] = lwgeom_from_gserialized(g);
424 }
425
426 /* Calculate k-means on the list! */
427 r = lwgeom_cluster_kmeans((const LWGEOM **)geoms, N, k, max_radius);
428
429 /* Clean up */
430 for (i = 0; i < N; i++)
431 if (geoms[i])
432 lwgeom_free(geoms[i]);
433
434 pfree(geoms);
435
436 if (!r)
437 {
438 context->isdone = true;
439 context->isnull = true;
440 PG_RETURN_NULL();
441 }
442
443 /* Safe the result */
444 memcpy(context->result, r, sizeof(int) * N);
445 lwfree(r);
446 context->isdone = true;
447 }
448
449 if (context->isnull)
450 PG_RETURN_NULL();
451
452 curpos = WinGetCurrentPosition(winobj);
453 PG_RETURN_INT32(context->result[curpos]);
454}
char * r
Definition cu_in_wkt.c:24
LWGEOM * lwgeom_from_gserialized(const GSERIALIZED *g)
Allocate a new LWGEOM from a GSERIALIZED.
void lwgeom_free(LWGEOM *geom)
Definition lwgeom.c:1246
int * lwgeom_cluster_kmeans(const LWGEOM **geoms, uint32_t n, uint32_t k, double max_radius)
Take a list of LWGEOMs and a number of clusters and return an integer array indicating which cluster ...
Definition lwkmeans.c:321
void lwfree(void *mem)
Definition lwutil.c:248

References kmeans_context::isdone, kmeans_context::isnull, lwfree(), lwgeom_cluster_kmeans(), lwgeom_free(), lwgeom_from_gserialized(), r, and kmeans_context::result.

Here is the call graph for this function: