How to scale a MapView from Pixels to Meters - android

I'm making an Android application which uses Google Maps API, and I want to scale a MapView to X_pixels:X_meters.
For example, 5 pixels of the MapView in my screen, 20 meters on reality.
Is that possible?
Thx

Use the following code:
int nPixles = 5; //number of pixels
GeoPoint g0 = mapview.getProjection().fromPixels(0, mapview.getHeight()/2);
GeoPoint g1 = mapview.getProjection().fromPixels(nPixles, mapview.getHeight()/2);
float[] results = new float[1];
Location.distanceBetween(g0.getLatitudeE6()/1E6, g0.getLongitudeE6()/1E6, g1.getLatitudeE6(), g1.getLongitudeE6()/1E6, results);
float distanceInMeters = results[0];
This calculates distance in meters for latitude level at screen center. Because earth is spheric distance vary from bottom to the top of screen. This is mostly noticed with low zoom levels.
Regards.

Related

Move markers by a specific distance in meters from where they are

I have a collection of items and some of them may have the same coordinates.
As a result they are displayed as 1 marker in Google Maps since the markers are painted one on top of each other.
To address this I tried to "move" those markers by a few meters so that the markers do not collide.
I would like to move them to a 5 meters from where their location is.
I did the following following another SO answer:
double newLat = item.getLatitude() + (Math.random() - .005) / 15000;
double newLon = item.getLongitude() + (Math.random() - .005) / 15000;
The problem is that this moves the items a bit but it seems that some are moved by 4m others by 3m and I would like if possible to ensure that I will be between 4-6 meters (min/max)
How can I change my formula to do this?
I think that the best option could be using the SphericalUtil. computeOffset method from the Google Maps Android API Utility Library:
computeOffset
public static LatLng computeOffset(LatLng from,
double distance,
double heading)
Returns the LatLng resulting from moving a distance from an origin in the specified heading (expressed in degrees clockwise from north).
Parameters:
from - The LatLng from which to start.
distance - The distance to travel.
heading - The heading in degrees clockwise from north.
In your case you can set the distance to be 5 meters and randomise the heading parameter to be something between 0 and 360 degrees:
Random r = new Random();
int randomHeading = r.nextInt(360);
LatLng newLatLng = SphericalUtil.computeOffset(oldLatLng, 5, randomHeading);

I put the zoom to get my mobile screen focused to 5 km from my current location

I am creating an android app where I am displaying current location. I just want to know what should I put the zoom to get my mobile screen focused to 5 km from my current location. Thank You in advance.
That depends on the width of your map view element.
According to CameraPosition.Builder.zoom:
Sets the zoom level of the camera. Zoom level is defined such that at
zoom level 0, the whole world is approximately 256dp wide (assuming
that the camera is not tilted). Increasing the zoom level by 1 doubles
the width of the world on the screen. Hence at zoom level N, the width
of the world is approximately 256 * 2 N dp, i.e., at zoom level 2, the
whole world is approximately 1024dp wide.
When changing the camera position for a map, the zoom level of the
camera is restricted to a certain range depending on various factors
including location, map type and map size. Use
GoogleMap.getMinZoomLevel and GoogleMap.getMaxZoomLevel to find the
restrictions. Note that the camera zoom need not be an integer value.
You could try something like this:
private int calculateZoomLevel(int mapViewWidthInDp)
{
double equatorLength = 40075004; // in meters
double widthInDp = mapViewWidthInDp;
double metersPerDp = equatorLength / 256;
int zoomLevel = 0;
while ((metersPerDp * widthInDp) > 10000) {
metersPerDp /= 2;
++zoomLevel;
}
return zoomLevel;
}

google map api v2 zoom having center and distance between southwest and northeast

