PostGIS 3.0.6dev-r@@SVN_REVISION@@
Loading...
Searching...
No Matches

◆ ST_ClusterDBSCAN()

Datum ST_ClusterDBSCAN ( PG_FUNCTION_ARGS  )
extern

Definition at line 83 of file lwgeom_window.c.

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, (bool*)&(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}
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:108
void lwgeom_free(LWGEOM *geom)
Definition lwgeom.c:1138
#define LW_SUCCESS
Definition liblwgeom.h:111
void * lwalloc(size_t size)
Definition lwutil.c:227
void lwfree(void *mem)
Definition lwutil.c:242
#define LW_TRUE
Return types for functions with status returns.
Definition liblwgeom.h:107
void lwnotice(const char *fmt,...)
Write a notice out to the notice handler.
Definition lwutil.c:177
static LWGEOM * read_lwgeom_from_partition(WindowObject win_obj, uint32_t i, bool *is_null)
void UF_destroy(UNIONFIND *uf)
Definition lwunionfind.c:54
UNIONFIND * UF_create(uint32_t N)
Definition lwunionfind.c:35
uint32_t * UF_get_collapsed_cluster_ids(UNIONFIND *uf, const char *is_in_cluster)
dbscan_cluster_result cluster_assignments[1]

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(), read_lwgeom_from_partition(), UF_create(), UF_destroy(), UF_get_collapsed_cluster_ids(), and union_dbscan().

Here is the call graph for this function: