zoom over specific route google map
Asked Answered
S

9

16

enter image description herebelow is screen shot @antonio what i get after removing line

I have a list of random latitude and longitude points and I am drawing a route between them. My question is how to bound this route within google map I made below utility method

public static void drawRouteIntoMap(final List<? extends MapHelper> position, final GoogleMap googleMap) {
    /*List<MapHelper> position = new ArrayList<MapHelper>();
    for (int i = lastPosition; i < maps.size(); i++) {
        position.add(maps.get(i));
    }*/
    if (position.size() > 0 && Validator.isNotNull(googleMap)) {
        googleMap.clear();
        List<PolylineOptions> polylineOptionses = new ArrayList<PolylineOptions>();
        PolylineOptions option = null;
        Boolean lastPause = null;
        for (MapHelper map : position) {
            if (map.isPause()) {
                if (Validator.isNull(lastPause) || !lastPause) {
                    option = new PolylineOptions().width(5).color(Color.rgb(255, 0, 155)).geodesic(true);
                    polylineOptionses.add(option);
                }
                option.add(new LatLng(map.getLatitude(), map.getLongitude()));
            } else {
                if (Validator.isNull(lastPause) || lastPause) {
                    option = new PolylineOptions().width(5).color(Color.rgb(0, 179, 253)).geodesic(true);
                    polylineOptionses.add(option);
                }
                option.add(new LatLng(map.getLatitude(), map.getLongitude()));
            }
            lastPause = map.isPause();
        }
        for (PolylineOptions options : polylineOptionses) {
            googleMap.addPolyline(options);
        }
        if(Validator.isNotNull(option)){
            //List<LatLng> points = option.getPoints();
            final LatLngBounds.Builder mapBounds = new LatLngBounds.Builder();

            googleMap.setOnMapLoadedCallback(new GoogleMap.OnMapLoadedCallback() {
                @Override
                public void onMapLoaded() {
                    LatLng startPoint = new LatLng(position.get(0).getLatitude(), position.get(0).getLongitude());
                    googleMap.addMarker(new MarkerOptions().position(startPoint).title("start").icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_GREEN)));
                    mapBounds.include(startPoint);
                    LatLng endPoint = new LatLng(position.get(position.size() - 1).getLatitude(), position.get(position.size() - 1).getLongitude());
                    mapBounds.include(endPoint);
                    googleMap.addMarker(new MarkerOptions().position(endPoint).title("finish").icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_RED)));
                    googleMap.moveCamera(CameraUpdateFactory.newLatLngBounds(mapBounds.build(), 10));
                   /* googleMap.animateCamera(CameraUpdateFactory.newLatLngBounds(mapBounds.build(), 10));
                    googleMap.moveCamera(CameraUpdateFactory.zoomOut());*/

                }
            });
        }

    }
}

here last pause is boolean indicating whether it is paused point for indicating red color polyline.

but it is not working.Any help is appreciated.

Sigvard answered 23/9, 2016 at 9:7 Comment(4)
@Yvette i want to show this whole route in given mapview with lite mode such that entire route is clearly get visible with start point,end point and polyline between this two markerSigvard
@Yvette i have uploaded screen shot,there is list of such itemsSigvard
@Yvette yes i want to show this different routes withinn this map areaSigvard
Showing all points that were added to a map. #19672290Emanative
C
30

Try implementing this way

/**
 * Zooms a Route (given a List of LalLng) at the greatest possible zoom level.
 *
 * @param googleMap: instance of GoogleMap
 * @param lstLatLngRoute: list of LatLng forming Route
 */
public void zoomRoute(GoogleMap googleMap, List<LatLng> lstLatLngRoute) {

    if (googleMap == null || lstLatLngRoute == null || lstLatLngRoute.isEmpty()) return;

    LatLngBounds.Builder boundsBuilder = new LatLngBounds.Builder();
    for (LatLng latLngPoint : lstLatLngRoute)
        boundsBuilder.include(latLngPoint);

    int routePadding = 100;
    LatLngBounds latLngBounds = boundsBuilder.build();

    googleMap.moveCamera(CameraUpdateFactory.newLatLngBounds(latLngBounds, routePadding));
}

UPDATE

After looking at the image, there are layouts above map. So it would require you to set Variable Padding. You can do it as

googleMap.setPadding(left, top, right, bottom);

Note: While setting variable padding, you can initialize routePadding = 0; In your case, approximations are: left = right = 10, bottom=100, top=200. Once set, you can calibrate'em as per your requirement.

Recommendation: You can calculate the height of those (top and bottom) layouts in pixels and then set padding accordingly.

