63 return GEOSGeom_createEmptyPolygon();
88 if (
tree.tree == NULL)
101 tree.geom_ids[i] = i;
103 GEOSSTRtree_insert(
tree.tree,
tree.envelopes[i], &(
tree.geom_ids[i]));
109 tree.envelopes = NULL;
112 tree.geom_ids[i] = i;
113 GEOSSTRtree_insert(
tree.tree, geoms[i], &(
tree.geom_ids[i]));
125 GEOSSTRtree_destroy(
tree->tree);
129 for (i = 0; i <
tree->num_geoms; i++)
131 GEOSGeom_destroy(
tree->envelopes[i]);
165 .num_items_found = 0,
166 .items_found_size = 0
174 if (tree.
tree == NULL)
180 for (p = 0; p < num_geoms; p++)
182 const GEOSPreparedGeometry* prep = NULL;
184 if (!geoms[p] || GEOSisEmpty(geoms[p]))
196 int geos_type = GEOSGeomTypeId(geoms[p]);
203 if (geos_type != GEOS_POINT && geos_type != GEOS_MULTIPOINT)
208 prep = GEOSPrepare(geoms[p]);
210 geos_result = GEOSPreparedIntersects(prep, geoms[q]);
214 geos_result = GEOSIntersects(geoms[p], geoms[q]);
221 else if (geos_result)
229 GEOSPreparedGeom_destroy(prep);
246 cluster_intersecting(GEOSGeometry** geoms, uint32_t num_geoms, GEOSGeometry*** clusterGeoms, uint32_t* num_clusters)
257 cluster_success =
combine_geometries(uf, (
void**) geoms, num_geoms, (
void***) clusterGeoms, num_clusters, 0);
259 return cluster_success;
267 GEOSGeometry* query_envelope;
285 GEOSGeom_destroy(query_envelope);
327 .num_items_found = 0,
328 .items_found_size = 0
332 if (in_a_cluster_ret)
334 char* in_a_cluster =
lwalloc(num_geoms *
sizeof(
char));
335 for (i = 0; i < num_geoms; i++)
337 *in_a_cluster_ret = in_a_cluster;
344 if (tree.
tree == NULL)
350 for (p = 0; p < num_geoms; p++)
369 if (mindist == FLT_MAX)
397 .num_items_found = 0,
398 .items_found_size = 0
405 in_a_cluster =
lwalloc(num_geoms *
sizeof(
char));
406 memset(in_a_cluster, 0, num_geoms *
sizeof(
char));
408 if (in_a_cluster_ret)
409 *in_a_cluster_ret = in_a_cluster;
412 if (num_geoms < min_points)
414 if (!in_a_cluster_ret)
420 if (tree.
tree == NULL)
426 is_in_core =
lwalloc(num_geoms *
sizeof(
char));
427 memset(is_in_core, 0, num_geoms *
sizeof(
char));
428 neighbors =
lwalloc(min_points *
sizeof(uint32_t));
430 for (p = 0; p < num_geoms; p++)
432 uint32_t num_neighbors = 0;
453 if (num_neighbors >= min_points)
465 if (in_a_cluster[q] && !is_in_core[q])
470 if (mindist == FLT_MAX)
481 if (num_neighbors < min_points)
483 neighbors[num_neighbors++] = q;
488 if (num_neighbors == min_points)
493 for (j = 0; j < num_neighbors; j++)
518 if (!in_a_cluster_ret)
551 cluster_success =
combine_geometries(uf, (
void**) geoms, num_geoms, (
void***) clusterGeoms, num_clusters, 1);
553 return cluster_success;
566 *clusterGeoms =
lwalloc(*num_clusters *
sizeof(
void*));
568 void** geoms_in_cluster =
lwalloc(num_geoms *
sizeof(
void*));
570 for (i = 0, j = 0, k = 0; i < num_geoms; i++)
572 geoms_in_cluster[j++] = geoms[ordered_components[i]];
575 if ((i == num_geoms - 1) ||
576 (
UF_find(uf, ordered_components[i]) !=
UF_find(uf, ordered_components[i+1])))
586 memcpy(components, geoms_in_cluster, j *
sizeof(
LWGEOM*));
591 int srid = GEOSGetSRID(((GEOSGeometry**) geoms_in_cluster)[0]);
592 GEOSGeometry* combined = GEOSGeom_createCollection(GEOS_GEOMETRYCOLLECTION, (GEOSGeometry**) geoms_in_cluster, j);
593 GEOSSetSRID(combined, srid);
594 (*clusterGeoms)[k++] = combined;
601 lwfree(ordered_components);
GEOSGeometry * make_geos_point(double x, double y)
GEOSGeometry * make_geos_segment(double x1, double y1, double x2, double y2)
#define POINTTYPE
LWTYPE numbers, used internally by PostGIS.
void * lwrealloc(void *mem, size_t size)
double lwgeom_mindistance2d_tolerance(const LWGEOM *lw1, const LWGEOM *lw2, double tolerance)
Function handling min distance calculations and dwithin calculations.
const GBOX * lwgeom_get_bbox(const LWGEOM *lwgeom)
Get a non-empty geometry bounding box, computing and caching it if not already there.
void * lwalloc(size_t size)
LWCOLLECTION * lwcollection_construct(uint8_t type, int32_t srid, GBOX *bbox, uint32_t ngeoms, LWGEOM **geoms)
#define LW_TRUE
Return types for functions with status returns.
This library is the generic geometry handling section of PostGIS.
#define LW_ON_INTERRUPT(x)
static int dbscan_update_context(GEOSSTRtree *tree, struct QueryContext *cxt, LWGEOM **geoms, uint32_t p, double eps)
static GEOSGeometry * geos_envelope_surrogate(const LWGEOM *g)
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 union_dbscan(LWGEOM **geoms, uint32_t num_geoms, UNIONFIND *uf, double eps, uint32_t min_points, char **in_a_cluster_ret)
static int union_dbscan_minpoints_1(LWGEOM **geoms, uint32_t num_geoms, UNIONFIND *uf, double eps, char **in_a_cluster_ret)
static void query_accumulate(void *item, void *userdata)
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.
static void destroy_strtree(struct STRTree *tree)
Clean up STRTree after use.
static const int STRTREE_NODE_CAPACITY
static void union_if_available(UNIONFIND *uf, uint32_t p, uint32_t q, char *is_in_core, char *in_a_cluster)
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...
int union_intersecting_pairs(GEOSGeometry **geoms, uint32_t num_geoms, UNIONFIND *uf)
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...
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,...
static const POINT2D * getPoint2d_cp(const POINTARRAY *pa, uint32_t n)
Returns a POINT2D pointer into the POINTARRAY serialized_ptlist, suitable for reading from.
static uint32_t lwgeom_get_type(const LWGEOM *geom)
Return LWTYPE number.
static int lwgeom_is_empty(const LWGEOM *geom)
Return true or false depending on whether a geometry is an "empty" geometry (no vertices members)
static LWPOINT * lwgeom_as_lwpoint(const LWGEOM *lwgeom)
void UF_destroy(UNIONFIND *uf)
uint32_t UF_find(UNIONFIND *uf, uint32_t i)
UNIONFIND * UF_create(uint32_t N)
uint32_t * UF_ordered_by_cluster(UNIONFIND *uf)
void UF_union(UNIONFIND *uf, uint32_t i, uint32_t j)
uint32_t items_found_size
GEOSGeometry ** envelopes