64 return GEOSGeom_createEmptyPolygon();
89 if (
tree.tree == NULL)
102 tree.geom_ids[i] = i;
104 GEOSSTRtree_insert(
tree.tree,
tree.envelopes[i], &(
tree.geom_ids[i]));
110 tree.envelopes = NULL;
113 tree.geom_ids[i] = i;
114 GEOSSTRtree_insert(
tree.tree, geoms[i], &(
tree.geom_ids[i]));
126 GEOSSTRtree_destroy(
tree->tree);
130 for (i = 0; i <
tree->num_geoms; i++)
132 GEOSGeom_destroy(
tree->envelopes[i]);
166 .num_items_found = 0,
167 .items_found_size = 0
175 if (tree.
tree == NULL)
181 for (p = 0; p < num_geoms; p++)
183 const GEOSPreparedGeometry* prep = NULL;
185 if (!geoms[p] || GEOSisEmpty(geoms[p]))
197 int geos_type = GEOSGeomTypeId(geoms[p]);
204 if (geos_type != GEOS_POINT && geos_type != GEOS_MULTIPOINT)
209 prep = GEOSPrepare(geoms[p]);
211 geos_result = GEOSPreparedIntersects(prep, geoms[q]);
215 geos_result = GEOSIntersects(geoms[p], geoms[q]);
222 else if (geos_result)
230 GEOSPreparedGeom_destroy(prep);
258 cluster_success =
combine_geometries(uf, (
void**) geoms, num_geoms, (
void***) clusterGeoms, num_clusters, 0);
260 return cluster_success;
268 GEOSGeometry* query_envelope;
283 GEOSGeom_destroy(query_envelope);
325 .num_items_found = 0,
326 .items_found_size = 0
330 if (in_a_cluster_ret)
332 char* in_a_cluster =
lwalloc(num_geoms *
sizeof(
char));
333 for (i = 0; i < num_geoms; i++)
335 *in_a_cluster_ret = in_a_cluster;
342 if (tree.
tree == NULL)
348 for (p = 0; p < num_geoms; p++)
361 if (mindist == FLT_MAX)
389 .num_items_found = 0,
390 .items_found_size = 0
397 in_a_cluster =
lwalloc(num_geoms *
sizeof(
char));
398 memset(in_a_cluster, 0, num_geoms *
sizeof(
char));
400 if (in_a_cluster_ret)
401 *in_a_cluster_ret = in_a_cluster;
404 if (num_geoms <= min_points)
406 if (!in_a_cluster_ret)
412 if (tree.
tree == NULL)
418 is_in_core =
lwalloc(num_geoms *
sizeof(
char));
419 memset(is_in_core, 0, num_geoms *
sizeof(
char));
422 for (p = 0; p < num_geoms; p++)
439 if (num_neighbors >= min_points)
451 if (in_a_cluster[q] && !is_in_core[q])
456 if (mindist == FLT_MAX)
467 if (num_neighbors < min_points)
469 neighbors[num_neighbors++] = q;
474 if (num_neighbors == min_points)
479 for (j = 0; j < num_neighbors; j++)
504 if (!in_a_cluster_ret)
537 cluster_success =
combine_geometries(uf, (
void**) geoms, num_geoms, (
void***) clusterGeoms, num_clusters, 1);
539 return cluster_success;
552 *clusterGeoms =
lwalloc(*num_clusters *
sizeof(
void*));
554 void** geoms_in_cluster =
lwalloc(num_geoms *
sizeof(
void*));
556 for (i = 0, j = 0, k = 0; i < num_geoms; i++)
558 geoms_in_cluster[j++] = geoms[ordered_components[i]];
561 if ((i == num_geoms - 1) ||
562 (
UF_find(uf, ordered_components[i]) !=
UF_find(uf, ordered_components[i+1])))
572 memcpy(components, geoms_in_cluster, j *
sizeof(
LWGEOM*));
577 int srid = GEOSGetSRID(((GEOSGeometry**) geoms_in_cluster)[0]);
578 GEOSGeometry* combined = GEOSGeom_createCollection(GEOS_GEOMETRYCOLLECTION, (GEOSGeometry**) geoms_in_cluster, j);
579 GEOSSetSRID(combined, srid);
580 (*clusterGeoms)[k++] = combined;
587 lwfree(ordered_components);
GEOSGeometry * make_geos_point(double x, double y)
GEOSGeometry * make_geos_segment(double x1, double y1, double x2, double y2)
uint32_t lwgeom_get_type(const LWGEOM *geom)
Return LWTYPE number.
#define POINTTYPE
LWTYPE numbers, used internally by PostGIS.
LWPOINT * lwgeom_as_lwpoint(const LWGEOM *lwgeom)
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.
int lwgeom_is_empty(const LWGEOM *geom)
Return true or false depending on whether a geometry is an "empty" geometry (no vertices members)
const GBOX * lwgeom_get_bbox(const LWGEOM *lwgeom)
Get a non-empty geometry bounding box, computing and caching it if not already there.
LWCOLLECTION * lwcollection_construct(uint8_t type, int srid, GBOX *bbox, uint32_t ngeoms, LWGEOM **geoms)
void * lwalloc(size_t size)
#define LW_TRUE
Return types for functions with status returns.
const POINT2D * getPoint2d_cp(const POINTARRAY *pa, uint32_t n)
Returns a POINT2D pointer into the POINTARRAY serialized_ptlist, suitable for reading from.
This library is the generic geometry handling section of PostGIS.
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 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 union_intersecting_pairs(GEOSGeometry **geoms, uint32_t num_geoms, UNIONFIND *uf)
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,...
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