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

声明:此系列文章,不是说教,不是告诉任何人如何利用 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 .numYcentertile .numY ;

           tiles [count ].index .numXcentertile .numX ;

           tiles [count ].index .numYcentertile .numY ;

           tiles [count ].lefttoptopPoint ;

           tiles [count ].rightbottombottomPoint ;

      }

      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 .numXtilenum .numX ;

                            tiles [count ].index .numYtilenum .numY ;

                            tiles [count ].lefttoptopPoint ;

                            tiles [count ].rightbottombottomPoint ;

                      }

                      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 .numXtilenum .numX ;

                            tiles [count ].index .numYtilenum .numY ;

                            tiles [count ].lefttoptopPoint ;

                            tiles [count ].rightbottombottomPoint ;

                      }

                      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 .numYtilenum .numY ;

                            tiles [count ].lefttoptopPoint ;

                            tiles [count ].rightbottombottomPoint ;

                      }

                      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 .numXtilenum .numX ;

                            tiles [count ].index .numYtilenum .numY ;

                            tiles [count ].lefttoptopPoint ;

                            tiles [count ].rightbottombottomPoint ;

                      }

                      count ++;

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

                 }

           }

      }

}

 

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值