最新文章专题视频专题问答1问答10问答100问答1000问答2000关键字专题1关键字专题50关键字专题500关键字专题1500TAG最新视频文章推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37视频文章20视频文章30视频文章40视频文章50视频文章60 视频文章70视频文章80视频文章90视频文章100视频文章120视频文章140 视频2关键字专题关键字专题tag2tag3文章专题文章专题2文章索引1文章索引2文章索引3文章索引4文章索引5123456789101112131415文章专题3
当前位置: 首页 - 正文

7.基于Wms协议的Map开发(七:计算模块)

来源:动视网 责编:小OO 时间:2025-09-30 21:12:36
文档

7.基于Wms协议的Map开发(七:计算模块)

声明:此系列文章,不是说教,不是告诉任何人如何利用C++开发电子地图的教程,而且本人水平有限,也达不到教程的地步。只是利用此系列的文章,来记录开发基于C++应用在Windows下开发电子地图的过程。愿对C++开发感兴趣的朋友,熟知Gis开发的朋友,了解Wms、WFS协议的朋友,亦或是对GoogleMap之类感兴趣的朋友,共同讨论。(废话到此结束)。计算模块如果你看这个系列,我想可能你一直在找的就是这部分了。如何实现二分法切割,达到GoogleMap的效果。此模块是一个纯计算模块。跟以往章节不同
推荐度:
导读声明:此系列文章,不是说教,不是告诉任何人如何利用C++开发电子地图的教程,而且本人水平有限,也达不到教程的地步。只是利用此系列的文章,来记录开发基于C++应用在Windows下开发电子地图的过程。愿对C++开发感兴趣的朋友,熟知Gis开发的朋友,了解Wms、WFS协议的朋友,亦或是对GoogleMap之类感兴趣的朋友,共同讨论。(废话到此结束)。计算模块如果你看这个系列,我想可能你一直在找的就是这部分了。如何实现二分法切割,达到GoogleMap的效果。此模块是一个纯计算模块。跟以往章节不同
声明:此系列文章,不是说教,不是告诉任何人如何利用C++开发电子地图的教程,而且本人水平有限,也达不到教程的地步。只是利用此系列的文章,来记录开发基于C++应用在Windows下开发电子地图的过程。愿对C++开发感兴趣的朋友,熟知Gis开发的朋友,了解Wms、WFS协议的朋友,亦或是对GoogleMap之类感兴趣的朋友,共同讨论。(废话到此结束)。

计算模块

如果你看这个系列,我想可能你一直在找的就是这部分了。如何实现二分法切割,达到Google Map的效果。

此模块是一个纯计算模块。跟以往章节不同,这回我们先不看流程图。先给出两组公式,因为我一直提倡大家自行实现,因为我水平有限,设计的不好,希望大家在掌握原理之后,发挥聪明才智,自行设计。

以下的两组公式,是网络上可以找到又不能找到的,为什么呢?网上给的函数原型是有问题的。我经过验证和使用,修正了这套公式。仅供大家参考。

第一套公式:根据一个经纬度点计算此点处于当前缩放级别中的哪一个瓦块上(x:代表纬线方向上的编号,y:代表经线方向上的编号)。

第二套公式:根据当前缩放级别下指定的瓦块编号,计算出此瓦块左上及右下点的经纬度值。

根据本人的理解,第一套公式用于计算中心瓦块的编号,既用户点击的那个点在当前缩放级别下的瓦块编号,所以只是用一次。重点是第二套公式,人为的按照规律修改瓦块编号,送至此公式中,验证被计算的瓦块的左上或右下点是否在显示范围内的经纬度范围中。如果是,表明这个瓦块要被显示,否则不被显示。如果不很明白,那么请看此模块的设计流程图。

................................................未完待续................................................

如果还是没太明白,那么请看我的实现,我使用回调实现。

首先,将用户点击位置的经纬度值,和当前的缩放级别传入,用来计算这个点所在的瓦块的编号。

void BstarWmsPostOfficeDepot::CalculateXY(TILENUM& segNum)

{

    segNum.numX = (int)((180.0 + m_CenterPt.ptx)*pow(2,(double)(17-m_Zoom))/360.0);

     double temp1 = pow(2, (double)(17 - m_Zoom));

     double temp3 = (45.0 - m_CenterPt.pty/2.0);

     double a = tan(temp3*PI/180.0);

    double xxx = log(a);

     double temp2 = xxx/(2.0*PI);

    temp2 = -temp2 + 0.5;

     segNum.numY = (int)(temp1*temp2);

}

看来比较乱,主要为了调试时透视个步骤的值,而定义了很多临时变量。TILENUM这个结构体,包含两个int值,分别代表此点在纬线、经线两个方向上的标号。此函数也就是第一套公式的实现。

