文章版权由做者李晓晖和博客园共有,若转载请于明显处标明出处:http://www.cnblogs.com/naaoveGIS/。算法
在上一章里讲解地图平移功能的实现时,我在最后提出了两个问题:canvas
A.在地图平移后,矢量图层的canvas的XY都发生了变化,此时根据地理坐标转换为屏幕坐标公式得出的屏幕坐标,在canvas上能将要素正确显示吗?微信
B.矢量图层canvas的原点坐标XY有须要还原成初始的(0,0)的时候吗?工具
对这两个问题我给出的答案是:不能和须要。设计
在这一章里,咱们将详细讲解得出这两个答案的缘由。3d
在地图平移时,咱们作了两个操做:一个是对MapCanvas的原点坐标XY进行了变化,第二个是对此时屏幕的实际地理范围作了变化。详细的实现过程以及公式能够参考上一章WebGIS中平移功能的设计和实现。blog
而这两个操做都须要用到一个共同的参数,即此时操做偏移量(moveX,moveY)。可是,此时操做偏移量并非偏移补偿量。偏移补偿量,是针对于初始坐标(0,0),此时canvas的左上角坐标XY的总体偏移量,咱们用作(sumMoveX,sumMoveY)来表示。事件
假设,此时地图的canvas原点已经被平移了(sumMoveX,sumMoveY),当咱们再次使用地理或业务服务端的矢量服务,解析返回的矢量数据中的Geometry时,会先把Geometry中的地理坐标转换屏幕坐标,而后再将此时用屏幕坐标绘出的要素添加到该canvas中。可是,问题来了,咱们会发现,此时的要素并不在咱们想要的位置上(实际坐标处),而是在了其余地方从而发生了偏移。这也是咱们第一个问题的完整描述。get
在讨论此问题前,咱们有必要回看一下我在第十章中给出的屏幕坐标和地理坐标互转换的公式:博客
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表示一张瓦片的像素大小。
咱们仔细观察地理坐标转换为屏幕坐标的公式,其原理是,用此时的地理坐标减去屏幕容器左上角所表明的地理坐标,而后除以一个像素所表明的地理长度,得出此时相对于屏幕容器左上角坐标的屏幕坐标。
你们看个人描述中,反复提到的是屏幕容器左上角坐标,何为屏幕容器左上角坐标呢?咱们再看下上一章我给出的平移原理示意图:
这其中的容器左上角屏幕坐标就是初始时和canvas左上角A点重叠的坐标(0,0)。
因此,当咱们把一个相对于(0,0)的要素,加入到一个左上角已经变为(sumMoveX,sumMoveY)的canvas中时,便发生了要素位置偏移的问题。
知道了引起偏移的问题,咱们便只须要对症下药便可。即当咱们把矢量数据中的地理坐标变为屏幕坐标后,再减去一个偏移补偿量便可。
也就是:
ScreenXY=geoXYToSreenXY(geoXY)-sumMoveXY
表如今代码层面上,即是绘制时,将转换获得的屏幕坐标减去偏移补偿量。
要弄清楚这个问题,咱们得再次研究坐标转换公式。在这个公式中涉及到一个重要的参数,即sliceLevelLength,当前地图级别下瓦片长度所表明的实际地理长度。
试想,当咱们的地图级别变化了,则此参数sliceLevelLength也变化了,若是sumMoveXY仍是以前的那个数字,那么sumMoveXY所表明 实际地理长度便再也不是正确的地理长度了。
这样会致使一个问题,地图级别变化后,若是继续使用以前的sumMoveXY值,获得的转换后的屏幕坐标会发生偏移。
此时,咱们若是采用这样一种作法,在地图级别变化后,将全部的sumMoveXY都变成0,即从新恢复到未发生偏移的状态下,则能很好的解决若是保留sumMoveXY值所引起的位置偏移问题。
表如今代码层面上,即是每次地图进行级别变化时,会抛出一个zoom事件,图层应该监听此事件,而后将图层(canvas)的作上角坐标XY变为0。
这里,我继续给出两个问题:
A.本但愿每次点击鼠标后能在鼠标点击的地方画出一个圆点,但是当拖动了地图后,鼠标再点击到地图上时,却没有将圆点画在点击的地方,而是偏移了。
B.一样也是想点击鼠标后能在鼠标点击的地方画出一个圆点,即便不拖动地图,当鼠标点击到已经画出的要素上后,发现如今画出的圆点偏移到其余地方了。
在解答上面两个问题时,我首先给出一组实验数据。
stageXY:全局舞台的坐标;
localXY: 本地坐标系;
geoPoint:此时的地理坐标;
mapDrawCanvas:此图层(Canvas)的原点坐标;
screenPoint:此时将地理坐标转换为屏幕坐标后的坐标;
fixedSreenPoint:将screenPoint减去偏移量后的修正坐标;
1)未拖动地图时,即没有偏移补偿量时:
2)拖动地图后,即有偏移补偿量时:
在不拖动地图和拖动地图的状况下,stageXY和将地理坐标转换成屏幕坐标后的screenPoint是能很好的对应的。其缘由,咱们在仔细的看了地理坐标转换成屏幕坐标的公式后就不难理解了,由于转换回来的屏幕坐标其相对的是(0,0)坐标,而此mapDrawCanvas所对应的stageXY坐标即是相对于(0,0)的。
这个结论告诉咱们,用于坐标转换的屏幕坐标最好是stageXY。
观察实验结论,将screenPoint减去偏移量后获得的fixedScreenPoint去掉最小偏差即是等于localXY。而想要在一个容器内画图,必须是使用其localXY坐标。
咱们发现,当容器(mapDrawCanvas)的原点坐标(mapDrawCanvas .x, mapDrawCanvas .y)变化后,在本地坐标系下所得的localXY也发生了相关的变化。而这个偏移量,即可以直接使用容器的原点。
由结论1咱们能够知道,用于坐标转换的坐标最好是stageXY。
问题1的缘由在于,使用localXY做为屏幕坐标,而后将localXY转换成地理坐标后进行保存。在地图平移后,此时保存的地理坐标便再也不是正确的地理坐标了,因而要素绘制时发生了偏移。
问题2的缘由在于,当咱们点击到一个要素后,此时得到的localXY再也不是相对于容器mapDrawCanvas的本地坐标了,而是相对于该被点击要素的本地坐标。因此坐标转换后会出现很严重的偏移。
在这一章里,咱们详细对偏移补偿量的本质及其形成的问题和解决方法。在这一章里,咱们提到了不少以前已经讲到的内容,主要包括坐标转换以及平移本质。最后我给出了一个简单的实验数据,为你们进一步讲解了偏移补偿量的本质。
在下一章里,咱们将跟你们一块儿讨论工具条中长度量算工具和面积量算工具所涉及的算法、设计和实现。但愿你们持续关注。
-----欢迎转载,但保留版权,请于明显处标明出处:http://www.cnblogs.com/naaoveGIS/
若是您以为本文确实帮助了您,能够微信扫一扫,进行小额的打赏和鼓励,谢谢 ^_^