Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Replacement for ItemizedOverlay in Google maps V2 for Android?

Tags:

android

maps

In V1 of Google Maps for Android I implemented a form of clustering using the ItemizedOverlay class. Each cluster has a center point (lat/lon), radius (in miles) and a count of the number of items in the cluster. I used ItemizedOverlay.draw(Canvas, MapView, shadow) to draw the clusters using Canvas object methods such as drawCircle() and drawText(). Each cluster consisted of a filled circle (sized according to the space required for the count) containing the count and a circle showing the radius.

After reading the docs on V2 and playing with the demo app, I see no equivalent to ItemizedOverlay, and no obvious alternative. I suspect that the only way to do this is to maintain a list of clusters myself, and then subclass MapView and provide an implementation of its onDraw() method.

Have I missed something in the V2 API that would be better than subclassing MapView?

Thanks,

Mark

like image 994
Mark Peters Avatar asked Dec 19 '12 17:12

Mark Peters


People also ask

What is the latest version of google Maps for Android?

July 18, 2022 The Maps SDK for Android version 18.1. 0 is now available. See the Release Notes for information about this release and for all previous releases. If you are a new user, see Set Up in the Google Cloud Console to start the installation process.

Is Google Maps for Android?

With the Maps SDK for Android, add maps to your Android app including Wear OS apps using Google Maps data, map displays, and map gesture responses. You can also provide additional information for map locations and support user interaction by adding markers, polygons, and overlays to your map.


1 Answers

After some research, I haven't found any better option than creating Bitmap for Marker on the fly either. But I'm also creating circle with polygon on the map. Be aware that this is not really high-performance solution, but for my case it is a decent option. Code sample:

private static final int CIRCLE_POLYGON_VERTICES = 16;
private static final double EARTH_RADIUS = 6378.1d;


private List<LatLng> createCirclePolygon(LatLng center, double r) {
    List<LatLng> res = new ArrayList<LatLng>(CIRCLE_POLYGON_VERTICES);

    double r_latitude = MathUtils.rad2deg(r/EARTH_RADIUS);
    double r_longitude = r_latitude / Math.cos(MathUtils.deg2rad(center.latitude));

    for (int point = 0; point < CIRCLE_POLYGON_VERTICES + 1; point++) {
         double theta = Math.PI * ((double)point / (CIRCLE_POLYGON_VERTICES / 2));
         double circle_x = center.longitude + (r_longitude * Math.cos(theta));  
         double circle_y = center.latitude + (r_latitude * Math.sin(theta));     

         res.add(new LatLng(circle_y, circle_x));
     }
     return res;
}   

private Bitmap getClusteredLabel(String cnt, Context ctx) {
    Resources r = ctx.getResources();
    Bitmap res = BitmapFactory.decodeResource(r, R.drawable.map_cluster_bg);        
    res = res.copy(Bitmap.Config.ARGB_8888, true);
    Canvas c = new Canvas(res);

    Paint textPaint = new Paint();
    textPaint.setAntiAlias(true);
    textPaint.setTextAlign(Paint.Align.CENTER);
    textPaint.setTypeface(Typeface.DEFAULT_BOLD);
    textPaint.setColor(Color.WHITE);
    textPaint.setTextSize(21);      

    c.drawText(String.valueOf(cnt), res.getWidth()/2, res.getHeight()/2 + textPaint.getTextSize() / 3, textPaint);

    return res;
}   

public void createClusteredOverlay(MapPinData point, GoogleMap map, Context ctx) {
    if (point.getCount() > 1) {
        map.addMarker(new MarkerOptions().position(point.getLatLng()).anchor(0.5f, 0.5f).icon(BitmapDescriptorFactory.fromBitmap(getClusteredLabel(String.valueOf(point.getCount()), ctx))));

        map.addPolygon(new PolygonOptions()         
        .addAll(createCirclePolygon(point.getLatLng(), point.getRadius()))
        .fillColor(Color.argb(50, 0, 0, 10))     
        .strokeWidth(0)
        );
    } else {
        map.addMarker(new MarkerOptions().position(point.getLatLng()).title(point.getTitle()));
    }
}

My MathUtils methods:

public static double deg2rad(double deg) {
    return (deg * Math.PI / 180.0);
}

public static double rad2deg(double rad) {
    return (rad * 180.0 / Math.PI);
}   

If you have radius in miles, you should change EARTH_RADIUS constant to miles, 3963 AFAIK.

like image 83
user711058 Avatar answered Oct 06 '22 00:10

user711058