If the map is rendering on the GoogleMap, it's easy to get the center and zoom of the boundary with the code:
final LatLngBounds.Builder builder = new LatLngBounds.Builder();
for (LatLng latlng : list) {
builder.include(latlng);
}
mMap.setOnCameraChangeListener(new OnCameraChangeListener() {
@Override
public void onCameraChange(CameraPosition arg0) {
// Move camera.
mMap.moveCamera(CameraUpdateFactory.newLatLngBounds(builder.build(), 10));
// Remove listener to prevent position reset on camera move.
mMap.setOnCameraChangeListener(null);
LatLng center = mMap.getCameraPosition().target;
float zoom = mMap.getCameraPosition().zoom;
}
});
But when we need to export by batch or from the server side, we won't load each map data onto the map view to execute above code. So I find a way to calculate them by formula.
The center point is simple to do:
final LatLngBounds bounds = builder.build();
LatLng ne = bounds.northeast;
LatLng sw = bounds.southwest;
LatLng center = new LatLng((ne.latitude + sw.latitude)/2,
(ne.longitude + sw.longitude)/2);
There are several ways to calculate the zoom level, but I find this code in Javascript by John S is more accurate (I convert them into java code)
public static int getBoundsZoomLevel(LatLng northeast,LatLng southwest,
int width, int height) {
final int GLOBE_WIDTH = 256; // a constant in Google's map projection
final int ZOOM_MAX = 21;
double latFraction = (latRad(northeast.latitude) - latRad(southwest.latitude)) / Math.PI;
double lngDiff = northeast.longitude - southwest.longitude;
double lngFraction = ((lngDiff < 0) ? (lngDiff + 360) : lngDiff) / 360;
double latZoom = zoom(height, GLOBE_WIDTH, latFraction);
double lngZoom = zoom(width, GLOBE_WIDTH, lngFraction);
double zoom = Math.min(Math.min(latZoom, lngZoom),ZOOM_MAX);
return (int)(zoom);
}
private static double latRad(double lat) {
double sin = Math.sin(lat * Math.PI / 180);
double radX2 = Math.log((1 + sin) / (1 - sin)) / 2;
return Math.max(Math.min(radX2, Math.PI), -Math.PI) / 2;
}
private static double zoom(double mapPx, double worldPx, double fraction) {
final double LN2 = .693147180559945309417;
return (Math.log(mapPx / worldPx / fraction) / LN2);
}
Thank you for the zoom level method, works like a charm :).
ReplyDeleteMany times it give zoom level 0.
ReplyDeletecan u please provide example
ReplyDeleteHi,
DeleteThis is 3 years old post! I haven't worked with Android app anymore. Not sure above code is still working.
Anyway, basically once you have a bounds (locations/points collection) then you can get
LatLng ne = bounds.northeast;
LatLng sw = bounds.southwest;
then pass them into the getBoundsZoomLevel(LatLng northeast,LatLng southwest, int width, int height)
width, height are dimension of the image you'll want to generate
once we get the zoom level, pass it to Google static maps API
See examples here:
https://developers.google.com/maps/documentation/static-maps/styling#examples
it works nice, thank u
ReplyDelete