Skip to content

Commit

Permalink
Clean-up.
Browse files Browse the repository at this point in the history
Re-name "SimpleDistanceBased" to "NonHierarchicalDistanceBased"
  • Loading branch information
broady committed Oct 2, 2013
1 parent ffa92c4 commit 8f509d4
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 33 deletions.
18 changes: 6 additions & 12 deletions library/src/com/google/maps/android/clustering/ClusterManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import com.google.maps.android.MarkerManager;
import com.google.maps.android.clustering.algo.Algorithm;
import com.google.maps.android.clustering.algo.PreCachingDecorator;
import com.google.maps.android.clustering.algo.SimpleDistanceBased;
import com.google.maps.android.clustering.algo.NonHierarchicalDistanceBased;
import com.google.maps.android.clustering.view.ClusterView;
import com.google.maps.android.clustering.view.DefaultClusterView;

Expand All @@ -20,7 +20,6 @@
*/
public class ClusterManager<T extends ClusterItem> implements GoogleMap.OnCameraChangeListener {
private static final String TAG = ClusterManager.class.getName();
private static final boolean ASYNC = true;

private final MarkerManager mMarkerManager;
private final MarkerManager.Collection mMarkers;
Expand All @@ -46,7 +45,7 @@ public ClusterManager(Context context, GoogleMap map, MarkerManager markerManage
mClusterMarkers = markerManager.newCollection();
mMarkers = markerManager.newCollection();
mView = new DefaultClusterView<T>(context, map, this);
setAlgorithm(new SimpleDistanceBased<T>());
setAlgorithm(new NonHierarchicalDistanceBased<T>());
mClusterTask = new ClusterTask();
}

Expand Down Expand Up @@ -113,12 +112,7 @@ public void removeItem(T item) {
public void cluster() {
mClusterTask.cancel(true);
mClusterTask = new ClusterTask();
if (ASYNC) {
mClusterTask.execute(mMap.getCameraPosition().zoom);
} else {
Set<? extends Cluster<T>> clusters = mClusterTask.doInBackground(mMap.getCameraPosition().zoom);
mClusterTask.onPostExecute(clusters);
}
mClusterTask.execute(mMap.getCameraPosition().zoom);
}

/**
Expand All @@ -141,7 +135,7 @@ public void onCameraChange(CameraPosition cameraPosition) {

/**
* Runs the clustering algorithm in a background thread, then re-paints when results come
* back..
* back.
*/
private class ClusterTask extends AsyncTask<Float, Void, Set<? extends Cluster<T>>> {
@Override
Expand All @@ -157,12 +151,12 @@ protected void onPostExecute(Set<? extends Cluster<T>> clusters) {
}

public void setOnClusterClickListener(OnClusterClickListener<T> listener) {
this.mOnClusterClickListener = listener;
mOnClusterClickListener = listener;
mView.setOnClusterClickListener(listener);
}

public void setOnClusterItemClickListener(OnClusterItemClickListener<T> listener) {
this.mOnClusterItemClickListener = listener;
mOnClusterItemClickListener = listener;
mView.setOnClusterItemClickListener(listener);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,19 +19,20 @@
import java.util.Set;

/**
* A simple clustering algorithm.
* A simple clustering algorithm with O(nlog n) performance. Resulting clusters are not
* hierarchical.
* <p>
* High level algorithm:
* 1. Iterate over items in the order they were added (candidate clusters).<br>
* 2. Create a cluster with the center of the item. <br>
* 3. Add all items that are within a certain distance to the cluster. <br>
* 4. Remove those items from the list of candidate clusters.
* 4. Move any items out of an existing cluster if they are closer to another cluster. <br>
* 5. Remove those items from the list of candidate clusters.
* <p/>
* This means that items that were added first will tend to have more items in their cluster.
* Clusters have the center of the first element (not the centroid of the items within it).
*/
public class SimpleDistanceBased<T extends ClusterItem> implements Algorithm<T> {
public static final int MAX_DISTANCE_AT_ZOOM = 100;
public class NonHierarchicalDistanceBased<T extends ClusterItem> implements Algorithm<T> {
public static final int MAX_DISTANCE_AT_ZOOM = 100; // essentially 100 dp.

private final LinkedHashSet<QuadItem<T>> mItems = new LinkedHashSet<QuadItem<T>>();
private final PointQuadTree<QuadItem<T>> mQuadTree = new PointQuadTree<QuadItem<T>>(0, 1, 0, 1);
Expand Down Expand Up @@ -60,30 +61,33 @@ public void clearItems() {
@Override
public void removeItem(T item) {
// TODO: delegate QuadItem#hashCode and QuadItem#equals to its item.
throw new UnsupportedOperationException("SimpleDistanceBased.remove not implemented");
throw new UnsupportedOperationException("NonHierarchicalDistanceBased.remove not implemented");
}

@Override
public Set<? extends Cluster<T>> getClusters(double zoom) {
int discreteZoom = (int) zoom;
final int discreteZoom = (int) zoom;

double zoomSpecificSpan = MAX_DISTANCE_AT_ZOOM / Math.pow(2, discreteZoom) / 256;
final double zoomSpecificSpan = MAX_DISTANCE_AT_ZOOM / Math.pow(2, discreteZoom) / 256;

Set<QuadItem<T>> visitedCandidates = new HashSet<QuadItem<T>>();
HashSet<Cluster<T>> results = new HashSet<Cluster<T>>();
Map<QuadItem<T>, Double> distanceToCluster = new HashMap<QuadItem<T>, Double>();
Map<QuadItem<T>, StaticCluster<T>> itemToCluster = new HashMap<QuadItem<T>, StaticCluster<T>>();
final Set<QuadItem<T>> visitedCandidates = new HashSet<QuadItem<T>>();
final Set<Cluster<T>> results = new HashSet<Cluster<T>>();
final Map<QuadItem<T>, Double> distanceToCluster = new HashMap<QuadItem<T>, Double>();
final Map<QuadItem<T>, StaticCluster<T>> itemToCluster = new HashMap<QuadItem<T>, StaticCluster<T>>();

// TODO: Investigate use of ConcurrentSkipListSet.
for (QuadItem<T> candidate : mItems) {
if (visitedCandidates.contains(candidate)) continue;
if (visitedCandidates.contains(candidate)) {
// Candidate is already part of another cluster.
continue;
}

Bounds searchBounds = createBoundsFromSpan(candidate.getPoint(), zoomSpecificSpan);
Collection<QuadItem<T>> clusterItems = mQuadTree.search(searchBounds);
if (clusterItems.size() == 1) {
// Only the current market is in range.
// Only the current marker is in range. Just add the single item to the results.
results.add(candidate);
visitedCandidates.add(candidate);
distanceToCluster.put(candidate, 0d);
continue;
}
StaticCluster<T> cluster = new StaticCluster<T>(candidate.mClusterItem.getPosition());
Expand All @@ -97,6 +101,7 @@ public Set<? extends Cluster<T>> getClusters(double zoom) {
if (existingDistance < distance) {
continue;
}
// Move item to the closer cluster.
itemToCluster.get(clusterItem).remove(clusterItem.mClusterItem);
}
distanceToCluster.put(clusterItem, distance);
Expand All @@ -122,6 +127,8 @@ private double distanceSquared(Point a, Point b) {
}

private Bounds createBoundsFromSpan(Point p, double span) {
// TODO: Use a span that takes into account the visual size of the marker, not just its
// LatLng.
double halfSpan = span / 2;
return new Bounds(
p.x - halfSpan, p.x + halfSpan,
Expand Down
11 changes: 5 additions & 6 deletions library/src/com/google/maps/android/quadtree/PointQuadTree.java
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@
* See http://en.wikipedia.org/wiki/Quadtree for details on the data structure.
* This class is not thread safe.
*/
@Deprecated // Experimental.
public class PointQuadTree<T extends PointQuadTree.Item> {
public interface Item {
Point getPoint();
Expand Down Expand Up @@ -62,7 +61,7 @@ public interface Item {
/**
* Child quads.
*/
private PointQuadTree[] mChildren = null;
private PointQuadTree<T>[] mChildren = null;

/**
* Creates a new quad tree with specified bounds.
Expand Down Expand Up @@ -125,10 +124,10 @@ private boolean insert(double x, double y, T item) {
*/
private void split() {
mChildren = new PointQuadTree[]{
new PointQuadTree(mBounds.minX, mBounds.midX, mBounds.minY, mBounds.midY, mDepth + 1),
new PointQuadTree(mBounds.midX, mBounds.maxX, mBounds.minY, mBounds.midY, mDepth + 1),
new PointQuadTree(mBounds.minX, mBounds.midX, mBounds.midY, mBounds.maxY, mDepth + 1),
new PointQuadTree(mBounds.midX, mBounds.maxX, mBounds.midY, mBounds.maxY, mDepth + 1)
new PointQuadTree<T>(mBounds.minX, mBounds.midX, mBounds.minY, mBounds.midY, mDepth + 1),
new PointQuadTree<T>(mBounds.midX, mBounds.maxX, mBounds.minY, mBounds.midY, mDepth + 1),
new PointQuadTree<T>(mBounds.minX, mBounds.midX, mBounds.midY, mBounds.maxY, mDepth + 1),
new PointQuadTree<T>(mBounds.midX, mBounds.maxX, mBounds.midY, mBounds.maxY, mDepth + 1)
};

List<T> items = mItems;
Expand Down

0 comments on commit 8f509d4

Please sign in to comment.