OpenLayers学习14-投影Projection

做投影转换的类
默认可以转换 geographic (EPSG:4326等) 和 web mercator (EPSG:900913等), 计算公式在最后边
其他投影的转换需要单独引入proj4js : http://proj4js.org/

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
OpenLayers.Projection = OpenLayers.Class({
// Proj4js.Proj实例对象
proj: null,
// projCode字串
projCode: null,
//title正则
titleRegEx: /\+title=[^\+]*/,
// 构造, 包装pro4js projection对象
initialize: function(projCode, options) {
OpenLayers.Util.extend(this, options);
this.projCode = projCode;
if (typeof Proj4js == "object") {
//缓存new Proj4js对象
this.proj = new Proj4js.Proj(projCode);
}
},
// 有proj缓存用proj.srsCode, 否则用projCode
getCode: function() {
return this.proj ? this.proj.srsCode : this.projCode;
},
// this.proj缓存里的.proj.units
getUnits: function() {
return this.proj ? this.proj.units : null;
},
//返回code
toString: function() {
return this.getCode();
},
//判等
equals: function(projection) {
var p = projection, equals = false;
if (p) {
if (!(p instanceof OpenLayers.Projection)) {
p = new OpenLayers.Projection(p);//不是对象的, 构造一下. 这没用CLSS_NAME判断
}
if ((typeof Proj4js == "object") && this.proj.defData && p.proj.defData) {
//忽略title
equals = this.proj.defData.replace(this.titleRegEx, "") ==
p.proj.defData.replace(this.titleRegEx, "");
} else if (p.getCode) {
var source = this.getCode(), target = p.getCode();
//使用同一投影???
equals = source == target ||
!!OpenLayers.Projection.transforms[source] &&
OpenLayers.Projection.transforms[source][target] ===
OpenLayers.Projection.nullTransform;
}
}
return equals;
},
//GC, 删掉缓存对象
//delete和直接null还不一样, delete以后本实例就没有这一项了. 等于这个对象就废了
destroy: function() {
delete this.proj;
delete this.projCode;
},
CLASS_NAME: "OpenLayers.Projection"
});
// 缓存对象, 后边执行过程里往里add
OpenLayers.Projection.transforms = {};
//默认值对象:
//Keys 就是 SRS code, 84没用过...
OpenLayers.Projection.defaults = {
"EPSG:4326": {//经纬度
units: "degrees",
maxExtent: [-180, -90, 180, 90],
yx: true
},
"CRS:84": {
units: "degrees",
maxExtent: [-180, -90, 180, 90]
},
"EPSG:900913": {//墨卡托
units: "m",
maxExtent: [-20037508.34, -20037508.34, 20037508.34, 20037508.34]
}
};
// 切换from和to的投影类型
OpenLayers.Projection.addTransform = function(from, to, method) {
if (method === OpenLayers.Projection.nullTransform) {
var defaults = OpenLayers.Projection.defaults[from];
if (defaults && !OpenLayers.Projection.defaults[to]) {
OpenLayers.Projection.defaults[to] = defaults;
}
}
//要是缓存中没有, 初始化一个新的
if(!OpenLayers.Projection.transforms[from]) {
OpenLayers.Projection.transforms[from] = {};
}
// 缓存的[from][to] 里边存的是method方法
OpenLayers.Projection.transforms[from][to] = method;
};
//转换方法, 从缓存中读: 缓存[源] 和 缓存[目标], 返回经过转换的point对象
OpenLayers.Projection.transform = function(point, source, dest) {
if (source && dest) {
if (!(source instanceof OpenLayers.Projection)) {
source = new OpenLayers.Projection(source);//source实例
}
if (!(dest instanceof OpenLayers.Projection)) {
dest = new OpenLayers.Projection(dest);//dest实例
}
if (source.proj && dest.proj) {
point = Proj4js.transform(source.proj, dest.proj, point);//使用Proj4js.transform转换
} else {
var sourceCode = source.getCode();
var destCode = dest.getCode();
var transforms = OpenLayers.Projection.transforms;
//同时有 缓存[源] 和 缓存[目标]
if (transforms[sourceCode] && transforms[sourceCode][destCode]) {
transforms[sourceCode][destCode](point);//证明之前add过, 调用转换方法
}
}
}
return point;
};
// 只是返回原point点
OpenLayers.Projection.nullTransform = function(point) {
return point;
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
//默认自带经纬度和墨卡托的转换, map方法做各个转换的映射
(function() {
var pole = 20037508.34;
//反转墨卡托
function inverseMercator(xy) {
xy.x = 180 * xy.x / pole;
xy.y = 180 / Math.PI * (2 * Math.atan(Math.exp((xy.y / pole) * Math.PI)) - Math.PI / 2);
return xy;
}
//转换墨卡托
function forwardMercator(xy) {
xy.x = xy.x * pole / 180;
var y = Math.log(Math.tan((90 + xy.y) * Math.PI / 360)) / Math.PI * pole;
xy.y = Math.max(-20037508.34, Math.min(y, 20037508.34));
return xy;
}
//映射方法
function map(base, codes) {
var add = OpenLayers.Projection.addTransform;
var same = OpenLayers.Projection.nullTransform;
var i, len, code, other, j;
for (i=0, len=codes.length; i<len; ++i) {
code = codes[i];
//墨卡托与经纬度坐标的相互转换
add(base, code, forwardMercator);
add(code, base, inverseMercator);
for (j=i+1; j<len; ++j) {
other = codes[j];
//墨卡托与墨卡托 或 经纬度与经纬度 的转换
add(code, other, same);
add(other, code, same);
}
}
}
//墨卡托列表 / 经纬度列表
var mercator = ["EPSG:900913", "EPSG:3857", "EPSG:102113", "EPSG:102100"],
geographic = ["CRS:84", "urn:ogc:def:crs:EPSG:6.6:4326", "EPSG:4326"],
i;
for (i=mercator.length-1; i>=0; --i) {
map(mercator[i], geographic);//墨卡托和经纬度的一一对应
}
for (i=geographic.length-1; i>=0; --i) {
map(geographic[i], mercator);//经纬度和墨卡托的一一对应
}
})();