在 Android 中获取可见地图的半径
Get Radius Of Visible Map in Android
是否有任何可能的方法从中点找到可见地图的半径?
我想从 API 获取地图中心点附近的位置,而 API 需要纬度、经度和半径。我能够从中心点获取纬度和经度,但找不到获取半径的方法。
谢谢
编辑:以下答案适用于 Google 地图 JavaScript API v3
=-=-=-=-=-=-=
我想答案是:可以。
根据documentation,您可以通过以下方式计算两点之间的距离:computeDistanceBetween(LatLngFrom, LatLngTo)
也可以通过getBounds()
方法得到地图的边界,在google.maps.Map class.
中
对于 Google 地图 Android API,您可以通过...
从地图参考中,通过 getProjection() 获得 Projection
。而且,
a projection is used to translate between on screen location and geographic coordinates..
所以从投影中,我们可以使用getVisibleRegion(), and to get the VisibleRegion of the map, which contains a LatLngBounds,这是一个包含2个LatLng
变量的class,一个用于边界的东北角,一个用于西南角。
因此代码应如下所示:
googleMap.setOnCameraChangeListener(new GoogleMap.OnCameraChangeListener() {
@Override
public void onCameraChange(CameraPosition position) {
LatLngBounds bounds = googleMap.getProjection().getVisibleRegion().latLngBounds;
LatLng northeast = bounds.northeast;
LatLng southwest = bounds.southwest;
Context context = getApplicationContext();
CharSequence text = "ne:"+northeast+" sw:"+southwest;
int duration = Toast.LENGTH_SHORT;
Toast toast = Toast.makeText(context, text, duration);
toast.show();
}
});
=-=-=-=-=-=
编辑:
可能是我太天真了,只有NE和SW可以解决这个问题,但仅限于用户没有旋转地图或为3D地图倾斜的特殊情况。
因此,您可以直接获取 VisibleRegion
,它提供了 4 个变量,farRight、farLeft、nearRight、nearLeft,每个代表该区域的 4 个角。
然后我们可以计算这 4 个点的区域的宽度和高度,并选择较小的一个(好吧,我猜有时宽度可能会大于高度。)
对于计算,我们可以使用 Location.distanceBetween(x1,y1,x2,y2,result)
函数...
这使得代码如下所示:
VisibleRegion visibleRegion = googleMap.getProjection().getVisibleRegion();
LatLng farRight = visibleRegion.farRight;
LatLng farLeft = visibleRegion.farLeft;
LatLng nearRight = visibleRegion.nearRight;
LatLng nearLeft = visibleRegion.nearLeft;
float[] distanceWidth = new float[2];
Location.distanceBetween(
(farRight.latitude+nearRight.latitude)/2,
(farRight.longitude+nearRight.longitude)/2,
(farLeft.latitude+nearLeft.latitude)/2,
(farLeft.longitude+nearLeft.longitude)/2,
distanceWidth
);
float[] distanceHeight = new float[2];
Location.distanceBetween(
(farRight.latitude+nearRight.latitude)/2,
(farRight.longitude+nearRight.longitude)/2,
(farLeft.latitude+nearLeft.latitude)/2,
(farLeft.longitude+nearLeft.longitude)/2,
distanceHeight
);
float distance;
if (distanceWidth[0]>distanceHeight[0]){
distance = distanceWidth[0];
} else {
distance = distanceHeight[0];
}
非常感谢你的回答@kaho,它对我帮助很大(即使你用同样的方式计算了distanceWidth和distanceHeight)。
澄清:
farLeft LatLng 对象,定义相机的左上角。
farRight LatLng 对象,定义相机的右上角。
nearLeft LatLng 对象,定义相机的左下角。
nearRight LatLng 对象,定义相机的右下角。
已编辑:我不知道为什么我们把简单的计算变得有点复杂,可见半径只是可见对角线的一半,仅此而已!
private double getMapVisibleRadius() {
VisibleRegion visibleRegion = map.getProjection().getVisibleRegion();
float[] diagonalDistance = new float[1];
LatLng farLeft = visibleRegion.farLeft;
LatLng nearRight = visibleRegion.nearRight;
Location.distanceBetween(
farLeft.latitude,
farLeft.longitude,
nearRight.latitude,
nearRight.longitude,
diagonalDistance
);
return diagonalDistance[0] / 2;
}
我还记录了我的结果以与@jossef-harush 的结果进行比较,它大约是:
完整区域,甚至角落!
我没有看到其他答案覆盖整个地图区域;
见下图,为了测试它,我画了一个圆形叠加层以查看计算半径的边界,它没有覆盖整个地图区域。
我的修改很简单,我用Pythagorean theorem找到了合适的半径来包含地图"rectangle"。
private double getMapVisibleRadius() {
VisibleRegion visibleRegion = googleMap.getProjection().getVisibleRegion();
float[] distanceWidth = new float[1];
float[] distanceHeight = new float[1];
LatLng farRight = visibleRegion.farRight;
LatLng farLeft = visibleRegion.farLeft;
LatLng nearRight = visibleRegion.nearRight;
LatLng nearLeft = visibleRegion.nearLeft;
Location.distanceBetween(
(farLeft.latitude + nearLeft.latitude) / 2,
farLeft.longitude,
(farRight.latitude + nearRight.latitude) / 2,
farRight.longitude,
distanceWidth
);
Location.distanceBetween(
farRight.latitude,
(farRight.longitude + farLeft.longitude) / 2,
nearRight.latitude,
(nearRight.longitude + nearLeft.longitude) / 2,
distanceHeight
);
double radiusInMeters = Math.sqrt(Math.pow(distanceWidth[0], 2) + Math.pow(distanceHeight[0], 2)) / 2;
return radiusInMeters;
}
对于 Kotlin 用户,从 setOnCameraIdleListener
调用此函数
private fun getMapVisibleRadius(): Double {
val visibleRegion: VisibleRegion = mMap.projection.visibleRegion
val distanceWidth = FloatArray(1)
val distanceHeight = FloatArray(1)
val farRight: LatLng = visibleRegion.farRight
val farLeft: LatLng = visibleRegion.farLeft
val nearRight: LatLng = visibleRegion.nearRight
val nearLeft: LatLng = visibleRegion.nearLeft
Location.distanceBetween((farLeft.latitude + nearLeft.latitude) / 2, farLeft.longitude, (farRight.latitude + nearRight.latitude) / 2, farRight.longitude, distanceWidth)
Location.distanceBetween(farRight.latitude,
(farRight.longitude + farLeft.longitude) / 2, nearRight.latitude, (nearRight.longitude + nearLeft.longitude) / 2, distanceHeight)
val radiusInMeters = Math.sqrt((Math.pow(distanceWidth.get(0).toString().toDouble(), 2.0))
+ Math.pow(distanceHeight.get(0).toString().toDouble(), 2.0)) / 2
return radiusInMeters
}
是否有任何可能的方法从中点找到可见地图的半径?
我想从 API 获取地图中心点附近的位置,而 API 需要纬度、经度和半径。我能够从中心点获取纬度和经度,但找不到获取半径的方法。
谢谢
编辑:以下答案适用于 Google 地图 JavaScript API v3
=-=-=-=-=-=-=
我想答案是:可以。
根据documentation,您可以通过以下方式计算两点之间的距离:computeDistanceBetween(LatLngFrom, LatLngTo)
也可以通过getBounds()
方法得到地图的边界,在google.maps.Map class.
对于 Google 地图 Android API,您可以通过...
从地图参考中,通过 getProjection() 获得 Projection
。而且,
a projection is used to translate between on screen location and geographic coordinates..
所以从投影中,我们可以使用getVisibleRegion(), and to get the VisibleRegion of the map, which contains a LatLngBounds,这是一个包含2个LatLng
变量的class,一个用于边界的东北角,一个用于西南角。
因此代码应如下所示:
googleMap.setOnCameraChangeListener(new GoogleMap.OnCameraChangeListener() {
@Override
public void onCameraChange(CameraPosition position) {
LatLngBounds bounds = googleMap.getProjection().getVisibleRegion().latLngBounds;
LatLng northeast = bounds.northeast;
LatLng southwest = bounds.southwest;
Context context = getApplicationContext();
CharSequence text = "ne:"+northeast+" sw:"+southwest;
int duration = Toast.LENGTH_SHORT;
Toast toast = Toast.makeText(context, text, duration);
toast.show();
}
});
=-=-=-=-=-= 编辑:
可能是我太天真了,只有NE和SW可以解决这个问题,但仅限于用户没有旋转地图或为3D地图倾斜的特殊情况。
因此,您可以直接获取 VisibleRegion
,它提供了 4 个变量,farRight、farLeft、nearRight、nearLeft,每个代表该区域的 4 个角。
然后我们可以计算这 4 个点的区域的宽度和高度,并选择较小的一个(好吧,我猜有时宽度可能会大于高度。)
对于计算,我们可以使用 Location.distanceBetween(x1,y1,x2,y2,result)
函数...
这使得代码如下所示:
VisibleRegion visibleRegion = googleMap.getProjection().getVisibleRegion();
LatLng farRight = visibleRegion.farRight;
LatLng farLeft = visibleRegion.farLeft;
LatLng nearRight = visibleRegion.nearRight;
LatLng nearLeft = visibleRegion.nearLeft;
float[] distanceWidth = new float[2];
Location.distanceBetween(
(farRight.latitude+nearRight.latitude)/2,
(farRight.longitude+nearRight.longitude)/2,
(farLeft.latitude+nearLeft.latitude)/2,
(farLeft.longitude+nearLeft.longitude)/2,
distanceWidth
);
float[] distanceHeight = new float[2];
Location.distanceBetween(
(farRight.latitude+nearRight.latitude)/2,
(farRight.longitude+nearRight.longitude)/2,
(farLeft.latitude+nearLeft.latitude)/2,
(farLeft.longitude+nearLeft.longitude)/2,
distanceHeight
);
float distance;
if (distanceWidth[0]>distanceHeight[0]){
distance = distanceWidth[0];
} else {
distance = distanceHeight[0];
}
非常感谢你的回答@kaho,它对我帮助很大(即使你用同样的方式计算了distanceWidth和distanceHeight)。
澄清:
farLeft LatLng 对象,定义相机的左上角。
farRight LatLng 对象,定义相机的右上角。
nearLeft LatLng 对象,定义相机的左下角。
nearRight LatLng 对象,定义相机的右下角。
已编辑:我不知道为什么我们把简单的计算变得有点复杂,可见半径只是可见对角线的一半,仅此而已!
private double getMapVisibleRadius() {
VisibleRegion visibleRegion = map.getProjection().getVisibleRegion();
float[] diagonalDistance = new float[1];
LatLng farLeft = visibleRegion.farLeft;
LatLng nearRight = visibleRegion.nearRight;
Location.distanceBetween(
farLeft.latitude,
farLeft.longitude,
nearRight.latitude,
nearRight.longitude,
diagonalDistance
);
return diagonalDistance[0] / 2;
}
我还记录了我的结果以与@jossef-harush 的结果进行比较,它大约是:
完整区域,甚至角落!
我没有看到其他答案覆盖整个地图区域;
见下图,为了测试它,我画了一个圆形叠加层以查看计算半径的边界,它没有覆盖整个地图区域。
我的修改很简单,我用Pythagorean theorem找到了合适的半径来包含地图"rectangle"。
private double getMapVisibleRadius() {
VisibleRegion visibleRegion = googleMap.getProjection().getVisibleRegion();
float[] distanceWidth = new float[1];
float[] distanceHeight = new float[1];
LatLng farRight = visibleRegion.farRight;
LatLng farLeft = visibleRegion.farLeft;
LatLng nearRight = visibleRegion.nearRight;
LatLng nearLeft = visibleRegion.nearLeft;
Location.distanceBetween(
(farLeft.latitude + nearLeft.latitude) / 2,
farLeft.longitude,
(farRight.latitude + nearRight.latitude) / 2,
farRight.longitude,
distanceWidth
);
Location.distanceBetween(
farRight.latitude,
(farRight.longitude + farLeft.longitude) / 2,
nearRight.latitude,
(nearRight.longitude + nearLeft.longitude) / 2,
distanceHeight
);
double radiusInMeters = Math.sqrt(Math.pow(distanceWidth[0], 2) + Math.pow(distanceHeight[0], 2)) / 2;
return radiusInMeters;
}
对于 Kotlin 用户,从 setOnCameraIdleListener
private fun getMapVisibleRadius(): Double {
val visibleRegion: VisibleRegion = mMap.projection.visibleRegion
val distanceWidth = FloatArray(1)
val distanceHeight = FloatArray(1)
val farRight: LatLng = visibleRegion.farRight
val farLeft: LatLng = visibleRegion.farLeft
val nearRight: LatLng = visibleRegion.nearRight
val nearLeft: LatLng = visibleRegion.nearLeft
Location.distanceBetween((farLeft.latitude + nearLeft.latitude) / 2, farLeft.longitude, (farRight.latitude + nearRight.latitude) / 2, farRight.longitude, distanceWidth)
Location.distanceBetween(farRight.latitude,
(farRight.longitude + farLeft.longitude) / 2, nearRight.latitude, (nearRight.longitude + nearLeft.longitude) / 2, distanceHeight)
val radiusInMeters = Math.sqrt((Math.pow(distanceWidth.get(0).toString().toDouble(), 2.0))
+ Math.pow(distanceHeight.get(0).toString().toDouble(), 2.0)) / 2
return radiusInMeters
}