51

I believe this is a limitation of the recent Google Maps API v2. They have recently added the ability to draw a Circle on the ground - but if you want to position the camera such that it shows the entire Circle, there exists no way to do so.

One can call CameraUpdateFactory#newLatLngBounds(bounds, padding) where "bounds" is a LatLngBounds and "padding" is a distance in pixels. The issue is that there is no way to create a LatLng and a radius into a LatLngBounds.

The constructor for LatLngBounds only takes 2 LatLng instances and generates a rectangle where these are the NW and SE corners.

Warlax
  • 2,459
  • 5
  • 30
  • 41

5 Answers5

124

Just like Risadinha mentioned, you can easily achieve that with android-maps-utils. Just add:

compile 'com.google.maps.android:android-maps-utils:0.4.4'

to your gradle dependencies, use the following code:

public LatLngBounds toBounds(LatLng center, double radiusInMeters) {
    double distanceFromCenterToCorner = radiusInMeters * Math.sqrt(2.0);
    LatLng southwestCorner =
                SphericalUtil.computeOffset(center, distanceFromCenterToCorner, 225.0);
    LatLng northeastCorner = 
                SphericalUtil.computeOffset(center, distanceFromCenterToCorner, 45.0);
    return new LatLngBounds(southwestCorner, northeastCorner);
}

EDIT:

Our goal is to calculate two points (LatLngs):

  • southwestCorner

and

  • northeastCorner

From the javadoc of the SphericalUtil you can read that 225 and 45 are heading values, and the distanceFromCenterToCorner is the distance. Further explanation of the values in the picture below:

visual explanation

Bartek Lipinski
  • 30,698
  • 10
  • 94
  • 132
  • 1
    What is 225 and 45 ? And why sqrt is required? – Yuliya Tarasenko Sep 15 '15 at 12:20
  • 8
    FYI, in case anyone else is wondering (as I was), the `distance`, and therefore the `radius`, is in meters. – Aphex Oct 28 '15 at 14:25
  • Why is it multiplied with sqrt(2). Isn't the second parameter the distance in meters? – Robert Dolca Dec 20 '15 at 03:46
  • 2
    @RobertDolca it's multiplied because you want to calculate the distance from the center to the top-right (or bottom-left) **corner**. If you didn't multiply it by `sqrt(2)` you would get the distance from the center to the top (or to the bottom) **edge**. – Bartek Lipinski Jan 12 '16 at 21:24
  • Hi @BartekLipinski, I just posted question here http://stackoverflow.com/questions/35295605/how-to-calculate-number-of-pixels-that-are-equals-to-a-radius-of-circle-on-googl – cgr Feb 09 '16 at 15:36
  • 2
    The latest is: compile 'com.google.maps.android:android-maps-utils:0.4.4' – Ben Schmidt Jan 04 '17 at 20:18
  • Hi @BartekLipinski I am using your answer for RectangularBounds of Places SDK. But in some cases (may be for a particular direction) it is showing place which twice of the restrictions. – Shahbaz Hashmi Feb 27 '19 at 06:36
22

With the javascript library you can draw a circle with a center and radius and then get its bounds.

centerSfo = new google.maps.LatLng(37.7749295, -122.41941550000001);
circle = new google.maps.Circle({radius: 5000, center: centerSfo});
bounds = circle.getBounds();

You could do the same using the android api.

