Android Open Source - smartnavi Grid Marker Clusterer






From Project

Back to project page smartnavi.

License

The source code is released under:

Apache License

If you think the Android project smartnavi listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

package org.osmdroid.bonuspack.clustering;
/*from  ww w. j  a v  a  2s  .co  m*/
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.drawable.BitmapDrawable;
import android.support.v4.util.LongSparseArray;

import org.osmdroid.bonuspack.overlays.Marker;
import org.osmdroid.util.BoundingBoxE6;
import org.osmdroid.views.MapView;

import java.util.ArrayList;

/**
 * Grid-based Clustering algorithm: all markers inside the same cell belong to the same cluster.
 * The grid size is specified in screen pixels. <br/>
 * <p/>
 * TODO: check what happens with map rotation. <br/>
 * TODO: clustering is not perfectly stable: if you zoom in then out, the mapview lat/lon span may change a little bit,
 * potentially changing the grid positioning. <br/>
 * <p/>
 * Largely inspired from (open source) Google Maps Android utility library.
 *
 * @author M.Kergall
 * @see https://github.com/googlemaps/android-maps-utils
 */
public class GridMarkerClusterer extends MarkerClusterer {

    /**
     * cluster icon anchor
     */
    public float mAnchorU = Marker.ANCHOR_CENTER, mAnchorV = Marker.ANCHOR_CENTER;
    /**
     * anchor point to draw the number of markers inside the cluster icon
     */
    public float mTextAnchorU = Marker.ANCHOR_CENTER, mTextAnchorV = Marker.ANCHOR_CENTER;
    protected int mGridSize = 50; //in pixels
    protected Paint mTextPaint;

    public GridMarkerClusterer(Context ctx) {
        super(ctx);
        mTextPaint = new Paint();
        mTextPaint.setColor(Color.WHITE);
        mTextPaint.setTextSize(15.0f);
        mTextPaint.setFakeBoldText(true);
        mTextPaint.setTextAlign(Paint.Align.CENTER);
        mTextPaint.setAntiAlias(true);
    }

    /**
     * If you want to change the default text paint (color, size, font)
     */
    public Paint getTextPaint() {
        return mTextPaint;
    }

    /**
     * Change the size of the clustering grid, in pixels. Default is 50px.
     */
    public void setGridSize(int gridSize) {
        mGridSize = gridSize;
    }

    /**
     * Grid-based clustering algorithm
     */
    @Override
    public ArrayList<StaticCluster> clusterer(MapView mapView) {
        Rect mScreenRect = mapView.getIntrinsicScreenRect(null);

        BoundingBoxE6 bb = mapView.getBoundingBox();
        double latSpan = bb.getLatitudeSpanE6() * 1E-6;
        double lonSpan = bb.getLongitudeSpanE6() * 1E-6;
        //Log.d("ZOOM", "latSpan="+latSpan+"  lonSpan="+lonSpan);

        //convert grid size from pixels to degrees:
        double gridSizeX, gridSizeY;
        gridSizeX = lonSpan * (double) mGridSize / (double) (mScreenRect.right - mScreenRect.left);
        gridSizeY = latSpan * (double) mGridSize / (double) (mScreenRect.bottom - mScreenRect.top);

        int numCellsW = (int) (360.0f / gridSizeX);
        //Log.d("ZOOM", "zoomlevel="+mapView.getZoomLevel()+"  cells="+numCellsW);
        //Log.d("ZOOM", "gridSizeX="+gridSizeX+"  gridSizeY="+gridSizeY);

        ArrayList<StaticCluster> clusters = new ArrayList<StaticCluster>();
        LongSparseArray<StaticCluster> sparseArray = new LongSparseArray<StaticCluster>();
        for (Marker item : mItems) {
            //TODO - add 180 Degree to prevent negative values
            long gridX = (long) (item.getPosition().getLongitude() / gridSizeX);
            long gridY = (long) (item.getPosition().getLatitude() / gridSizeY);
            long coord = numCellsW * gridX + gridY;
            StaticCluster cluster = sparseArray.get(coord);
            //Log.d("ZOOM", "coord="+coord+" =>cluster:"+(cluster==null?"new":"add"));
            if (cluster == null) {
                //GeoPoint clusterCorner = new GeoPoint(gridSizeY*(double)gridY, gridSizeX*(double)gridX);
                cluster = new StaticCluster(item.getPosition() /*clusterCorner*/);
                sparseArray.put(coord, cluster);
                clusters.add(cluster);
            }
            cluster.add(item);
        }
        return clusters;
    }

    /**
     * Build the marker for a cluster.
     * Uses the cluster icon, and displays inside the number of markers it contains. <br/>
     * In the standard Google coordinate system for Marker icons: <br/>
     * - The cluster icon is anchored at mAnchorU, mAnchorV. <br/>
     * - The text showing the number of markers is anchored at mTextAnchorU, mTextAnchorV.
     * This text is centered horizontally and vertically.
     */
    @Override
    public Marker buildClusterMarker(StaticCluster cluster, MapView mapView) {
        Marker m = new Marker(mapView);
        m.setPosition(cluster.getPosition());
        m.setInfoWindow(null);
        m.setAnchor(mAnchorU, mAnchorV);
        Bitmap finalIcon = Bitmap.createBitmap(mClusterIcon.getWidth(), mClusterIcon.getHeight(), mClusterIcon.getConfig());
        Canvas iconCanvas = new Canvas(finalIcon);
        iconCanvas.drawBitmap(mClusterIcon, 0, 0, null);
        String text = "" + cluster.getSize();
        int textHeight = (int) (mTextPaint.descent() + mTextPaint.ascent());
        iconCanvas.drawText(text,
                mTextAnchorU * finalIcon.getWidth(),
                mTextAnchorV * finalIcon.getHeight() - textHeight / 2,
                mTextPaint);
        m.setIcon(new BitmapDrawable(mapView.getContext().getResources(), finalIcon));
        return m;
    }

