Get Radius Of Visible Map in Android

安稳与你 提交于 2019-11-29 01:22:12
kaho

For the Google Maps Android API, you can get the bounds by...

From the map reference, get the Projection by getProjection(). And,

a projection is used to translate between on screen location and geographic coordinates..

So from the projection, we can use the getVisibleRegion(), and to get the VisibleRegion of the map, which contains a LatLngBounds, which is a class that contains 2 LatLng variables, one for the Northeast corner of the bound and one for the Southwest corner.

So the code should look something like this:

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

=-=-=-=-=-= edit:

May be I was too naive, given only the NE and SW can solve this problem, but only under the special case where user did not rotate the map or tilt up for the 3D map.

So instead, you can just grab the VisibleRegion, which provided 4 variable, farRight, farLeft, nearRight, nearLeft, each represent 4 conners of the area.

Then we can calculate the width and height of the area for that 4 points and pick the smaller one (well, sometime width can be greater than height I guess.)

And for the calculation, we can just use the Location.distanceBetween(x1,y1,x2,y2,result) function...

which makes the code look like the following:

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

thank you so much for your answer @kaho, it helped me alot (even you calculated the distanceWidth and distanceHeight in the same way).

Clarification:

  • farLeft LatLng object that defines the top left corner of the camera.

  • farRight LatLng object that defines the top right corner of the camera.

  • nearLeft LatLng object that defines the bottom left corner of the camera.

  • nearRight LatLng object that defines the bottom right corner of the camera.

EDITED: I don't know why we made a simple calculation become a bit complicated, the visible radius is just A HALF OF VISIBLE DIAGONAL LINE, that's all!

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

I also logged my results to compare with @jossef-harush 's results and it's approximately:

Full area, even corners!

I don't see other answers cover the entire map area;

see image below, to test it I drew a circle overlay to see the bounds of the calculated radius, it does not cover entire map area.

my modification is quite simple, I've used Pythagorean theorem to find the suitable radius to contain the map "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;
}
KishanSolanki124

For the Kotlin users, call this function from 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)

    return Math.sqrt((Math.pow(distanceWidth[0].toString().toDouble(), 2.0))
            + Math.pow(distanceHeight[0].toString().toDouble(), 2.0)) / 2
}
kaho

edit: The following answer is for Google Maps JavaScript API v3
=-=-=-=-=-=-=

I think the answer would be: Yes, you can.

According to the documentation, you can calculate distance between 2 points by: computeDistanceBetween(LatLngFrom, LatLngTo)

Also you can get the boundary of the map by using getBounds() method, which is in the google.maps.Map class.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!