Android Maps Point Clustering

前端 未结 7 1659
春和景丽
春和景丽 2020-11-29 17:18

Is there any code for Point Clustering in android? How can i load thousand pinpoint without having performance issues?

7条回答
  •  执念已碎
    2020-11-29 17:48

    I have reworked in the above code and controlled the no of overlay icon in the map view and separated the group and single point.

    My Code:

    MMapView.java

    import java.util.ArrayList;
    import java.util.List;
    
    import android.content.Context;
    import android.graphics.BitmapFactory;
    import android.graphics.Canvas;
    import android.graphics.drawable.BitmapDrawable;
    import android.graphics.drawable.Drawable;
    import android.util.AttributeSet;
    
    import com.google.android.maps.GeoPoint;
    import com.google.android.maps.MapView;
    import com.google.android.maps.Overlay;
    import com.impiger.maphighlight.R;
    
    //Reference - http://stackoverflow.com/questions/7447350/android-maps-point-clustering
    
    public class MMapView extends MapView {
    
        private static final String TAG = MMapView.class.getSimpleName();
        private static final int MAX_VISIBLE_POINTS = 1;
        private PMapViewOverlay itemizedOverlay;
        private List mapOverlays;
        private List geoPoints = new ArrayList();
        private BitmapDrawable drawable;
        private Context context;
        private Drawable emptyDrawable;
        private int count;
        private int oldZoomLevel = -1;
        ArrayList mOverlays;
    
        public MMapView(Context context, AttributeSet attrs) {
            super(context, attrs);
            this.context = context;
            mapOverlays = getOverlays();
            drawable = new BitmapDrawable(
                    BitmapFactory.decodeResource(getResources(),
                            R.drawable.blue_65));
            itemizedOverlay = new PMapViewOverlay(drawable, context);
            emptyDrawable = context.getResources().getDrawable(
                    R.drawable.marker);
            mOverlays = new ArrayList();
            init();
        }
    
        private GeoPoint getPoint(double lat, double lon) {
            return (new GeoPoint((int) (lat * 1000000.0), (int) (lon * 1000000.0)));
        }
    
        private void init(){
            putPoint(11, 77, true);
            putPoint(11.5, 76.6, false);
            putPoint(10.98383, 77.32112, false);
            putPoint(10, 77, false);
            putPoint(11, 78, false);
            putPoint(11, 77.5, false);
            putPoint(10.5, 77, false);
            putPoint(12, 77, false);
            putPoint(11.77, 77.11, false);
            putPoint(12.1, 78.33, false);
            putPoint(11.83, 77.293, false);
            putPoint(11.12, 77, false);
            putPoint(11.13, 77, false);
            putPoint(11.14, 77, false);
            putPoint(11.15, 77, false);
            putPoint(11.12, 77.2, false);
            putPoint(11.13, 77.34, false);
            putPoint(11.14, 77.4, false);
            putPoint(11.15, 77.1977, false);
            putPoint(11.347373, 77.5627783, true);
            putPoint(11.53454, 76.696645, false);
            putPoint(10.19282, 77.847373, false);
            putPoint(10.4728, 76.39388, false);
            putPoint(11.4563, 78, false);
            putPoint(11.73663, 77.5927, false);
            putPoint(10.5674, 77.6762, false);
            putPoint(12.02882, 77.672782, false);
            putPoint(11.7767876, 77.1123423, false);
            putPoint(12.18332, 78.33, false);
            putPoint(11.8393883, 77.293938783, false);
            putPoint(11.388323, 77.9478723, false);
            putPoint(11.1345645, 77.97723, false);
            putPoint(11.1423423, 77.73774, false);
            putPoint(11.1552, 77.793783, false);
            putPoint(11.127895434, 77.2944554, false);
            putPoint(11.13232345, 77.342234, false);
            putPoint(11.14456573, 77.4, false);
            putPoint(11.159765, 77.1977, false);
        }
    
    
        public void putPoint(double lat, double lon, boolean isMyPosition) {
            int latitude = (int) (lat * 1E6);
            int longitude = (int) (lon * 1E6);
            GeoPoint geo = new GeoPoint(latitude, longitude);
            geo = getPoint(lat, lon);
    
            /*
             * Remove doubles
             */
            Boolean alreadyExists = false;
            for (GeoPoint item : geoPoints) {
                if (item.getLatitudeE6() == geo.getLatitudeE6()
                        && item.getLongitudeE6() == geo.getLongitudeE6()) {
                    alreadyExists = true;
                }
            }
            if (!alreadyExists) {
                geoPoints.add(geo);
            }
        }
    
        /*
         * Place the overlays
         */
        public void placeOverlays() {
            itemizedOverlay.removeAllOverlays();
            getOverlays().clear();
            mapOverlays.clear();
            mOverlays.clear();
            int i = 1;
            for (GeoPoint item : geoPoints) {
                OverlayItemExtended overlayitem = new OverlayItemExtended(item,
                        "title "+i, "snippet");
                // Here is where the magic happens
                addOverlayItemClustered(overlayitem, this,
                        geoPoints.size());
                i++;
            }
    
            for(int j=0;j 0){
                        itemizedOverlay = new PMapViewOverlay(drawable, context);
                        itemizedOverlay.addOverlayItem(overlayItem);
                    }else{
                        itemizedOverlay = new PMapViewOverlay(emptyDrawable, context);
                        itemizedOverlay.addOverlayItem(overlayItem);
                    }
                    mapOverlays.add(itemizedOverlay);
                }
            }
        }
    
        /*
         * Update the points at panned / zoom etc
         */
        public void dispatchDraw(Canvas canvas) {
            super.dispatchDraw(canvas);
            if (getZoomLevel() != oldZoomLevel) {
                placeOverlays();
            }
            oldZoomLevel = getZoomLevel();
        }
    
        public void addOverlayItemClustered(OverlayItemExtended thisOverlay,
                MapView mapView, int totalPoints) {
            for (OverlayItemExtended otherOverlay : mOverlays) {
                /*
                 * Thresshold for the clustering
                 */
                /*
                 * Zoom level >15 don't cluster If less than Max_Visible_points
                 * don't cluster
                 */
                if (mapView.getZoomLevel() >= 14
                        || (MAX_VISIBLE_POINTS > totalPoints)
                        && PointCluster.getOverLayItemDistance(thisOverlay,
                                otherOverlay, mapView) > 60) {
                    mOverlays.add(thisOverlay);
                    return;
                }
                if (PointCluster.getOverLayItemDistance(thisOverlay, otherOverlay,
                        mapView) < 90 && !thisOverlay.isClustered) {
                    // Here is where the clustering actually happens
                    if (otherOverlay.isMaster) {
                        thisOverlay.isMaster = false;
                        // otherOverlay.isMaster = false;
                        thisOverlay.isClustered = true;
                        otherOverlay.isClustered = true;
                        otherOverlay.slaves.push(thisOverlay);
                        thisOverlay.parent = otherOverlay;
                    } else if (PointCluster.getOverLayItemDistance(thisOverlay,
                            otherOverlay.parent, mapView) < 90
                            && otherOverlay.isClustered) {
                        thisOverlay.isMaster = false;
                        thisOverlay.isClustered = true;
                        thisOverlay.parent = otherOverlay.parent;
                        otherOverlay.parent.slaves.push(thisOverlay);
                    }
                }
            }
            mOverlays.add(thisOverlay);
        }
    }
    

    OverlayItemExtended.java

    import java.util.Stack;
    
    import com.google.android.maps.GeoPoint;
    import com.google.android.maps.OverlayItem;
    
    public class OverlayItemExtended extends OverlayItem {
    
        public boolean isClustered = false;
        public boolean isMaster = true;
        public boolean isMe = false;
        public OverlayItemExtended parent;
        public Stack slaves = new Stack();
    
        public OverlayItemExtended(GeoPoint point, String title, String snippet) {
            super(point, title, snippet);
        }
    }
    

    PMapViewOverlay.java

    import java.util.ArrayList;
    
    import android.content.Context;
    import android.graphics.Canvas;
    import android.graphics.Color;
    import android.graphics.Paint;
    import android.graphics.Point;
    import android.graphics.drawable.Drawable;
    import android.widget.Toast;
    
    import com.google.android.maps.GeoPoint;
    import com.google.android.maps.ItemizedOverlay;
    import com.google.android.maps.MapView;
    
    @SuppressWarnings("rawtypes")
    public class PMapViewOverlay extends ItemizedOverlay {
    
        private static final String TAG = PMapViewOverlay.class.getSimpleName();
        private Context context;
        private ArrayList mOverlays;
    
        public PMapViewOverlay(Drawable defaultMarker, Context context) {
            super(boundCenterBottom(defaultMarker));
            this.context = context;
            mOverlays = new ArrayList();
    
            paint.setTextAlign(Paint.Align.CENTER);
            paint.setTextSize(25);
            paint.setAntiAlias(true);
            paint.setStrokeWidth(5);
            paint.setColor(Color.WHITE);
        }
    
        @Override
        protected OverlayItemExtended createItem(int i) {
            return mOverlays.get(i);
        }
    
        @Override
        public int size() {
            return mOverlays.size();
        }
    
        public void addOverlayItem(OverlayItemExtended overlay) {
            mOverlays.add(overlay);
            populate();
        }
    
        public void removeAllOverlays() {
            mOverlays.clear();
            populate();
        }
    
        public void removePointsButMe() {
            for (int i = 0; i < mOverlays.size(); i++) {
                OverlayItemExtended overlay = mOverlays.get(i);
                if (overlay.isMe) {
                    mOverlays.clear();
                    addOverlayItem(overlay);
                    break;
                }
            }
            populate();
        }
    
        Paint paint = new Paint();
    
        @Override
        public void draw(Canvas canvas, MapView mapView, boolean shadow) {
            super.draw(canvas, mapView, shadow);
    
            // cycle through all overlays
            for (int index = 0; index < mOverlays.size(); index++) {
                OverlayItemExtended item = mOverlays.get(index);
    
                // Converts lat/lng-Point to coordinates on the screen
                GeoPoint point = item.getPoint();
                Point ptScreenCoord = new Point();
                mapView.getProjection().toPixels(point, ptScreenCoord);
    
                if (item.isMaster) {
                    if (item.slaves.size() > 0) {
                        canvas.drawText(item.slaves.size() + 1 + "",
                                ptScreenCoord.x, ptScreenCoord.y - 13, paint);
                    }
                }
            }
        }
    
        @Override
        protected boolean onTap(int index) {
            OverlayItemExtended item = mOverlays.get(index);
            if (item.isMaster) {
                if (item.slaves.size() == 0) {
                    Toast.makeText(context, "You tapped item " + item.getTitle(),
                            Toast.LENGTH_LONG).show();
                }
            }
            return super.onTap(index);
        }
    }
    

    I didn't change any code in PointCluster.java.

    I hope this will help somebody.enter image description here

提交回复
热议问题