地图的滚动问题 ( 积分: 100 )

  • 主题发起人 主题发起人 shappy
  • 开始时间 开始时间
S

shappy

Unregistered / Unconfirmed
GUEST, unregistred user!
中国地图出版社的地图,地图滚动时十分流畅,而且地图边缘的路名自动调整位置.按照我的估计,应该是打开地图时已经画好全图,移动时只是移动画好的底图(不再重画甚是不作窗口剪裁),并实时计算标签路名的位置.这方面我有点迷惑,他是如何重算所有路名标签的位置的,对于和视口不相交的路线,可以不重算路名标签的位置,但是这样一来对于有相交的路线如何擦除原来的路名并写入新的路名了,如果全部重写标签的位置,那计算量是否太大,能否做到这么流畅的效果?听听大家的意见.
 
中国地图出版社的地图,地图滚动时十分流畅,而且地图边缘的路名自动调整位置.按照我的估计,应该是打开地图时已经画好全图,移动时只是移动画好的底图(不再重画甚是不作窗口剪裁),并实时计算标签路名的位置.这方面我有点迷惑,他是如何重算所有路名标签的位置的,对于和视口不相交的路线,可以不重算路名标签的位置,但是这样一来对于有相交的路线如何擦除原来的路名并写入新的路名了,如果全部重写标签的位置,那计算量是否太大,能否做到这么流畅的效果?听听大家的意见.
 
好象不是这样吧
地图在库里都是流格式的,在界面上拖到哪里就从库中读到哪里
要是一次性全读到内存,还不要爆掉咯
它的速度快可能是算法比较好吧,关注中
 
我觉得应该是先画全图,不然不可能那么流畅,毕竟计算视口剪裁是非常大计算量的.而且比较明细的感觉就是如果地图稍大些读取就明显慢了.对于视口剪裁的话地图数据量如果差别不是很大计算量差别是不多的.
 
不会是画全图的,拖动流畅应该是采用新的算法,比如说,把屏幕范围内地图显示出来的同时,也加载了它周边一定宽度的地图,这个范围会随着拖动中心点的位置动态计算,所以你每次拖动的时候其实也是在加载其周围的地图,这样的话就会显得很流畅
 
这也是一个可能.不过有两个疑问.
1 看过cohen-sutherland算法的应该知道,对于同一个几何体视口的大小和计算量的相关性不是非常大,当然视口小了包含的对象也少,计算量<可能>有所减少,我觉得应该不会减少很多.关于这个算法我另外开一个题目讨论.
2 实际上移动的时候重算的区域应该是两个矩形,要进行两次运算,能否减少计算真是难知.而且还有一个边界问题,对于多边形由于上一次剪裁会给多边形增加一个边界,如果移动刚好扩展了那个多变形,你如何知道应该擦除多边形的哪些<多余>的边呢?
 
还有一个想法就是预读视口边缘的地图,视口滚动不会那么多,也可以实现比较快速的滚动,不知道我的想法是否对(没有时间实践测试).
另外我上面还提到一个问题就是如何处理滚动时的路名标签.
 
to shappy:你能提出这个问题很好,事实上这个效果的算法不难,有这么几个关键点要注意:
1,计算机制图在算法一级都是很快的(除非你设计的算法有问题),慢在GDI的绘图操作上面。
2,可以肯定地说,这个算法的绘图区域就是你所见到的这个范围,不存在把地图全部读出来,先一次画好,再移动视图的问题,这样是不可行的。
3,算法核心技术是:先不考虑动态注记的问题,地图是绘在缓冲位图中,再BitBlt到前端DC中;当地图平移时,比如上部出现几个象素的InvalidRect时(即一个MouseMove事件产生的区域),绘图区域就重绘这个区域,而更多的范围是不用重绘的(因为有缓冲位图不断地绘制到前端)。由于这个区域是很小的,所以绘图速度极快(你可以去试),肉眼根本感觉不到绘图的过程存在。绘好这个范围后,再和原来的位图融合成一个新位图,然后再以此类推,进行下一次MouseMove事件的响应...所以说,你一次对地图的拖放操作,中间是通过无数次的这样细小的重绘组成的,每次速度都很快,就是你会感到地图无缝平移的效果了。
4,再来谈注记。你肯定已经注到拖放时,注记在全图范围内也是动态注记的,因此,你肯定会问:如果原图不重绘,只用缓冲位图的话,如何擦除一些注记位置?实际上注记和图形不是一体的。我是有三层缓冲,第一层是只放图形,上面只有地图的点、线和多边形,第二层是图形和注记融合在一起的位图,也就是说注记和图形是在第二层缓冲中合为一体的,第三层当然就是前端DC了,就是把第二层位图BitBlt到前端的结果。那么在一次地图拖放过程中,这三个缓冲是如何进行配合的呢?我们看一下一次MouseMove事件响应的过程:拖出一块InvalidRect后,重绘此空白区域,然后和原来第三层位图重新组合成第三层,然后把第三层缓冲画到第二层上,再在上面注记,再画到第一层缓冲上...你可能会问:注记速度会这么快吗?答案是,可以这么快的。
 
后退
顶部