android GoogleMap获取缩放级别的可见区域半径

92vpleto  于 2022-12-09  发布在  Android
关注(0)|答案(2)|浏览(183)

我正在构建一个应用程序,从onCameraIdle中的API加载数据。请求需要目标位置和一个半径,以便给予结果。
我用来从当前摄影机获取半径的代码是:

/**
 * @param map The Map on which to compute the radius.
 * @return The circle radius of the area visible on map, in meters.
 */
public float getRadiusVisibleOnMap(GoogleMap map) {
    VisibleRegion visibleRegion = map.getProjection().getVisibleRegion();

    LatLng farRight = visibleRegion.farRight;
    LatLng farLeft = visibleRegion.farLeft;
    LatLng nearRight = visibleRegion.nearRight;
    LatLng nearLeft = visibleRegion.nearLeft;

    float[] distanceWidth = new float[1];
    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[1];
    Location.distanceBetween(
            (farRight.latitude + nearRight.latitude) / 2,
            (farRight.longitude + nearRight.longitude) / 2,
            (farLeft.latitude + nearLeft.latitude) / 2,
            (farLeft.longitude + nearLeft.longitude) / 2,
            distanceHeight
    );

    float radius;

    if (distanceWidth[0] > distanceHeight[0]) {
        radius = distanceWidth[0];
    } else {
        radius = distanceHeight[0];
    }

    return radius;
}

我从here那里得到的
在某些情况下,我只需要知道缩放级别就可以获得半径,这样当缩放动画完成时,信息就已经加载到Map上了。
我试图调整代码从here得到半径知道缩放水平,而不是反过来。

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;
}

我得到了公式:

公式不正确。它没有输出正确的尺寸。对于缩放级别为14,我使用相机的VisibleRegion得到的半径尺寸为2.697331km。如果我使用公式计算半径,结果为0.008km。

vnjpjtjt

vnjpjtjt1#

看起来最好的做法是找到一个最小的半径值,以适应Map矩形内。
你几乎就到了,使用下面修改过的函数,它使用Pythagorean theorem来找到包含Map的“矩形”所需的最小半径。

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

    googleMap.setOnCameraIdleListener(() -> {
        CameraPosition cameraPosition = googleMap.getCameraPosition();
        double radiusInMeters = getMapVisibleRadius();
        double radiusInKilometers = radiusInMeters / 1000;
        double latitude = cameraPosition.target.latitude;
        double longitude = cameraPosition.target.longitude;

        // TODO you take it from here, 
        // I use firebase to get relevant markers based on the lat,long,radius

    });
}

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;
}
6pp0gazn

6pp0gazn2#

作为对使用Maps Compose Library的每个人的更新,我可以推荐CameraPositionState上的这个扩展函数,以直接获得可见半径:

fun CameraPositionState.visibleRadius(): Double {
    this.projection?.visibleRegion?.let { visibleRegion ->
        val distanceWidth = FloatArray(1)
        val distanceHeight = FloatArray(1)
        val farRight = visibleRegion.farRight
        val farLeft = visibleRegion.farLeft
        val nearRight = visibleRegion.nearRight
        val 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
        )
        return sqrt(
            distanceWidth[0].toDouble().pow(2.0) + distanceHeight[0].toDouble().pow(2.0)
        ) / 2
    }
    return -1.0
}

稍后,您可以在UI代码中使用它,如下所示:

LaunchedEffect(cameraPositionState.isMoving) {
    if (!cameraPositionState.isMoving) {
        viewModel.onUpdateVisibleRadius(
            visibleRadius = cameraPositionState.visibleRadius(),
        )
    }
}

相关问题