Capitally answered 29/9, 2016 at 22:4 Comment(8)
why you chosse padding value of 100?Sigvard
Padding is used so that the Markers (if existent at points) don't get clipped during zoom and the Route doesn't touch the Map Edges. You can set your own Custom Value (e.g., the Height or Width of the Marker Image). It could even be 0 if you wish the Route should touch the Map Edges.Capitally
i have tried your solution but still in some route marker is get clipped i can upload screen shotSigvard
Try increasing the Padding >= 2 * Height of Marker (in pixels)Capitally
currently i am using BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_RED) this method for markerSigvard
do you know what will be default height because in documentation it is saying about constant onlySigvard
I don't have any idea about that but as a work-around you can continue increasing the padding until your Markers are not clipped. Also, did the above solution helped in any way??Capitally
it is working but still for some routes marker or route is 60% visible. so can u please help on calculating padding dynamically.@Rishabh Dutt Sharma i uploaded screen shot that i got after trying this solution (padding values are : 15(Left), 205(Top), 10(Right), 110(Bottom))Sigvard
S
7

The reason, why zooming in is not working might be because map has not been inflated yet at the time of calling the method:

moveCamera(com.google.android.gms.maps.CameraUpdate)

Try adding ViewTreeObserver.OnGlobalLayoutListener to the map:

ViewTreeObserver vto = googleMap.getViewTreeObserver();
ViewTreeObserver.OnGlobalLayoutListener globalLayoutListener = new ViewTreeObserver.OnGlobalLayoutListener() {
    @Override
    public void onGlobalLayout() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
            googleMap.getViewTreeObserver().removeOnGlobalLayoutListener(this);
        } else {
            googleMap.getViewTreeObserver().removeGlobalOnLayoutListener(this);
        }
        googleMap.moveCamera(CameraUpdateFactory.newLatLngBounds(mapBounds.build(), 10));
    }
};
vto.addOnGlobalLayoutListener(globalLayoutListener);

If the method above does not work GoogleMap has it's own listener for layout, you might use that:

googleMap.setOnCameraChangeListener(new OnCameraChangeListener() {

    @Override
    public void onCameraChange(CameraPosition arg0) {
        googleMap.moveCamera(CameraUpdateFactory.newLatLngBounds(mapBounds.build(), 10));
        googleMap.setOnCameraChangeListener(null);
    }
});

However, as of play-services-maps 9.4.0 version of the API the method above is deprecated. Use one of:

Seidule answered 28/9, 2016 at 9:6 Comment(0)
S
4

You need to include all the points that form the polyline into your mapBounds object.

Also, you are updating the camera using animateCamera and then you are moving it using moveCamera. This second camera update overrides the first one. Just remove the line

googleMap.moveCamera(CameraUpdateFactory.zoomOut());

This line is also innecesary (you don't need to move and animate the camera, just one of them):

googleMap.moveCamera(CameraUpdateFactory.newLatLngBounds(mapBounds.build(), 10));

If you need to zoom out a bit your map you can play with the padding parameter of the CameraUpdateFactory.newLatLngBounds method.

Split answered 30/9, 2016 at 11:41 Comment(8)
i have uploaded screen shot see markers are not displaying properly this is justone route there can be different other routes like thisSigvard
How are you drawing your route? Could you post an example?Split
please check it i uploaded methodSigvard
You need to add all the points that form the polyline to your mapBoundsSplit
see i uploaded image in this i have included all the points in mapbounds forming polyline. still end marker is not visibleSigvard
OK, now the problem is that you need to increase the padding of the CameraUpdateFactory.newLatLngBounds to fit the Marker that lays on the topSplit
so how can i determine padding every time depand on route pathSigvard
Let us continue this discussion in chat.Sigvard
D
3

I implemented a similar solution to @rishabh-dutt-sharma with a couple of twists:

  • First of all, before zooming check if the points are already inside the view. If they are, do not change it. This means less unneeded changes in the UI for the user.
  • Second, a special case is when there is just one point. This is useful when showing a list of markers, and maybe is not needed in your particular case. The reason of why is this useful is because in the case of single point, the zoom usually is increased to the maximum, and usually this is too much.

This is the code (adapted from my original code, I hope there are no typos):

    public void zoomRoute(GoogleMap googleMap, List<LatLng> lstLatLngRoute) {

        if (googleMap == null || lstLatLngRoute == null || lstLatLngRoute.isEmpty()) return;

        LatLngBounds currentLatLongBounds =
                googleMap.getProjection().getVisibleRegion().latLngBounds;
        boolean updateBounds = false;

        for (LatLng latLng : lstLatLngRoute) {
            if (!currentLatLongBounds.contains(latLng)) {
                updateBounds = true;
            }
        }

        if (updateBounds) {

            CameraUpdate cameraUpdate;

            if (lstLatLngRoute.size() == 1) {

                LatLng latLng = lstLatLngRoute.iterator().next();
                cameraUpdate = CameraUpdateFactory.newLatLng(latLng);

            } else {

                LatLngBounds.Builder builder = LatLngBounds.builder();
                for (LatLng latLng : lstLatLngRoute) {
                    builder.include(latLng);
                }
                LatLngBounds latLongBounds = builder.build();

                cameraUpdate =
                        CameraUpdateFactory.newLatLngBounds(latLongBounds, MAP_ZOOM_PADDING);

            }

            try {
                googleMap.animateCamera(cameraUpdate, MAP_CAMERA_ANIMATION_DURATION_IN_MILLIS,
                        new GoogleMap.CancelableCallback() {
                            @Override
                            public void onFinish() {
                            }

                            @Override
                            public void onCancel() {
                            }
                        });
            } catch (IllegalStateException ex) {
                // Ignore it. We're just being a bit lazy, as this exception only happens if
                // we try to animate the camera before the map has a size
            }
        }
    }
Dicarlo answered 3/10, 2016 at 12:50 Comment(2)
what will be the value of this constants for padding & animation duration secondSigvard
Padding is the number of pixels, I use 90dp for density independence, which you can store in a dimen resource or convert from a constant with a routine like this: public static float dipToPixels(Context context, float dipValue) { DisplayMetrics metrics = context.getResources().getDisplayMetrics(); return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dipValue, metrics); }. Animation duration is in milliseconds, I use 500 for fast and smooth animations.Dicarlo
P
3

