PostGIS  2.5.7dev-r@@SVN_REVISION@@

◆ ST_ClusterKMeans()

Datum ST_ClusterKMeans ( PG_FUNCTION_ARGS  )

Definition at line 173 of file lwgeom_window.c.

174 {
175  WindowObject winobj = PG_WINDOW_OBJECT();
176  kmeans_context *context;
177  int64 curpos, rowcount;
178 
179  rowcount = WinGetPartitionRowCount(winobj);
180  context = (kmeans_context *)
181  WinGetPartitionLocalMemory(winobj,
182  sizeof(kmeans_context) + sizeof(int) * rowcount);
183 
184  if (!context->isdone)
185  {
186  int i, k, N;
187  bool isnull, isout;
188  LWGEOM **geoms;
189  int *r;
190 
191  /* What is K? If it's NULL or invalid, we can't procede */
192  k = DatumGetInt32(WinGetFuncArgCurrent(winobj, 1, &isnull));
193  if (isnull || k <= 0)
194  {
195  context->isdone = true;
196  context->isnull = true;
197  PG_RETURN_NULL();
198  }
199 
200  /* We also need a non-zero N */
201  N = (int) WinGetPartitionRowCount(winobj);
202  if (N <= 0)
203  {
204  context->isdone = true;
205  context->isnull = true;
206  PG_RETURN_NULL();
207  }
208 
209  /* Error out if N < K */
210  if (N<k)
211  {
212  lwpgerror("K (%d) must be smaller than the number of rows in the group (%d)", k, N);
213  }
214 
215  /* Read all the geometries from the partition window into a list */
216  geoms = palloc(sizeof(LWGEOM*) * N);
217  for (i = 0; i < N; i++)
218  {
219  GSERIALIZED *g;
220  Datum arg = WinGetFuncArgInPartition(winobj, 0, i,
221  WINDOW_SEEK_HEAD, false, &isnull, &isout);
222 
223  /* Null geometries are entered as NULL pointers */
224  if (isnull)
225  {
226  geoms[i] = NULL;
227  continue;
228  }
229 
230  g = (GSERIALIZED*)PG_DETOAST_DATUM_COPY(arg);
231  geoms[i] = lwgeom_from_gserialized(g);
232  }
233 
234  /* Calculate k-means on the list! */
235  r = lwgeom_cluster_2d_kmeans((const LWGEOM **)geoms, N, k);
236 
237  /* Clean up */
238  for (i = 0; i < N; i++)
239  if (geoms[i])
240  lwgeom_free(geoms[i]);
241 
242  pfree(geoms);
243 
244  if (!r)
245  {
246  context->isdone = true;
247  context->isnull = true;
248  PG_RETURN_NULL();
249  }
250 
251  /* Safe the result */
252  memcpy(context->result, r, sizeof(int) * N);
253  pfree(r);
254  context->isdone = true;
255  }
256 
257  if (context->isnull)
258  PG_RETURN_NULL();
259 
260  curpos = WinGetCurrentPosition(winobj);
261  PG_RETURN_INT32(context->result[curpos]);
262 }
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:1144
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 ...
Definition: lwkmeans.c:240

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

Here is the call graph for this function: