Reputation: 3557
I have a circular overlay that can change according to the user's preferences: they have a circle of radius 'r' around them and a slider can change 'r' accordingly. So far it works perfectly well.
My problem is I don't know how to find the proper conversion from the circle's radius to the map's metric. As an example, given the circle below, what is the distance covered with the given radius?
Upvotes: 0
Views: 378
Reputation: 3137
I think what you're looking for is a meters-to-pixels calculation. You can get this from the projection:
// Get projection
Projection proj = mMapView.getProjection();
// How many pixels in 100 meters for this zoom level
float pixels = proj.metersToPixels(100);
// How many meters in 100 pixels for this zoom level
float meters = 1 / proj.metersToPixels(1 / 100);
// You could also get a raw meters-per-pixels value by using TileSystem.GroundResolution()
Two things to remember - this value will change not only based on what zoom level but based on what latitude you are at on the maps.
Upvotes: 0
Reputation: 3557
So here's how you do it...
Jedil is correct you have to find your screen width/height, the dpi of the screen, etc. So, looking through this old osmdroid source I sorta figured out this:
//Get the x and y dpi
this.xdpi = this.context.getResources().getDisplayMetrics().xdpi;
this.ydpi = this.context.getResources().getDisplayMetrics().ydpi;
//Get the screen width/height
this.screenWidth = this.context.getResources().getDisplayMetrics().widthPixels;
this.screenHeight = this.context.getResources().getDisplayMetrics().heightPixels;
// DPI corrections for specific models
String manufacturer = null;
try {
final Field field = android.os.Build.class.getField("MANUFACTURER");
manufacturer = (String) field.get(null);
} catch (final Exception ignore) {
}
if ("motorola".equals(manufacturer) && "DROIDX".equals(android.os.Build.MODEL)) {
// If the screen is rotated, flip the x and y dpi values
WindowManager windowManager = (WindowManager) this.context
.getSystemService(Context.WINDOW_SERVICE);
if (windowManager.getDefaultDisplay().getOrientation() > 0) {
this.xdpi = (float) (this.screenWidth / 3.75);
this.ydpi = (float) (this.screenHeight / 2.1);
} else {
this.xdpi = (float) (this.screenWidth / 2.1);
this.ydpi = (float) (this.screenHeight / 3.75);
}
} else if ("motorola".equals(manufacturer) && "Droid".equals(android.os.Build.MODEL)) {
// http://www.mail-archive.com/[email protected]/msg109497.html
this.xdpi = 264;
this.ydpi = 264;
}
// set default max length to 1 inch
maxLength = 2.54f;
That's how you get the 'constants' (at least in the device's eyes). To convert...
// calculate dots per centimeter
int xdpcm = (int) ((float) xdpi / 2.54);
int ydpcm = (int) ((float) ydpi / 2.54);
// get length in pixel
int xLen = (int) (maxLength * xdpcm);
int yLen = (int) (maxLength * ydpcm);
// Two points, xLen apart, at scale bar screen location
IGeoPoint p1 = projection.fromPixels((screenWidth / 2) - (xLen / 2), yOffset);
IGeoPoint p2 = projection.fromPixels((screenWidth / 2) + (xLen / 2), yOffset);
// get distance in meters between points
final int xMeters = ((GeoPoint) p1).distanceTo(p2);
...and it's a similar, if not near-identical, matter to get the yMeters (hint: use screenHeight).
Admittedly, I'm not totally sure of what the lines IGeoPoint...
are doing but I realize the conversion is there. Hoping this helps someone out in the future. For a better understanding of the above code, please see the link I've posted.
Upvotes: 0
Reputation: 2903
You must know what is the scale of the map you are showing. Having scale of the map you could convert pixels size to metric size. And having this proportion you can convert radius given in pixels to meters.
Upvotes: 1