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

posted @ 2010-03-05 12:52  Delphi爱好者  阅读(568)  评论(0编辑  收藏  举报