Ok, mit einigen anfänglichen Problemen ist die Aufgabe relativ einfach.
Maßstab, dargestellt als f.ex 1: 50000, bedeutet, dass eine Einheit auf der Karte 50.000 Einheiten in der realen Welt entspricht.
Für eine Papierkarte im Maßstab 1: 50000 bedeutet dies, dass 1 Meter auf der Karte 50.000 Metern in der realen Welt entspricht, oder um es einfacher zu machen: 1 cm auf der Karte entspricht 50 Metern in der realen Welt. So weit, ist es gut.
Wenn Computer (oder Telefonbildschirme) die Show betreten, ist es viel schwieriger: Die Maßeinheit auf einem Bildschirm ist ein Pixel, das nicht direkt auf Zentimeter abgebildet wird. OpenLayers verwenden (oder zumindest wo) die "Punkte pro Zoll" und gehen davon aus, dass ein Zoll 72 Pixel entspricht (dies ist auf 72-dpi-Bildschirmen sinnvoll, auf Retina-Displays jedoch falsch. Aber bleiben wir vorerst bei 72 dpi (wie es die meisten Mapping-Bibliotheken tun (ich denke, Korrekturen sind willkommen)).
OpenLayers hat eine Funktion OpenLayers.Util.getResolutionFromScale (siehe Quelle ):
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;
};
Mit Einheiten = "Grad" (was EPSG: 4490 ist, nach dem, was ich erfahre) erhalten wir Zoll_per Einheit = 4374754 (OpenLayers.INCHES_PER_UNIT ["Grad"])
Ein Maßstab von 1: 50000 (entspricht 1/50000 = 0,00002) (dies berechnet penLayers.Util.normalizeScale) ergibt normScale = 0,00002
- OpenLayers.DOTS_PER_INCH = 72
Wir können dann die Auflösung als berechnen
1 / (0.00002 * 4374754 * 72) = 0.00015873908440210453
Wenn wir den Mittelpunkt (lon = 100, lat = 30), die Pixelgröße des Ansichtsfensters (w = 400, h = 600) und die Auflösung kennen, können wir die Funktion berechne Grenzen aus OpenLayers.Map verwenden (siehe Quelle ):
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;
},
was wir reduzieren können auf:
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
};
}
Wenn wir dies mit unseren Werten bezeichnen, erhalten wir:
calculateBounds({"lon": 100, "lat": 30}, 0.00015873908440210453, {"w": 400, "h":600});
{
left: 99.96825218311957,
bottom: 29.95237827467937,
right: 100.03174781688043,
top: 30.04762172532063
}
Wir können all dies dann zu einer Funktion kombinieren, die für Grade mit angegebenem Skalennenner funktioniert:
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
};
}