tricky Android Google Map zoom while maintaining center point - android

It's not easy explaining my problem but I will try.
I have an android GoogleMap, on top of it, I have an ImageView positioned at its center at all times. If I drag/pan the map, the pin will always be in the center of the GoogleMap.
Now, I add a marker, somewhere on the map. I want to zoom such that the center point remains in the center of the map, and the marker is visible within the map, and to the highest zoom level.
The problem is if I simply check if the marker is within boundaries of the map or not, and then keep zooming in/out till it is, this process will always repeat itself, i.e. trying to zoom in and if the marker became outside, then zoom out.
The problem is I rely on an OnCameraChange listener which will keep calling itself everytime I zoom in or out, hence, the process of zooming in/out will keep occuring indefinitely
journeyGoogleMap.setOnCameraChangeListener(new OnCameraChangeListener()
{
#Override
public void onCameraChange(final CameraPosition position)
{
Basically, what I need is a function where I can provide the center LatLng and the markerLatLng and it will automatically calculate the LatLngBounds making sure my center is within the center of the LatLng bounds, and then I can simply use
public static CameraUpdate newLatLngBounds (LatLngBounds bounds, int width, int height, int padding)
as shown in the link below
https://developers.google.com/maps/documentation/android/reference/com/google/android/gms/maps/CameraUpdateFactory#newLatLngBounds(com.google.android.gms.maps.model.LatLngBounds,int, int,int)
If you need anymore clarification please do tell me

You need to calculate LatLngBounds from two points:
Your marker position and
Place on the opposite side of your current center.
The second is calculated like this:
LatLng other = new LatLng(2 * center.latitude - position.latitude, 2 * center.longitude - position.longitude);
See LatLngBoundsUtils.fromCenterAndPositions for a general solution.

Use googleMap.getProjection().getVisibleRegion() to get all four corners of screen as LatLng values forming trapezium. Calculate where trapezium intersects with line drawn through center and your marker. Scale factor is (distance from center to marker / distance from center to intersection point). Now just scale trapezium with this scale factor relative to center. This is new visible regison.
You may also use getVisibleRegion().latLngBounds to simplify calculation, but note that some areas of returned rectangle are actually not visible.

Related

Android GoogleMap: add a marker in a form of a line with angle from origin

I have a list of coordinates (yLat, xLon) with an angle (bearing in degrees, e.g. 160) to draw on my map, and I would like to do it with lines or arrows which start from the coordinates and head to the bearing.
I started to do it using a Polyline:
LatLng thisPoint = new LatLng(yLat, xLon);
Polyline site = googleMap.addPolyline(new PolylineOptions()
.add(thisPoint, new LatLng(11.593, 104.932))
.width(5)
.color(Color.MAGENTA));
However the line is too small when I zoom out: I want the line to be always the same size on the screen to show the direction to the user and independently of the zoom level.
See the example below: on the first screenshot the magenta line is big enough, but on the second one after zooming out, the line becomes smaller and we cannot see the direction as clearly.
Any suggestion?
I found the best way to address my need: I created a marker with an icon with a vertical arrow in the middle of a transparent square (R.mipmap.ic_arrow_up), then I create the marker applying a rotation of the desired angle:
googleMap.addMarker(new MarkerOptions()
.position(myLatLng)
.title(myTitle)
.snippet(mySnippet)
.icon(BitmapDescriptorFactory.fromResource(R.mipmap.ic_arrow_up))
.rotation(myAngle));
Hope this helps other people

Get the LatLngBouds from a camera position

I want to get the LatLng of the top right corner and bottom left corner of a Google Map frame to create a LatLngBounds. Is it possible to do that?
This can easily be determined using the Map View API:
yourMapFragment.getMap().getProjection().getVisibleRegion().latLngBounds
Which the docs state is:
The smallest bounding box that includes the visible region defined in this class.
Alternatively, you can also get the individual corners of the projection by replacing latLngBounds with farLeft, farRight, nearLeft or nearRight
In your case, you can simply use
LatLng bottomLeft =
yourMapFragment.getMap().getProjection().getVisibleRegion().nearLeft;
LatLng topRight =
yourMapFragment.getMap().getProjection().getVisibleRegion().farRight;
Of course. You have the Visible Region Object, that has the coordinates of all the four angles. Please refer to documentation.

How to put marker at bottom of map instead of center(by default) of map with zoom enabled in android?

In live track app I want to animate camera above marker and want to put marker always at bottom in newLocationChanged.
If I am building CameraPosition without zoom, It works fine.
But with zoom also I need to achieve same.
Use the screen boundaries to get the desired position:
As per documentation:
getBounds()
Return Value: LatLngBounds
Returns the lat/lng bounds of the current viewport. If more than one copy of the world is visible, the bounds range in longitude from -180 to 180 degrees inclusive. If the map is not yet initialized (i.e. the mapType is still null), or center and zoom have not been set then the result is null or undefined.

Attain maximum zoom on google map showing all markers

i have 5 markers to display on the map, out of which 4 are very near to each other and the fifth one is a little bit distant to these 4. now when i display the map i want all these 5 markers to be shown on map and the with the highest possible zoom. i dont care whether they are on the border of the screen or in the center of the screen.i mean the markers can be scattered on the screen but all i want is that all markers should visible to the user and with the highest possible zoom.
i have tried this Android map v2 zoom to show all the markers . but the result is that it is showing all markers at the center of the map with very little zoom. actually i have calculated screen dimensions using this code.
DisplayMetrics metrics=new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrics);
float height=metrics.heightPixels/metrics.xdpi;
float width=metrics.widthPixels/metrics.ydpi;
but i dont know why there is very little zoom. But wen i saw android documentation, i think the function is doing justice by doing whatever it said it will do.
public static CameraUpdate newLatLngBounds (LatLngBounds bounds, int width, int height, int padding)
Returns a CameraUpdate that transforms the camera such that the specified
latitude/longitude bounds are centered on screen within a bounding box of specified
dimensions at the greatest possible zoom level. You can specify additional padding,
to further restrict the size of the bounding box. The returned CameraUpdate has a
bearing of 0 and a tilt of 0.
Unlike newLatLngBounds(LatLngBounds, int), you can use the CameraUpdate returned by
this method to change the camera prior to the map's the layout phase, because the
arguments specify the desired size of the bounding box.
as it says it keeps all the markers at the center of the map. i do not want that. i want all the markers visible to the user with the maximum possible zoom and markers scattered. can anybody please help me?
Your calculation of float width and height is incorrect.
What your width holds now is inches (value of approx. 2 on phones). You need not to divide pixels width.

Google MapView zoomout to span a circle

I have a MapView centered at point P. The user can't change the MapView center, but he can choose a radius of a circle to be display around point P, and change it dynamically with the map being redrawn at each change to show the new circle.
The thing is, i want the map to zoom in or out as necessary, in order to display the entire circle at the viewable area. I've tried this:
Projection proj = m_Map.getProjection();
Point mapCenterPixles = new Point();
proj.toMapPixels(center, mapCenterPixles);
float radiusPixels = proj.metersToEquatorPixels(newRadius);
IGeoPoint topLeft = proj.fromPixels(mapCenterPixles.x - radiusPixels,
mapCenterPixles.y - radiusPixels);
IGeoPoint bottomRight = proj.fromPixels(mapCenterPixles.x
+ radiusPixels, mapCenterPixles.y + radiusPixels);
m_Map.getController().zoomToSpan(
topLeft.getLatitudeE6() - bottomRight.getLatitudeE6(),
topLeft.getLongitudeE6() - bottomRight.getLongitudeE6());
But it seems i'm missing something, as the values passed to zoomToSpan() cause no chnage, I'm kind of lost here, can someone please shed some light on how to zoom the map to span a bounding box of the circle given its radius in meters, and its center points?
Google Maps zoom levels are defined in powers of two, so MapController#zoomToSpan() also zooms by powers of two.
Ergo, if the span you compute above is already displayable within the current zoom level, it's likely nothing would actually change visually in the map until you need to go to the next larger or smaller zoom level.
This behavior is somewhat vaguely described in the documentation for MapController#zoomToSpan

Categories

Resources