Set a max zoom level on LatLngBounds builder

落花浮王杯 提交于 2019-11-27 10:09:11

问题


I haven't found an answer in my search, there are a few answers on SO but they didn't work for me.

I have 2 markers on the map and I am using LatLngBounds builder in order to let the camera zoom to the right zoom level to include them both. Everything works as expected aside one thing, when the 2 markers are really close to each other, the map is very very zoomed and well, it doesn't make any sense to have this level of zooming.

LatLngBounds.Builder builder = new LatLngBounds.Builder();
builder.include(firstMarker.getPosition());
builder.include(secondMarker.getPosition());
LatLngBounds bounds = builder.build();

CameraUpdate cu = CameraUpdateFactory.newLatLngBounds(bounds, markerPadding);

Is there a way to force a certain level of zoom, after which the camera won't zoom ? This would avoid having the map too zoomed in/out. Basically I am using 15.0f as level of zoom. If the points are too far away I want the zoom to fit them both. If points are getting close I don't want the zoom level to go beyond 15.0f.


回答1:


I have a similar case, where I want at least a map diagonal of 2 kilometers. Therefore I just add two additional points to the builder: the first 1 km north-west of the center of the original bounds and the second 1 km south-east of the center. If these are inside the bounds, they do not change anything. If they are outside of the original bounds, they increase the bounds to a meaningful size.

Here is a full code example:

public LatLngBounds createBoundsWithMinDiagonal(MarkerOptions firstMarker, MarkerOptions secondMarker) {
    LatLngBounds.Builder builder = new LatLngBounds.Builder();
    builder.include(firstMarker.getPosition());
    builder.include(secondMarker.getPosition());

    LatLngBounds tmpBounds = builder.build();
    /** Add 2 points 1000m northEast and southWest of the center.
     * They increase the bounds only, if they are not already larger
     * than this. 
     * 1000m on the diagonal translates into about 709m to each direction. */
    LatLng center = tmpBounds.getCenter();
    LatLng northEast = move(center, 709, 709);
    LatLng southWest = move(center, -709, -709);
    builder.include(southWest);
    builder.include(northEast);
    return builder.build();     
}

private static final double EARTHRADIUS = 6366198;
/**
 * Create a new LatLng which lies toNorth meters north and toEast meters
 * east of startLL
 */
private static LatLng move(LatLng startLL, double toNorth, double toEast) {
    double lonDiff = meterToLongitude(toEast, startLL.latitude);
    double latDiff = meterToLatitude(toNorth);
    return new LatLng(startLL.latitude + latDiff, startLL.longitude
            + lonDiff);
}

private static double meterToLongitude(double meterToEast, double latitude) {
    double latArc = Math.toRadians(latitude);
    double radius = Math.cos(latArc) * EARTHRADIUS;
    double rad = meterToEast / radius;
    return Math.toDegrees(rad);
}


private static double meterToLatitude(double meterToNorth) {
    double rad = meterToNorth / EARTHRADIUS;
    return Math.toDegrees(rad);
}



回答2:


I implemented this solution according to the answer by user2808624, but using the SphericalUtil from the Android Maps Utility Library to do the calculations.

final double HEADING_NORTH_EAST = 45;
final double HEADING_SOUTH_WEST = 215;
LatLng center = tmpBounds.getCenter();
LatLng norhtEast = SphericalUtil.computeOffset(center, 709,HEADING_NORTH_EAST);
LatLng southWest = SphericalUtil.computeOffset(center, 709,HEADING_SOUTH_WEST );



回答3:


Here is a much shorter version based on user2808624's answer.

        LatLngBounds bounds = builder.build();
        LatLng center = bounds.getCenter();
        builder.include(new LatLng(center.latitude-0.001f,center.longitude-0.001f));
        builder.include(new LatLng(center.latitude+0.001f,center.longitude+0.001f));
        bounds = builder.build();

Its a bit sloppy, but you can use 0.001 to zoom no less than a city block, 0.01 for no less than a city view. Only advantage is its only 4 extra lines of code.




回答4:


Coming late but maybe someone has the same issue I had: I received bounds from a Place, not from a LatLngBounds.Builder:

