com.google.maps.android.clustering.Cluster Java Examples

The following examples show how to use com.google.maps.android.clustering.Cluster. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: PreCachingAlgorithmDecorator.java    From android-maps-utils with Apache License 2.0 6 votes vote down vote up
private Set<? extends Cluster<T>> getClustersInternal(int discreteZoom) {
    Set<? extends Cluster<T>> results;
    mCacheLock.readLock().lock();
    results = mCache.get(discreteZoom);
    mCacheLock.readLock().unlock();

    if (results == null) {
        mCacheLock.writeLock().lock();
        results = mCache.get(discreteZoom);
        if (results == null) {
            results = mAlgorithm.getClusters(discreteZoom);
            mCache.put(discreteZoom, results);
        }
        mCacheLock.writeLock().unlock();
    }
    return results;
}
 
Example #2
Source File: CustomMarkerClusteringDemoActivity.java    From android-maps-utils with Apache License 2.0 6 votes vote down vote up
/**
 * Get a descriptor for multiple people (a cluster) to be used for a marker icon. Note: this
 * method runs on the UI thread. Don't spend too much time in here (like in this example).
 *
 * @param cluster cluster to draw a BitmapDescriptor for
 * @return a BitmapDescriptor representing a cluster
 */
private BitmapDescriptor getClusterIcon(Cluster<Person> cluster) {
    List<Drawable> profilePhotos = new ArrayList<>(Math.min(4, cluster.getSize()));
    int width = mDimension;
    int height = mDimension;

    for (Person p : cluster.getItems()) {
        // Draw 4 at most.
        if (profilePhotos.size() == 4) break;
        Drawable drawable = getResources().getDrawable(p.profilePhoto);
        drawable.setBounds(0, 0, width, height);
        profilePhotos.add(drawable);
    }
    MultiDrawable multiDrawable = new MultiDrawable(profilePhotos);
    multiDrawable.setBounds(0, 0, width, height);

    mClusterImageView.setImageDrawable(multiDrawable);
    Bitmap icon = mClusterIconGenerator.makeIcon(String.valueOf(cluster.getSize()));
    return BitmapDescriptorFactory.fromBitmap(icon);
}
 
Example #3
Source File: GridBasedAlgorithm.java    From android-maps-utils with Apache License 2.0 6 votes vote down vote up
@Override
public Set<? extends Cluster<T>> getClusters(float zoom) {
    long numCells = (long) Math.ceil(256 * Math.pow(2, zoom) / mGridSize);
    SphericalMercatorProjection proj = new SphericalMercatorProjection(numCells);

    HashSet<Cluster<T>> clusters = new HashSet<Cluster<T>>();
    LongSparseArray<StaticCluster<T>> sparseArray = new LongSparseArray<StaticCluster<T>>();

    synchronized (mItems) {
        for (T item : mItems) {
            Point p = proj.toPoint(item.getPosition());

            long coord = getCoord(numCells, p.x, p.y);

            StaticCluster<T> cluster = sparseArray.get(coord);
            if (cluster == null) {
                cluster = new StaticCluster<T>(proj.toLatLng(new Point(Math.floor(p.x) + .5, Math.floor(p.y) + .5)));
                sparseArray.put(coord, cluster);
                clusters.add(cluster);
            }
            cluster.add(item);
        }
    }

    return clusters;
}
 
Example #4
Source File: CustomMarkerClusteringDemoActivity.java    From android-maps-utils with Apache License 2.0 6 votes vote down vote up
@Override
public boolean onClusterClick(Cluster<Person> cluster) {
    // Show a toast with some info when the cluster is clicked.
    String firstName = cluster.getItems().iterator().next().name;
    Toast.makeText(this, cluster.getSize() + " (including " + firstName + ")", Toast.LENGTH_SHORT).show();

    // Zoom in the cluster. Need to create LatLngBounds and including all the cluster items
    // inside of bounds, then animate to center of the bounds.

    // Create the builder to collect all essential cluster items for the bounds.
    LatLngBounds.Builder builder = LatLngBounds.builder();
    for (ClusterItem item : cluster.getItems()) {
        builder.include(item.getPosition());
    }
    // Get the LatLngBounds
    final LatLngBounds bounds = builder.build();

    // Animate camera to the bounds
    try {
        getMap().animateCamera(CameraUpdateFactory.newLatLngBounds(bounds, 100));
    } catch (Exception e) {
        e.printStackTrace();
    }

    return true;
}
 
