OpenLayers学习5-工具类Util_2

一: 鼠标操作

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
//判断div是不是触发evt对象的根对象(最父级对象)
//这个和事件关系比较紧密, 还不知道为什么这么处理...
OpenLayers.Util.mouseLeft = function (evt, div) {
//兼容IE, 获得事件源
var target = (evt.relatedTarget) ? evt.relatedTarget : evt.toElement;
//直到追溯至根节点
while (target != div && target != null) {
target = target.parentNode;
}
//如果div是根对象, 返回true
return (target != div);
};
//浮点精度
OpenLayers.Util.DEFAULT_PRECISION = 14;
//把对象转成浮点型
OpenLayers.Util.toFloat = function (number, precision) {
if (precision == null) {
precision = OpenLayers.Util.DEFAULT_PRECISION;//默认精度
}
//本来就是"number"型, 直接parseFloat
if (typeof number !== "number") {
number = parseFloat(number);
}
return precision === 0 ? number : //精度0
parseFloat(number.toPrecision(precision));//指数形式
};

二: 距离计算

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
//计算两点距离
//角度转弧度
OpenLayers.Util.rad = function(x) {return x*Math.PI/180;};
//弧度转角度
OpenLayers.Util.deg = function(x) {return x*180/Math.PI;};
//a:长半轴, b短半轴, c扁率
OpenLayers.Util.VincentyConstants = {
a: 6378137,
b: 6356752.3142,
f: 1/298.257223563
};
//计算两点距离
//提供两个带lat和lon的对象, 计算出以km为单位的距离
//计算公式完全看不懂...
OpenLayers.Util.distVincenty = function(p1, p2) {
var ct = OpenLayers.Util.VincentyConstants;
var a = ct.a, b = ct.b, f = ct.f;
var L = OpenLayers.Util.rad(p2.lon - p1.lon);
var U1 = Math.atan((1-f) * Math.tan(OpenLayers.Util.rad(p1.lat)));
var U2 = Math.atan((1-f) * Math.tan(OpenLayers.Util.rad(p2.lat)));
var sinU1 = Math.sin(U1), cosU1 = Math.cos(U1);
var sinU2 = Math.sin(U2), cosU2 = Math.cos(U2);
var lambda = L, lambdaP = 2*Math.PI;
var iterLimit = 20;
while (Math.abs(lambda-lambdaP) > 1e-12 && --iterLimit>0) {
var sinLambda = Math.sin(lambda), cosLambda = Math.cos(lambda);
var sinSigma = Math.sqrt((cosU2*sinLambda) * (cosU2*sinLambda) +
(cosU1*sinU2-sinU1*cosU2*cosLambda) * (cosU1*sinU2-sinU1*cosU2*cosLambda));
if (sinSigma==0) {
return 0; // co-incident points
}
var cosSigma = sinU1*sinU2 + cosU1*cosU2*cosLambda;
var sigma = Math.atan2(sinSigma, cosSigma);
var alpha = Math.asin(cosU1 * cosU2 * sinLambda / sinSigma);
var cosSqAlpha = Math.cos(alpha) * Math.cos(alpha);
var cos2SigmaM = cosSigma - 2*sinU1*sinU2/cosSqAlpha;
var C = f/16*cosSqAlpha*(4+f*(4-3*cosSqAlpha));
lambdaP = lambda;
lambda = L + (1-C) * f * Math.sin(alpha) *
(sigma + C*sinSigma*(cos2SigmaM+C*cosSigma*(-1+2*cos2SigmaM*cos2SigmaM)));
}
if (iterLimit==0) {
return NaN; // formula failed to converge
}
var uSq = cosSqAlpha * (a*a - b*b) / (b*b);
var A = 1 + uSq/16384*(4096+uSq*(-768+uSq*(320-175*uSq)));
var B = uSq/1024 * (256+uSq*(-128+uSq*(74-47*uSq)));
var deltaSigma = B*sinSigma*(cos2SigmaM+B/4*(cosSigma*(-1+2*cos2SigmaM*cos2SigmaM)-
B/6*cos2SigmaM*(-3+4*sinSigma*sinSigma)*(-3+4*cos2SigmaM*cos2SigmaM)));
var s = b*A*(sigma-deltaSigma);
var d = s.toFixed(3)/1000; // round to 1mm precision
return d;
};
//计算出经纬度(给定经纬度, 角度, 距离)
//公式看不懂
OpenLayers.Util.destinationVincenty = function(lonlat, brng, dist) {
var u = OpenLayers.Util;
var ct = u.VincentyConstants;
var a = ct.a, b = ct.b, f = ct.f;
var lon1 = lonlat.lon;
var lat1 = lonlat.lat;
var s = dist;
var alpha1 = u.rad(brng);
var sinAlpha1 = Math.sin(alpha1);
var cosAlpha1 = Math.cos(alpha1);
var tanU1 = (1-f) * Math.tan(u.rad(lat1));
var cosU1 = 1 / Math.sqrt((1 + tanU1*tanU1)), sinU1 = tanU1*cosU1;
var sigma1 = Math.atan2(tanU1, cosAlpha1);
var sinAlpha = cosU1 * sinAlpha1;
var cosSqAlpha = 1 - sinAlpha*sinAlpha;
var uSq = cosSqAlpha * (a*a - b*b) / (b*b);
var A = 1 + uSq/16384*(4096+uSq*(-768+uSq*(320-175*uSq)));
var B = uSq/1024 * (256+uSq*(-128+uSq*(74-47*uSq)));
var sigma = s / (b*A), sigmaP = 2*Math.PI;
while (Math.abs(sigma-sigmaP) > 1e-12) {
var cos2SigmaM = Math.cos(2*sigma1 + sigma);
var sinSigma = Math.sin(sigma);
var cosSigma = Math.cos(sigma);
var deltaSigma = B*sinSigma*(cos2SigmaM+B/4*(cosSigma*(-1+2*cos2SigmaM*cos2SigmaM)-
B/6*cos2SigmaM*(-3+4*sinSigma*sinSigma)*(-3+4*cos2SigmaM*cos2SigmaM)));
sigmaP = sigma;
sigma = s / (b*A) + deltaSigma;
}
var tmp = sinU1*sinSigma - cosU1*cosSigma*cosAlpha1;
var lat2 = Math.atan2(sinU1*cosSigma + cosU1*sinSigma*cosAlpha1,
(1-f)*Math.sqrt(sinAlpha*sinAlpha + tmp*tmp));
var lambda = Math.atan2(sinSigma*sinAlpha1, cosU1*cosSigma - sinU1*sinSigma*cosAlpha1);
var C = f/16*cosSqAlpha*(4+f*(4-3*cosSqAlpha));
var L = lambda - (1-C) * f * sinAlpha *
(sigma + C*sinSigma*(cos2SigmaM+C*cosSigma*(-1+2*cos2SigmaM*cos2SigmaM)));
var revAz = Math.atan2(sinAlpha, -tmp); // final bearing
return new OpenLayers.LonLat(lon1+u.deg(L), u.deg(lat2));
};

