提供一种js map api共享与开放空间数据的思路
在客户端中把空间数据编码为base64的优势就不在此赘述,不了解这种编码方法的朋友可以参考相关资料。
在sqlserver2k5中利用CLR-UDF实现空间查询一文中我举例了一个空间查询的sql语句,如果在其后追加
一句,则sqlserver(2000以后就支持了)自动将查询结果以XML的方式输出,其中BLOB字段以BASE64编码的方式输出。
例如有一个geometry字段的节点为:
AgAAAAEAAABbI4JxcBJbQM1bdR2q1TZA
</geometry>
这是一个MultiPoint类型(这是一个用与举例的自定义格式,类似iso spatial schema。空间数据的存储格式有很多,如想实现数据共享,采用OGC的SFS无疑是最好的选择)的空间数据。其的格式如表示下
| MultiPoint类型 | 点的个数 | x1 , y1 | x2, y2 | ......|
类型用一个整数表示(本例中MulitPoint的值是2),占4个byte。点个数也是整型,也是4个字节。其后的坐标值为double型,占8个字节。
这个字符串“AgAAAAEAAABbI4JxcBJbQM1bdR2q1TZA”的数据为“2,1,108.288113,22.834627”
其表示一个有一个点的MultiPoint类型,坐标为108.288113,22.834627。
从base64编码得到数据首先要对其进行解码,这很简单,但大家知道js的数据类型只有number型,它可以支持的很大(可以用alert(Number.MAX_VALUE)看看,是1.7976931348623157e+308)。但在进行位运算的时候,IE的js却只支持32位整数。这是在是太。。。FAINT了。。。也就是说,在IE的js中,不可能象数据类型完备的高级语言那样通过按位运算来求值。我当时几乎放弃了。。。。山重水复疑无路啊。。。还好,忽然发现了parseInt函数,总算找到那一村了。
具体不再废话,看代码吧:
(某些注释掉部分为关联其他js库,我已修改过,可不予理会)
2 // Copyright (c) All rights reserved.
3 // File : core.Base64Reader.js
4 // Author : Edison1024, micro1024(a)gmail.com
5 // Description :
6 // Dependencies :
7 // Date Created : 2005.10.11
8 //--------------------------------------------------------------------------
9 // Date Modified By Description
10 //--------------------------------------------------------------------------
11 //
12 //**************************************************************************
13
14
15 function Base64Reader(base64String)
16 {
17 var _offset = 0;
18 var _buffer = _base64Decode(base64String);
19
20 function _base64Decode(input)
21 {
22 if((input.length % 4)!=0)
23 {
24 throw new Error("Invaild base64 encoding.");
25 return;
26 }
27 var rgExp = new RegExp("^[A-Z0-9/+=]*$", "g");
28 if(/*!isNull(input.match(rgExp))*/input.match(rgExp) != null)
29 {
30 throw new Error("There were invalid base64 characters in the input string");
31 return;
32 }
33
34 var base64Code = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
35
36 var output = new Array();
37 var chr1, chr2, chr3;
38 var enc1, enc2, enc3, enc4;
39 var i = 0;
40
41 do
42 {
43 enc1 = base64Code.indexOf(input.charAt(i++));
44 enc2 = base64Code.indexOf(input.charAt(i++));
45 enc3 = base64Code.indexOf(input.charAt(i++));
46 enc4 = base64Code.indexOf(input.charAt(i++));
47
48 chr1 = (enc1 << 2) | (enc2 >> 4);
49 chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
50 chr3 = ((enc3 & 3) << 6) | enc4;
51
52 output.push(chr1);
53 if (enc3 != 64)
54 {
55 output.push(chr2);
56 }
57 if (enc4 != 64)
58 {
59 output.push(chr3);
60 }
61
62 chr1 = chr2 = chr3 = "";
63 enc1 = enc2 = enc3 = enc4 = "";
64 }
65 while (i < input.length);
66
67 return output;
68 }
69
70 /*JScript的数据类型局限,下面的算法是无法求出正确结果的。
71 JScript没有long型,虽然他的number型可以很大,但经过我详细测,
72 发现进行按位运算的时候却只支持32位整数。
73 不知道ECMAScript规范的Scripting实现就是这样还是M$IE的Scripting的实现有问题。
74 在NS和FF中我没测试过。
75 */
76 //function _byteToDouble(buffer)
77 //{
78 // var l;
79 // l = buffer[0];
80 // l &= 0xff;
81 // l |= (buffer[1] << 8);
82 // l &= 0xffff;
83 // l |= (buffer[2] << 16);
84 // l &= 0xffffff;
85 // l |= (buffer[3] << 24);
86 // l &= 0xffffffff;
87 // l |= (buffer[4] << 32);
88 // l &= 0xffffffffff;
89 // l |= (buffer[5] << 40);
90 // l &= 0xffffffffffff;
91 // l |= (buffer[6] << 48);
92 // l &= 0xffffffffffffff;
93 // l |= (buffer[7] << 56);
94
95 // alert(l);
96 //
97 // var s = ((l >> 63) == 0) ? 1 : -1;
98 // var e = ((l >> 52) & 0x7ff);
99 // var m = (e == 0) ?
100 // (l & 0xfffffffffffff) << 1 :
101 // (l & 0xfffffffffffff) | 0x10000000000000;
102
103 // return s * m * Math.pow(2, (e - 1075));
104 //}
105
106 /*这是我给出的实现,利用了parseInt()函数把二进制的字符串转成long型的数据,然后由公式求出double*/
107 function _byteToDouble(buffer, start, end)
108 {
109 if(/*buffer.getType() != "Array" || */(end - start) != 8)
110 throw new Error("Failed to read data invalid arguments error message");
111
112 var longBits = "";
113 for(var i = start; i < end; i++)
114 {
115 var temp = buffer[i].toString(2);
116 while(temp.length < 8)
117 {
118 temp = "0" + temp;
119 }
120 longBits = temp + longBits;
121 }
122
123 var s = (longBits.substring(0, 1) == "0") ? 1 : -1;
124 var e = (parseInt(longBits.substring(0, 12), 2) & 0x7ff);
125 var m = (e == 0) ?
126 ("0000000000" + longBits.substring(12, 64) + "0") :
127 ("00000000001" + longBits.substring(12, 64));
128 m = parseInt(m, 2);
129
130 return s * m * Math.pow(2, (e - 1075));
131 }
132
133
134 function _byteToInt(buffer, start, end)
135 {
136 if(/*buffer.getType() != "Array" || */(end - start) != 4)
137 throw new Error("Failed to read data invalid arguments error message");
138
139 var intBits = 0;
140 for(var i = end; i-- > start;)
141 {
142 intBits <<= 8;
143 intBits |= buffer[i] & 255;
144 }
145 return intBits;
146 }
147
148 this.readInt = function()
149 {
150 return _byteToInt(_buffer, _offset, _offset += 4);
151 }
152
153 this.readDouble = function()
154 {
155 return _byteToDouble(_buffer, _offset, _offset += 8);
156 }
157 }
158
159
160
打包及测试文件下载
Base64Reader.rar