- 首先是創(chuàng)建多邊形外接的矩形,將多邊形頂點全部遍歷一遍,取到最大和最小的經緯度值。經度最大為東,經度最小為西。緯度最大為北,緯度最小為南。將這幾個組合一下,獲得西北點,東北點,東南點和西南點,就可以弄出一個矩形出來
- 然后是計算這個外接矩形穿過了多少條緯度線,跟之前那個場景是一樣的。rect是上面那個函數創(chuàng)建的數組,可以看到西北點的索引是0,西南點的索引是3,所以計算西北到西南的點,也就是這個外接矩形的高度。這個方法返回有l(wèi)en條緯度線穿過,而且穿過的緯度相差lat。

- 最后就是結合上面幾個場景,改寫一下最終的生成函數,這里你是直接將生成的橫線畫了出來,如果需要做折線連接順序處理,還需要聲明一個數組去存儲生成的點,比如當緯度線的索引是奇數時,橫線從西往東畫,也就是先放西邊的點再放東邊的點;如果緯度線索引是偶數時,橫線從東往西畫,也就是反過來。這里就留給你自己處理了

到這里,基本上已經完成了90%,剩下10%那部分最簡單了。簡單么?你歪著頭問,到現在為止只是多邊形與緯度線相交啊,現實中無人機又不可能都是沿著緯度在地圖上橫著飛!它可以在地圖上沿任意方向飛行的,可上面的做法,只能讓無人機橫著走??!
別急,你這時候要淡定,你要想想開頭不是還留了一個transform
函數么?
這個transform
的作用是讓坐標(x,y)
繞著(tx,ty)
旋轉deg
度后在縮放SySx
倍得到一個的新坐標(_x,_y)
。沒錯,這次我們要拿這些坐標進行旋轉運動。
而且牛頓告訴過你:
運動都是相對的
先放一張gif圖,看看如何繪制一個斜45度角的航線:

GIF.gif
先讓多邊形繞著中心點旋轉想要的角度,將得到的新多邊形再與緯度線做相交操作,獲取到那些交點之后,再將那些交點旋轉回來。換句話說,變換前它是一個任意多邊形,變換后,它還是一個任意多邊形,都是滿足上面已經預設好的場景的。這樣的好處顯而易見,你不需要修改上面的任何一個函數,也不需要去多寫一條兩個一次函數求交點的公式。把問題化到最簡單的場景去,只需要添加變換的代碼:

這里你一定要牢記,lng是經度,對應x;lat是緯度,對應y(被leaflet框架坑哭的我QuQ。。。 然后,將原來的代碼加上去

小瑕疵
也許細心的你發(fā)現了,gif圖里面轉是轉了,斜45度的角也是畫出來了,但是旋轉后的圖形好像是被拉長了!旋轉回來時又會被壓肥回來。這個嘛。。。
這個問題其實我在寫驗證的時候也發(fā)現了,粗略計算多邊形面積和航線掃過的面積的比值,總是發(fā)現0度的比值最接近于1,90度的比值最小,不管多邊形是什么形狀。
最開始我一直以為是面積算法的原因,直到寫這篇文章的時候去寫那個gif動畫后才發(fā)現,多邊形變換后變形了,轉換后與緯度相交的數量變多了。而我猜想變形的原因可能是,地球并不是一個平面,它是彎的你知道吧,這些經緯度雖然是投影到了平面上了,但實際上它們是在一個球上。直接拿經緯度變換相當于先在球上做了旋轉,然后在投影到地圖的平面上,這樣看起來就像是被拉長了。
所以,你不能直接變換經緯度,而是要將經緯度換算成地圖上的像素坐標,變換完之后再轉回來,這樣圖像就不會被拉長了。
因此先來兩個像素系與經緯度坐標系轉換的方法壓壓驚:

然后將原來的createRotatePolygon
函數改為

這樣就解決了拉長的問題:

GIF.gif
看到這里,相信你已經完全掌握了這種思路,即使你是使用iOS或者android的sdk,你也應該可以很快將思路“移植”過去。
至于那個折線的順序,這個只是在push進polyline數組的時候判斷一下i的奇偶修改不同的push順序,很簡單就得到那種折線效果,我相信你是會寫的,這里就不著筆墨了。
更多的源碼請訪問:github.com/Char-Ten/cp…
寫在最后
終于寫完了此文,真是不容易。這個思路,從最開始思想混亂與Leaflet框架緊密耦合,到一步步解耦,到自己決定寫一個適用于各個地圖平臺的庫,到寫這篇文章,差不多已經過去兩個星期了。我發(fā)現,很多問題是你調試過程中發(fā)現不了的,等到你調試好了,決定寫一篇裝逼的文章,在寫的過程中你就會發(fā)現各種調試中出現不了的問題,比如那個變換變形的問題。
在動手前,關于此類的教程文章少之又少,唯一可以找到比較符合場景的竟然是百度文庫里面的一篇論文:
基于作業(yè)航向的不規(guī)則區(qū)域作業(yè)航線規(guī)劃算法研究
論文懂吧,長倒是不長,就是臭,里面堆砌著各種奇奇怪怪的術語。之后看了兩天后才明白他的實現思路,大同小異,只不過不知道他怎么搞的,新弄出一個坐標系出來,感覺這樣是增加了思路的復雜度啊。所以在他的算法的基礎上我做了簡化,不做坐標系偏移,取代的是變換地塊坐標,這樣實現起來相對簡單些。
因此在這里,小小貢獻一下這個思路吧,也讓以后有人像我這樣被坑去寫這種無人機航線規(guī)劃的,能夠很快地實現,不用再去看那些奇奇怪怪的論文了。。。
最后最后最后,安利一下github.com/Char-Ten/cp… 這個庫(已經無恥到這個地步了。。。),可以接入百度、高德、leaflet,然后算航線!什么?你不需要。。。那你需要計算地圖上多邊形地塊的面積不?我也提供算面積的方法,百度地圖、高德地圖都沒有這種算面積的方法!好評給個star!謝謝大家?。▔蛄宋?!(╯‵□′)╯︵┻━┻)
如果你有更好的實現思路,或者新的使用場景,或者有使用問題,或者有bug,歡迎在下面評論。。?;蛘咧苯犹醝ssue: github.com/Char-Ten/cp…