I want to perform a zoom on a region in google map
map.animateCamera(CameraUpdateFactory.newLatLngBounds(new LatLngBounds(southwest, northeast), padding)
the problem is that i dont have: southwest and northeast points
I just have the center of the map (LatLnt) and the distance in meters between southwest and northeast,
I'd like to know how to calculate southwest and northeast points from map_center and the distance?
any help is welcome
thank you in advance.
This answer assumes that you are using a square map. In other words that the angle from the starting point is 45 degrees (also assuming that the map is flat which means the distances are small). I am also assuming that you are not at either of the poles (yeah I know duh!).
Ok with that in mind it is simple geometry. Since you know the start point and the length from the Southwest corner to the Northeast corner I use half this distance as that is the distance from the starting point to each of these points. I am then finding the x and y component (which is the same with a square map) of this "half distance". To do this I just use the formula latlongOffset equals half of the "half distance" times the square root of 2.
the code is as follows (you provide a LatLng startPoint, Double someDistance, and int padding):
LatLng southwest, northeast;
Double swLat, neLat, swLng, neLng;
Double halfSomeDistance = someDistance / 2.0;
Double latlongOffset = halfSomeDistance * Math.sqrt(2.0) / 2.0;
swLat = startPoint.latitude - latlongOffset;
swLng = startPoint.longitude - latlongOffset;
neLat = startPoint.latitude + latlongOffset;
neLng = startPoint.longitude + latlongOffset;
southwest = new LatLng(swLat, swLng);
northeast = new LatLng(neLat, neLng);
map.animateCamera(CameraUpdateFactory.newLatLngBounds(new LatLngBounds(southwest, northeast), padding));
If you are not using a square map you will need to use right triangle geometry to get the latOffset and lngOffset as they will not be the same.
I hope this helps.

Get pixel distance in meters for mapView

I want to know how much meters is a certain pixel distance, at a given zoom level.
Reason: I want to know the radius, in meters, of a circle in the mapView, which fits perfectly in the mapView -> radiusPixels = mapView.getWidth()/2;
I found the method mapView.getProjection().metersToEquatorPixels(radiusMeters), which does the opposite of that what I need. But there's no inverse for this method or anything else useful.
My (probably naive) approach to solve it is as follows:
private double getFittingRadiusInMeters() {
return getMeters(mapView.getWidth() / 2);
}
private double getMeters(int pixels) {
Projection proj = mapView.getProjection();
Point mapCenterPixels = new Point(mapView.getWidth() / 2, mapView.getHeight() / 2);
//create 2 geopoints which are at pixels distance
GeoPoint centerGeoPoint = proj.fromPixels(mapCenterPixels.x, mapCenterPixels.y);
GeoPoint otherGeoPoint = proj.fromPixels(mapCenterPixels.x + pixels, mapCenterPixels.y);
Location loc = new Location("");
loc.setLatitude(centerGeoPoint.getLatitudeE6() / 1E6);
loc.setLongitude(centerGeoPoint.getLongitudeE6() / 1E6);
Location loc2 = new Location("");
loc2.setLatitude(otherGeoPoint.getLatitudeE6() / 1E6);
loc2.setLongitude(otherGeoPoint.getLongitudeE6() / 1E6);
return loc.distanceTo(loc2);
}
But it doesn't work well. I always get circles which are far smaller than the mapView - the radius is too small.
I know the distanceTo method says "approximate" but the radius differ significantly from the expected size. Should not be an effect of the approximation.
Thanks.
There is a small mistake in your approach.
You are calculating the value for screen half with at screen center level. The distance found is only valid to draw a circle at the same Latitude value (the Longitude may change without problem).
Because earth is shperic, the distance for the same number of pixels calculated at different Latitude levels, produces different results. Moving from Equador level to position closer to Pole level, same number of pixels result a in smaller distance in meters.
However, this will only be noticable if you call getFittingRadiusInMeters() with map positioned in a very distant Latitude from where you draw the circle.
Otherwise, it should work fine.
Solution
The method getMeters() should receive as parameter a GeoPoint (or at least the Latitude) that should be used to calculate the distance.
Regards.

How to compute a radius around a point in an Android MapView?

I have a MapView that I'm displaying a "useful radius" (think accuracy of coordinate) in. Using MapView's Projection's metersToEquatorPixels, which is admittedly just for equatorial distance) isn't giving me an accurate enough distance (in pixels). How would you compute this if you wanted to display a circle around your coordinate, given radius?
So, Google Maps uses a Mercator projection. This means that the further you get from the equator the more distorted the distances become. According to this discussion, the proper way to convert for distances is something like:
public static int metersToRadius(float meters, MapView map, double latitude) {
return (int) (map.getProjection().metersToEquatorPixels(meters) * (1/ Math.cos(Math.toRadians(latitude))));
}
mMap.addCircle(
new CircleOptions().center(
new LatLng(
bounds.getCenter().latitude,
bounds.getCenter().longitude
)
)
.radius(50000)
.strokeWidth(0f)
.fillColor(0x550000FF)
);
projection.toPixels(GeoP, pt);
float radius = projection.metersToEquatorPixels(50);
Try this and see... i used it on my MapRadius and it seems to be working

Categories

Resources