接下来看看第二套公式的实现,以备后用。

void BstarWmsPostOfficeDepot::GetLatLonFromXY(TILENUM centertile,POINT_D& topPoint,POINT_D& bottomPoint)

{    

topPoint.ptx = (double)360.0*centertile.numX/(pow(2, (double)(17 - m_Zoom))) - (double)180.0;

    bottomPoint.ptx = (double)360.0*(centertile.numX+1)/(pow(2, (double)(17 - m_Zoom))) - (double)180.0;

    double step1 = pow(2, (double)(17 - m_Zoom));

    double step2 = (centertile.numY/step1 - 0.5)*2.0*PI;

    double step3 = pow(E,step2);

    double step4 = atan(step3)*180.0/PI;

    bottomPoint.pty = -(45.0 - step4)*2.0;

    if (fabs(bottomPoint.pty)<0.000001)

        bottomPoint.pty = 0;

    step2 = ((centertile.numY+1)/step1 - 0.5)*2.0*PI;

    step3 = pow(E,step2);

    step4 = atan(step3)*180.0/PI;

    topPoint.pty = -(45.0 - step4)*2.0;

    if (fabs(topPoint.pty)<0.000001)

        topPoint.pty = 0;

}

最后,回调计算将被显示的模块的标号。

首先看调用此回调的位置

void BstarWmsPostOfficeDepot::CalculateTiles(TILENUM centertile, TILES tiles[], int& count)

{

    count = 0;

    //根据中心点所在图块编号,计算该图块的经纬度范围

    POINT_D topPoint,bottomPoint;

    GetLatLonFromXY(centertile,topPoint,bottomPoint);

    m_tilewidth = bottomPoint.ptx - topPoint.ptx;

    m_tileheight = topPoint.pty - bottomPoint.pty;

    //将中心点所在瓦片加入到被显示瓦片集中

    if (tiles != NULL)

    {

        m_CenterTileNum.numX = centertile.numX;

        m_CenterTileNum.numY =  centertile.numY;

        tiles[count].index.numX =  centertile.numX;

        tiles[count].index.numY =  centertile.numY;

        tiles[count].lefttop =  topPoint;

        tiles[count].rightbottom =  bottomPoint;

    }

    count++;

    //根据中心点经纬度范围计算被显示图块集

    RECTLATLON centertileRect;

    centertileRect.lefttop = topPoint;

    centertileRect.rightbottom = bottomPoint;

    centertileRect.leftbottom.ptx = topPoint.ptx;

    centertileRect.leftbottom.pty = bottomPoint.pty;

    centertileRect.righttop.ptx = bottomPoint.ptx;

    centertileRect.righttop.pty = topPoint.pty;

    GetOtherTiles(ALL,centertile, centertileRect, tiles, count);

    return;

}

再看看回调函数自身的实现

void BstarWmsPostOfficeDepot::GetOtherTiles(int NotWay,TILENUM centertile, RECTLATLON centertileRect, TILES tiles[], int& count)

{

    if (count >= MAX_TILE_COUNT)

    {

        return;

    }

    TILENUM tilenum;

    POINT_D topPoint,bottomPoint;

    RECTLATLON Toprect,Rightrect,Bottomrect,Leftrect;

    //计算上

    if(UP != NotWay)

    {

        if (count >= MAX_TILE_COUNT)

        {

            return;

        }

        tilenum.numX = centertile.numX;

        tilenum.numY = centertile.numY + 1;

        GetLatLonFromXY(tilenum,topPoint,bottomPoint);

         Toprect.lefttop = topPoint;

        Toprect.rightbottom = bottomPoint;

        Toprect.leftbottom.ptx = topPoint.ptx;

        Toprect.leftbottom.pty = bottomPoint.pty;

        Toprect.righttop.ptx = bottomPoint. ptx;

        Toprect.righttop.pty = topPoint.pty;

        if (IsInRect(Toprect.leftbottom,TotalRect)||

            IsInRect(Toprect.rightbottom,TotalRect))

        {

            if (IsValidPt(topPoint)&&IsValidPt(bottomPoint)&&(!IsExisted(tilenum,count)))

            {

                if (tiles != NULL)

                {

                    tiles[count].index.numX =  tilenum.numX;

                    tiles[count].index.numY =  tilenum.numY;

                    tiles[count].lefttop =  topPoint;

                    tiles[count].rightbottom =  bottomPoint;

                }

                count++;

                GetOtherTiles(DOWN,tilenum, Toprect, tiles, count);

            }

        }

    }

    //计算右

    if(RIGHT != NotWay)

    {

        if (count >= MAX_TILE_COUNT)

        {

            return;

        }

        tilenum.numX = centertile.numX + 1;

        tilenum.numY = centertile.numY;

        GetLatLonFromXY(tilenum,topPoint,bottomPoint);

        Rightrect.lefttop = topPoint;

        Rightrect.rightbottom = bottomPoint;

        Rightrect.leftbottom.ptx = topPoint.ptx;

        Rightrect.leftbottom.pty = bottomPoint.pty;

        Rightrect.righttop.ptx = bottomPoint. ptx;

        Rightrect.righttop.pty = topPoint.pty;

        if (IsInRect(Rightrect.lefttop,TotalRect)||

            IsInRect(Rightrect.leftbottom,TotalRect))

        {

            if (IsValidPt(topPoint)&&IsValidPt(bottomPoint)&&(!IsExisted(tilenum,count)))

            {

                if (tiles != NULL)

                {

                    tiles[count].index.numX =  tilenum.numX;

                    tiles[count].index.numY =  tilenum.numY;

                    tiles[count].lefttop =  topPoint;

                    tiles[count].rightbottom =  bottomPoint;

                }

                count++;

                GetOtherTiles(LEFT,tilenum, Rightrect, tiles, count);

            }

        }

    }

    //计算下

    if(DOWN != NotWay)

    {

        if (count >= MAX_TILE_COUNT)

        {

            return;

        }

        tilenum.numX = centertile.numX;

        tilenum.numY = centertile.numY - 1;

        GetLatLonFromXY(tilenum,topPoint,bottomPoint);

        Bottomrect.lefttop = topPoint;

        Bottomrect.rightbottom = bottomPoint;

        Bottomrect.leftbottom.ptx = topPoint.ptx;

        Bottomrect.leftbottom.pty = bottomPoint.pty;

        Bottomrect.righttop.ptx = bottomPoint. ptx;

        Bottomrect.righttop.pty = topPoint.pty;

        if (IsInRect(Bottomrect.lefttop,TotalRect)||

            IsInRect(Bottomrect.righttop,TotalRect))

        {

            if (IsValidPt(topPoint)&&IsValidPt(bottomPoint)&&(!IsExisted(tilenum,count)))

            {

                if (tiles != NULL)

                {

                    tiles[count].index.numX =  tilenum.numX;

                    tiles[count].index.numY =  tilenum.numY;

                    tiles[count].lefttop =  topPoint;

                    tiles[count].rightbottom =  bottomPoint;

                }

                count++;

                GetOtherTiles(UP,tilenum, Bottomrect, tiles, count);

            }

        }

    }

    //计算左

    if(LEFT != NotWay)

    {

        if (count >= MAX_TILE_COUNT)

        {

            return;

        }

        tilenum.numX = centertile.numX - 1;

        tilenum.numY = centertile.numY;

        GetLatLonFromXY(tilenum,topPoint,bottomPoint);

        Leftrect.lefttop = topPoint;

        Leftrect.rightbottom = bottomPoint;

        Leftrect.leftbottom.ptx = topPoint.ptx;

        Leftrect.leftbottom.pty = bottomPoint.pty;

        Leftrect.righttop.ptx = bottomPoint. ptx;

        Leftrect.righttop.pty = topPoint.pty;

        if (IsInRect(Leftrect.righttop,TotalRect)||

            IsInRect(Leftrect.rightbottom,TotalRect))

        {

            if (IsValidPt(topPoint)&&IsValidPt(bottomPoint)&&(!IsExisted(tilenum,count)))

            {

                if (tiles != NULL)

                {

                    tiles[count].index.numX =  tilenum.numX;

                    tiles[count].index.numY =  tilenum.numY;

                    tiles[count].lefttop =  topPoint;

                    tiles[count].rightbottom =  bottomPoint;

                }

                count++;

                GetOtherTiles(RIGHT,tilenum, Leftrect, tiles, count);

            }

        }

    }

}

................................................未完待续................................................

文档

7.基于Wms协议的Map开发(七:计算模块)

声明:此系列文章,不是说教,不是告诉任何人如何利用C++开发电子地图的教程,而且本人水平有限,也达不到教程的地步。只是利用此系列的文章,来记录开发基于C++应用在Windows下开发电子地图的过程。愿对C++开发感兴趣的朋友,熟知Gis开发的朋友,了解Wms、WFS协议的朋友,亦或是对GoogleMap之类感兴趣的朋友,共同讨论。(废话到此结束)。计算模块如果你看这个系列,我想可能你一直在找的就是这部分了。如何实现二分法切割,达到GoogleMap的效果。此模块是一个纯计算模块。跟以往章节不同
推荐度:
  • 热门焦点

最新推荐

猜你喜欢

热门推荐

专题
Top