Maybe you can try an iterative approach:
You first use ST_ClusterDBSCAN
with a big eps
and a small minpoints
, and then you isolate the points that are in a cluster too big for you, for exemple using the radius of the bounding circle (general idea, not tested):
sqrt(ST_Area(ST_MinimumBoundingCircle(ST_Collect(points)))/pi) > your_threshold group by cluster_number
Then you do an other ST_ClusterDBSCAN
on them with more stricts parameters (shorter eps
and/or bigger minpoints
). The main difficulty here relies on the choosing of how many steps and what parameters for each step, it depends on the actual result that you want.
If you do that a couple of time you should in fine have only small clusters, without loosing the aggregation in sparser areas.
EDIT: in my idea, that would look like that (I used max_cluster_id_big
in the end to be sure the cluster id doesn't overlap):
INSERT INTO villages_clustered
WITH big_cluster_element AS (
SELECT
ROW_NUMBER() OVER() as id,
name,
way,
ST_ClusterDBSCAN(way, eps := 2000, minpoints := 1) over () AS cluster_id_big,
geom
FROM villages
), big_cluster AS (
SELECT
cluster_id_big,
sqrt(ST_Area(ST_MinimumBoundingCircle(ST_Collect(geom)))/pi()) as radius
FROM big_cluster_element
GROUP BY cluster_id_big
), big_cluster_element_with_radius AS (
SELECT
id,
name,
way,
bc.radius,
bce.cluster_id_big
geom
FROM big_cluster_element bce
LEFT JOIN big_cluster bc
ON bce.cluster_id_big=bc.cluster_id_big
), small_cluster_element AS (
SELECT
id,
name,
way,
ST_ClusterDBSCAN(way, eps := 500, minpoints := 3) over () AS cluster_id_small,
geom
FROM big_cluster_element_with_radius bc
WHERE bc.radius > 10000
), max_id_big AS (
SELECT
max(cluster_id_big) as max_cluster_id_big
FROM big_cluster_element
)
SELECT
id,
name,
way,
coalesce(cluster_id_small+max_cluster_id_big, cluster_id_big) as cluster_id,
geom
FROM max_id_big, big_cluster_element bce
LEFT JOIN small_cluster_element sce
ON bce.id = sce.id
eps
parameter :) You say you want 10km clusters, so try an appropriate value for that. You have to take care of your coordinate values, which SRID is your data in if it is Geometries, not Geographies? Also you might like postgis.net/docs/manual-dev/ST_ClusterWithin.html as easier approach. – bugmenot123 Jul 23 '19 at 9:46ST_ClusterWithin
?!? Cause it only returns clustered geometries?!? Right? So how could I get back to the villages themselfs? Yes... the eps is not stable, right? It will vary depending how far away from the equator I am? The thing is that some, or even most clusters seem to be about 10km. But some are waaaaay bigger, which I don't understand. The srid of my data is: 3857 – Georg Jul 23 '19 at 13:05eps
, I don't get those huge clusters any more. But still, I have a lot of geometries that then don't have any cluster, even though there are other villages nearby – Georg Jul 23 '19 at 14:00