三: URL操作

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
//从URL里解析参数, 参数里有逗号的话会写入数组
//第二个参数options, 若true表示把含逗号的参数写入数组, 默认true
OpenLayers.Util.getParameters = function(url, options) {
options = options || {};
//优先用传入的url, 否则用location.href
url = (url === null || url === undefined) ? window.location.href : url;
var paramsString = "";
if (OpenLayers.String.contains(url, '?')) {
var start = url.indexOf('?') + 1;//从?后边开始截取
var end = OpenLayers.String.contains(url, "#") ?
url.indexOf('#') : url.length;//有#截到#, 否则截到最后一位
paramsString = url.substring(start, end);
}
var parameters = {};//准备空的结果对象
var pairs = paramsString.split(/[&;]/);//按照"&"切分成数组
for(var i=0, len=pairs.length; i<len; ++i) {
var keyValue = pairs[i].split('=');//每个部分按"="切分
//若有key
if (keyValue[0]) {
var key = keyValue[0];
//对key解码
try {
key = decodeURIComponent(key);
} catch (err) {
key = unescape(key);
}
//val里"+"替换成空格
var value = (keyValue[1] || '').replace(/\+/g, " ");
//对val解码
try {
value = decodeURIComponent(value);
} catch (err) {
value = unescape(value);
}
//有些OGC的参数里带"," 按逗号切分
if (options.splitArgs !== false) {
value = value.split(",");
}
//要是没逗号, 就不写入数组
if (value.length == 1) {
value = value[0];
}
parameters[key] = value;//写入对象
}
}
return parameters;
};
//自增id的记录
OpenLayers.Util.lastSeqID = 0;
//根据前缀,生成"前缀_自增id"
OpenLayers.Util.createUniqueID = function(prefix) {
if (prefix == null) {
prefix = "id_";
} else {
prefix = prefix.replace(OpenLayers.Util.dotless, "_");//把"."换成"_"
}
OpenLayers.Util.lastSeqID += 1; //自增
return prefix + OpenLayers.Util.lastSeqID;
};

四: 比例尺相关的计算

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
//Scale = 图上距离/实地距离 , Resolution = 一像素代表多少地图单位
//单位对象配置
//相对来说是动态的配置对象, 比我之前在init函数里计算的思路要好
OpenLayers.INCHES_PER_UNIT = {
'inches': 1.0,
'ft': 12.0,
'mi': 63360.0,
'm': 39.37,
'km': 39370,
'dd': 4374754,
'yd': 36
};
OpenLayers.INCHES_PER_UNIT["in"]= OpenLayers.INCHES_PER_UNIT.inches;
OpenLayers.INCHES_PER_UNIT["degrees"] = OpenLayers.INCHES_PER_UNIT.dd;
OpenLayers.INCHES_PER_UNIT["nmi"] = 1852 * OpenLayers.INCHES_PER_UNIT.m;//动态的配置
OpenLayers.METERS_PER_INCH = 0.02540005080010160020;
OpenLayers.Util.extend(OpenLayers.INCHES_PER_UNIT, {
"Meter": 1.0 / OpenLayers.METERS_PER_INCH, //EPSG:9001
"Foot": 0.30480060960121920243 / OpenLayers.METERS_PER_INCH, //EPSG:9003
...
//DPI的默认值
OpenLayers.DOTS_PER_INCH = 72;
//比例尺计算,
//已经是分数形式的( 1.0) ? (1.0 / scale)
: scale;
return normScale;
};
//由Scale计算出Resolution, 默认单位是"degrees"
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;
};
//由Resolution计算对应的Scale, 默认单位是"degrees"
OpenLayers.Util.getScaleFromResolution = function (resolution, units) {
if (units == null) {
units = "degrees";
}
var scale = resolution * OpenLayers.INCHES_PER_UNIT[units] *
OpenLayers.DOTS_PER_INCH;
return scale;
};