I used Location.distanceBetween(...) to find out if the bounds were too small, and then use a minimum zoom level with the center of the bounds:

if (areBoundsTooSmall(bounds, 300)) {
    mMap.animateCamera(CameraUpdateFactory.newLatLngZoom(bounds.getCenter(), 17));
} else {
    mMap.animateCamera(CameraUpdateFactory.newLatLngBounds(bounds, 20));
}

The check method is:

private boolean areBoundsTooSmall(LatLngBounds bounds, int minDistanceInMeter) {
    float[] result = new float[1];
    Location.distanceBetween(bounds.southwest.latitude, bounds.southwest.longitude, bounds.northeast.latitude, bounds.northeast.longitude, result);
    return result[0] < minDistanceInMeter;
}

I used min zoom level 17 and padding 20 for bounds that are too small, too small is definded here by min distance in meter 300. You can adjust the numbers as you need.




回答5:


It is just simple:

LatLngBounds.Builder latlngBuilder = new LatLngBounds.Builder();

LatLng sydney1 = new LatLng(57.149651, -2.099075);

LatLng sydney2 = new LatLng(51.621441, -3.943646);

latlngBuilder.include(sydney1);
latlngBuilder.include(sydney2);

googlemap.animateCamera(CameraUpdateFactory.newLatLngBounds(latlngBuilder.build(), 100));



回答6:


Google has added an api for limiting max/min zoom levels.

GoogleMap.setMaxZoomPreference()
GoogleMap.setMinZoomPreference()



回答7:


Quick fix is:

gMap.setOnMapLoadedCallback(this);
CameraUpdate cu = CameraUpdateFactory.newLatLngBounds(bounds, padding);
gMap.setMaxZoomPreference(10);
gMap.animateCamera(cu);


@Override
public void onMapLoaded() {
    gMap.resetMinMaxZoomPreference();
}

Beware that it could halt zoom until map is fully reloaded. But as a quick fix it works.




回答8:


Have you considered making a map fragment that is hidden, and using that to determine your zoom/bounds? It's obviously not the best computationally, but it's probably the easiest/most accurate solution. For instance, it's complex to make a mathematical solution that works near the poles and across 0 degrees longitude (if you care). If you use a map, that's all built in already. You could also obviously use this solution on your existing map, but the user would see a bounce.

Here's how you'd do it:

  1. Go to the bounds as you've defined above
  2. Get the zoom using map.getCameraPosition().zoom.
  3. If zoom > 15 zoom out to 15 using CameraUpdateFactory.zoomTo(15)



回答9:


Following from the answers by user2808624 and dvdrlee, I wrote an extension in Kotlin:

fun LatLngBounds.Builder.createBoundsWithZoomMaintained(bounds: LatLngBounds) : LatLngBounds  {
    val HEADING_NORTH_EAST = 45.0   //NorthEast angle
    val HEADING_SOUTH_WEST = 215.0  //SouthWest angle
    val center = bounds.center
    val northEast = SphericalUtil.computeOffset(center, 709.0, HEADING_NORTH_EAST)  //1000 metres on the diagonal translates to 709 metres on either side.
    val southWest = SphericalUtil.computeOffset(center, 709.0, HEADING_SOUTH_WEST)
    this.include(northEast).include(southWest)
    return this.build()
}

This would typically be in your Utils or Extensions file, and then you can use it from anywhere simply like this:

var bounds = builder.build()  //To include all your existing points.
bounds = builder.createBoundsWithZoomMaintained(bounds)  //Updated bounds.
mMap.animateCamera(CameraUpdateFactory.newLatLngBounds(bounds, 10)) 



回答10:


There is no way to limit zoom levels as of 4.0.30, but you may track this issue.

The easy way would be to force zoom level like on this video: http://www.youtube.com/watch?v=-nCZ37HdheY
Basically they are calling animateCamera when certain zoom level is reached.

That would look a bit weird, because you then have 2 animations that are not started by the user.

The hard way would be doing the math yourself. Try working with CameraUpdateFactory.newLatLngZoom with LatLng as a center between these points and your max zoom when you detect points are close to each other.



来源:https://stackoverflow.com/questions/20571951/set-a-max-zoom-level-on-latlngbounds-builder

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