You have tagged your question with OpenStreetMap, so I am assuming you are interested in the data in OSM's zoom levels.
Please have a look at: Zoom Levels
Usually you would not look at the whole world, at the same zoom level, as you would a small city. Your example is at zoom level 17, which has a scale of 1:4000.
You would look at the world either at zoom level 1 or 2.
This is because, at higher zoom levels, a humungous number of tiles would be required. How many you ask? Look at this page: Tile Disk Usage
You will see that at zoom level 17, there are 17,179,869,184 tiles, out of which 429,535,936 have been seen so far. Each is 256 by 256 pixels. And that is a lot of pixels.
Ok, with some initial issues cleared out the task is relatively simple.
Scale, prepresented as f.ex 1:50000 means that one unit on the map corresponds to 50.000 units in the real world.
For a paper map printed a scale of 1:50000 this means that 1 meter on the map corresponds to 50.000 meters in the real world, or to make it easier: 1 cm on the map corresponds to 50 meter in the real world. So far, so good.
When computer (or phone screens) enter the show it's much more difficult: the unit of measure on a screen is a pixel, which doesn't map directly to centimeters. OpenLayers are (or at least where) using the "Dots per inch", and assumed that one inch corresponds to 72 pixels (this makes some sense on 72 dpi screens, but is wrong on i.e Retina Displays. But for now, lets stick to 72 dpi (as this is what most mapping libraries does (I think, corrections welcome)).
OpenLayers has a function OpenLayers.Util.getResolutionFromScale (see source):
OpenLayers.Util.getResolutionFromScale = function (scale, units) {
var resolution;
if (scale) {
if (units == null) {
units = "degrees";
}
var normScale = OpenLayers.Util.normalizeScale(scale);
resolution = 1 / (normScale * OpenLayers.INCHES_PER_UNIT[units]
* OpenLayers.DOTS_PER_INCH);
}
return resolution;
};
With units="degrees" (which EPSG:4490 is, from what I gather) we get inches_per unit = 4374754 (OpenLayers.INCHES_PER_UNIT["degrees"])
a scale of 1:50000 (which corresponds to 1/50000 = 0.00002) (this is what penLayers.Util.normalizeScale computes) gives normScale = 0.00002
- OpenLayers.DOTS_PER_INCH = 72
We can then calculate resolution as
1 / (0.00002 * 4374754 * 72) = 0.00015873908440210453
Knowing the center point (lon=100, lat=30), the pixel size of the viewport(w=400, h=600) and the resolution we can then use the calculateBounds function from OpenLayers.Map (see source):
calculateBounds: function(center, resolution) {
var extent = null;
if (center == null) {
center = this.getCachedCenter();
}
if (resolution == null) {
resolution = this.getResolution();
}
if ((center != null) && (resolution != null)) {
var halfWDeg = (this.size.w * resolution) / 2;
var halfHDeg = (this.size.h * resolution) / 2;
extent = new OpenLayers.Bounds(center.lon - halfWDeg,
center.lat - halfHDeg,
center.lon + halfWDeg,
center.lat + halfHDeg);
}
return extent;
},
which we can reduce to:
function calculateBounds(center, resolution, size) {
var halfWDeg = (size.w * resolution) / 2;
var halfHDeg = (size.h * resolution) / 2;
return {
"left": center.lon - halfWDeg,
"bottom": center.lat - halfHDeg,
"right": center.lon + halfWDeg,
"top": center.lat + halfHDeg
};
}
Calling this with our values gives:
calculateBounds({"lon": 100, "lat": 30}, 0.00015873908440210453, {"w": 400, "h":600});
{
left: 99.96825218311957,
bottom: 29.95237827467937,
right: 100.03174781688043,
top: 30.04762172532063
}
We can then combine all this to a function that works for degrees with scale denominator given:
function calculateBounds(center, scaleDenominator, size) {
var resolution = 1 / ((1 / scaleDenominator) * 4374754 * 72)
var halfWDeg = (size.w * resolution) / 2;
var halfHDeg = (size.h * resolution) / 2;
return {
"left": center.lon - halfWDeg,
"bottom": center.lat - halfHDeg,
"right": center.lon + halfWDeg,
"top": center.lat + halfHDeg
};
}
Best Answer
To calculate scale you need to know two things, a distance on the map and the length of the same line in pixels or inches etc. You then divide one by the other to give a ratio of 1pixel (or inch) to X metres (or feet).
To make life easier we usually use the width or height of the map as we know the bounding box of the map, and the size of the image. If you are paranoid then calculate both height and width based scale and pick one or the other.