18

Is there any possible way of finding radius of the visible map from the middle point?

Google Map

I want to get the near places against the center point of the map from an API, and that API require lat,lng and radius. I am able to get lat and lng from center point but couldnt find a way to get radius .

thanks

awaistoor
  • 786
  • 2
  • 11
  • 36

5 Answers5

21

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];
                }
Sevle
  • 3,109
  • 2
  • 19
  • 31
kaho
  • 4,746
  • 1
  • 16
  • 24
  • 1
    I was going to say the rest is only a math problem, but I guess I was too naive. by the way, the distance is in meter. – kaho Mar 25 '15 at 21:41
  • Definitely the second approach you suggested worked very well. Thank you @kaho – Anil Gorthy Oct 19 '16 at 17:27
  • @kaho As **Think twice code once** said the approach is good but I guess while calculating the height you have mistakenly cosidered the latitude which eventually give the width again. You should consider longitude as **Think twice code once** has done – Apoorv Karkare Jun 13 '18 at 10:22
14

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!

enter image description here

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:

enter image description here

Phong Nguyen
  • 6,897
  • 2
  • 26
  • 36
2

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".


enter image description here


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;
}
Jossef Harush Kadouri
  • 32,361
  • 10
  • 130
  • 129
  • thank man! I figured out my answer is not properly. But I also find out more simple way to calculate the visible radius. we already have coordinate values so we don't need to apply *Pythagorean* that have to calculate distance 2 times for width and height, you can check my updated answer – Phong Nguyen Jan 16 '19 at 11:15
  • How to exclude area which is not part of Visible Map/Region? I'm talking about left/right radius curve which is out of visibility. – VVB Apr 26 '19 at 05:37
  • 1
    VVB the facto one use case for circle is to use the geo latlong + radius to filter only relevant data from your DB. You can manually filter out the results that are out of the viewport according to the viewport's rectangle bounding box – Jossef Harush Kadouri Apr 26 '19 at 06:34
2

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)

    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
}
Kishan Solanki
  • 13,761
  • 4
  • 85
  • 82
0

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.

Sevle
  • 3,109
  • 2
  • 19
  • 31
kaho
  • 4,746
  • 1
  • 16
  • 24
  • thanks for the reply but isn't these methods and these links refer to v3? which is only available for javascript right now? – awaistoor Mar 24 '15 at 20:51