121{
122 WindowObject win_obj = PG_WINDOW_OBJECT();
123 uint32_t row = WinGetCurrentPosition(win_obj);
124 uint32_t ngeoms = WinGetPartitionRowCount(win_obj);
126
127 if (row == 0)
128 {
129 uint32_t i;
130 uint32_t* result_ids;
132 char* is_in_cluster = NULL;
134 bool tolerance_is_null;
135 bool minpoints_is_null;
136 Datum tolerance_datum = WinGetFuncArgCurrent(win_obj, 1, &tolerance_is_null);
137 Datum minpoints_datum = WinGetFuncArgCurrent(win_obj, 2, &minpoints_is_null);
138 double tolerance = DatumGetFloat8(tolerance_datum);
139 int minpoints = DatumGetInt32(minpoints_datum);
140
142
143
144 if (tolerance_is_null || tolerance < 0)
145 {
146 lwpgerror("Tolerance must be a positive number, got %g", tolerance);
147 PG_RETURN_NULL();
148 }
149 if (minpoints_is_null || minpoints < 0)
150 {
151 lwpgerror("Minpoints must be a positive number, got %d", minpoints);
152 }
153
157 for (i = 0; i < ngeoms; i++)
158 {
159 bool geom_is_null;
162
163 if (!geoms[i]) {
164
165 lwpgerror("Error reading geometry.");
166 PG_RETURN_NULL();
167 }
168 }
169
170 if (
union_dbscan(geoms, ngeoms, uf, tolerance, minpoints, minpoints > 1 ? &is_in_cluster : NULL) ==
LW_SUCCESS)
172
173 for (i = 0; i < ngeoms; i++)
174 {
176 }
178
180 {
182 if (is_in_cluster)
184 lwpgerror("Error during clustering");
185 PG_RETURN_NULL();
186 }
187
189 for (i = 0; i < ngeoms; i++)
190 {
191 if (minpoints > 1 && !is_in_cluster[i])
192 {
194 }
195 else
196 {
198 }
199 }
200
203 }
204
206 PG_RETURN_NULL();
207
209}
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)
void * lwalloc(size_t size)
#define LW_TRUE
Return types for functions with status returns.
static LWGEOM * read_lwgeom_from_partition(WindowObject win_obj, uint32_t i, bool *is_null)
static cluster_context * fetch_cluster_context(WindowObject win_obj, uint32_t ngeoms)
void UF_destroy(UNIONFIND *uf)
UNIONFIND * UF_create(uint32_t N)
uint32_t * UF_get_collapsed_cluster_ids(UNIONFIND *uf, const char *is_in_cluster)
cluster_entry clusters[1]