you can do one thing, find out the distance between 2 latitude and longitude and make check over distance that you got.See,how it work . It's a trick it might useful for you.

googleMap.moveCamera(CameraUpdateFactory.newLatLng(reachLocationLatLng));
if (dist > 2 && dist <= 5) {
googleMap.animateCamera(CameraUpdateFactory.zoomTo(13.0f));
mapZoomLevel = 12;
} else if (dist > 5 && dist <= 10) {
googleMap.animateCamera(CameraUpdateFactory.zoomTo(12.0f));
mapZoomLevel = 11;
} else if (dist > 10 && dist <= 20) {
googleMap.animateCamera(CameraUpdateFactory.zoomTo(11.0f));
mapZoomLevel = 11;
} else if (dist > 20 && dist <= 40) {
googleMap.animateCamera(CameraUpdateFactory.zoomTo(10.0f));
mapZoomLevel = 10;
} else if (dist > 40 && dist < 100) {
googleMap.animateCamera(CameraUpdateFactory.zoomTo(9.0f));
mapZoomLevel = 9;
} else if (dist > 100 && dist < 200) {
googleMap.animateCamera(CameraUpdateFactory.zoomTo(8.0f));
mapZoomLevel = 8;
} else if (dist > 200 && dist < 400) {
googleMap.animateCamera(CameraUpdateFactory.zoomTo(7.0f));
mapZoomLevel = 7;
} else if (dist > 400 && dist < 700) {
googleMap.animateCamera(CameraUpdateFactory.zoomTo(6.0f));
mapZoomLevel = 7;
} else if (dist > 700 && dist < 1000) {
googleMap.animateCamera(CameraUpdateFactory.zoomTo(5.0f));
mapZoomLevel = 6;
} else if (dist > 1000) {
googleMap.animateCamera(CameraUpdateFactory.zoomTo(4.0f));
mapZoomLevel = 5;
} else {
googleMap.animateCamera(CameraUpdateFactory.zoomTo(14.0f));
mapZoomLevel = 14;
}

Thanks hope this will help you.

Passbook answered 4/10, 2016 at 3:29 Comment(0)
H
1
 googleMap.moveCamera(CameraUpdateFactory.newLatLngZoom(endPoint,zoomLevel));

Try it if it helps you

Heger answered 23/9, 2016 at 9:42 Comment(7)
what zoomlevel shold i setSigvard
you can try for any number 10, 12, 15 and check the changesHeger
after all these lines i add this or at any other place?Sigvard
googleMap.moveCamera(CameraUpdateFactory.newLatLngBounds(mapBounds.build(), 10)); replace this lineHeger
which values you have tried and what you can see as outputHeger
Let us continue this discussion in chat.Sigvard
This wont help you when your source and destination are varyingLabourite
E
0

How I did it.

Android - plotting gps coordinate on custom map

Yes you can draw points that aren't on the visible map. Get around this by setting up a LatLngBounds. Then display the map for the LatLngBounds. You can also move the map to display the LatLngBounds. There's nothing tricky here no tangents or slopes or hyperbolic curvature of the earth. All that's taken care of by the point which is in degrees so don't over think your solution. If you turn the map the points will turn with it. So add your points to the map find the bounds and tilt the camera. Tilt the camera back and all the points will still be on screen! This will get you started with the all the points on the screen.

