Ok, với một số vấn đề ban đầu đã xóa nhiệm vụ tương đối đơn giản.
Tỷ lệ, được đặt trước là f.ex 1: 50000 có nghĩa là một đơn vị trên bản đồ tương ứng với 50.000 đơn vị trong thế giới thực.
Đối với bản đồ giấy được in tỷ lệ 1: 50000, điều này có nghĩa là 1 mét trên bản đồ tương ứng với 50.000 mét trong thế giới thực hoặc để dễ dàng hơn: 1 cm trên bản đồ tương ứng với 50 mét trong thế giới thực. Càng xa càng tốt.
Khi máy tính (hoặc màn hình điện thoại) vào chương trình, điều đó khó khăn hơn nhiều: đơn vị đo trên màn hình là một pixel, không ánh xạ trực tiếp đến centimet. OpenLayers đang (hoặc ít nhất là ở đâu) sử dụng "Dots per inch" và giả sử rằng một inch tương ứng với 72 pixel (điều này có ý nghĩa trên màn hình 72 dpi, nhưng sai trên màn hình Retina. Nhưng bây giờ, hãy kiên trì 72 dpi (vì đây là điều mà hầu hết các thư viện lập bản đồ thực hiện (tôi nghĩ, điều chỉnh đều được chào đón)).
OpenLayers có chức năng OpenLayers.Util.getResolutionFromScale (xem nguồn ):
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;
};
Với các đơn vị = "độ" (mà EPSG: 4490 là, từ những gì tôi thu thập được), chúng tôi nhận được inch_per unit = 4374754 (OpenLayers.INCHES_PER_UNIT ["độ"])
tỷ lệ 1: 50000 (tương ứng với 1/50000 = 0,00002) (đây là những gì penLayers.Util.n normalizeScale tính toán) cho NormScale = 0,00002
- OpenLayers.DOTS_PER_INCH = 72
Sau đó chúng ta có thể tính toán độ phân giải như
1 / (0.00002 * 4374754 * 72) = 0.00015873908440210453
Biết điểm trung tâm (lon = 100, lat = 30), kích thước pixel của chế độ xem (w = 400, h = 600) và độ phân giải, sau đó chúng ta có thể sử dụng hàm tính toánBound từ OpenLayers.Map (xem nguồn ):
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;
},
mà chúng ta có thể giảm xuống:
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
};
}
Gọi điều này với các giá trị của chúng tôi mang lại:
calculateBounds({"lon": 100, "lat": 30}, 0.00015873908440210453, {"w": 400, "h":600});
{
left: 99.96825218311957,
bottom: 29.95237827467937,
right: 100.03174781688043,
top: 30.04762172532063
}
Sau đó, chúng ta có thể kết hợp tất cả điều này với một hàm hoạt động theo độ với mẫu số tỷ lệ đã cho:
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
};
}