Example #5
Source File: PlacesFragment.java    From narrate-android with Apache License 2.0 5 votes vote down vote up
@Override
public boolean onClusterClick(Cluster<EntryMarker> entryMarkerCluster) {
    Log.d("", "onClusterClick()");
    ArrayList<Entry> entries = new ArrayList<>();

    for ( EntryMarker marker : entryMarkerCluster.getItems())
        entries.add(marker.entry);

    mListDialog.setData(entries);
    mListDialog.show(getFragmentManager(), "EntryListDialogFragment");

    return true;
}
 
Example #6
Source File: PreCachingAlgorithmDecorator.java    From android-maps-utils with Apache License 2.0 5 votes vote down vote up
@Override
public Set<? extends Cluster<T>> getClusters(float zoom) {
    int discreteZoom = (int) zoom;
    Set<? extends Cluster<T>> results = getClustersInternal(discreteZoom);
    // TODO: Check if requests are already in-flight.
    if (mCache.get(discreteZoom + 1) == null) {
        // It seems this cannot use a thread pool due to thread locking issues (#660)
        new Thread(new PrecacheRunnable(discreteZoom + 1)).start();
    }
    if (mCache.get(discreteZoom - 1) == null) {
        // It seems this cannot use a thread pool due to thread locking issues (#660)
        new Thread(new PrecacheRunnable(discreteZoom - 1)).start();
    }
    return results;
}
 
Example #7
Source File: DefaultClusterRenderer.java    From android-maps-utils with Apache License 2.0 5 votes vote down vote up
/**
 * Gets a BitmapDescriptor for the given cluster that contains a rough count of the number of
 * items. Used to set the cluster marker icon in the default implementations of
 * {@link #onBeforeClusterRendered(Cluster, MarkerOptions)} and
 * {@link #onClusterUpdated(Cluster, Marker)}.
 *
 * @param cluster cluster to get BitmapDescriptor for
 * @return a BitmapDescriptor for the marker icon for the given cluster that contains a rough
 * count of the number of items.
 */
@NonNull
protected BitmapDescriptor getDescriptorForCluster(@NonNull Cluster<T> cluster) {
    int bucket = getBucket(cluster);
    BitmapDescriptor descriptor = mIcons.get(bucket);
    if (descriptor == null) {
        mColoredCircleBackground.getPaint().setColor(getColor(bucket));
        descriptor = BitmapDescriptorFactory.fromBitmap(mIconGenerator.makeIcon(getClusterText(bucket)));
        mIcons.put(bucket, descriptor);
    }
    return descriptor;
}
 
Example #8
Source File: DefaultClusterRenderer.java    From android-maps-utils with Apache License 2.0 5 votes vote down vote up
/**
 * Gets the "bucket" for a particular cluster. By default, uses the number of points within the
 * cluster, bucketed to some set points.
 */
protected int getBucket(@NonNull Cluster<T> cluster) {
    int size = cluster.getSize();
    if (size <= BUCKETS[0]) {
        return size;
    }
    for (int i = 0; i < BUCKETS.length - 1; i++) {
        if (size < BUCKETS[i + 1]) {
            return BUCKETS[i];
        }
    }
    return BUCKETS[BUCKETS.length - 1];
}
 
Example #9
Source File: DefaultClusterRenderer.java    From android-maps-utils with Apache License 2.0 5 votes vote down vote up
public void queue(Set<? extends Cluster<T>> clusters) {
    synchronized (this) {
        // Overwrite any pending cluster tasks - we don't care about intermediate states.
        mNextClusters = new RenderTask(clusters);
    }
    sendEmptyMessage(RUN_TASK);
}
 
Example #10
Source File: DefaultClusterRenderer.java    From android-maps-utils with Apache License 2.0 4 votes vote down vote up
@Override
public void onClustersChanged(Set<? extends Cluster<T>> clusters) {
    mViewModifier.queue(clusters);
}
 
Example #11
Source File: ScreenBasedAlgorithmAdapter.java    From android-maps-utils with Apache License 2.0 4 votes vote down vote up
@Override
public Set<? extends Cluster<T>> getClusters(float zoom) {
    return mAlgorithm.getClusters(zoom);
}
 
Example #12
Source File: NonHierarchicalDistanceBasedAlgorithm.java    From android-maps-utils with Apache License 2.0 4 votes vote down vote up
@Override
public Set<? extends Cluster<T>> getClusters(float zoom) {
    final int discreteZoom = (int) zoom;

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

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

    synchronized (mQuadTree) {
        for (QuadItem<T> candidate : getClusteringItems(mQuadTree, zoom)) {
            if (visitedCandidates.contains(candidate)) {
                // Candidate is already part of another cluster.
                continue;
            }

            Bounds searchBounds = createBoundsFromSpan(candidate.getPoint(), zoomSpecificSpan);
            Collection<QuadItem<T>> clusterItems;
            clusterItems = mQuadTree.search(searchBounds);
            if (clusterItems.size() == 1) {
                // 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<>(candidate.mClusterItem.getPosition());
            results.add(cluster);

            for (QuadItem<T> clusterItem : clusterItems) {
                Double existingDistance = distanceToCluster.get(clusterItem);
                double distance = distanceSquared(clusterItem.getPoint(), candidate.getPoint());
                if (existingDistance != null) {
                    // Item already belongs to another cluster. Check if it's closer to this cluster.
                    if (existingDistance < distance) {
                        continue;
                    }
                    // Move item to the closer cluster.
                    itemToCluster.get(clusterItem).remove(clusterItem.mClusterItem);
                }
                distanceToCluster.put(clusterItem, distance);
                cluster.add(clusterItem.mClusterItem);
                itemToCluster.put(clusterItem, cluster);
            }
            visitedCandidates.addAll(clusterItems);
        }
    }
    return results;
}
 
Example #13
Source File: DetailMarkerRenderer.java    From animation-samples with Apache License 2.0 4 votes vote down vote up
@Override
protected boolean shouldRenderAsCluster(Cluster<Detail> cluster) {
    return cluster.getSize() > MIN_CLUSTER_SIZE;
}
 
Example #14
Source File: DefaultClusterRenderer.java    From android-maps-utils with Apache License 2.0 4 votes vote down vote up
private RenderTask(Set<? extends Cluster<T>> clusters) {
    this.clusters = clusters;
}
 
Example #15
Source File: CustomMarkerClusteringDemoActivity.java    From android-maps-utils with Apache License 2.0 4 votes vote down vote up
@Override
public void onClusterInfoWindowClick(Cluster<Person> cluster) {
    // Does nothing, but you could go to a list of the users.
}
 
Example #16
Source File: CustomMarkerClusteringDemoActivity.java    From android-maps-utils with Apache License 2.0 4 votes vote down vote up
@Override
protected boolean shouldRenderAsCluster(Cluster cluster) {
    // Always render clusters.
    return cluster.getSize() > 1;
}
 
Example #17
Source File: CustomMarkerClusteringDemoActivity.java    From android-maps-utils with Apache License 2.0 4 votes vote down vote up
@Override
protected void onClusterUpdated(@NonNull Cluster<Person> cluster, Marker marker) {
    // Same implementation as onBeforeClusterRendered() (to update cached markers)
    marker.setIcon(getClusterIcon(cluster));
}
 
Example #18
Source File: CustomMarkerClusteringDemoActivity.java    From android-maps-utils with Apache License 2.0 4 votes vote down vote up
@Override
protected void onBeforeClusterRendered(@NonNull Cluster<Person> cluster, MarkerOptions markerOptions) {
    // Draw multiple people.
    // Note: this method runs on the UI thread. Don't spend too much time in here (like in this example).
    markerOptions.icon(getClusterIcon(cluster));
}
 
Example #19
Source File: MainActivity.java    From ExamplesAndroid with Apache License 2.0 4 votes vote down vote up
@Override
public void onClusterInfoWindowClick(Cluster cluster) {
    Toast.makeText(MainActivity.this,"asd",Toast.LENGTH_SHORT).show();
}
 
Example #20
Source File: DefaultClusterRenderer.java    From android-maps-utils with Apache License 2.0 2 votes vote down vote up
/**
 * Determine whether the cluster should be rendered as individual markers or a cluster.
 * @param cluster cluster to examine for rendering
 * @return true if the provided cluster should be rendered as a single marker on the map, false
 * if the items within this cluster should be rendered as individual markers instead.
 */
protected boolean shouldRenderAsCluster(@NonNull Cluster<T> cluster) {
    return cluster.getSize() >= mMinClusterSize;
}
 
Example #21
Source File: DefaultClusterRenderer.java    From android-maps-utils with Apache License 2.0 2 votes vote down vote up
/**
 * Called before the marker for a Cluster is added to the map.
 * The default implementation draws a circle with a rough count of the number of items.
 *
 * The first time {@link ClusterManager#cluster()} is invoked on a set of items
 * {@link #onBeforeClusterRendered(Cluster, MarkerOptions)} will be called and
 * {@link #onClusterUpdated(Cluster, Marker)} will not be called. If an item is removed and
 * re-added (or updated) and {@link ClusterManager#cluster()} is invoked
 * again, then {@link #onClusterUpdated(Cluster, Marker)} will be called and
 * {@link #onBeforeClusterRendered(Cluster, MarkerOptions)} will not be called.
 *
 * @param cluster cluster to be rendered
 * @param markerOptions markerOptions representing the provided cluster
 */
protected void onBeforeClusterRendered(@NonNull Cluster<T> cluster, @NonNull MarkerOptions markerOptions) {
    // TODO: consider adding anchor(.5, .5) (Individual markers will overlap more often)
    markerOptions.icon(getDescriptorForCluster(cluster));
}
 
Example #22
Source File: ClusterRenderer.java    From android-maps-utils with Apache License 2.0 2 votes vote down vote up
/**
 * Called when the view needs to be updated because new clusters need to be displayed.
 *
 * @param clusters the clusters to be displayed.
 */
void onClustersChanged(Set<? extends Cluster<T>> clusters);
 
Example #23
Source File: DefaultClusterRenderer.java    From android-maps-utils with Apache License 2.0 2 votes vote down vote up
/**
 * Called after the marker for a Cluster has been added to the map.
 *
 * @param cluster the cluster that was just added to the map
 * @param marker the marker representing the cluster that was just added to the map
 */
protected void onClusterRendered(@NonNull Cluster<T> cluster, @NonNull Marker marker) {
}
 
Example #24
Source File: DefaultClusterRenderer.java    From android-maps-utils with Apache License 2.0 2 votes vote down vote up
/**
 * Called when a cached marker for a Cluster already exists on the map so the marker may
 * be updated to the latest cluster values. Default implementation updated the icon with a
 * circle with a rough count of the number of items. Note that the contents of the cluster may
 * not have changed since the cached marker was created - implementations of this method are
 * responsible for checking if something changed (if that matters to the implementation).
 *
 * The first time {@link ClusterManager#cluster()} is invoked on a set of items
 * {@link #onBeforeClusterRendered(Cluster, MarkerOptions)} will be called and
 * {@link #onClusterUpdated(Cluster, Marker)} will not be called. If an item is removed and
 * re-added (or updated) and {@link ClusterManager#cluster()} is invoked
 * again, then {@link #onClusterUpdated(Cluster, Marker)} will be called and
 * {@link #onBeforeClusterRendered(Cluster, MarkerOptions)} will not be called.
 *
 * @param cluster cluster being updated
 * @param marker cached marker that contains a potentially previous state of the cluster
 */
protected void onClusterUpdated(@NonNull Cluster<T> cluster, @NonNull Marker marker) {
    // TODO: consider adding anchor(.5, .5) (Individual markers will overlap more often)
    marker.setIcon(getDescriptorForCluster(cluster));
}
 
Example #25
Source File: DefaultClusterRenderer.java    From android-maps-utils with Apache License 2.0 2 votes vote down vote up
/**
 * Get the marker from a Cluster
 *
 * @param cluster which you will obtain its marker
 * @return a marker from a cluster or null if it does not exists
 */
public Marker getMarker(Cluster<T> cluster) {
    return mClusterMarkerCache.get(cluster);
}
 
Example #26
Source File: DefaultClusterRenderer.java    From android-maps-utils with Apache License 2.0 2 votes vote down vote up
/**
 * Get the Cluster from a marker
 *
 * @param marker which you will obtain its Cluster
 * @return a Cluster from a marker or null if it does not exists
 */
public Cluster<T> getCluster(Marker marker) {
    return mClusterMarkerCache.get(marker);
}
 
Example #27
Source File: DefaultClusterRenderer.java    From android-maps-utils with Apache License 2.0 2 votes vote down vote up
/**
 * @param c            the cluster to render.
 * @param markersAdded a collection of markers to append any created markers.
 * @param animateFrom  the location to animate the markerWithPosition from, or null if no
 *                     animation is required.
 */
public CreateMarkerTask(Cluster<T> c, Set<MarkerWithPosition> markersAdded, LatLng animateFrom) {
    this.cluster = c;
    this.newMarkers = markersAdded;
    this.animateFrom = animateFrom;
}
 
Example #28
Source File: Algorithm.java    From android-maps-utils with Apache License 2.0 votes vote down vote up
Set<? extends Cluster<T>> getClusters(float zoom);