    /**
     * Build clusters markers to be used at next draw
     */
    @Override
    public void renderer(ArrayList<StaticCluster> clusters, Canvas canvas, MapView mapView) {
        for (StaticCluster cluster : clusters) {
            if (cluster.getSize() == 1) {
                //cluster has only 1 marker => use it as it is:
                cluster.setMarker(cluster.getItem(0));
            } else {
                //only draw 1 Marker at Cluster center, displaying number of Markers contained
                Marker m = buildClusterMarker(cluster, mapView);
                cluster.setMarker(m);
            }
        }
    }

}




Java Source Code List

com.ilm.sandwich.BackgroundService.java
com.ilm.sandwich.BuildConfig.java
com.ilm.sandwich.Config.java
com.ilm.sandwich.GoogleMapActivity.java
com.ilm.sandwich.Info.java
com.ilm.sandwich.MySupportMapFragment.java
com.ilm.sandwich.OsmMapActivity.java
com.ilm.sandwich.Settings.java
com.ilm.sandwich.StartChooser.java
com.ilm.sandwich.TouchableWrapper.java
com.ilm.sandwich.tools.Core.java
com.ilm.sandwich.tools.HttpRequests.java
com.ilm.sandwich.tools.Locationer.java
com.ilm.sandwich.tools.MapDownload.java
com.ilm.sandwich.tools.MyItemizedOverlay.java
com.ilm.sandwich.tools.PlacesAutoComplete.java
com.ilm.sandwich.tools.PlacesTextSearch.java
com.ilm.sandwich.tools.Statistics.java
com.ilm.sandwich.tools.SuggestionsAdapter.java
org.osmdroid.bonuspack.BuildConfig.java
org.osmdroid.bonuspack.BuildConfig.java
org.osmdroid.bonuspack.cachemanager.CacheManager.java
org.osmdroid.bonuspack.clustering.GridMarkerClusterer.java
org.osmdroid.bonuspack.clustering.MarkerClusterer.java
org.osmdroid.bonuspack.clustering.StaticCluster.java
org.osmdroid.bonuspack.kml.ColorStyle.java
org.osmdroid.bonuspack.kml.IconStyle.java
org.osmdroid.bonuspack.kml.KmlDocument.java
org.osmdroid.bonuspack.kml.KmlFeature.java
org.osmdroid.bonuspack.kml.KmlFolder.java
org.osmdroid.bonuspack.kml.KmlGeometry.java
org.osmdroid.bonuspack.kml.KmlGroundOverlay.java
org.osmdroid.bonuspack.kml.KmlLineString.java
org.osmdroid.bonuspack.kml.KmlMultiGeometry.java
org.osmdroid.bonuspack.kml.KmlPlacemark.java
org.osmdroid.bonuspack.kml.KmlPoint.java
org.osmdroid.bonuspack.kml.KmlPolygon.java
org.osmdroid.bonuspack.kml.LineStyle.java
org.osmdroid.bonuspack.kml.Style.java
org.osmdroid.bonuspack.location.FlickrPOIProvider.java
org.osmdroid.bonuspack.location.GeoNamesPOIProvider.java
org.osmdroid.bonuspack.location.GeocoderGisgraphy.java
org.osmdroid.bonuspack.location.GeocoderNominatimOld.java
org.osmdroid.bonuspack.location.GeocoderNominatim.java
org.osmdroid.bonuspack.location.NominatimPOIProvider.java
org.osmdroid.bonuspack.location.POI.java
org.osmdroid.bonuspack.location.PicasaPOIProvider.java
org.osmdroid.bonuspack.mapsforge.GenericMapView.java
org.osmdroid.bonuspack.mapsforge.MapsForgeTileModuleProvider.java
org.osmdroid.bonuspack.mapsforge.MapsForgeTileProvider.java
org.osmdroid.bonuspack.mapsforge.MapsForgeTileSource.java
org.osmdroid.bonuspack.overlays.DefaultInfoWindow.java
org.osmdroid.bonuspack.overlays.ExtendedOverlayItem.java
org.osmdroid.bonuspack.overlays.FolderOverlay.java
org.osmdroid.bonuspack.overlays.GroundOverlay.java
org.osmdroid.bonuspack.overlays.InfoWindow.java
org.osmdroid.bonuspack.overlays.ItemizedOverlayWithBubble.java
org.osmdroid.bonuspack.overlays.MapEventsOverlay.java
org.osmdroid.bonuspack.overlays.MapEventsReceiver.java
org.osmdroid.bonuspack.overlays.MarkerInfoWindow.java
org.osmdroid.bonuspack.overlays.Marker.java
org.osmdroid.bonuspack.overlays.Polygon.java
org.osmdroid.bonuspack.overlays.Polyline.java
org.osmdroid.bonuspack.routing.GoogleRoadManager.java
org.osmdroid.bonuspack.routing.MapQuestRoadManager.java
org.osmdroid.bonuspack.routing.OSRMRoadManager.java
org.osmdroid.bonuspack.routing.RoadLeg.java
org.osmdroid.bonuspack.routing.RoadManager.java
org.osmdroid.bonuspack.routing.RoadNode.java
org.osmdroid.bonuspack.routing.Road.java
org.osmdroid.bonuspack.utils.BonusPackHelper.java
org.osmdroid.bonuspack.utils.DouglasPeuckerReducer.java
org.osmdroid.bonuspack.utils.HttpConnection.java
org.osmdroid.bonuspack.utils.PolylineEncoder.java
org.osmdroid.bonuspack.utils.WebImageCache.java