64 return GEOSGeom_createEmptyPolygon();
85 if (tree.
tree == NULL)
110 GEOSSTRtree_insert(tree.
tree, geoms[i], &(tree.
geom_ids[i]));
122 GEOSSTRtree_destroy(tree->
tree);
162 .num_items_found = 0,
163 .items_found_size = 0
171 if (tree.
tree == NULL)
177 for (p = 0; p < num_geoms; p++)
179 const GEOSPreparedGeometry* prep = NULL;
181 if (!geoms[p] || GEOSisEmpty(geoms[p]))
193 int geos_type = GEOSGeomTypeId(geoms[p]);
200 if (geos_type != GEOS_POINT && geos_type != GEOS_MULTIPOINT)
205 prep = GEOSPrepare(geoms[p]);
207 geos_result = GEOSPreparedIntersects(prep, geoms[q]);
211 geos_result = GEOSIntersects(geoms[p], geoms[q]);
218 else if (geos_result)
226 GEOSPreparedGeom_destroy(prep);
254 cluster_success =
combine_geometries(uf, (
void**) geoms, num_geoms, (
void***) clusterGeoms, num_clusters, 0);
256 return cluster_success;
264 GEOSGeometry* query_envelope;
279 GEOSGeom_destroy(query_envelope);
321 .num_items_found = 0,
322 .items_found_size = 0
326 if (in_a_cluster_ret)
328 char* in_a_cluster =
lwalloc(num_geoms *
sizeof(
char));
329 for (i = 0; i < num_geoms; i++)
331 *in_a_cluster_ret = in_a_cluster;
338 if (tree.
tree == NULL)
344 for (p = 0; p < num_geoms; p++)
357 if (mindist == FLT_MAX)
385 .num_items_found = 0,
386 .items_found_size = 0
393 in_a_cluster =
lwalloc(num_geoms *
sizeof(
char));
394 memset(in_a_cluster, 0, num_geoms *
sizeof(
char));
396 if (in_a_cluster_ret)
397 *in_a_cluster_ret = in_a_cluster;
400 if (num_geoms <= min_points)
402 if (!in_a_cluster_ret)
408 if (tree.
tree == NULL)
414 is_in_core =
lwalloc(num_geoms *
sizeof(
char));
415 memset(is_in_core, 0, num_geoms *
sizeof(
char));
418 for (p = 0; p < num_geoms; p++)
435 if (num_neighbors >= min_points)
447 if (in_a_cluster[q] && !is_in_core[q])
452 if (mindist == FLT_MAX)
463 if (num_neighbors < min_points)
465 neighbors[num_neighbors++] = q;
470 if (num_neighbors == min_points)
475 for (j = 0; j < num_neighbors; j++)
500 if (!in_a_cluster_ret)
533 cluster_success =
combine_geometries(uf, (
void**) geoms, num_geoms, (
void***) clusterGeoms, num_clusters, 1);
535 return cluster_success;
548 *clusterGeoms =
lwalloc(*num_clusters *
sizeof(
void*));
550 void** geoms_in_cluster =
lwalloc(num_geoms *
sizeof(
void*));
552 for (i = 0, j = 0, k = 0; i < num_geoms; i++)
554 geoms_in_cluster[j++] = geoms[ordered_components[i]];
557 if ((i == num_geoms - 1) ||
558 (
UF_find(uf, ordered_components[i]) !=
UF_find(uf, ordered_components[i+1])))
568 memcpy(components, geoms_in_cluster, j *
sizeof(
LWGEOM*));
573 int srid = GEOSGetSRID(((GEOSGeometry**) geoms_in_cluster)[0]);
574 GEOSGeometry* combined = GEOSGeom_createCollection(GEOS_GEOMETRYCOLLECTION, (GEOSGeometry**) geoms_in_cluster, j);
575 GEOSSetSRID(combined, srid);
576 (*clusterGeoms)[k++] = combined;
583 lwfree(ordered_components);
void UF_destroy(UNIONFIND *uf)
GEOSGeometry * make_geos_segment(double x1, double y1, double x2, double y2)
static void query_accumulate(void *item, void *userdata)
GEOSGeometry ** envelopes
LWCOLLECTION * lwcollection_construct(uint8_t type, int srid, GBOX *bbox, uint32_t ngeoms, LWGEOM **geoms)
double lwgeom_mindistance2d_tolerance(const LWGEOM *lw1, const LWGEOM *lw2, double tolerance)
Function handling min distance calculations and dwithin calculations.
uint32_t lwgeom_get_type(const LWGEOM *geom)
Return LWTYPE number.
uint32_t items_found_size
static int union_dbscan_general(LWGEOM **geoms, uint32_t num_geoms, UNIONFIND *uf, double eps, uint32_t min_points, char **in_a_cluster_ret)
int cluster_intersecting(GEOSGeometry **geoms, uint32_t num_geoms, GEOSGeometry ***clusterGeoms, uint32_t *num_clusters)
Takes an array of GEOSGeometry* and constructs an array of GEOSGeometry*, where each element in the c...
LWPOINT * lwgeom_as_lwpoint(const LWGEOM *lwgeom)
GEOSGeometry * make_geos_point(double x, double y)
static const int STRTREE_NODE_CAPACITY
static int union_dbscan_minpoints_1(LWGEOM **geoms, uint32_t num_geoms, UNIONFIND *uf, double eps, char **in_a_cluster_ret)
uint32_t UF_find(UNIONFIND *uf, uint32_t i)
const POINT2D * getPoint2d_cp(const POINTARRAY *pa, int n)
Returns a POINT2D pointer into the POINTARRAY serialized_ptlist, suitable for reading from...
static struct STRTree make_strtree(void **geoms, uint32_t num_geoms, char is_lwgeom)
Make a GEOSSTRtree that stores a pointer to a variable containing the array index of the input geoms...
int cluster_within_distance(LWGEOM **geoms, uint32_t num_geoms, double tolerance, LWGEOM ***clusterGeoms, uint32_t *num_clusters)
Takes an array of LWGEOM* and constructs an array of LWGEOM*, where each element in the constructed a...
uint32_t * UF_ordered_by_cluster(UNIONFIND *uf)
#define LW_TRUE
Return types for functions with status returns.
static void union_if_available(UNIONFIND *uf, uint32_t p, uint32_t q, char *is_in_core, char *in_a_cluster)
const GBOX * lwgeom_get_bbox(const LWGEOM *lwgeom)
Get a non-empty geometry bounding box, computing and caching it if not already there.
static void destroy_strtree(struct STRTree *tree)
Clean up STRTree after use.
UNIONFIND * UF_create(uint32_t N)
void * lwrealloc(void *mem, size_t size)
#define POINTTYPE
LWTYPE numbers, used internally by PostGIS.
static int dbscan_update_context(GEOSSTRtree *tree, struct QueryContext *cxt, LWGEOM **geoms, uint32_t p, double eps)
void UF_union(UNIONFIND *uf, uint32_t i, uint32_t j)
void * lwalloc(size_t size)
int lwgeom_is_empty(const LWGEOM *geom)
Return true or false depending on whether a geometry is an "empty" geometry (no vertices members) ...
static int combine_geometries(UNIONFIND *uf, void **geoms, uint32_t num_geoms, void ***clustersGeoms, uint32_t *num_clusters, char is_lwgeom)
Uses a UNIONFIND to identify the set with which each input geometry is associated, and groups the geometries into GeometryCollections.
static int union_intersecting_pairs(GEOSGeometry **geoms, uint32_t num_geoms, UNIONFIND *uf)
static GEOSGeometry * geos_envelope_surrogate(const LWGEOM *g)
This library is the generic geometry handling section of PostGIS.
int union_dbscan(LWGEOM **geoms, uint32_t num_geoms, UNIONFIND *uf, double eps, uint32_t min_points, char **in_a_cluster_ret)