PostGIS  3.4.0dev-r@@SVN_REVISION@@

◆ ST_ClusterDBSCAN()

Datum ST_ClusterDBSCAN ( PG_FUNCTION_ARGS  )

Definition at line 119 of file lwgeom_window.c.

120 {
121  WindowObject win_obj = PG_WINDOW_OBJECT();
122  uint32_t row = WinGetCurrentPosition(win_obj);
123  uint32_t ngeoms = WinGetPartitionRowCount(win_obj);
124  cluster_context* context = fetch_cluster_context(win_obj, ngeoms);
125 
126  if (row == 0) /* beginning of the partition; do all of the work now */
127  {
128  uint32_t i;
129  uint32_t* result_ids;
130  LWGEOM** geoms;
131  char* is_in_cluster = NULL;
132  UNIONFIND* uf;
133  bool tolerance_is_null;
134  bool minpoints_is_null;
135  Datum tolerance_datum = WinGetFuncArgCurrent(win_obj, 1, &tolerance_is_null);
136  Datum minpoints_datum = WinGetFuncArgCurrent(win_obj, 2, &minpoints_is_null);
137  double tolerance = DatumGetFloat8(tolerance_datum);
138  int minpoints = DatumGetInt32(minpoints_datum);
139 
140  context->is_error = LW_TRUE; /* until proven otherwise */
141 
142  /* Validate input parameters */
143  if (tolerance_is_null || tolerance < 0)
144  {
145  lwpgerror("Tolerance must be a positive number", tolerance);
146  PG_RETURN_NULL();
147  }
148  if (minpoints_is_null || minpoints < 0)
149  {
150  lwpgerror("Minpoints must be a positive number", minpoints);
151  }
152 
153  initGEOS(lwnotice, lwgeom_geos_error);
154  geoms = lwalloc(ngeoms * sizeof(LWGEOM*));
155  uf = UF_create(ngeoms);
156  for (i = 0; i < ngeoms; i++)
157  {
158  bool geom_is_null;
159  geoms[i] = read_lwgeom_from_partition(win_obj, i, &geom_is_null);
160  context->clusters[i].is_null = geom_is_null;
161 
162  if (!geoms[i]) {
163  /* TODO release memory ? */
164  lwpgerror("Error reading geometry.");
165  PG_RETURN_NULL();
166  }
167  }
168 
169  if (union_dbscan(geoms, ngeoms, uf, tolerance, minpoints, minpoints > 1 ? &is_in_cluster : NULL) == LW_SUCCESS)
170  context->is_error = LW_FALSE;
171 
172  for (i = 0; i < ngeoms; i++)
173  {
174  lwgeom_free(geoms[i]);
175  }
176  lwfree(geoms);
177 
178  if (context->is_error)
179  {
180  UF_destroy(uf);
181  if (is_in_cluster)
182  lwfree(is_in_cluster);
183  lwpgerror("Error during clustering");
184  PG_RETURN_NULL();
185  }
186 
187  result_ids = UF_get_collapsed_cluster_ids(uf, is_in_cluster);
188  for (i = 0; i < ngeoms; i++)
189  {
190  if (minpoints > 1 && !is_in_cluster[i])
191  {
192  context->clusters[i].is_null = LW_TRUE;
193  }
194  else
195  {
196  context->clusters[i].cluster_id = result_ids[i];
197  }
198  }
199 
200  lwfree(result_ids);
201  UF_destroy(uf);
202  }
203 
204  if (context->clusters[row].is_null)
205  PG_RETURN_NULL();
206 
207  PG_RETURN_INT32(context->clusters[row].cluster_id);
208 }
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)
#define LW_FALSE
Definition: liblwgeom.h:94
void lwgeom_free(LWGEOM *geom)
Definition: lwgeom.c:1155
#define LW_SUCCESS
Definition: liblwgeom.h:97
void lwfree(void *mem)
Definition: lwutil.c:242
void * lwalloc(size_t size)
Definition: lwutil.c:227
#define LW_TRUE
Return types for functions with status returns.
Definition: liblwgeom.h:93
void lwnotice(const char *fmt,...)
Write a notice out to the notice handler.
Definition: lwutil.c:177
static cluster_context * fetch_cluster_context(WindowObject win_obj, uint32_t ngeoms)
Definition: lwgeom_window.c:63
static LWGEOM * read_lwgeom_from_partition(WindowObject win_obj, uint32_t i, bool *is_null)
Definition: lwgeom_window.c:71
uint32_t * UF_get_collapsed_cluster_ids(UNIONFIND *uf, const char *is_in_cluster)
Definition: lwunionfind.c:146
void UF_destroy(UNIONFIND *uf)
Definition: lwunionfind.c:54
UNIONFIND * UF_create(uint32_t N)
Definition: lwunionfind.c:35
cluster_entry clusters[1]
Definition: lwgeom_window.c:59
uint32_t cluster_id
Definition: lwgeom_window.c:50
char is_null
Definition: lwgeom_window.c:51

References cluster_entry::cluster_id, cluster_context::clusters, fetch_cluster_context(), cluster_context::is_error, cluster_entry::is_null, LW_FALSE, LW_SUCCESS, LW_TRUE, lwalloc(), lwfree(), lwgeom_free(), lwgeom_geos_error(), lwnotice(), read_lwgeom_from_partition(), UF_create(), UF_destroy(), UF_get_collapsed_cluster_ids(), and union_dbscan().

Here is the call graph for this function: