2 個多邊形的關係無非:html
先向你們闡述個人應用場景:需求方欲經過在地圖上繪製蜂窩以分配員工所負責區域。純手工繪製易將道路、樓、園林、水系等切割引起劃分糾紛,故咱們接入一叫 block 的服務,根據繪製點返回周圍的 N 個 block 即真正的地理分區(不切割道路、樓、園林、水系等),咱們將這 N 個 block 合併造成一整個蜂窩。但繪製點跨度較大時將遺漏其間細小 block 產生縫隙,更糟糕的狀況是產生零散塊兒使合併結果不爲一總體。此刻需獲知每一零散塊兒與蜂窩的關係,丟棄相離及被徹底包含的,併入相交的。git
業務場景再也不贅述,直接上代碼:github
import MD5 from 'md5' import TURF from 'turf' /** * 獲取 N 個多邊形面積 * @param callback * @param opts * polygons(List{ polygonOpts })(必傳): 多邊形對象 List * order(String)(默認不排序): ascend(升序) 或 descend(降序) * @param polygonOpts * path(Path)(必傳): 路徑 [[lng(Number), lat(Number)], ...] */ export function getPolygonsArea (callback, opts = {}) { var polygons = opts.polygons var response = { polygons: [] } for (let i = 0; i < polygons.length; i++) { // 獲取多邊形面積 let area = TURF.area(TURF.polygon([polygons[i].path])) response.polygons.push({ ...polygons[i], area: area }) } switch (opts.order) { // 升序排列 case 'ascend': response.polygons.sort((a, b) => a.area - b.area) break // 降序排列 case 'descend': response.polygons.sort((a, b) => b.area - a.area) break default: break } callback && callback(response) } /** * 獲取 2 個多邊形相交關係 * @param callback * @param opts * polygonA(Polygon{ polygonOpts })(必傳): 多邊形對象 A * polygonB(Polygon{ polygonOpts })(必傳): 多邊形對象 B * @param polygonOpts * path(Path)(必傳): 路徑 [[lng(Number), lat(Number)], ...] */ export function getPolygonsRelation (callback, opts = {}) { var polygonA = TURF.polygon([opts.polygonA.path]) var polygonB = TURF.polygon([opts.polygonB.path]) // 獲取 polygonA 與 polygonB 交集 var intersection = TURF.intersect(polygonA, polygonB) if (intersection) { let geometry = intersection.geometry switch (geometry.type) { case 'Point': callback && callback({ relation: 'pointIntersectant', desc: '相交的(交集爲單點)', intersection: geometry, polygonA: opts.polygonA, polygonB: opts.polygonB }) return case 'MultiPoint': callback && callback({ relation: 'multiPointIntersectant', desc: '相交的(交集爲多點)', intersection: geometry, polygonA: opts.polygonA, polygonB: opts.polygonB }) return case 'LineString': callback && callback({ relation: 'tangent', desc: '相切的(交集爲單線)', intersection: geometry, polygonA: opts.polygonA, polygonB: opts.polygonB }) return case 'MultiLineString': callback && callback({ relation: 'multiTangent', desc: '相切的(交集爲多線)', intersection: geometry, polygonA: opts.polygonA, polygonB: opts.polygonB }) return // 交集爲多個多邊形 case 'MultiPolygon': callback && callback({ relation: 'multiIntersectant', desc: '相交的(多處交集)', intersection: geometry, polygonA: opts.polygonA, polygonB: opts.polygonB }) return // 交集爲單個多邊形 case 'Polygon': getPolygonsArea((res) => { // 面積較小多邊形 let minPolygon = res.polygons[0] // 面積較大多邊形 let maxPolygon = res.polygons[1] // 判斷 2 個多邊形 path 是否如出一轍 if (MD5(minPolygon.path) === MD5(maxPolygon.path)) { callback && callback({ relation: 'equal', desc: '相等的', intersection: intersection, polygonA: opts.polygonA, polygonB: opts.polygonB }) return } // 判斷較小多邊形 path 與交集多邊形 path 是否如出一轍 if (MD5(minPolygon.path) === MD5(geometry.coordinates[0])) { callback && callback({ relation: 'included', desc: '包含的', intersection: intersection, polygonA: opts.polygonA, polygonB: opts.polygonB, minPolygon: minPolygon, maxPolygon: maxPolygon }) return } callback && callback({ relation: 'intersectant', desc: '相交(一處交集)', intersection: intersection, polygonA: opts.polygonA, polygonB: opts.polygonB }) }, { polygons: [opts.polygonA, opts.polygonB], order: 'ascend' }) return default: callback && callback({ relation: 'fixedIntersectant', desc: '相交的(多種類型交集)', intersection: geometry, polygonA: opts.polygonA, polygonB: opts.polygonB }) return } } else { callback && callback({ relation: 'separated', desc: '相離的', intersection: intersection, polygonA: opts.polygonA, polygonB: opts.polygonB }) } }
機智的你發現我利用了第三方庫 turf,未自行研究大量幾何算法。此分享內容很少,代碼量較小,望勿嫌棄。俗話說「君子善假於物也」,俗話又說「天下代碼一大抄,看你會抄不會抄」...算法
做者:呆戀小喵spa
個人後花園:https://sunmengyuan.github.io...code
個人 github:https://github.com/sunmengyuanhtm