查了些资料,找到一种方法,可以解决坐标点很多的问题。google maps的GPolygon类提供一种工厂方法fromEncoded(),这种方法可以加载由大量坐标点变换成的折线编码。google给出了编码折线的算法格式,如下:
编码折线存储任意给定的一组点的两种类型的编码信息:这些点的经纬度,以及用于显示这些点的最大缩放级别。级别使用无符号值编码,而点坐标需要使用有符号的值,所以这两种情况的编码过程稍有不同。下面说明了此过程。如果仅有几个静态的点,您还可以使用交互的折线编码工具。
编码经纬度
编码过程将二进制值转换为一系列使用常见的 base64 编码的 ASCII 字符代码:为了确保正确显示这些字符,将编码值转换为 ASCII 之前编码值会加上 63(ASCII 字符“?”)。这种算法还通过检查每个字节组中的最低有效位,来确定给定点中是否还有额外的字符代码;如果该位设置为 1,则该点未完全形成,可能后面有其他数据。
此外,为了节省空间,点仅包含与上个点的偏移值(除了第一个点外)。所有点都使用 Base64 编码为有符号整数,因为经度和纬度是有符号值。折线中的编码格式需要表示两个坐标,分别以合理精度表示经度和纬度。如果最大经度是 +/- 180 度,精度为 5 个小数位(180.00000 到 -180.00000),则可能会需要 32 位有符号二进制整数值。
请注意在字符字面值 (string literal) 中,反斜杠被解释为转义符。 此工具的任何输出都会将反斜杠字符转换为字符串字面值中的双反斜杠。
下面说明了编码此类有符号值的步骤。
取初始有符号值:
-179.9832104
将其取十进制值乘以 1e5,并取整:
-17998321
将十进制值转换为二进制值。请注意负值必须求反,并以值填充字节边界:
00000001 00010010 10100001 11110001
11111110 11101101 10100001 00001110
11111110 11101101 01011110 00001111
变换二进制值:
11111110 11101101 01011110 00001111 0
如果原来的十进制值是负数,则对以下编码求反:
00000001 00010010 10100001 11110000 1
将该二进制值分为 5 位一组的块(从右手边开始):
00001 00010 01010 10000 11111 00001
将这些 5 位一组的块倒序放置:
00001 11111 10000 01010 00010 00001
如果后面还有一个位块,则将每个值与 0x20 进行或操作 (OR):
100001 111111 110000 101010 100010 000001
将每个值转换为十进制值:
33 63 48 42 34 1
将每个值加上 63:
96 126 111 105 97 64
将每个值转换为其 ASCII 对应值:
`~oia@
算法里的有些步骤呢不是很明白,不过根据算法写出了c++代码。
#include "stdafx.h"
#include "math.h"
#include "string"
#include "iostream"
//四舍五入取整函数
int interger(double x)
{
int y;
if(x<0)
y=int(x-0.5);
else if(x>=0)
y=int(x+0.5);
return y;
}
int _tmain(int argc, _TCHAR* argv[])
{
double col=-179.9832104;//设置成double型,双精度浮点型,10位有效数字,float是单精度浮点型,只有6位有效数字
int num;
num=interger(col*100000);
int sgn_num;
//变换二进制值,左移,低位补0
sgn_num=num<<1;
if(num<0)
{
sgn_num=~(sgn_num);//对负数求反
}
string result="";
//将该二进制值分为5位一组的块
while(sgn_num>=0x20)
//0x20是ascII码中可见字符的开始
{
int x;
//与0x1f与,保证只取后5位二进制
x=sgn_num&0x1f;
//进行异或加上63
x=x|0x20;
x=x+63;
//char(x)可以得到对应的ASCII符号,加入result
result+=char(x);
//二进制右移5位
sgn_num>>=5;
}
result+=char(sgn_num+63);//最后一组值
cout<<result;
return 0;
}
输出值为:·~oia@