PostGIS  2.4.9dev-r@@SVN_REVISION@@

◆ ST_ClusterDBSCAN()

Datum ST_ClusterDBSCAN ( PG_FUNCTION_ARGS  )

Definition at line 83 of file lwgeom_window.c.

References dbscan_context::cluster_assignments, dbscan_cluster_result::cluster_id, dbscan_context::is_error, dbscan_cluster_result::is_null, LW_FALSE, LW_SUCCESS, LW_TRUE, lwalloc(), lwfree(), lwgeom_free(), lwgeom_geos_error(), lwnotice(), PG_FUNCTION_INFO_V1(), read_lwgeom_from_partition(), ST_ClusterKMeans(), UF_create(), UF_destroy(), UF_get_collapsed_cluster_ids(), and union_dbscan().

Referenced by read_lwgeom_from_partition().

84 {
85  WindowObject win_obj = PG_WINDOW_OBJECT();
86  uint32_t row = WinGetCurrentPosition(win_obj);
87  uint32_t ngeoms = WinGetPartitionRowCount(win_obj);
88  dbscan_context* context = WinGetPartitionLocalMemory(win_obj, sizeof(dbscan_context) + ngeoms * sizeof(dbscan_cluster_result));
89 
90  if (row == 0) /* beginning of the partition; do all of the work now */
91  {
92  uint32_t i;
93  uint32_t* result_ids;
94  LWGEOM** geoms;
95  char* is_in_cluster = NULL;
96  UNIONFIND* uf;
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);
103 
104  context->is_error = LW_TRUE; /* until proven otherwise */
105 
106  /* Validate input parameters */
107  if (tolerance_is_null || tolerance < 0)
108  {
109  lwpgerror("Tolerance must be a positive number", tolerance);
110  PG_RETURN_NULL();
111  }
112  if (minpoints_is_null || minpoints < 0)
113  {
114  lwpgerror("Minpoints must be a positive number", minpoints);
115  }
116 
117  initGEOS(lwnotice, lwgeom_geos_error);
118  geoms = lwalloc(ngeoms * sizeof(LWGEOM*));
119  uf = UF_create(ngeoms);
120  for (i = 0; i < ngeoms; i++)
121  {
122  geoms[i] = read_lwgeom_from_partition(win_obj, i, &(context->cluster_assignments[i].is_null));
123 
124  if (!geoms[i]) {
125  /* TODO release memory ? */
126  lwpgerror("Error reading geometry.");
127  PG_RETURN_NULL();
128  }
129  }
130 
131  if (union_dbscan(geoms, ngeoms, uf, tolerance, minpoints, minpoints > 1 ? &is_in_cluster : NULL) == LW_SUCCESS)
132  context->is_error = LW_FALSE;
133 
134  for (i = 0; i < ngeoms; i++)
135  {
136  lwgeom_free(geoms[i]);
137  }
138  lwfree(geoms);
139 
140  if (context->is_error)
141  {
142  UF_destroy(uf);
143  if (is_in_cluster)
144  lwfree(is_in_cluster);
145  lwpgerror("Error during clustering");
146  PG_RETURN_NULL();
147  }
148 
149  result_ids = UF_get_collapsed_cluster_ids(uf, is_in_cluster);
150  for (i = 0; i < ngeoms; i++)
151  {
152  if (minpoints > 1 && !is_in_cluster[i])
153  {
154  context->cluster_assignments[i].is_null = LW_TRUE;
155  }
156  else
157  {
158  context->cluster_assignments[i].cluster_id = result_ids[i];
159  }
160  }
161 
162  lwfree(result_ids);
163  UF_destroy(uf);
164  }
165 
166  if (context->cluster_assignments[row].is_null)
167  PG_RETURN_NULL();
168 
169  PG_RETURN_INT32(context->cluster_assignments[row].cluster_id);
170 }
HeapTupleHeader row
Definition: mvt.h:54
dbscan_cluster_result cluster_assignments[1]
Definition: lwgeom_window.c:61
void UF_destroy(UNIONFIND *uf)
Definition: lwunionfind.c:53
void lwnotice(const char *fmt,...)
Write a notice out to the notice handler.
Definition: lwutil.c:177
void lwfree(void *mem)
Definition: lwutil.c:244
static LWGEOM * read_lwgeom_from_partition(WindowObject win_obj, uint32_t i, bool *is_null)
Definition: lwgeom_window.c:65
void lwgeom_free(LWGEOM *geom)
Definition: lwgeom.c:1099
#define LW_SUCCESS
Definition: liblwgeom.h:80
int union_dbscan(LWGEOM **geoms, uint32_t num_geoms, UNIONFIND *uf, double eps, uint32_t min_points, char **is_in_cluster_ret)
unsigned int uint32_t
Definition: uthash.h:78
void lwgeom_geos_error(const char *fmt,...)
#define LW_FALSE
Definition: liblwgeom.h:77
#define LW_TRUE
Return types for functions with status returns.
Definition: liblwgeom.h:76
UNIONFIND * UF_create(uint32_t N)
Definition: lwunionfind.c:34
void * lwalloc(size_t size)
Definition: lwutil.c:229
uint32_t * UF_get_collapsed_cluster_ids(UNIONFIND *uf, const char *is_in_cluster)
Definition: lwunionfind.c:145
Here is the call graph for this function:
Here is the caller graph for this function: