文章版权由作者李晓晖和博客园共有,若转载请于明显处标明出处:http://www.cnblogs.com/naaoveGIS/

1.背景

在上一章里讲解地图平移功能的实现时,我在最后提出了两个问题:

A.在地图平移后,矢量图层的canvas的XY都发生了变化,此时根据地理坐标转换为屏幕坐标公式得出的屏幕坐标,在canvas上能将要素正确显示吗?

B.矢量图层canvas的原点坐标XY有需要还原成初始的(0,0)的时候吗?

对这两个问题我给出的答案是:不能和需要。

在这一章里,我们将详细讲解得出这两个答案的原因。

2.何为偏移补偿量?

在地图平移时,我们做了两个操作:一个是对MapCanvas的原点坐标XY进行了变化,第二个是对此时屏幕的实际地理范围做了变化。详细的实现过程以及公式可以参考上一章WebGIS中平移功能的设计和实现。

而这两个操作都需要用到一个共同的参数,即此时操作偏移量(moveX,moveY)。但是,此时操作偏移量并不是偏移补偿量。偏移补偿量,是针对于初始坐标(0,0),此时canvas的左上角坐标XY的整体偏移量,我们用做(sumMoveX,sumMoveY)来表示。

3.偏移补偿量的影响

3.1如果不考虑偏移补偿量,会出现的问题

假设,此时地图的canvas原点已经被平移了(sumMoveX,sumMoveY),当我们再次使用地理或业务服务端的矢量服务,解析返回的矢量数据中的Geometry时,会先把Geometry中的地理坐标转换屏幕坐标,然后再将此时用屏幕坐标绘出的要素添加到该canvas中。但是,问题来了,我们会发现,此时的要素并不在我们想要的位置上(实际坐标处),而是在了其他地方从而发生了偏移。这也是我们第一个问题的完整描述。

3.2出现此问题的原因

3.2.1 回顾屏幕坐标与地理坐标互转换公式

在讨论此问题前,我们有必要回看一下我在第十章中给出的屏幕坐标和地理坐标互转换的公式:

A.屏幕坐标转换为地理坐标

geoXY.x = screenGeoBounds.left + screenX * sliceLevelLength / tileSize;

geoXY.y = screenGeoBounds.top - screenY * sliceLevelLength / tileSize;

B.地理坐标转换为屏幕坐标

screenXY.x = (geoX - screenGeoBounds.left)/(sliceLevelLength/ tileSize);

screenXY.y = (screenGeoBounds.top - geoY)/(sliceLevelLength/ tileSize);

其中geoXY表示地理坐标,screenXY表示屏幕坐标,screenGeoBounds表示屏幕地理范围,slieceLevelLenth表示此事地图级别下的一张瓦片所代表的实际地理长度,tileSize表示一张瓦片的像素大小。

3.2.2 从公式分析产生偏移的问题

我们仔细观察地理坐标转换为屏幕坐标的公式,其原理是,用此时的地理坐标减去屏幕容器左上角所代表的地理坐标,然后除以一个像素所代表的地理长度,得出此时相对于屏幕容器左上角坐标的屏幕坐标。

大家看我的描述中,反复提到的是屏幕容器左上角坐标,何为屏幕容器左上角坐标呢?我们再看下上一章我给出的平移原理示意图:

这其中的容器左上角屏幕坐标就是初始时和canvas左上角A点重叠的坐标(0,0)。

所以,当我们把一个相对于(0,0)的要素,加入到一个左上角已经变为(sumMoveX,sumMoveY)的canvas中时,便发生了要素位置偏移的问题。

3.3如何解决此偏移问题

知道了引发偏移的问题,我们便只需要对症下药即可。即当我们把矢量数据中的地理坐标变为屏幕坐标后,再减去一个偏移补偿量即可。

也就是:

ScreenXY=geoXYToSreenXY(geoXY)-sumMoveXY

表现在代码层面上,便是绘制时,将转换得到的屏幕坐标减去偏移补偿量。

4.偏移补偿量何时归零?

要弄清楚这个问题,我们得再次研究坐标转换公式。在这个公式中涉及到一个重要的参数,即sliceLevelLength,当前地图级别下瓦片长度所代表的实际地理长度。

试想,当我们的地图级别变化了,则此参数sliceLevelLength也变化了,如果sumMoveXY还是之前的那个数字,那么sumMoveXY所代表 实际地理长度便不再是正确的地理长度了。

这样会导致一个问题,地图级别变化后,如果继续使用之前的sumMoveXY值,得到的转换后的屏幕坐标会发生偏移。

此时,我们如果采用这样一种做法,在地图级别变化后,将所有的sumMoveXY都变成0,即重新恢复到未发生偏移的状态下,则能很好的解决如果保留sumMoveXY值所引发的位置偏移问题。

表现在代码层面上,便是每次地图进行级别变化时,会抛出一个zoom事件,图层应该监听此事件,然后将图层(canvas)的做上角坐标XY变为0。

5.进一步探讨偏移补偿量本质以及其引发的问题

5.1 提出问题

这里,我继续给出两个问题:

A.本希望每次点击鼠标后能在鼠标点击的地方画出一个圆点,可是当拖动了地图后,鼠标再点击到地图上时,却没有将圆点画在点击的地方,而是偏移了。

B.同样也是想点击鼠标后能在鼠标点击的地方画出一个圆点,即使不拖动地图,当鼠标点击到已经画出的要素上后,发现现在画出的圆点偏移到其他地方了。

5.2实验及实验结果分析

在解答上面两个问题时,我首先给出一组实验数据。

stageXY:全局舞台的坐标;

localXY: 本地坐标系;

geoPoint:此时的地理坐标;

mapDrawCanvas:此图层(Canvas)的原点坐标;

screenPoint:此时将地理坐标转换为屏幕坐标后的坐标;

fixedSreenPoint:将screenPoint减去偏移量后的修正坐标;

1)未拖动地图时,即没有偏移补偿量时:

2)拖动地图后,即有偏移补偿量时:

5.2.1结论1—用于坐标转换的屏幕坐标最好是stageXY

在不拖动地图和拖动地图的情况下,stageXY和将地理坐标转换成屏幕坐标后的screenPoint是能很好的对应的。其原因,我们在仔细的看了地理坐标转换成屏幕坐标的公式后就不难理解了,因为转换回来的屏幕坐标其相对的是(0,0)坐标,而此mapDrawCanvas所对应的stageXY坐标便是相对于(0,0)的。

这个结论告诉我们,用于坐标转换的屏幕坐标最好是stageXY。

5.2.2 结论2-转换得到的屏幕坐标必须减去偏移量后才能等于此时的localXY

观察实验结论,将screenPoint减去偏移量后得到的fixedScreenPoint去掉最小误差便是等于localXY。而想要在一个容器内画图,必须是使用其localXY坐标。

5.2.3 结论3-偏移量便是容器的原点(mapDrawCanvas .x, mapDrawCanvas .y)

我们发现,当容器(mapDrawCanvas)的原点坐标(mapDrawCanvas .x, mapDrawCanvas .y)变化后,在本地坐标系下所得的localXY也发生了相关的变化。而这个偏移量,便可以直接使用容器的原点。

5.3 问题解答

由结论1我们可以知道,用于坐标转换的坐标最好是stageXY。

问题1的原因在于,使用localXY作为屏幕坐标,然后将localXY转换成地理坐标后进行保存。在地图平移后,此时保存的地理坐标便不再是正确的地理坐标了,于是要素绘制时发生了偏移。

问题2的原因在于,当我们点击到一个要素后,此时获得的localXY不再是相对于容器mapDrawCanvas的本地坐标了,而是相对于该被点击要素的本地坐标。所以坐标转换后会出现很严重的偏移。

6.总结

在这一章里,我们详细对偏移补偿量的本质及其造成的问题和解决方法。在这一章里,我们提到了很多之前已经讲到的内容,主要包括坐标转换以及平移本质。最后我给出了一个简单的实验数据,为大家进一步讲解了偏移补偿量的本质。

在下一章里,我们将跟大家一起讨论工具条中长度量算工具和面积量算工具所涉及的算法、设计和实现。希望大家持续关注。

                         -----欢迎转载,但保留版权,请于明显处标明出处:http://www.cnblogs.com/naaoveGIS/

如果您觉得本文确实帮助了您,可以微信扫一扫,进行小额的打赏和鼓励,谢谢 ^_^

                                          

(十六)WebGIS中偏移补偿量引发的问题之探讨的更多相关文章

  1. J2EE进阶(十六)Hibernate 中getHibernateTemplate()方法使用

    J2EE进阶(十六)Hibernate 中getHibernateTemplate()方法使用   spring 中获得由spring所配置的hibernate的操作对象,然后利用此对象进行,保存,修 ...

  2. (十二) WebGIS中矢量图层的设计

    文章版权由作者李晓晖和博客园共有,若转载请于明显处标明出处:http://www.cnblogs.com/naaoveGIS/. 1.前言 在前几章中我们已经了解了什么是矢量查询.屏幕坐标与地理坐标之 ...

  3. (十九)WebGIS中I查询的原理及设计(包含AGS、GeoServer、Supermap)

    文章版权由作者李晓晖和博客园共有,若转载请于明显处标明出处:http://www.cnblogs.com/naaoveGIS/. 1.背景 我们在使用arcmap时,经常会用到被称为I查询的工具.具体 ...

  4. (十八)WebGIS中清空功能和地图定位功能的设计以及实现

    文章版权由作者李晓晖和博客园共有,若转载请于明显处标明出处:http://www.cnblogs.com/naaoveGIS/. 1.背景 当地图中增加了很多元素后,对不同的元素需要进行一定的控制,最 ...

  5. (十五)WebGIS中平移功能的设计和实现

    文章版权由作者李晓晖和博客园共有,若转载请于明显处标明出处:http://www.cnblogs.com/naaoveGIS/. 1.前言 这一章我们将详细讲解WebGIS工具栏中另一个基础工具——平 ...

  6. (十)WebGIS中地理坐标与屏幕坐标间的转换原理

    文章版权由作者李晓晖和博客园共有,若转载请于明显处标明出处:http://www.cnblogs.com/naaoveGIS/. 1.前言 地图本身是拥有坐标的,一般可以大致分为平面坐标和经纬度坐标, ...

  7. (十四)WebGIS中地图放大缩小的设计和实现

    文章版权由作者李晓晖和博客园共有,若转载请于明显处标明出处:http://www.cnblogs.com/naaoveGIS/. 1.背景 在上一章中,我们给出了整个工具栏设计的核心,使用命令模式,并 ...

  8. 《C++游戏开发》十六 游戏中的寻路算法(二):迷宫&A*算法基础

    本系列文章由七十一雾央编写,转载请注明出处.  http://blog.csdn.net/u011371356/article/details/10289253 作者:七十一雾央 新浪微博:http: ...

  9. WPF入门教程系列十六——WPF中的数据绑定(二)

    三.绑定模式 通过上一文章中的示例,学习了简单的绑定方式.在这里的示例,要学习一下绑定的模式,和模式的使用效果. 首先,我们来做一个简单示例,这个示例是根据ListBox中的选中项,去改变TextBl ...

随机推荐

  1. 跨域无法获取自定义header的问题

    同域的时候,header里面的参数可以随便自己定义.服务端都是可以获取的. 但是跨域的时候,除了设置 <add name="Access-Control-Allow-Origin&qu ...

  2. TP5与TP3.X对比

    首先声明本章节并非是指导升级旧的项目到5.0,而是为了使用3.X版本的开发者更快的熟悉并上手这个全新的版本.同时也强烈建议开发者抛弃之前旧的思维模式,因为5.0是一个全新的颠覆重构版本. 需要摒弃的3 ...

  3. ntfs-3g

    CentOS默认源里没有ntfs3g,想要添加ntfs支持,无非是自己下载编译安装或者加源yum安装. 昨天重新安装了一个CentOS7,用的是添加aliyun的epel源来yum安装的方式,简单易行 ...

  4. c#解析XML到DATASET及dataset转为xml文件函数

    //将xml对象内容字符串转换为DataSet         public static DataSet ConvertXMLToDataSet(string xmlData)         { ...

  5. [学习笔记] Inten

  6. C#与Java对比学习:类型判断、类与接口继承、代码规范与编码习惯、常量定义

    类型判断符号: C#:object a;  if(a is int) { }  用 is 符号判断 Java:object a; if(a instanceof Integer) { } 用 inst ...

  7. 在 Azure 上使用 Docker运行 Mono

    Docker 是最近相当热门的一个名词,它是一个基于 Linux Container 的轻量化的虚拟技术,而微软也相当积极与 Docker 合作,在 Azure 上支持这个火热的技术,并且提供简单的方 ...

  8. 我的第一段jQuery代码

    说起 jQuery,很多人可能觉得,不算什么,就是个js类库.而,对于我,下面这几行代码,是一个新的开始. 多年来,我一直在使用MooTools ,他面向对象,写起来结构清晰分明,都是在原生js的基础 ...

  9. 说说Java程序和数据库交互的乱码解决

    本文就本人遇到的问题进行讲解 1.通过jdbc直连方式,连接Mysql数据库,从程序向数据库中写入数据出现的乱码解决方案. 当通过程序向Student表中写入一条数据时,写入数据库的内容会产生乱码. ...

  10. CSS效果集锦(持续更新中)

    高亮光弧效果 使用CSS3实现的一个高亮光弧效果,当鼠标hover到某一个元素上时,一道光弧从左向右闪过,效果如下: 代码如下: <!DOCTYPE html> <html lang ...