我正在尝试将 Google 地图以用户位置为中心,同时考虑到该位置的准确性,提供合理的缩放级别。谁能描述我应该如何计算它?涉及到哪些变量,你是如何实现的?
问问题
2811 次
3 回答
12
您正在寻找的是根据位置精度计算缩放级别的公式。
我设法想出了这个公式(在我的测试中)效果很好。
这可以简化(可能看起来不是这样):
这个看起来很吓人的东西就是你想要的。
EquatorLength
是 40,075,004 米。而Meters/Pixel
可以通过将精度圆的直径除以设备屏幕的长度(以像素为单位)来计算。
这是我用来测试这个公式的示例程序:
GoogleMap mMap;
@Override
protected void onStart() {
super.onStart();
mMap = ((MapFragment)getFragmentManager().findFragmentById(R.id.map)).getMap();
// Enable user's location layer
mMap.setMyLocationEnabled(true);
mMap.setOnMyLocationChangeListener(new GoogleMap.OnMyLocationChangeListener() {
@Override
public void onMyLocationChange(Location location) {
// Location lat-lng
LatLng loc = new LatLng(location.getLatitude(), location.getLongitude());
// Location accuracy diameter (in meters)
float accuracy = location.getAccuracy() * 2;
// Screen measurements
DisplayMetrics metrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrics);
// Use min(width, height) (to properly fit the screen
int screenSize = Math.min(metrics.widthPixels, metrics.heightPixels);
// Equators length
long equator = 40075004;
// The meters per pixel required to show the whole area the user might be located in
double requiredMpp = accuracy/screenSize;
// Calculate the zoom level
double zoomLevel = ((Math.log(equator / (256 * requiredMpp))) / Math.log(2)) + 1;
Log.e(TAG, String.format("Accuracy: %f. Screen Width: %d, Height: %d",
accuracy, metrics.widthPixels, metrics.heightPixels));
Log.e(TAG, String.format("Required M/Px: %f Zoom Level: %f Approx Zoom Level: %d",
requiredMpp, zoomLevel, calculateZoomLevel(screenSize, accuracy)));
// Center to user's position
mMap.animateCamera(CameraUpdateFactory.newLatLngZoom(loc, (float) zoomLevel));
// Prevent the camera centering on the user again
mMap.setOnMyLocationChangeListener(null);
}
});
}
private int calculateZoomLevel(int screenWidth, float accuracy) {
double equatorLength = 40075004; // in meters
double metersPerPixel = equatorLength / 256;
int zoomLevel = 1;
while ((metersPerPixel * (double) screenWidth) > accuracy) {
metersPerPixel /= 2;
zoomLevel++;
}
return zoomLevel;
}
有几点需要注意:
- 此答案基于此并实现它以检查生成的值
- 准确度是用户位置的半径,根据文档,它的正确率最高可达 68%。
非常欢迎任何更正。
于 2014-08-05T15:59:40.573 回答
1
如果您正在寻找简单的东西:
var zoom = Math.min(20, Math.max(1, Math.log2(591657550/accuracy)-2));
调整-2
以获得所需的缩放。
查看此答案以获取准确的图表对应缩放。
于 2019-03-28T18:26:16.593 回答
0
谢谢@Simas!我选择了您的算法来对 GMSMapView 进行此扩展,以根据 CLLocation 的准确性计算理想的缩放级别。
由于每个像素与屏幕上的 1 点不完全相同,我不得不进行调整以考虑配备 Retina 显示屏的设备:
extension GMSMapView {
func getIdealZoomLevel(usingLocation location:CLLocation)->Float {
let retinaScale = Double(UIScreen.mainScreen().scale)
let equatorLength : Double = 40075004 // in meters
var metersPerPixel = equatorLength / 256
let accuracy = location.horizontalAccuracy
// I used height because I'm on landscape, but moving forward I'll have to get the Min of the width and height.
// I also took only 75% of the height to give it some margin
let screenWidth : Double = Double( self.frame.size.height) * 0.75
var display = metersPerPixel * (screenWidth / retinaScale)
var zoomLevel : Float = 0.0
while (display > accuracy) {
metersPerPixel /= 2
display = metersPerPixel * (screenWidth / retinaScale)
zoomLevel += 1
}
return zoomLevel
}
}
这是我正在处理的一个 Swift 项目,现在,我能够在给定的 CLLocation 内显示包围半径的良好接近度。
希望这可以帮助。
于 2017-04-23T04:00:47.327 回答