Ich möchte, dass die Kartenansicht auf einen Radius von 1 km vergrößert wird, aber Sie können nicht herausfinden, wie?
Das Dokument sagt, dass die Zoomstufe 1 den Äquator der Erde auf 256 Pixel abbilden wird. Wie berechne ich also, welche Zoomstufe ich einstellen muss, damit die Kartenansicht den Bereich im Radius von 1 km anzeigt?
UPDATE:
Nachdem ich einige Blogbeiträge gelesen hatte, schrieb ich den folgenden Code:
private int calculateZoomLevel() {
double equatorLength = 6378140; // in meters
double widthInPixels = screenWidth;
double metersPerPixel = equatorLength / 256;
int zoomLevel = 1;
while ((metersPerPixel * widthInPixels) > 2000) {
metersPerPixel /= 2;
++zoomLevel;
}
Log.i("ADNAN", "zoom level = "+zoomLevel);
return zoomLevel;
}
Die Idee ist, dass ich zuerst Meter pro Pixel in der Zoomstufe 1 berechne, die laut Google den Äquator der Erde mit 256 Pixeln zeigt. Nun wird jede nachfolgende Zoomstufe um eine Stufe von 2 vergrößert, so dass ich für jede Zoomstufe die Hälfte der Meter pro Pixel verändere. Ich mache dies, bis ich eine Zoomstufe habe, bei der Meter pro Pixel multipliziert mit der Bildschirmbreite weniger als 2000, dh 2 km Durchmesser ergibt.
Aber ich glaube nicht, dass die Zoomstufe, die ich erhalte, die Karte mit einem Radius von 2 km darstellt. Kann mir jemand sagen, was ich hier falsch mache?
Der folgende Code wurde am Ende verwendet. In Anbetracht der Bildschirmbreite und der Tatsache, dass der Erdäquator auf der Zoomstufe 1 256 Pixel lang ist und jede nachfolgende Zoomstufe die Anzahl der zur Darstellung des Erdäquators erforderlichen Pixel verdoppelt, gibt die folgende Funktion die Zoomstufe zurück, in der der Bildschirm einen Bereich anzeigt von 2 km Breite.
private int calculateZoomLevel(int screenWidth) {
double equatorLength = 40075004; // in meters
double widthInPixels = screenWidth;
double metersPerPixel = equatorLength / 256;
int zoomLevel = 1;
while ((metersPerPixel * widthInPixels) > 2000) {
metersPerPixel /= 2;
++zoomLevel;
}
Log.i("ADNAN", "zoom level = "+zoomLevel);
return zoomLevel;
}
obwohl diese Antwort logisch ist und ich finde, dass sie funktioniert, aber die Ergebnisse nicht genau sind, weiß ich nicht warum, aber ich bin müde von diesem Ansatz, und diese Technik ist weitaus genauer.
1) Machen Sie einen Kreis mit dem gewünschten Radius
Circle circle = mGoogleMap.addCircle(new CircleOptions().center(new LatLng(latitude, longitude)).radius(getRadiusInMeters()).strokeColor(Color.RED));
circle.setVisible(true);
getZoomLevel(circle);
2) Übergeben Sie das Objekt an diese Funktion und stellen Sie die Zoomstufe ein .__ Hier ist ein Link
public int getZoomLevel(Circle circle) {
if (circle != null){
double radius = circle.getRadius();
double scale = radius / 500;
zoomLevel =(int) (16 - Math.log(scale) / Math.log(2));
}
return zoomLevel;
}
Am Ende habe ich die Utensilien verwendet von:
https://github.com/googlemaps/Android-maps-utils
Ich habe die Klasse aus der Bibliothek extrahiert, sodass Sie nicht die gesamte Bibliothek benötigen. Statt die Zoomstufe einzustellen, verwenden Sie Begrenzungen. Das Ergebnis ist das gleiche.
Code, um genau 1 Kilometer anzuzeigen:
animateToMeters(1000);
private void animateToMeters(int meters){
int mapHeightInDP = 200;
Resources r = getResources();
int mapSideInPixels = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, mapHeightInDP, r.getDisplayMetrics());
LatLng point = new LatLng(0, 0);
LatLngBounds latLngBounds = calculateBounds(point, meters);
if(latLngBounds != null){
cameraUpdate = CameraUpdateFactory.newLatLngBounds(latLngBounds, mapSideInPixels, mapSideInPixels, MARKER_BOUNDS);
if(mMap != null)
mMap.animateCamera(cameraUpdate);
}
}
private LatLngBounds calculateBounds(LatLng center, double radius) {
return new LatLngBounds.Builder().
include(SphericalUtil.computeOffset(center, radius, 0)).
include(SphericalUtil.computeOffset(center, radius, 90)).
include(SphericalUtil.computeOffset(center, radius, 180)).
include(SphericalUtil.computeOffset(center, radius, 270)).build();
}
Die Klasse wurde aus der Bibliothek extrahiert (geringfügig geändert):
public class SphericalUtil {
static final double EARTH_RADIUS = 6371009;
/**
* Returns hav() of distance from (lat1, lng1) to (lat2, lng2) on the unit sphere.
*/
static double havDistance(double lat1, double lat2, double dLng) {
return hav(lat1 - lat2) + hav(dLng) * cos(lat1) * cos(lat2);
}
/**
* Returns haversine(angle-in-radians).
* hav(x) == (1 - cos(x)) / 2 == sin(x / 2)^2.
*/
static double hav(double x) {
double sinHalf = sin(x * 0.5);
return sinHalf * sinHalf;
}
/**
* Computes inverse haversine. Has good numerical stability around 0.
* arcHav(x) == acos(1 - 2 * x) == 2 * asin(sqrt(x)).
* The argument must be in [0, 1], and the result is positive.
*/
static double arcHav(double x) {
return 2 * asin(sqrt(x));
}
private SphericalUtil() {}
/**
* Returns the heading from one LatLng to another LatLng. Headings are
* expressed in degrees clockwise from North within the range [-180,180).
* @return The heading in degrees clockwise from north.
*/
public static double computeHeading(LatLng from, LatLng to) {
// http://williams.best.vwh.net/avform.htm#Crs
double fromLat = toRadians(from.latitude);
double fromLng = toRadians(from.longitude);
double toLat = toRadians(to.latitude);
double toLng = toRadians(to.longitude);
double dLng = toLng - fromLng;
double heading = atan2(
sin(dLng) * cos(toLat),
cos(fromLat) * sin(toLat) - sin(fromLat) * cos(toLat) * cos(dLng));
return wrap(toDegrees(heading), -180, 180);
}
/**
* Returns the LatLng resulting from moving a distance from an Origin
* in the specified heading (expressed in degrees clockwise from north).
* @param from The LatLng from which to start.
* @param distance The distance to travel.
* @param heading The heading in degrees clockwise from north.
*/
public static LatLng computeOffset(LatLng from, double distance, double heading) {
distance /= EARTH_RADIUS;
heading = toRadians(heading);
// http://williams.best.vwh.net/avform.htm#LL
double fromLat = toRadians(from.latitude);
double fromLng = toRadians(from.longitude);
double cosDistance = cos(distance);
double sinDistance = sin(distance);
double sinFromLat = sin(fromLat);
double cosFromLat = cos(fromLat);
double sinLat = cosDistance * sinFromLat + sinDistance * cosFromLat * cos(heading);
double dLng = atan2(
sinDistance * cosFromLat * sin(heading),
cosDistance - sinFromLat * sinLat);
return new LatLng(toDegrees(asin(sinLat)), toDegrees(fromLng + dLng));
}
/**
* Returns the location of Origin when provided with a LatLng destination,
* meters travelled and original heading. Headings are expressed in degrees
* clockwise from North. This function returns null when no solution is
* available.
* @param to The destination LatLng.
* @param distance The distance travelled, in meters.
* @param heading The heading in degrees clockwise from north.
*/
public static LatLng computeOffsetOrigin(LatLng to, double distance, double heading) {
heading = toRadians(heading);
distance /= EARTH_RADIUS;
// http://lists.maptools.org/pipermail/proj/2008-October/003939.html
double n1 = cos(distance);
double n2 = sin(distance) * cos(heading);
double n3 = sin(distance) * sin(heading);
double n4 = sin(toRadians(to.latitude));
// There are two solutions for b. b = n2 * n4 +/- sqrt(), one solution results
// in the latitude outside the [-90, 90] range. We first try one solution and
// back off to the other if we are outside that range.
double n12 = n1 * n1;
double discriminant = n2 * n2 * n12 + n12 * n12 - n12 * n4 * n4;
if (discriminant < 0) {
// No real solution which would make sense in LatLng-space.
return null;
}
double b = n2 * n4 + sqrt(discriminant);
b /= n1 * n1 + n2 * n2;
double a = (n4 - n2 * b) / n1;
double fromLatRadians = atan2(a, b);
if (fromLatRadians < -PI / 2 || fromLatRadians > PI / 2) {
b = n2 * n4 - sqrt(discriminant);
b /= n1 * n1 + n2 * n2;
fromLatRadians = atan2(a, b);
}
if (fromLatRadians < -PI / 2 || fromLatRadians > PI / 2) {
// No solution which would make sense in LatLng-space.
return null;
}
double fromLngRadians = toRadians(to.longitude) -
atan2(n3, n1 * cos(fromLatRadians) - n2 * sin(fromLatRadians));
return new LatLng(toDegrees(fromLatRadians), toDegrees(fromLngRadians));
}
/**
* Returns the LatLng which lies the given fraction of the way between the
* Origin LatLng and the destination LatLng.
* @param from The LatLng from which to start.
* @param to The LatLng toward which to travel.
* @param fraction A fraction of the distance to travel.
* @return The interpolated LatLng.
*/
public static LatLng interpolate(LatLng from, LatLng to, double fraction) {
// http://en.wikipedia.org/wiki/Slerp
double fromLat = toRadians(from.latitude);
double fromLng = toRadians(from.longitude);
double toLat = toRadians(to.latitude);
double toLng = toRadians(to.longitude);
double cosFromLat = cos(fromLat);
double cosToLat = cos(toLat);
// Computes Spherical interpolation coefficients.
double angle = computeAngleBetween(from, to);
double sinAngle = sin(angle);
if (sinAngle < 1E-6) {
return from;
}
double a = sin((1 - fraction) * angle) / sinAngle;
double b = sin(fraction * angle) / sinAngle;
// Converts from polar to vector and interpolate.
double x = a * cosFromLat * cos(fromLng) + b * cosToLat * cos(toLng);
double y = a * cosFromLat * sin(fromLng) + b * cosToLat * sin(toLng);
double z = a * sin(fromLat) + b * sin(toLat);
// Converts interpolated vector back to polar.
double lat = atan2(z, sqrt(x * x + y * y));
double lng = atan2(y, x);
return new LatLng(toDegrees(lat), toDegrees(lng));
}
/**
* Returns distance on the unit sphere; the arguments are in radians.
*/
private static double distanceRadians(double lat1, double lng1, double lat2, double lng2) {
return arcHav(havDistance(lat1, lat2, lng1 - lng2));
}
/**
* Returns the angle between two LatLngs, in radians. This is the same as the distance
* on the unit sphere.
*/
static double computeAngleBetween(LatLng from, LatLng to) {
return distanceRadians(toRadians(from.latitude), toRadians(from.longitude),
toRadians(to.latitude), toRadians(to.longitude));
}
/**
* Returns the distance between two LatLngs, in meters.
*/
public static double computeDistanceBetween(LatLng from, LatLng to) {
return computeAngleBetween(from, to) * EARTH_RADIUS;
}
/**
* Returns the length of the given path, in meters, on Earth.
*/
public static double computeLength(List<LatLng> path) {
if (path.size() < 2) {
return 0;
}
double length = 0;
LatLng prev = path.get(0);
double prevLat = toRadians(prev.latitude);
double prevLng = toRadians(prev.longitude);
for (LatLng point : path) {
double lat = toRadians(point.latitude);
double lng = toRadians(point.longitude);
length += distanceRadians(prevLat, prevLng, lat, lng);
prevLat = lat;
prevLng = lng;
}
return length * EARTH_RADIUS;
}
/**
* Returns the area of a closed path on Earth.
* @param path A closed path.
* @return The path's area in square meters.
*/
public static double computeArea(List<LatLng> path) {
return abs(computeSignedArea(path));
}
/**
* Returns the signed area of a closed path on Earth. The sign of the area may be used to
* determine the orientation of the path.
* "inside" is the surface that does not contain the South Pole.
* @param path A closed path.
* @return The loop's area in square meters.
*/
public static double computeSignedArea(List<LatLng> path) {
return computeSignedArea(path, EARTH_RADIUS);
}
/**
* Returns the signed area of a closed path on a sphere of given radius.
* The computed area uses the same units as the radius squared.
* Used by SphericalUtilTest.
*/
static double computeSignedArea(List<LatLng> path, double radius) {
int size = path.size();
if (size < 3) { return 0; }
double total = 0;
LatLng prev = path.get(size - 1);
double prevTanLat = tan((PI / 2 - toRadians(prev.latitude)) / 2);
double prevLng = toRadians(prev.longitude);
// For each Edge, accumulate the signed area of the triangle formed by the North Pole
// and that Edge ("polar triangle").
for (LatLng point : path) {
double tanLat = tan((PI / 2 - toRadians(point.latitude)) / 2);
double lng = toRadians(point.longitude);
total += polarTriangleArea(tanLat, lng, prevTanLat, prevLng);
prevTanLat = tanLat;
prevLng = lng;
}
return total * (radius * radius);
}
/**
* Returns the signed area of a triangle which has North Pole as a vertex.
* Formula derived from "Area of a spherical triangle given two edges and the included angle"
* as per "Spherical Trigonometry" by Todhunter, page 71, section 103, point 2.
* See http://books.google.com/books?id=3uBHAAAAIAAJ&pg=PA71
* The arguments named "tan" are tan((pi/2 - latitude)/2).
*/
private static double polarTriangleArea(double tan1, double lng1, double tan2, double lng2) {
double deltaLng = lng1 - lng2;
double t = tan1 * tan2;
return 2 * atan2(t * sin(deltaLng), 1 + t * cos(deltaLng));
}
/**
* Wraps the given value into the inclusive-exclusive interval between min and max.
* @param n The value to wrap.
* @param min The minimum.
* @param max The maximum.
*/
static double wrap(double n, double min, double max) {
return (n >= min && n < max) ? n : (mod(n - min, max - min) + min);
}
/**
* Returns the non-negative remainder of x / m.
* @param x The operand.
* @param m The modulus.
*/
static double mod(double x, double m) {
return ((x % m) + m) % m;
}
}
Google Maps scheint nahe an Meilen/Pixel zu arbeiten. Bei Zoom = 13 ist 1 Meile = 100 Pixel. 2 Meilen = 200 Pixel. Jeder Zoom-Wert nimmt um einen Faktor 2 zu oder ab. Daher ist bei Zoom 14 1 Meilen = 200 Pixel und bei Zoom 12 1 Meilen = 50 Pixel.
Ich habe die akzeptierte Antwort so konvertiert, dass sie einen doppelten Wert zurückgibt, da die Google Maps-Bibliothek von Android Gleitkommazoomwerte verwendet und auch Breitengrade vom Äquator berücksichtigt.
public static double getZoomForMetersWide (
final double desiredMeters,
final double mapWidth,
final double latitude )
{
final double latitudinalAdjustment = Math.cos( Math.PI * latitude / 180.0 );
final double arg = EQUATOR_LENGTH * mapWidth * latitudinalAdjustment / ( desiredMeters * 256.0 );
return Math.log( arg ) / Math.log( 2.0 );
}
Nebenbei, für beste Ergebnisse auf Android nicht die tatsächliche Pixelanzahl der Ansicht, sondern die Dimension für die Pixeldichte des Geräts skaliert.
DisplayMetrics metrics = getResources().getDisplayMetrics();
float mapWidth = mapView.getWidth() / metrics.scaledDensity;
Hoffe das hilft jemandem.
Die Verwendung der Schleife zum Berechnen der Zoomstufe ist sehr naiv .. __ Es ist viel besser, Mathematik zu verwenden.
Hier die Funktion (Rückgabetyp: Float)
public static double calcZoom(int visible_distance, int img_width)
{
// visible_distance -> in meters
// img_width -> in pixels
visible_distance = Math.abs(visible_distance);
double equator_length = 40075016; // in meters
// for an immage of 256 pixel pixel
double zoom256 = Math.log(equator_length/visible_distance)/Math.log(2);
// adapt the zoom to the image size
int x = (int) (Math.log(img_width/256)/Math.log(2));
double zoom = zoom256 + x;
return zoom;
}
beispielaufruf:
public static void main(String[] args)
{
// computes the zoom for 1km=1000m for an image having 256 width
double zoom = MainClass.calcZoom(1000, 256);
System.out.println("zoom: " + String.valueOf(zoom));
return;
}
Die mathematischen Formeln zur Berechnung der Zoomstufe lauten:
equator_length = 40075016
zoom_level = logE(equator_length/distance)/logE(2) + logE(img_width/256)/logE(2)
// The zoom_level computed here is a float number.
Das war's Leute! :-)
ACHTUNG: Die oben genannte Lösung funktioniert nur für Zoomstufen neben dem Äquator. Wenn Sie eine Lösung suchen, die mit allen Breitengraden funktioniert, benötigen Sie die Länge der Parallele mit dem gleichen Breitengrad von die Zoomstufe, die Sie berechnen möchten. Die calcZoom
-Methode ändert sich in
private double calcZoom(int visible_distance, int img_width, double atLatitude) {
// visible_distance -> in meters
// img_width -> in pixels
double parallel_length = this.calcParallelLegth(atLatitude); // in meters
// for an immage of 256 pixel pixel
zoom256 = Math.log(parallel_length/visible_distance))/Math.log(2)
// adapt the zoom to the image size
x = (int) Math.log(img_width/256)/Math.log(2)
zoom = zoom256 + x
return zoom;
}
Dabei gibt this.calcParallelLegth(atLatitude)
die Länge der Parallele am atLatitude
-Breitengrad zurück.
Sie können die Länge selbst mit einer Bibliothek berechnen (vorzugsweise mit Vincenty-Formeln).
Alternative
Wenn Sie nicht über eine solche Bibliothek verfügen (oder nicht nach einer Bibliothek suchen oder einfach nur einen vollständigen Code möchten, der funktioniert) am Ende dieser Antwort können Sie den gesamten Arbeitscode mit einer Implementierung finden von double calcParallelLegth(double atLatitude)
, das eine Tabelle (berechnet mit Vincenty Formulas) mit paralleler Länge in allen Breiten mit 3% Toleranz verwendet.
HINWEIS:
SIE MÜSSEN UNTER NUR LESEN, WENN SIE UND DIE FORMEL VERSTEHEN (ODER WENN DIE FORMEL IS RECHTS)
Formeln Erklärung unten:
Einfach umsetzen!
Lassen Sie uns das Problem in zwei Teile teilen.
Teil 1
Berechnen Sie den Zoom für ein Bild der Größe 256 x 256
Teil 2
Passen Sie den Zoom für ein Bild mit einer anderen Größe an
Auflösung von Teil 1
Die Bildgröße beträgt 256x256 . Die Zoomstufe 0 zeigt den gesamten Äquator.
jede nachfolgende Zoomstufe ließ mich die Hälfte vorher sehen.
Equator ist 40.075.016 Meter lang (gemäß WGS-84 (* 1) und Vincenty-Formeln (* 2) )
zoom=0 -> 40,075,016 / 1 = 40,075,016 meters visible Note: 2^0=1
zoom=1 -> 40,075,016 / 2 = 20,037,508 meters visible Note: 2^1=2
zoom=2 -> 40,075,016 / 4 = 10,018,754 meters visible Note: 2^2=4
zoom=3 -> 40,075,016 / 8 = 5,009,377 meters visible Note: 2^3=8
zoom=4 -> 40,075,016 / 16 = 2,504,688.5 meters visible Note: 2^4=16
zoom=5 -> 40,075,016 / 2^5 = 1,252,344.25 meters visible Note= 2^5=32
zoom=6 -> 40,075,016 / 2^6 = 636,172.125 meters visible Note= 2^6=64
...
zoom -> equator_length / 2^zoom = visible_distance
Wie Sie oben sehen können, lassen Sie mich bei jeder nachfolgenden Zoomstufe die Hälfte vorher sehen.
zoom ist der gewünschte zoom_level.
visible_distance gibt an, wie viele Meter das Bild horizontal angezeigt wird.
wenn Sie 1 km wollen, müssen Sie zoom mit visible_distance = 1000 berechnen.
Lassen Sie uns die Zoomformeln herausfinden.
Hier macht Mathe ihre Magie ("langweiliges" Magie-Zeug).
equator_length / 2^zoom = visible_distance ->
-> equator_length / visible_distance = 2^zoom ->
-> log2(equator_length / visible_distance) = log2(2^zoom) -> (*3)
-> log2(equator_length / visible_distance) = zoom*log2(2) -> (*4)
-> log2(equator_length / visible_distance) = zoom*1 -> (*5)
-> log2(equator_length / visible_distance) = zoom ->
-> logE(equator_length / visible_distance)/logE(2) = zoom -> (*6)
die Zoomstufenformeln für ein 256x256-Bild lauten:
zoom256 = logE(equator_length/visible_distance) / logE(2)
Teil 1 Fertig !!
Auflösung Teil 2
Passen Sie den Zoom an die gewünschte Bildgröße an.
Jedes Mal, wenn sich die Bildbreite verdoppelt, erhöht sich der Zoom, um den gesamten Äquator zu sehen, um eins.
Beispiel:
In einem Bild 512x512 ist der Zoom erforderlich, um den gesamten Äquator zu sehen, 1 . In einem Bild 1024x1024 ist der Zoom erforderlich, um den gesamten Äquator zu sehen, 2 . In einem Bild 2048x2048 ist der Zoom erforderlich, um das Ganze zu sehen Äquator ist 3.
Das gesagt
width= 256 -> 256/256 = 1 -> zoom=0 (needed to see the whole equator)
width= 512 -> 512/256 = 2 -> zoom=1 (needed to see the whole equator)
width=1024 -> 1024/256 = 4 -> zoom=2 (needed to see the whole equator)
width=2048 -> 2048/256 = 8 -> zoom=3 (needed to see the whole equator)
width=4096 -> 4096/256 = 2^4 -> zoom=4 (needed to see the whole equator)
width=4096 -> 4096/256 = 2^5 -> zoom=5 (needed to see the whole equator)
... width -> width/256 = 2 ^ x -> zoom = x (wird benötigt, um den gesamten Äquator zu sehen)
dies bedeutet, dass (zoom_level ist)
- with an 512x512 image, the zoom needed is zoom256+1
- with an 1024x1024 image, the zoom needed is zoom256+2
- with an 2048x2048 image, the zoom needed is zoom256+3
...
- with an WIDTHxHEIGHT image, the zoom needed is zoom256+x
Wir benötigen x, um den Zoom an die gewünschte Bildgröße anzupassen.
Es ist also eine Frage des Extrakts x aus
width/256 = 2^x
Machen wir das
width/256 = 2^x ->
-> log2(width/256) = log2(2^x) -> (*3)
-> log2(width/256) = x * log2(2) -> (*4)
-> log2(width/256) = x * 1 -> (*5)
-> log2(width/256) = x ->
-> logE(width/256) / logE(2) = x -> (*6)
Jetzt haben wir die x Formel.
die Zoomstufenformeln für ein WIDTHxHEIGHT-Bild lauten:
zoom = zoom256 + x
Wenn Sie also 1km in einem 512x512-Bild sehen möchten,
zoom256 = logE(40075016/1000) / logE(2) = 15.29041547592718
x = logE(512/256) / logE(2) = 1
zoom = zoom256 + z = 15.29041547592718 + 1 = 16.29041547592718
Wenn es eine ganze Zahl sein muss
zoom = floor(zoom) = 16
ERLEDIGT!
(*3) expr1=expr2 <-> log(expr1)=log(expr2)
(*4) logN(a^b) = b * logN(a)
(*5) logN(N) = 1
(*6) logN(expr) = log(expr)/log(N)
(*7) log(a/b) = log(a) - log(b)
Hier ist der vollständige Code, der die Zoomstufe bei jeder Breite des Bildes berechnet.
class MainClass
{
public static int getParallelLength(double atLatitude)
{
int FR_LAT = 0; // from latitude
int TO_LAT = 1; // to latidude
int PA_LEN = 2; // parallel length in meters)
int PC_ERR = 3; // percentage error
// fr_lat| to_lat | par_len| perc_err
double tbl[][] = {
{ 0.00, 12.656250000000000, 40075016, 2.410},
{12.66, 17.402343750000000, 39107539, 2.180},
{17.40, 22.148437500000000, 38252117, 2.910},
{22.15, 25.708007812500000, 37135495, 2.700},
{25.71, 28.377685546875000, 36130924, 2.330},
{28.38, 31.047363281250000, 35285940, 2.610},
{31.05, 33.717041015625000, 34364413, 2.890},
{33.72, 35.719299316406250, 33368262, 2.380},
{35.72, 37.721557617187500, 32573423, 2.560},
{37.72, 39.723815917968750, 31738714, 2.750},
{39.72, 41.726074218750000, 30865121, 2.950},
{41.73, 43.227767944335938, 29953681, 2.360},
{43.23, 44.729461669921875, 29245913, 2.480},
{44.73, 46.231155395507812, 28517939, 2.620},
{46.23, 47.732849121093750, 27770248, 2.760},
{47.73, 49.234542846679688, 27003344, 2.900},
{49.23, 50.360813140869141, 26217745, 2.290},
{50.36, 51.487083435058594, 25616595, 2.380},
{51.49, 52.613353729248047, 25005457, 2.480},
{52.61, 53.739624023437500, 24384564, 2.580},
{53.74, 54.865894317626953, 23754152, 2.690},
{54.87, 55.992164611816406, 23114464, 2.800},
{55.99, 57.118434906005859, 22465745, 2.920},
{57.12, 57.963137626647949, 21808245, 2.280},
{57.96, 58.807840347290039, 21309508, 2.360},
{58.81, 59.652543067932129, 20806081, 2.440},
{59.65, 60.497245788574219, 20298074, 2.520},
{60.50, 61.341948509216309, 19785597, 2.610},
{61.34, 62.186651229858398, 19268762, 2.700},
{62.19, 63.031353950500488, 18747680, 2.800},
{63.03, 63.876056671142578, 18222465, 2.900},
{63.88, 64.509583711624146, 17693232, 2.250},
{64.51, 65.143110752105713, 17293739, 2.320},
{65.14, 65.776637792587280, 16892100, 2.390},
{65.78, 66.410164833068848, 16488364, 2.460},
{66.41, 67.043691873550415, 16082582, 2.530},
{67.04, 67.677218914031982, 15674801, 2.610},
{67.68, 68.310745954513550, 15265074, 2.690},
{68.31, 68.944272994995117, 14853450, 2.780},
{68.94, 69.577800035476685, 14439980, 2.870},
{69.58, 70.211327075958252, 14024715, 2.970},
{70.21, 70.686472356319427, 13607707, 2.300},
{70.69, 71.161617636680603, 13293838, 2.360},
{71.16, 71.636762917041779, 12979039, 2.430},
{71.64, 72.111908197402954, 12663331, 2.500},
{72.11, 72.587053477764130, 12346738, 2.570},
{72.59, 73.062198758125305, 12029281, 2.640},
{73.06, 73.537344038486481, 11710981, 2.720},
{73.54, 74.012489318847656, 11391862, 2.800},
{74.01, 74.487634599208832, 11071946, 2.890},
{74.49, 74.962779879570007, 10751254, 2.980},
{74.96, 75.319138839840889, 10429810, 2.310},
{75.32, 75.675497800111771, 10188246, 2.370},
{75.68, 76.031856760382652, 9946280, 2.430},
{76.03, 76.388215720653534, 9703923, 2.500},
{76.39, 76.744574680924416, 9461183, 2.560},
{76.74, 77.100933641195297, 9218071, 2.640},
{77.10, 77.457292601466179, 8974595, 2.710},
{77.46, 77.813651561737061, 8730766, 2.790},
{77.81, 78.170010522007942, 8486593, 2.880},
{78.17, 78.526369482278824, 8242085, 2.970},
{78.53, 78.793638702481985, 7997252, 2.290},
{78.79, 79.060907922685146, 7813420, 2.350},
{79.06, 79.328177142888308, 7629414, 2.410},
{79.33, 79.595446363091469, 7445240, 2.470},
{79.60, 79.862715583294630, 7260900, 2.540},
{79.86, 80.129984803497791, 7076399, 2.600},
{80.13, 80.397254023700953, 6891742, 2.680},
{80.40, 80.664523243904114, 6706931, 2.750},
{80.66, 80.931792464107275, 6521972, 2.830},
{80.93, 81.199061684310436, 6336868, 2.920},
{81.20, 81.399513599462807, 6151624, 2.250},
{81.40, 81.599965514615178, 6012600, 2.310},
{81.60, 81.800417429767549, 5873502, 2.360},
{81.80, 82.000869344919920, 5734331, 2.420},
{82.00, 82.201321260072291, 5595088, 2.480},
{82.20, 82.401773175224662, 5455775, 2.550},
{82.40, 82.602225090377033, 5316394, 2.620},
{82.60, 82.802677005529404, 5176947, 2.690},
{82.80, 83.003128920681775, 5037435, 2.770},
{83.00, 83.203580835834146, 4897860, 2.850},
{83.20, 83.404032750986516, 4758224, 2.930},
{83.40, 83.554371687350795, 4618528, 2.260},
{83.55, 83.704710623715073, 4513719, 2.320},
{83.70, 83.855049560079351, 4408878, 2.370},
{83.86, 84.005388496443629, 4304006, 2.430},
{84.01, 84.155727432807907, 4199104, 2.490},
{84.16, 84.306066369172186, 4094172, 2.560},
{84.31, 84.456405305536464, 3989211, 2.630},
{84.46, 84.606744241900742, 3884223, 2.700},
{84.61, 84.757083178265020, 3779207, 2.770},
{84.76, 84.907422114629298, 3674165, 2.850},
{84.91, 85.057761050993577, 3569096, 2.940},
{85.06, 85.170515253266785, 3464003, 2.270},
{85.17, 85.283269455539994, 3385167, 2.320},
{85.28, 85.396023657813203, 3306318, 2.380},
{85.40, 85.508777860086411, 3227456, 2.440},
{85.51, 85.621532062359620, 3148581, 2.500},
{85.62, 85.734286264632829, 3069693, 2.570},
{85.73, 85.847040466906037, 2990793, 2.630},
{85.85, 85.959794669179246, 2911882, 2.710},
{85.96, 86.072548871452454, 2832959, 2.780},
{86.07, 86.185303073725663, 2754025, 2.860},
{86.19, 86.298057275998872, 2675080, 2.950},
{86.30, 86.382622927703778, 2596124, 2.280},
{86.38, 86.467188579408685, 2536901, 2.330},
{86.47, 86.551754231113591, 2477672, 2.390},
{86.55, 86.636319882818498, 2418437, 2.440},
{86.64, 86.720885534523404, 2359197, 2.510},
{86.72, 86.805451186228311, 2299952, 2.570},
{86.81, 86.890016837933217, 2240701, 2.640},
{86.89, 86.974582489638124, 2181446, 2.710},
{86.97, 87.059148141343030, 2122186, 2.790},
{87.06, 87.143713793047937, 2062921, 2.870},
{87.14, 87.228279444752843, 2003652, 2.950},
{87.23, 87.291703683531523, 1944378, 2.280},
{87.29, 87.355127922310203, 1899919, 2.340},
{87.36, 87.418552161088883, 1855459, 2.390},
{87.42, 87.481976399867563, 1810996, 2.450},
{87.48, 87.545400638646242, 1766531, 2.510},
{87.55, 87.608824877424922, 1722063, 2.580},
{87.61, 87.672249116203602, 1677594, 2.650},
{87.67, 87.735673354982282, 1633122, 2.720},
{87.74, 87.799097593760962, 1588648, 2.790},
{87.80, 87.862521832539642, 1544172, 2.880},
{87.86, 87.925946071318322, 1499695, 2.960},
{87.93, 87.973514250402332, 1455215, 2.290},
{87.97, 88.021082429486341, 1421854, 2.340},
{88.02, 88.068650608570351, 1388493, 2.400},
{88.07, 88.116218787654361, 1355130, 2.460},
{88.12, 88.163786966738371, 1321766, 2.520},
{88.16, 88.211355145822381, 1288401, 2.580},
{88.21, 88.258923324906391, 1255036, 2.650},
{88.26, 88.306491503990401, 1221669, 2.730},
{88.31, 88.354059683074411, 1188302, 2.800},
{88.35, 88.401627862158421, 1154934, 2.880},
{88.40, 88.449196041242431, 1121565, 2.970},
{88.45, 88.484872175555438, 1088195, 2.290},
{88.48, 88.520548309868445, 1063167, 2.350},
{88.52, 88.556224444181453, 1038139, 2.410},
{88.56, 88.591900578494460, 1013110, 2.470},
{88.59, 88.627576712807468, 988081, 2.530},
{88.63, 88.663252847120475, 963052, 2.590},
{88.66, 88.698928981433482, 938022, 2.660},
{88.70, 88.734605115746490, 912992, 2.740},
{88.73, 88.770281250059497, 887961, 2.810},
{88.77, 88.805957384372505, 862930, 2.900},
{88.81, 88.841633518685512, 837899, 2.980},
{88.84, 88.868390619420268, 812867, 2.300},
{88.87, 88.895147720155023, 794093, 2.360},
{88.90, 88.921904820889779, 775319, 2.420},
{88.92, 88.948661921624534, 756545, 2.480},
{88.95, 88.975419022359290, 737771, 2.540},
{88.98, 89.002176123094046, 718996, 2.610},
{89.00, 89.028933223828801, 700221, 2.680},
{89.03, 89.055690324563557, 681446, 2.750},
{89.06, 89.082447425298312, 662671, 2.830},
{89.08, 89.109204526033068, 643896, 2.910},
{89.11, 89.129272351584135, 625121, 2.250},
{89.13, 89.149340177135201, 611039, 2.300},
{89.15, 89.169408002686268, 596957, 2.350},
{89.17, 89.189475828237335, 582876, 2.410},
{89.19, 89.209543653788401, 568794, 2.470},
{89.21, 89.229611479339468, 554712, 2.530},
{89.23, 89.249679304890535, 540630, 2.600},
{89.25, 89.269747130441601, 526548, 2.670},
{89.27, 89.289814955992668, 512466, 2.740},
{89.29, 89.309882781543735, 498384, 2.820},
{89.31, 89.329950607094801, 484302, 2.900},
{89.33, 89.350018432645868, 470219, 2.990},
{89.35, 89.365069301809172, 456137, 2.310},
{89.37, 89.380120170972475, 445575, 2.370},
{89.38, 89.395171040135779, 435013, 2.420},
{89.40, 89.410221909299082, 424451, 2.480},
{89.41, 89.425272778462386, 413889, 2.550},
{89.43, 89.440323647625689, 403328, 2.610},
{89.44, 89.455374516788993, 392766, 2.680},
{89.46, 89.470425385952296, 382204, 2.760},
{89.47, 89.485476255115600, 371642, 2.840},
{89.49, 89.500527124278904, 361080, 2.920},
{89.50, 89.511815276151381, 350518, 2.260},
{89.51, 89.523103428023859, 342596, 2.310},
{89.52, 89.534391579896337, 334674, 2.360},
{89.53, 89.545679731768814, 326753, 2.420},
{89.55, 89.556967883641292, 318831, 2.480},
{89.56, 89.568256035513770, 310910, 2.540},
{89.57, 89.579544187386247, 302988, 2.610},
{89.58, 89.590832339258725, 295066, 2.680},
{89.59, 89.602120491131203, 287145, 2.750},
{89.60, 89.613408643003680, 279223, 2.830},
{89.61, 89.624696794876158, 271301, 2.910},
{89.62, 89.633162908780520, 263380, 2.250},
{89.63, 89.641629022684882, 257438, 2.300},
{89.64, 89.650095136589243, 251497, 2.360},
{89.65, 89.658561250493605, 245556, 2.410},
{89.66, 89.667027364397967, 239615, 2.470},
{89.67, 89.675493478302329, 233673, 2.540},
{89.68, 89.683959592206691, 227732, 2.600},
{89.68, 89.692425706111052, 221791, 2.670},
{89.69, 89.700891820015414, 215849, 2.750},
{89.70, 89.709357933919776, 209908, 2.830},
{89.71, 89.717824047824138, 203967, 2.910},
{89.72, 89.724173633252406, 198026, 2.250},
{89.72, 89.730523218680673, 193570, 2.300},
{89.73, 89.736872804108941, 189114, 2.350},
{89.74, 89.743222389537209, 184658, 2.410},
{89.74, 89.749571974965477, 180202, 2.470},
{89.75, 89.755921560393745, 175746, 2.530},
{89.76, 89.762271145822012, 171290, 2.600},
{89.76, 89.768620731250280, 166834, 2.670},
{89.77, 89.774970316678548, 162378, 2.740},
{89.77, 89.781319902106816, 157922, 2.820},
{89.78, 89.787669487535084, 153466, 2.900},
{89.79, 89.794019072963351, 149010, 2.990},
{89.79, 89.798781262034552, 144554, 2.310},
{89.80, 89.803543451105753, 141212, 2.360},
{89.80, 89.808305640176954, 137869, 2.420},
{89.81, 89.813067829248155, 134527, 2.480},
{89.81, 89.817830018319356, 131185, 2.540},
{89.82, 89.822592207390556, 127843, 2.610},
{89.82, 89.827354396461757, 124501, 2.680},
{89.83, 89.832116585532958, 121159, 2.750},
{89.83, 89.836878774604159, 117817, 2.830},
{89.84, 89.841640963675360, 114475, 2.910},
{89.84, 89.845212605478764, 111133, 2.250},
{89.85, 89.848784247282168, 108627, 2.300},
{89.85, 89.852355889085572, 106120, 2.360},
{89.85, 89.855927530888977, 103614, 2.410},
{89.86, 89.859499172692381, 101107, 2.470},
{89.86, 89.863070814495785, 98601, 2.540},
{89.86, 89.866642456299189, 96094, 2.600},
{89.87, 89.870214098102593, 93588, 2.670},
{89.87, 89.873785739905998, 91081, 2.750},
{89.87, 89.877357381709402, 88575, 2.830},
{89.88, 89.880929023512806, 86068, 2.910},
{89.88, 89.883607754865352, 83562, 2.240},
{89.88, 89.886286486217898, 81682, 2.300},
{89.89, 89.888965217570444, 79802, 2.350},
{89.89, 89.891643948922990, 77922, 2.410},
{89.89, 89.894322680275536, 76042, 2.470},
{89.89, 89.897001411628082, 74162, 2.530},
{89.90, 89.899680142980628, 72282, 2.600},
{89.90, 89.902358874333174, 70402, 2.660},
{89.90, 89.905037605685720, 68523, 2.740},
{89.91, 89.907716337038266, 66643, 2.820},
{89.91, 89.910395068390812, 64763, 2.900},
{89.91, 89.913073799743358, 62883, 2.980},
{89.91, 89.915082848257768, 61003, 2.310},
{89.92, 89.917091896772178, 59593, 2.360},
{89.92, 89.919100945286587, 58183, 2.420},
{89.92, 89.921109993800997, 56773, 2.480},
{89.92, 89.923119042315406, 55363, 2.540},
{89.92, 89.925128090829816, 53953, 2.610},
{89.93, 89.927137139344225, 52543, 2.680},
{89.93, 89.929146187858635, 51134, 2.750},
{89.93, 89.931155236373044, 49724, 2.830},
{89.93, 89.933164284887454, 48314, 2.910},
{89.93, 89.934671071273257, 46904, 2.250},
{89.93, 89.936177857659061, 45846, 2.300},
{89.94, 89.937684644044865, 44789, 2.360},
{89.94, 89.939191430430668, 43731, 2.410},
{89.94, 89.940698216816472, 42674, 2.470},
{89.94, 89.942205003202275, 41617, 2.540},
{89.94, 89.943711789588079, 40559, 2.600},
{89.94, 89.945218575973882, 39502, 2.670},
{89.95, 89.946725362359686, 38444, 2.740},
{89.95, 89.948232148745490, 37387, 2.820},
{89.95, 89.949738935131293, 36329, 2.900}
};
for(int r=0; r < tbl.length; r++)
{
double fromLat = tbl[r][FR_LAT];
double toLat = tbl[r][TO_LAT];
double atLat = atLatitude;
if(fromLat <= atLat && atLat < toLat)
{
double parallelLength = tbl[r][PA_LEN];
return (int)parallelLength;
}
}
return 0;
}
public static double calcZoom(int visible_distance, int img_width, double atLat)
{
// visible_distance -> in meters
// img_width -> in pixels
// atLat -> the latitude you want the zoom level
visible_distance = Math.abs(visible_distance);
double parallel_length = MainClass.getParallelLength(atLat); // in meters
// for an immage of 256 pixel pixel
double zoom256 = Math.log(parallel_length/visible_distance)/Math.log(2);
// adapt the zoom to the image size
int x = (int) (Math.log(img_width/256)/Math.log(2));
double zoom = zoom256 + x;
return zoom;
}
public static void main(String[] args)
{
int len;
double zoom;
// equator length
len = MainClass.getParallelLength(0);
System.out.println("parallel length at 0: " + String.valueOf(len));
// legth parallel at latitude 89.9 (near the north pole)
len = MainClass.getParallelLength(89.9);
System.out.println("parallel length at 89.9: " + String.valueOf(len));
// the zoom level needed to see 100km=100000m in a img having
// width 256 at equator latitude
zoom = MainClass.calcZoom(100000, 256, 0);
System.out.println("zoom (100km, width:256, lat:0): " + String.valueOf(zoom));
// the zoom level needed to see 100km=100000m in a img having
// width 512 at equator latitude
zoom = MainClass.calcZoom(100000, 512, 0);
System.out.println("zoom (100km, width:512, lat:0): " + String.valueOf(zoom));
// the zoom level needed to see 100km=100000m in a img having
// width 256 at latitude 60
zoom = MainClass.calcZoom(100000, 256, 60);
System.out.println("zoom (100km, width:256, lat:60): " + String.valueOf(zoom));
return;
}
}
FINAL Arbeitslösung:
public static void getZoomForMetersWide(GoogleMap googleMap, int mapViewWidth, LatLng latLngPoint, int desiredMeters) {
DisplayMetrics metrics = App.getAppCtx().getResources().getDisplayMetrics();
float mapWidth = mapViewWidth / metrics.density;
final int EQUATOR_LENGTH = 40075004;
final int TIME_ANIMATION_MILIS = 1500;
final double latitudinalAdjustment = Math.cos(Math.PI * latLngPoint.latitude / 180.0);
final double arg = EQUATOR_LENGTH * mapWidth * latitudinalAdjustment / (desiredMeters * 256.0);
double valToZoom = Math.log(arg) / Math.log(2.0);
googleMap.animateCamera(CameraUpdateFactory.newLatLngZoom(latLngPoint, Float.valueOf(String.valueOf(valToZoom))), TIME_ANIMATION_MILIS , null);
}
p.s. Verwenden Sie @sho answer und @Lionel Briand comment
Ich bin mir sicher, dass es viele Methoden gibt, um das zu finden
mMap.setOnCameraChangeListener(new GoogleMap.OnCameraChangeListener() {
private float currentZoom = -1;
@Override
public void onCameraChange(CameraPosition position) {
if (position.zoom != currentZoom){
currentZoom = position.zoom; // here you get zoom level
Toast.makeText(this, "Zoom Value is : "+currentZoom, Toast.LENGTH_SHORT).show();
}
}
});