12

I am drawing the circle on map with specifying the radius and it'll draw the circle successfully. But when I change the size of circle using seekbar I need to feet the circle in screen and zoom the map of that level, I have not idea about this, need your guideline thank you.

Pratik
  • 30,639
  • 18
  • 84
  • 159
  • If it was the Javascript API you could do map.fitBounds(myCircle.getBounds()); but I don't know if the same functionality is available in Android. – Marcelo Jul 03 '12 at 11:42
  • It's android I have specify the tag here, and I know about that and also know the spantozoom() available in android. but I have single point this method not usable, if I find the latlng from center point to radius distance any latlng then this method is useful – Pratik Jul 03 '12 at 12:10
  • I found the solution check my answer – Pratik Aug 03 '12 at 11:32
  • Pls find my solution on it. I did the same in one of my project. thanks – Rajneesh Shukla Mar 26 '19 at 02:24

5 Answers5

24

We can also get the zoom level for map from the drawn circle

Circle circle = googleMap.addCircle(circleOptions);

googleMap.animateCamera(CameraUpdateFactory.newLatLngZoom(
                        circleOptions.getCenter(), getZoomLevel(circle)

// Methode for zoomlevel

public int getZoomLevel(Circle circle) {
    int zoomLevel = 11;
    if (circle != null) {
        double radius = circle.getRadius() + circle.getRadius() / 2;
        double scale = radius / 500;
        zoomLevel = (int) (16 - Math.log(scale) / Math.log(2));
    }
    return zoomLevel;
}
Anand Tiwari
  • 1,583
  • 10
  • 22
  • Perfect solution! Thank you @Anand Tiwari – Matan Dahan Apr 09 '17 at 14:46
  • 6
    @AnandTiwari Works almost perfect, for some values I get 90% of the circle in. Can you explain the `/ 500` and the `16 -`? – ilomambo Oct 05 '17 at 06:22
  • Works perfect! Thanks a lot for the solution. – Abhi Apr 30 '18 at 10:03
  • do you know what the 500 stands for ? what does it mean to scale by 500 ? – j2emanue Sep 02 '19 at 08:30
  • This function is on the path towards the right answer, but it's composed onto magic numbers. There must be a mathematical explanation. This worked for me but I had to (obviously) change `zoomLevel` and `scale` accordingly. – venir Mar 02 '23 at 14:58
3

build.gradle:

dependencies {
    compile 'com.google.maps.android:android-maps-utils:0.4+'
}

public static LatLngBounds getLatLngBoundsFromCircle(Circle circle){
    if(circle != null){
        return new LatLngBounds.Builder()
                .include(SphericalUtil.computeOffset(circle.getCenter(), circle.getRadius() * Math.sqrt(2), 45))
                .include(SphericalUtil.computeOffset(circle.getCenter(), circle.getRadius() * Math.sqrt(2), 225))
                .build();
    }
    return null;
}

map.animateCamera( CameraUpdateFactory
    .newLatLngBounds(MapUtils.getLatLngBoundsFromCircle(mapCircle),20) );
Shimon Doodkin
  • 4,310
  • 34
  • 37
1

After long time I found the solution from somewhere.

here is the method which was giving me the min lat/lng and max lat/lng. Based on this I have getting the latspan and longspan.

public void boundingCoordinates(double distance, double radius) {

    if (radius < 0d || distance < 0d)
        throw new IllegalArgumentException();

    // angular distance in radians on a great circle
    double radDist = distance / radius;

    double radLat = Math.toRadians(gp.getLatitudeE6()/1e6); // here is your single point latitude gp.getLatitude
    double radLon = Math.toRadians(gp.getLongitudeE6()/1e6); // here is your single point longitude gp.getlongitude

    double minLat = radLat - radDist;
    double maxLat = radLat + radDist;

    double minLon, maxLon;
    if (minLat > MIN_LAT && maxLat < MAX_LAT) {
        double deltaLon = Math.asin(Math.sin(radDist) /Math.cos(radLat));
        minLon = radLon - deltaLon;

        if (minLon < MIN_LON) 
            minLon += 2d * Math.PI;

        maxLon = radLon + deltaLon;

        if (maxLon > MAX_LON) 
            maxLon -= 2d * Math.PI;
    } else {
        // a pole is within the distance
        minLat = Math.max(minLat, MIN_LAT);
        maxLat = Math.min(maxLat, MAX_LAT);
        minLon = MIN_LON;
        maxLon = MAX_LON;
    }

    minLat = Math.toDegrees(minLat);
    minLon = Math.toDegrees(minLon);
    maxLat = Math.toDegrees(maxLat);
    maxLon = Math.toDegrees(maxLon);

    minGeo = new GeoPoint((int)(minLat*1e6),(int)(minLon*1e6));
    maxGeo = new GeoPoint((int)(maxLat*1e6),(int)(maxLon*1e6));
}

now you pass the distance in any unit as per that you have to pass the radius of earth for example if you pass 2 km then the radius of earth is in km say 6370.997.

you can try it, its cool thing

Pratik
  • 30,639
  • 18
  • 84
  • 159
  • Thanks for the code. but what is the use of minGeo and maxGeo? how may i zoom map view and fit circle – Asanka Senavirathna Jan 30 '13 at 09:53
  • 1
    minGeo and maxGeo was used for minimum/maximum latitude and longitude value through this you can get the span latitude and longitude value for passing in zoomToSpan method using mapControl object – Pratik Jan 30 '13 at 10:02
0

In my code I am adding a transparent circle around a marker which has dynamic radius and zooming the map camera so it fit to screen.

it is working 100% fine in my project.

@Override
public void onMapReady(GoogleMap googleMap) {
    mMap = googleMap;
    mMap.setOnMarkerClickListener(this);

    MapsInitializer.initialize(Objects.requireNonNull(getContext()));

    // Add a marker on Property location
    LatLng propertyLatlng = new LatLng(getLatitude(), getLongitude());

    //  draw transparent blue circle around marker
    try {
        CircleOptions circleOptions = new CircleOptions()
                .center(propertyLatlng)
                .radius(Double.parseDouble(radius) / 0.00062137)
                .strokeColor(BLUE_TRANSPARENT)
                .strokeWidth(0)
                .fillColor(BLUE_TRANSPARENT);
        Circle circle = mMap.addCircle(circleOptions);
        googleMap.moveCamera(CameraUpdateFactory.newLatLngZoom(
                circleOptions.getCenter(), getZoomLevel(circle)));
    } catch (Exception e) {
        AppLogger.logError(TAG, e.getMessage());
    }

}

/**
 * @param circle : circle
 * @return : return zoom level according to circle radius
 */
public float getZoomLevel(Circle circle) {
    int zoomLevel = 11;
    if (circle != null) {
        double radius = circle.getRadius() + circle.getRadius() / 2;
        double scale = radius / 500;
        zoomLevel = (int) (16 - Math.log(scale) / Math.log(2));
    }
    return zoomLevel+.4f;
}
Rajneesh Shukla
  • 1,048
  • 13
  • 21
0
  double getZoomLevel() {
    double zoomLevel = 0.0;
    double newRadius = radiusOfCircle + radiusOfCircle / 2;
    double scale = newRadius / 500;
    zoomLevel = (6 - log(scale) / log(2));
    return zoomLevel;
  }

This worked for me

Thanks to @Anand Tiwari

Jayasurya
  • 79
  • 1
  • 3