王強+雷中英
摘 要: 根據(jù)開發(fā)人員對多邊形進行空間操作的需求,研究在開源Leaflet的Javascript庫的基礎(chǔ)上實現(xiàn)WEBGIS前端的多邊形切割功能。給WEBGIS管理平臺提供實時在線動態(tài)切割和動態(tài)顯示,避免后臺切割以及軟件預(yù)處理的不必要麻煩。
關(guān)鍵詞: Leaflet; WEBGIS; 多邊形; 切割
中圖分類號:TP311 文獻標志碼:A 文章編號:1006-8228(2017)02-45-04
0 引言
在一般場景中,對多邊形切割的實現(xiàn)基本由軟件操作完成或者由后臺插件提供切割接口完成,并不是在前端部分實現(xiàn)。因為前端計算量巨大會產(chǎn)生不盡人意的效率問題,也會出現(xiàn)瀏覽器崩潰、卡頓的現(xiàn)象。而近年來前端技術(shù)的發(fā)展突飛猛進,其計算能力大大提升,由此帶來其實現(xiàn)的可能性,而且也已經(jīng)出現(xiàn)可用插件。本文探討基leaflet為WEBGIS框架,實現(xiàn)多邊形切割插件。
1 切割思路及其算法
1.1 構(gòu)造初始切割對象
參照leaflet官方自帶的插件,采用面向?qū)ο蟮乃季S來構(gòu)建切割類CutPolygon。CutPolygon繼承于leaflet的核心類Hander,代碼如下:
var CutPolygon=L.Handler.extend({
includes: L.Mixin.Events,
options: {},
initialize: function (map, options) {
L.Handler.prototype.initialize.call(this, map);
L.setOptions(this, options);
this._map=map;
this._layerGroup=new L.FeatureGroup();
this._map.addLayer(this._layerGroup);
},
在CutPolygon中首先includes使切割對象賦予事件委托的方法。然后再CutPolygon的初始化方法中完成以下幾步:
⑴ 首先執(zhí)行hander的初始化方法;
⑵ 傳入map地圖對象以及其他屬性;
⑶ Cutpolygon的_map屬性對象指向map參數(shù);
⑷ 聲明一個圖層_layerGroup并添加進map去;
1.2 鼠標捕捉
該插件初始化使用時提供鼠標捕捉多邊形上的點。多邊形的本質(zhì)為由大于等于一條線段所組成的線段首位銜接的不閉合的折線。(注:首尾銜接的不閉合為多邊形,直線為折線的特殊情況)。所以求解點到多邊形的距離的問題就轉(zhuǎn)化為求解點到每個線段的距離。求解思路如下。
如圖1、圖2所示。標注:線段l;偏離距離H;匹配的結(jié)果坐標點P0;鼠標點p及p到l的距離h;線段兩個端點A1、A2;線段所在直線l1;過線段兩端點做線段的法線p1、p2;P1、p2與線段所成內(nèi)夾角分別為a,b;P到A1和A2的距離分別為d1,d2;
以上是針對單條線段進行的判斷,在一個多邊形中有n條線段,則對n條線段按照以上計算方式得到共n個捕捉匹配點,對集合Zn求出最小值Hmin作為當前位置p相對多邊形的捕捉點。
1.3 切割算法
多邊形按簡易程度又可分為凹多邊形、凸多邊形以及帶島狀內(nèi)環(huán)的多邊形。由于凸多邊形可以看作是凹多邊形的特例,所以本文以凹多邊形為代表的任意多邊形來實現(xiàn)切割算法,針對帶島狀內(nèi)環(huán)的多邊形我們進行搭橋無島化處理生成新的凹多邊形來進行切割[1-2](無島化將在另外一篇文章講解)。
1.3.1 存儲構(gòu)造函數(shù)
為了數(shù)據(jù)便于管理,代碼開始先定義一個構(gòu)造函數(shù)用于存儲交點以及多邊形頂點。該構(gòu)造函數(shù)參數(shù)為:距離,維度,經(jīng)度,在多變行所在的索引,多邊形。具體的代碼參考如下(注:當不要距離參數(shù)時可默認設(shè)置為0):
1.3.2 切割步驟
先構(gòu)建實例多邊形P,由點P0,P1,…,P10組成。顯而易見,多邊形P是一個標準的凹多邊形,切割算法將以多邊形P為例進行說明,如圖3所示。
通過鼠標雙擊拾取多邊形上一點a0,并將該多邊形存儲為FOCUSON焦點多邊形數(shù)據(jù)集中(注:若鼠標處于某一個多邊形內(nèi)該多邊形自動存儲為FOCUSON焦點多邊形數(shù)據(jù)集中,若在多邊形外則把_layerGroup圖層中所有的多邊形都加入FOCUSON焦點多邊形數(shù)據(jù)集中,鼠標對所有多邊形計算距離,取最近點為拾取點,切割線第一點確定后自動將點所在多邊形確定為FOCUSON數(shù)據(jù)集中惟一的多邊形)。
鼠標自動在FOCUSON的多邊形上拾取第二點a5(注:需判斷a5在多邊形P中的索引是否等于a0的索引,防止處于同邊的情況),拾取的點與第一點構(gòu)建一條線段Polyline,隨著鼠標移動,Polyline也動態(tài)地改變。具體按照以下步驟。
⑴ 首先判斷交點數(shù)是否大于2,若等于2則計算以兩個交點作為端點的線段的中點,計算此中點是否處于多邊形P內(nèi),處于執(zhí)行⑵,反之結(jié)束,多邊形P沒有切割,切割無效[3]。
⑵ 將a與多邊形P相交的交點按照交點所在線段的索引排序,按照上圖排序為[4]。
⑶ 按照⑵的索引排序,以切割線端點為節(jié)點將⑵結(jié)果分成兩部分(a0→a5;a5→a0)。
⑷ 設(shè)a0與a5交點所在多邊形P邊的索引分別為Index0和Index5,針對線段a與多邊形P切割的結(jié)果可分為以下兩種情況[5]:
情況一:若⑵的結(jié)果a0→a5是相臨兩點沒有中間交點,那么在多邊形P的坐標點P0,P1,…,P10中,尋找處于(Index0+1,Index5)范圍內(nèi)所有的點,如圖3所示可得
⑴
ZN中的坐標點滿足要求,按照索引順序判斷a5→a0之間兩兩相臨交點的中心點是否處于多邊形P內(nèi),若結(jié)果為正確的話則不取處于相臨兩交點之間的多邊形頂點,反之取多邊形的頂點,并按照索引順序保存。如圖3所示,a5→a0方向判斷的結(jié)果為:
⑵
最后將⑴的Wn拼接于⑵的Zn的尾部形成:
⑶
式⑶中的Points首尾閉合形成的多邊形就是切割后的結(jié)果之一。
情況二:若⑵的結(jié)果a5→a0方向的有多個交點。按照索引順序判斷a5→a0之間兩兩相臨交點的中心點是否處于多邊形P內(nèi),若結(jié)果為否的話則按照索引順序保存相臨兩交點及處于兩交點之間的多邊形的頂點,保存坐標將構(gòu)成切割多邊形的結(jié)果之一,反之不做處理。循環(huán)遍歷每相臨兩點處理得到結(jié)果保存如上圖所示處理結(jié)果為:
⑷
情況一和情況二都需要注意一種特殊情況,當多邊形的起點P0處于某一個切割多邊形內(nèi)時即P0處于處于兩個交點之間區(qū)域時,點的索引排序則需要單獨處理。
1.3.3 多邊形切割流程圖
CutPolygon對象只提供對外調(diào)用接口,使用者并不需要了解內(nèi)部如何處理。在此簡單梳理使用時的內(nèi)部流程圖。在聲明CutPolygon對象后,先進行添加需要切割的多邊形,然后初始化屬性參數(shù),CutPolygon對象內(nèi)部初始化事件,然后通過鼠標移動事件mousemove和鼠標雙擊事件dblclick來完成切割。CutPolygon內(nèi)部還提供自身調(diào)用的私有函數(shù),如:判斷點是否在多邊形內(nèi),WGS84坐標轉(zhuǎn)Web墨卡托坐標,根據(jù)索引排序,刪除圖層所有要素,切割完刪除被切割的多邊形,CutPolygon數(shù)據(jù)更新,事件的注冊和注銷以及更新等[6]。以下為簡化的流程圖。
2 實現(xiàn)效果
2.1 調(diào)用參考
在了解原理之后該如何調(diào)用寫好的基于leaflet的開發(fā)的多邊形切割的插件呢?在前端代碼中,調(diào)用leaflet并聲明map之后。新建CutPolygon對象,在構(gòu)件需要切割的多邊形的時候?qū)隒utPolygon對象中,然后初始化一下事件,即可調(diào)用。本文參照官方插件模式,也通過enbale開啟切割,通過disable/ESC來關(guān)閉切割功能。以下為部分調(diào)用代碼:
3 結(jié)論
經(jīng)過以上方法設(shè)計出來的功能,在某公司研發(fā)的國土調(diào)查宗地管理系統(tǒng)得到應(yīng)用,基本滿足需求。在未來的發(fā)展中,這些基本功能需求是遠遠不夠的,而且緩沖區(qū),空間要素的拓撲關(guān)系判斷等等也需不斷適應(yīng)新需求。針對本文而言,該方法切割還缺少針對大量空間要素的一次性裁剪,這樣可以實現(xiàn)批量裁剪,節(jié)省大量時間以及多要素裁剪的同步性。這些問題在后期需要繼續(xù)完善。
參考文獻(References):
[1] 吳信才.地理信息系統(tǒng)原理與方法[M].電子工業(yè)出版社,
2002.
[2] 周培德.計算幾何[M].清華大學出版社,2000.
[3] 陳瑞卿,周健,虞烈.一種判斷點與多邊形關(guān)系的快速算法[J].
西安交通大學學報,2007.41(1):59-63
[4] 劉強,陳玉健.論兩條直線段的求交[J].計算機學報,1997.20
(12):1119-1123
[5] 田光,謝忠,吳亮.基于簡單要素模型的多邊形分割算法[J].地
理與地理信息科學,2010.26(1):24-28
[6] 孫小淋.基于JavaScript的消息管理機制探討[J].軟件,
2013.7.