17
votes

I want to draw a circle on map view. I want the user to input the radius and for that radius I have to show circle on map. After that I have to display markers on some locations on that circle.

I know how to display markers on on map view.

How can I draw circle on map view and to show markers on that circle boundary.

6
This library may help - github.com/i-schuetz/map_areasUser

6 Answers

35
votes

Just to bring this up to date... they've made it very easy to do on Google Maps API v2.

    mMap.addCircle(new CircleOptions()
        .center(center)
        .radius(radius)
        .strokeWidth(0f)
        .fillColor(0x550000FF));

Where radius is in meters.

As for markers on the boundary, that should be relatively easy to do - just follow the 'Circles' Demo in the Google Maps sample code here: https://developers.google.com/maps/documentation/android/intro#sample_code

10
votes

In case someone was looking for an answer using Google Maps API v2, here's a snippet of what I did. It's really more of a geographical approach.

public class MapDrawer {

private GoogleMap map;
private static int EARTH_RADIUS = 6371000;

public MapDrawer(GoogleMap map) {
    this.map = map;
}

private LatLng getPoint(LatLng center, int radius, double angle) {
    // Get the coordinates of a circle point at the given angle
    double east = radius * Math.cos(angle);
    double north = radius * Math.sin(angle);

    double cLat = center.latitude;
    double cLng = center.longitude;
    double latRadius = EARTH_RADIUS * Math.cos(cLat / 180 * Math.PI);

    double newLat = cLat + (north / EARTH_RADIUS / Math.PI * 180);
    double newLng = cLng + (east / latRadius / Math.PI * 180);

    return new LatLng(newLat, newLng);
}

public Polygon drawCircle(LatLng center, int radius) {
    // Clear the map to remove the previous circle
    map.clear();
    // Generate the points
    List<LatLng> points = new ArrayList<LatLng>();
    int totalPonts = 30; // number of corners of the pseudo-circle
    for (int i = 0; i < totalPonts; i++) {
        points.add(getPoint(center, radius, i*2*Math.PI/totalPonts));
    }
    // Create and return the polygon
    return map.addPolygon(new PolygonOptions().addAll(points).strokeWidth(2).strokeColor(0x700a420b));
}

}

The good thing about this is that you don't have to redraw anything after zooming or panning the map - the circle gets resized and moved accordingly. The downside is that this doesn't work if you want a circle on either north or south pole - it'll all go bezerk, but, hopefully, that's not the case 99% of the time :)

8
votes

In the implementation of the ItemizedOverlay, do something like the method drawCircle from the onDraw method

protected void drawCircle(Canvas canvas, Point curScreenCoords) {
    curScreenCoords = toScreenPoint(curScreenCoords);
    int CIRCLE_RADIUS = 50;
    // Draw inner info window
    canvas.drawCircle((float) curScreenCoords.x, (float) curScreenCoords.y, CIRCLE_RADIUS, getInnerPaint());
    // if needed, draw a border for info window
    canvas.drawCircle(curScreenCoords.x, curScreenCoordsy, CIRCLE_RADIUS, getBorderPaint());
}

private Paint innerPaint, borderPaint;

public Paint getInnerPaint() {
    if (innerPaint == null) {
        innerPaint = new Paint();
        innerPaint.setARGB(225, 68, 89, 82); // gray
        innerPaint.setAntiAlias(true);
    }
    return innerPaint;
}

public Paint getBorderPaint() {
    if (borderPaint == null) {
        borderPaint = new Paint();
        borderPaint.setARGB(255, 68, 89, 82);
        borderPaint.setAntiAlias(true);
        borderPaint.setStyle(Style.STROKE);
        borderPaint.setStrokeWidth(2);
    }
    return borderPaint;
}

@Override
protected void onDraw(Canvas canvas) {
    Point p = new Point();
    for(OverlayItem item : items) {
        drawCircle(canvas, getProjection().toPixels(item.getPoint(), p));
    }
}
4
votes

This isn't perfect, but here's a little code I put together to put a circle on a map. You could easily expand on it to set the colour of the circle etc. Most of the other code samples I've seen haven't taken into account scaling the circle size with the zoom level which is a common requirement when creating circles. Circle Radius is in meters.

import com.google.android.maps.GeoPoint;
import com.google.android.maps.MapView;
import com.google.android.maps.Overlay;
import com.google.android.maps.Projection;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Point;
public class CircleOverlay extends Overlay {

    Context context;
    double mLat;
    double mLon;
    float mRadius;

     public CircleOverlay(Context _context, double _lat, double _lon, float radius ) {
            context = _context;
            mLat = _lat;
            mLon = _lon;
            mRadius = radius;
     }

     public void draw(Canvas canvas, MapView mapView, boolean shadow) {

         super.draw(canvas, mapView, shadow); 

         Projection projection = mapView.getProjection();

         Point pt = new Point();

         GeoPoint geo = new GeoPoint((int) (mLat *1e6), (int)(mLon * 1e6));

         projection.toPixels(geo ,pt);
         float circleRadius = projection.metersToEquatorPixels(mRadius);

         Paint innerCirclePaint;

         innerCirclePaint = new Paint();
         innerCirclePaint.setColor(Color.BLUE);
         innerCirclePaint.setAlpha(25);
         innerCirclePaint.setAntiAlias(true);

         innerCirclePaint.setStyle(Paint.Style.FILL);

         canvas.drawCircle((float)pt.x, (float)pt.y, circleRadius, innerCirclePaint);
    }
}
2
votes

For Kotlin, to draw a circle in the center of the map, you can use

mMap.setOnCameraIdleListener {
        val midLatLng: LatLng = mMap.cameraPosition.target

        mMap.addCircle(CircleOptions()
                .center(midLatLng)
                .radius(radiusInMeters)
                .strokeWidth(1f)
                .fillColor(0x880000FF))
}

mMap is GoogleMap

0
votes

If you put the following code in your overlay's draw method, it will draw a circle radius 20 px in the centre of your mapView

@Override
public boolean draw(Canvas canvas, MapView mapView, boolean shadow,
long when) {
    ....
    ....

    Paint lp4;
    lp4 = new Paint();
    lp4.setColor(Color.RED);
    lp4.setAntiAlias(true);
    lp4.setStyle(Style.STROKE);
    canvas.drawCircle(mapView.getWidth()/2, mapView.getHeight()/2, 20, lp4);

    ....
    ....
    mapView.invalidate();
}

You should be able to adapt it to suit your needs