これらの条件を考えると:
- のようなスケール
1:50000
- ビューポートの中心は
100°E, 20°N
- ビューポートのサイズは
400x600
ビューポートの境界ボックスを計算するにはどうすればよいですか?
マップの地理座標系はEPSG:4490です。
それらをメルカトルや緯度 _ 経度 _投影などの別の投影法で表示したいと思います(おそらくこれはいわゆる非投影です)。
ビューポートのサイズはピクセル単位です。
これらの条件を考えると:
1:50000
100°E, 20°N
400x600
ビューポートの境界ボックスを計算するにはどうすればよいですか?
マップの地理座標系はEPSG:4490です。
それらをメルカトルや緯度 _ 経度 _投影などの別の投影法で表示したいと思います(おそらくこれはいわゆる非投影です)。
ビューポートのサイズはピクセル単位です。
回答:
さて、いくつかの初期の問題が解決されたので、タスクは比較的簡単です。
縮尺は、f.ex 1:50000として表され、マップ上の1つの単位が実世界の50.000単位に対応することを意味します。
1:50000の縮尺で印刷された紙の地図の場合、これは、地図上の1メートルが現実世界の50.000メートルに対応すること、または簡単にするために、地図上の1 cmが現実世界の50メートルに対応することを意味します。ここまでは順調ですね。
コンピューター(または電話スクリーン)がショーに入るとき、それははるかに困難です。スクリーン上の測定単位はピクセルであり、センチメートルに直接マッピングされません。OpenLayersは(または少なくともその場所で)「1インチあたりのドット数」を使用しており、1インチは72ピクセルに相当すると想定されています(これは72 dpi画面では理にかなっていますが、Retinaディスプレイでは間違っています。しかし、今のところ、 72 dpi(これはほとんどのマッピングライブラリが行うことです(私は、修正を歓迎します))。
OpenLayersにはOpenLayers.Util.getResolutionFromScale関数があります(ソースを参照)。
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;
};
units = "degrees"(EPSG:4490は、私が収集したものです)を使用すると、inch_per unit = 4374754(OpenLayers.INCHES_PER_UNIT ["degrees"])が得られます。
1:50000のスケール(これは1/50000 = 0.00002に対応します)(これはpenLayers.Util.normalizeScaleが計算するものです)は、normScale = 0.00002を与えます
次に、次のように解像度を計算できます
1 / (0.00002 * 4374754 * 72) = 0.00015873908440210453
中心点(lon = 100、lat = 30)、ビューポートのピクセルサイズ(w = 400、h = 600)、およびOpenLayers.MapのcalculateBounds関数を使用できる解像度(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;
},
これを次のように削減できます。
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
};
}
これを私たちの値で呼び出すと、次のようになります。
calculateBounds({"lon": 100, "lat": 30}, 0.00015873908440210453, {"w": 400, "h":600});
{
left: 99.96825218311957,
bottom: 29.95237827467937,
right: 100.03174781688043,
top: 30.04762172532063
}
次に、これらすべてを、与えられたスケール分母を使用して、度数に対して機能する関数に組み合わせることができます。
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
};
}
dpi
価値です。だよね?