(十六)WebGIS中偏移補償量引起的問題之探討

文章版權由做者李曉暉和博客園共有,若轉載請於明顯處標明出處:http://www.cnblogs.com/naaoveGIS/算法

1.背景

在上一章裏講解地圖平移功能的實現時,我在最後提出了兩個問題:canvas

A.在地圖平移後,矢量圖層的canvas的XY都發生了變化,此時根據地理座標轉換爲屏幕座標公式得出的屏幕座標,在canvas上能將要素正確顯示嗎?微信

B.矢量圖層canvas的原點座標XY有須要還原成初始的(0,0)的時候嗎?工具

對這兩個問題我給出的答案是:不能和須要。設計

在這一章裏,咱們將詳細講解得出這兩個答案的緣由。3d

2.何爲偏移補償量?

在地圖平移時,咱們作了兩個操做:一個是對MapCanvas的原點座標XY進行了變化,第二個是對此時屏幕的實際地理範圍作了變化。詳細的實現過程以及公式能夠參考上一章WebGIS中平移功能的設計和實現。blog

而這兩個操做都須要用到一個共同的參數,即此時操做偏移量(moveX,moveY)。可是,此時操做偏移量並非偏移補償量。偏移補償量,是針對於初始座標(0,0),此時canvas的左上角座標XY的總體偏移量,咱們用作(sumMoveX,sumMoveY)來表示。事件

3.偏移補償量的影響

3.1若是不考慮偏移補償量,會出現的問題

假設,此時地圖的canvas原點已經被平移了(sumMoveX,sumMoveY),當咱們再次使用地理或業務服務端的矢量服務,解析返回的矢量數據中的Geometry時,會先把Geometry中的地理座標轉換屏幕座標,而後再將此時用屏幕座標繪出的要素添加到該canvas中。可是,問題來了,咱們會發現,此時的要素並不在咱們想要的位置上(實際座標處),而是在了其餘地方從而發生了偏移。這也是咱們第一個問題的完整描述。get

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/

                                                                           若是您以爲本文確實幫助了您,能夠微信掃一掃,進行小額的打賞和鼓勵,謝謝 ^_^

                                          

相關文章
相關標籤/搜索