GoogleMap 编码折线算法 BCB实现
公司一直用BCB做开发的. 用到了此算法.结果在Google搜索上找到的几乎全是Java版的.所以决定自己写.下面是我的代码. 现贴出来供大家参考下.
//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
#include "math.h"
#include "GooglePolyline.h"
#include "Minux\MMath.h" //这个可以.去掉.是为了.调用下面.Round函数用的.
//---------------------------------------------------------------------------
/*二进制转换为十进制(8位)*/
int __fastcall BintoDec(char* b)
{
int j = 0,v = 0;
int Len = strlen(b);
if (Len < 1) return Len;
for(int i=Len-1; i>=0; i--)
{
if (b[i]=='1')
v += (int)pow(2,j);
j++;
}
return v;
}
//---------------------------------------------------------------------------
String __fastcall Rights(String Value, int iLen)
{
int i;
i = Value.Length() - iLen + 1;
if (i<=0) i = 1;
String ret = Value.SubString(i,iLen);
return ret;
}
//---------------------------------------------------------------------------
String __fastcall EncodePolyline(double* LngBuf, double* LatBuf, unsigned int BufLen)
{
double TmpLng, TmpLat;
String ret;
for (int i=0, iLoop=BufLen; i<iLoop; i++)
{
TmpLng = LngBuf[i];
TmpLat = LatBuf[i];
if (i != 0)
{
TmpLng = LngBuf[i] - LngBuf[i-1];
TmpLat = LatBuf[i] - LatBuf[i-1];
}
ret += EncodePoint(TmpLng);
ret += EncodePoint(TmpLat);
}
return ret;
}
//---------------------------------------------------------------------------
String __fastcall EncodePoint(double col)
{
/*1.取初始有符号值 col */
/*2.将其取十进制值乘以 1e5,并取整:*/
// Round是自定义函数.此处如果用Int取整的.话.三位小数时就会出.问题.用的到的朋友自己.Google下看把.
int num = (Round)(col * 100000);
/*3.将十进制值转换为二进制值*/
char buf[128]; itoa(num,buf,2);
/*4.末位+0*/
strcat(buf,"0");
/*5.如果原来的十进制值是负数,则对以下编码求反.并去除前面的0*/
if (num<0)
{
for(int i=0,iLoop=strlen(buf);i<iLoop;i++)
{
if (buf[i]=='0')
buf[i] = '1';
else
buf[i] = '0';
}
}
char *ptr, c = '1';
ptr = strchr(buf,c);
if (ptr==NULL) return ""; //问题
String str = ptr;
int Len = strlen(ptr);
/*6.将该二进制值分为 5 位一组的块(从右侧开始)*/
/*7.将这些 5 位一组的块倒序放置*/
/*8.如果后面还有一个位块,则将每个值与 0x20 进行“或”操作 (OR)*/
/*9.将每个值转换为十进制*/
/*10. 每个值+63 并将每个值转换为其对应的 ASCII 字符*/
int cord = Len/5;
int remainder = Len%5;
if (cord*5 < Len)
{
cord += 1; //组数
}
if (remainder==1) str = "0000" + str;
if (remainder==2) str = "000" + str;
if (remainder==3) str = "00" + str;
if (remainder==4) str = "0" + str;
TStringList* ts = new TStringList;
String ret;
for(int i=0,iLoop=cord; i<iLoop; i++)
{
ts->Add(Rights(str,5));
str = str.SubString(1,str.Length()-5);
int x = BintoDec(ts->Strings[i].c_str());
if (i!=cord-1)
x = x | 0x20;
x = x + 63;
ret += String(char(x));
}
delete ts;
return ret;
}
//---------------------------------------------------------------------------
String __fastcall EncodeLevels(int* LevBuf, int BufLen)
{
int TmpLev;
String ret;
for(int i=0, iLoop=BufLen; i<iLoop; i++)
{
ret += EncodeLevel(LevBuf[i]);
}
return ret;
}
//---------------------------------------------------------------------------
String __fastcall EncodeLevel(int Level)
{
char buf[128];
itoa(Level,buf,2);
char *ptr, c = '1';
ptr = strchr(buf,c);
if (ptr==NULL) return ""; //问题
String str = ptr;
int Len = strlen(ptr);
int cord = Len/5;
int remainder = Len%5;
if (cord*5 < Len)
{
cord += 1; //组数
}
if (remainder==1) str = "0000" + str;
if (remainder==2) str = "000" + str;
if (remainder==3) str = "00" + str;
if (remainder==4) str = "0" + str;
TStringList* ts = new TStringList;
String ret;
for(int i=0,iLoop=cord; i<iLoop; i++)
{
ts->Add(Rights(str,5));
str = str.SubString(1,str.Length()-5);
int x = BintoDec(ts->Strings[i].c_str());
if (i!=cord-1)
x = x | 0x20;
x = x + 63;
ret += String(char(x));
}
delete ts;
return ret;
}
//---------------------------------------------------------------------------
已经通过 .Google算法.实例.测试.
http://code.google.com/intl/zh-CN/apis/maps/documentation/polylinealgorithm.html