ascoppa
  • 247
  • 2
  • 4
  • yep, this is probably the best answer I could get here. Just small update: var circle = new window.google.maps.Circle({center: ,map: , radius: , //fillColor: '#FF0000' <- for testing}); var bounds = circle.getBounds(); circle.setMap(null); var rectangle = new window.google.maps.Rectangle({ bounds: bounds, editable: true, draggable: true }); rectangle.setMap(); – st35ly Apr 28 '16 at 09:57
  • 8
    Actually, you can't, since there is no getBounds method. – Tima Dec 08 '16 at 12:03
  • Yes, [there is in APIv3](https://developers.google.com/maps/documentation/javascript/reference?hl=fr#Circle) and it works great! APIv2 doesn't have it, and need a workaround. So since OP is very old, it should rather address the later API v3. – not2qubit Jan 28 '18 at 21:00
  • You linked the Javascript API, the Android API doesn't have it – Michel Feinstein Oct 09 '18 at 18:30
12

This is totally doable.

The LatLng is the center of your circle correct? What you want to do is inscribe your circle inside of the LatLngBounds (Circle inside a Square problem), so the entire thing will show up on the map.

If you draw this on paper you can see that you have everything you need to calculate your LatLngBounds.

Remember how to find the lengths of the sides of a right triangle?

a² + b² = c²

If you draw a line from the center of your circle to the NW (upper left) corner, and another straight to the Western wall (straight line from center, to the left) of the square you have a triangle. Now you can use the equation above to solve for c since you know the the length of the other sides of the triangle (the circle's radius).

So now your equation becomes

r² + r² = c²

which reduces to

2r² = c²

which further reduces to

c = squareRoot(2) * r

Now you have the distance. This is of course an oversimplification, because the Earth is not flat. If the distances aren't huge, you could use the same equation above, but modified to project a spherical earth onto a plane:

http://en.wikipedia.org/wiki/Geographical_distance#Flat-surface_formulae

Notice this also uses the Pythagorean theorem, same as we did above.

Next you will need to calculate your endpoints (NW, and SE corners) from your center point given a bearing, and the distance you found above.

enter image description here

This post may help: Calculate endpoint given distance, bearing, starting point

Don't forget to convert your degrees to radians when using the equation from the post linked above! ( Multiply degrees by pi/180 )

Community
  • 1
  • 1
Christopher Perry
  • 38,891
  • 43
  • 145
  • 187
  • 1
    @EmilAdz It's slightly incorrect at the moment, because the distance equation is calculating a planar value, when it should be calculating a geodesic value. Unless the reader is a [Flat-Earther](http://en.wikipedia.org/wiki/Flat_Earth_Society), then it's probably fine. – Christopher Perry Mar 10 '13 at 08:54
  • Thanks @ChristopherPerry but I was kind of hoping for some way to do this via existing Android APIs. While your solution is correct (for small enough circles), it would be a larger amount of error-prone logic to rewrite. – Warlax Mar 10 '13 at 21:00
  • Well, I've had to roll my own code plenty of times for things that X framework didn't provide. Why not do some TDD and write some tests to drive out the code and then you know its working how you are expecting? It shouldn't be one large function, this can be broken into pieces, and each piece individually tested so if there is an error you'll know exactly where to look, or refine your algorithm. – Christopher Perry Mar 10 '13 at 21:39
  • Hi @ChristopherPerry, there is some information I could get from this answer for my need. I want to calculate the no of pixels on device for a radius for 'X' zoom level. Basically I have my own circle overlayed on map to create zone. Now I want to adjust the width of circle according to zoom level. Could you please help me with a clue ? – cgr Feb 08 '16 at 22:59
  • Hi @ChristopherPerry, I just posted question here http://stackoverflow.com/questions/35295605/how-to-calculate-number-of-pixels-that-are-equals-to-a-radius-of-circle-on-googl – cgr Feb 09 '16 at 15:36
4

There is a utility library by Google for that:

http://googlemaps.github.io/android-maps-utils/

Recommended by Google for this task and example code: http://code.google.com/p/gmaps-api-issues/issues/detail?id=5704

Risadinha
  • 16,058
  • 2
  • 88
  • 91
2

While Bartek Lipinski's answer is correct if your LatLngBounds define a square, most LatLngBounds define rectangles, and as such, the bearings of the North-East and the South-West points from the center will not always be 45 and 255 degrees.

Therefore if you are looking to get the LatLngBounds of a radius from a center for any quadrilateral, use the coordinates of your initial bounds.northeast and bounds.southwest like this (using SphericalUtils):

LatLng northEast = SphericalUtil.computeOffset(center, radius * Math.sqrt(2.0), SphericalUtil.computeHeading(center, bounds.northeast));
LatLng southWest = SphericalUtil.computeOffset(center, radius * Math.sqrt(2.0), (180 + (180 + SphericalUtil.computeHeading(center, bounds.southwest))));

(180 + (180 + x)) calculates the bearing of the South-West point from the center clockwise.

Ian Wambai
  • 203
  • 3
  • 19