26 #include "../postgis_config.h"
31 #include "windowapi.h"
38 #include "lwgeom_pg.h"
68 Datum arg = WinGetFuncArgInPartition(win_obj, 0, i, WINDOW_SEEK_HEAD,
false, is_null, NULL);
85 WindowObject win_obj = PG_WINDOW_OBJECT();
86 uint32_t row = WinGetCurrentPosition(win_obj);
87 uint32_t ngeoms = WinGetPartitionRowCount(win_obj);
95 char* is_in_cluster = NULL;
97 bool tolerance_is_null;
98 bool minpoints_is_null;
99 Datum tolerance_datum = WinGetFuncArgCurrent(win_obj, 1, &tolerance_is_null);
100 Datum minpoints_datum = WinGetFuncArgCurrent(win_obj, 2, &minpoints_is_null);
101 double tolerance = DatumGetFloat8(tolerance_datum);
102 int minpoints = DatumGetInt32(minpoints_datum);
107 if (tolerance_is_null || tolerance < 0)
109 lwpgerror(
"Tolerance must be a positive number", tolerance);
112 if (minpoints_is_null || minpoints < 0)
114 lwpgerror(
"Minpoints must be a positive number", minpoints);
120 for (i = 0; i < ngeoms; i++)
126 lwpgerror(
"Error reading geometry.");
131 if (
union_dbscan(geoms, ngeoms, uf, tolerance, minpoints, minpoints > 1 ? &is_in_cluster : NULL) ==
LW_SUCCESS)
134 for (i = 0; i < ngeoms; i++)
145 lwpgerror(
"Error during clustering");
150 for (i = 0; i < ngeoms; i++)
152 if (minpoints > 1 && !is_in_cluster[i])
175 WindowObject winobj = PG_WINDOW_OBJECT();
177 int64 curpos, rowcount;
179 rowcount = WinGetPartitionRowCount(winobj);
181 WinGetPartitionLocalMemory(winobj,
192 k = DatumGetInt32(WinGetFuncArgCurrent(winobj, 1, &isnull));
193 if (isnull || k <= 0)
201 N = (int) WinGetPartitionRowCount(winobj);
212 lwpgerror(
"K (%d) must be smaller than the number of rows in the group (%d)", k, N);
216 geoms = palloc(
sizeof(
LWGEOM*) * N);
217 for (i = 0; i < N; i++)
220 Datum arg = WinGetFuncArgInPartition(winobj, 0, i,
221 WINDOW_SEEK_HEAD,
false, &isnull, &isout);
238 for (i = 0; i < N; i++)
252 memcpy(context->
result,
r,
sizeof(
int) * N);
260 curpos = WinGetCurrentPosition(winobj);
261 PG_RETURN_INT32(context->
result[curpos]);
LWGEOM * lwgeom_from_gserialized(const GSERIALIZED *g)
Allocate a new LWGEOM from a GSERIALIZED.
void lwgeom_geos_error(const char *fmt,...)
int union_dbscan(LWGEOM **geoms, uint32_t num_geoms, UNIONFIND *uf, double eps, uint32_t min_points, char **is_in_cluster_ret)
void lwgeom_free(LWGEOM *geom)
LWGEOM * lwpoint_as_lwgeom(const LWPOINT *obj)
void * lwalloc(size_t size)
#define LW_TRUE
Return types for functions with status returns.
LWPOINT * lwpoint_construct_empty(int srid, char hasz, char hasm)
int * lwgeom_cluster_2d_kmeans(const LWGEOM **geoms, uint32_t ngeoms, uint32_t k)
Take a list of LWGEOMs and a number of clusters and return an integer array indicating which cluster ...
This library is the generic geometry handling section of PostGIS.
void lwnotice(const char *fmt,...)
Write a notice out to the notice handler.
PG_FUNCTION_INFO_V1(ST_ClusterDBSCAN)
Datum ST_ClusterKMeans(PG_FUNCTION_ARGS)
static LWGEOM * read_lwgeom_from_partition(WindowObject win_obj, uint32_t i, bool *is_null)
Datum ST_ClusterDBSCAN(PG_FUNCTION_ARGS)
uint32_t * UF_get_collapsed_cluster_ids(UNIONFIND *uf, const char *is_in_cluster)
void UF_destroy(UNIONFIND *uf)
UNIONFIND * UF_create(uint32_t N)
dbscan_cluster_result cluster_assignments[1]