1616
1717package com .google .maps .android .clustering .algo ;
1818
19+ import com .google .android .gms .maps .model .LatLng ;
20+ import com .google .maps .android .clustering .Cluster ;
1921import com .google .maps .android .clustering .ClusterItem ;
2022import com .google .maps .android .geometry .Bounds ;
21- import com .google .maps .android .quadtree .PointQuadTree ;
2223
2324import java .util .ArrayList ;
2425import java .util .Collection ;
26+ import java .util .HashMap ;
2527import java .util .HashSet ;
28+ import java .util .Map ;
2629import java .util .Set ;
2730
2831/**
2932 * A variant of {@link CentroidNonHierarchicalDistanceBasedAlgorithm} that uses
3033 * continuous zoom scaling and Euclidean distance for clustering.
3134 *
32- * <p>This class overrides {@link #getClusteringItems(PointQuadTree, float)} to compute
35+ * <p>This class overrides {@link #getClusters( float)} to compute
3336 * clusters with a zoom-dependent radius, while keeping the centroid-based cluster positions.</p>
3437 *
3538 * @param <T> the type of cluster item
@@ -38,15 +41,21 @@ public class ContinuousZoomEuclideanCentroidAlgorithm<T extends ClusterItem>
3841 extends CentroidNonHierarchicalDistanceBasedAlgorithm <T > {
3942
4043 @ Override
41- protected Collection < QuadItem < T >> getClusteringItems ( PointQuadTree < QuadItem < T >> quadTree , float zoom ) {
44+ public Set <? extends Cluster < T >> getClusters ( float zoom ) {
4245 // Continuous zoom — no casting to int
4346 final double zoomSpecificSpan = getMaxDistanceBetweenClusteredItems () / Math .pow (2 , zoom ) / 256 ;
4447
4548 final Set <QuadItem <T >> visitedCandidates = new HashSet <>();
46- final Collection <QuadItem <T >> result = new ArrayList <>();
49+ final Set <Cluster <T >> results = new HashSet <>();
50+ final Map <QuadItem <T >, Double > distanceToCluster = new HashMap <>();
51+ final Map <QuadItem <T >, StaticCluster <T >> itemToCluster = new HashMap <>();
52+
4753 synchronized (mQuadTree ) {
48- for (QuadItem <T > candidate : mItems ) {
49- if (visitedCandidates .contains (candidate )) continue ;
54+ for (QuadItem <T > candidate : getClusteringItems (mQuadTree , zoom )) {
55+ if (visitedCandidates .contains (candidate )) {
56+ // Candidate is already part of another cluster.
57+ continue ;
58+ }
5059
5160 Bounds searchBounds = createBoundsFromSpan (candidate .getPoint (), zoomSpecificSpan );
5261 Collection <QuadItem <T >> clusterItems = new ArrayList <>();
@@ -58,11 +67,46 @@ protected Collection<QuadItem<T>> getClusteringItems(PointQuadTree<QuadItem<T>>
5867 }
5968 }
6069
70+ if (clusterItems .size () == 1 ) {
71+ // Only the current marker is in range. Just add the single item to the results.
72+ results .add (candidate );
73+ visitedCandidates .add (candidate );
74+ distanceToCluster .put (candidate , 0d );
75+ continue ;
76+ }
77+ StaticCluster <T > cluster = new StaticCluster <>(candidate .mClusterItem .getPosition ());
78+ results .add (cluster );
79+
80+ for (QuadItem <T > clusterItem : clusterItems ) {
81+ Double existingDistance = distanceToCluster .get (clusterItem );
82+ double distance = distanceSquared (clusterItem .getPoint (), candidate .getPoint ());
83+ if (existingDistance != null ) {
84+ // Item already belongs to another cluster. Check if it's closer to this cluster.
85+ if (existingDistance < distance ) {
86+ continue ;
87+ }
88+ // Move item to the closer cluster.
89+ itemToCluster .get (clusterItem ).remove (clusterItem .mClusterItem );
90+ }
91+ distanceToCluster .put (clusterItem , distance );
92+ cluster .add (clusterItem .mClusterItem );
93+ itemToCluster .put (clusterItem , cluster );
94+ }
6195 visitedCandidates .addAll (clusterItems );
62- result .add (candidate );
6396 }
6497 }
65- return result ;
66- }
6798
68- }
99+ // Now, apply the centroid logic from CentroidNonHierarchicalDistanceBasedAlgorithm
100+ Set <StaticCluster <T >> newClusters = new HashSet <>();
101+ for (Cluster <T > cluster : results ) {
102+ LatLng centroid = computeCentroid (cluster .getItems ());
103+ StaticCluster <T > newCluster = new StaticCluster <>(centroid );
104+ for (T item : cluster .getItems ()) {
105+ newCluster .add (item );
106+ }
107+ newClusters .add (newCluster );
108+ }
109+
110+ return newClusters ;
111+ }
112+ }
0 commit comments