Same as the samples get a reference to a google map.

private void setUpMapIfNeeded() {
// Do a null check to confirm that we have not already instantiated the
// map.

if (mMap == null) {
    // Try to obtain the map from the SupportMapFragment.
    // mMap = mMapFragment.getMap();
    // // Check if we were successful in obtaining the map.

    // Try to obtain the map from the SupportMapFragment.
    mMap = ((SupportMapFragment) getSupportFragmentManager()
            .findFragmentById(R.id.map)).getMap();
    // use the settings maptype

    // Check if we were successful in obtaining the map.
    if (mMap != null) {
        setUpMap();
    }
}
}

Let's get started finding the boundry of the map.

import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.LatLngBounds;
A field for LatLngBounds and a LatLngBounds.Builder

private LatLngBounds bounds;
private LatLngBounds.Builder myLatLngBuilder;
initialize the LatLngBounds.Builder

myLatLngBuilder = new LatLngBounds.Builder();
for each point on your map.

LatLng myLatLng = new LatLng(latitude, longitude);
myLatLngBuilder.include(myLatLng);
Then when your finished adding points build your boundary.

bounds = myLatLngBuilder.build();
Now I have the bounds of all the points on my map and I can display just that area of the map. This code I lifted from the map samples.

final View mapView = getSupportFragmentManager().findFragmentById(
            R.id.map).getView();
    if (mapView.getViewTreeObserver().isAlive()) {
        mapView.getViewTreeObserver().addOnGlobalLayoutListener(
                new OnGlobalLayoutListener() {
                    @SuppressWarnings("deprecation")
                    // We use the new method when supported
                    @SuppressLint("NewApi")
                    // We check which build version we are using.
                    @Override
                    public void onGlobalLayout() {
                        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
                            mapView.getViewTreeObserver()
                                    .removeGlobalOnLayoutListener(this);
                        } else {
                            mapView.getViewTreeObserver()
                                    .removeOnGlobalLayoutListener(this);
                        }
                        mMap.moveCamera(CameraUpdateFactory
                                .newLatLngBounds(bounds, 50));
                    }
                });
    }
Emanative answered 3/10, 2016 at 21:12 Comment(0)
V
0

This is very late to answer try with this shortest way

First of All get your current location latlongs then your write code for your destination lat longs then calculate distance between your current location and destination location with this code

private double distance(double lat1, double lon1, double lat2, double lon2) {
  double theta = lon1 - lon2;
  double dist = Math.sin(deg2rad(lat1)) * Math.sin(deg2rad(lat2)) + Math.cos(deg2rad(lat1)) * Math.cos(deg2rad(lat2)) * Math.cos(deg2rad(theta));
  dist = Math.acos(dist);
  dist = rad2deg(dist);
  dist = dist * 60 * 1.1515;
   return (dist);
}
private double deg2rad(double deg) {
  return (deg * Math.PI / 180.0);
}
private double rad2deg(double rad) {
  return (rad * 180.0 / Math.PI);
}
  • you can never get same lat longs data because of GPS count 95 meters from your current location to display current location pin or lat long data. either you are same location you can never find exact lat long data this must be differ in points so thats by you need to get distance your current location to your fix lat long data points.

  • when ever you find "distance" from your destination points to current lat long then fire this code to animate camera and zoom.

    map.moveCamera( CameraUpdateFactory.newLatLngZoom(new LatLng(xxxx,xxxx),21));
    
Visionary answered 4/10, 2016 at 4:8 Comment(0)
C
0

Probably This would be most simple solution for above mentioned problem, It worked for me very well.

Add all the waypoints to the target under GoogleMapOptions:camera, then it will automatically set the zoom and center the map with respect to Polyline( given Route).

loadMap() {

let mapOptions: GoogleMapOptions = {
  camera: {
    target: this.wayPoints,
    zoom: 25,
    tilt: 30
  }
};

this.map = GoogleMaps.create('map_canvas', mapOptions);
this.map.one(GoogleMapsEvent.MAP_READY)
  .then(() => {
    console.log('Map is ready!');


   this.map.addPolyline({
      points:this.wayPoints,
      color:'#586bff',
      width: 8,
      geodesic:true,
    });
});
}

The waypoints( this.wayPoints ) should be in this format:

[{lat: 52.33806, lng: 8.61179},
{lat: 52.33812, lng: 8.61185},
{lat: 52.33812, lng: 8.61186},
{lat: 52.33812, lng: 8.61188}]
Couch answered 20/3, 2018 at 14:21 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.