目錄
前言
一、場景需求
1、Leaflet.js的不足
2、Turf.js
二、原始數(shù)據(jù)展示
1、點(diǎn)位數(shù)據(jù)展示?
2、定義樣式
3、定位數(shù)據(jù)初始化
三、Turfjs中bbox生成?
1、官網(wǎng)講解
2、軌跡bbox生成
四、Turfjs生成外包多邊形
1、官網(wǎng)例子
2、凸多邊形生成
總結(jié)
前言
????????在一些共享出行的應(yīng)用地圖中,以美團(tuán)共享騎行為例,在城市的重要地方會設(shè)置電子圍欄。防止由于共享單車無序停放而導(dǎo)致影響交通出行的障礙。比如在星城,湘江一橋及橘子洲景區(qū)就是設(shè)置了禁停區(qū)??梢钥匆幌孪旅娴牡貓D:
????????這里的禁停區(qū)就是一個非常明顯的電子圍欄的應(yīng)用。?于此同時在面向GIS的安防領(lǐng)域,這方面的應(yīng)用同樣層出不窮。通過在地圖上設(shè)置電子圍欄,在安裝了定位的自行車,就可以實現(xiàn)基于位置的管理。
????????還有一些需求是這樣的,我們可以獲取車輛或者行人或者工程機(jī)械的工作GPS軌跡,根據(jù)這些GPS軌跡,我們不僅要得到軌跡線信息,同時還要根據(jù)軌跡線,可以大致還原目標(biāo)的大致范圍。這里的范圍可能是一個矩形框(gis的bbox概念),也有可能是一個包含了軌跡信息的最大包圍框,是一個面數(shù)據(jù),而不是一個矩形數(shù)據(jù)。那么這種需求應(yīng)該怎么處理呢?能否在前端實現(xiàn)這樣的需求呢?
????????本文就將重點(diǎn)介紹這種實現(xiàn)的方式,主要講解Turf.js在求解范圍多邊形的兩種實現(xiàn)方式,通過代碼的方式讓讀者對實現(xiàn)過程更加的了解和掌握,可以快速的在學(xué)習(xí)和生產(chǎn)中進(jìn)行應(yīng)用。如果您當(dāng)前也碰到了在webgis中進(jìn)行展示,那么可以看看這篇博客,希望對您有所幫助。
一、場景需求
????????這里介紹一下原來在項目當(dāng)中遇到的一個場景,權(quán)當(dāng)拋磚引玉,場景不盡相同,如有雷同,不慎榮幸。場景需求是這樣的,需要在Webgis中展示某安裝了定位的工程機(jī)械的工作點(diǎn)位移動情況,已天為一個展示窗口,把每天的點(diǎn)位信息在地圖上展示出來。在此基礎(chǔ)之上,需要求解出該工程機(jī)械的最大活動范圍,同時用不同的顏色標(biāo)識出來。
當(dāng)時拿到這個需求之后呢,只是將這些點(diǎn)的信息整合起來,然后使用Leaflet的獲取Bouds方法來求解包圍框,通過getBounds()獲取的包圍框其實是一個最大矩形,是覆蓋了當(dāng)前空間數(shù)據(jù)四至的矩形。由于當(dāng)時沒有仔細(xì)考慮,使用getBounds()獲取的范圍會擴(kuò)了許多,因為矩形的四條邊都是直線,因此有很多區(qū)域是被錯誤的劃分到了這個范圍中。
????????因此,這里需要一種更加靈活的方式,能更加準(zhǔn)確的把這個區(qū)域的范圍標(biāo)記得更加的精準(zhǔn),保證這個面不僅包含目標(biāo)范圍,又沒有浪費(fèi)多余的空間。
1、Leaflet.js的不足
????????在之前的博客中,介紹了很多Leaflet這個二維地圖的開發(fā)組件,可以直接用于WegGIS系統(tǒng)的開發(fā),可以作為底圖展示和底圖可視化的基座。但是對于這些需要動態(tài)繪制的空間對象,能力稍顯不足。在查找了一些資料以后,并沒有發(fā)現(xiàn)比較便捷的實現(xiàn)方式。因此需要考慮使用其它的技術(shù)組件來滿足上述的需求。
2、Turf.js
????????turf.js是一款面向webgis的前端地理空間分析庫,其中包含了許多的實用的小工具,在實際項目開發(fā)當(dāng)中,可以實現(xiàn)無縫銜接和繼承接入,由于是面向客戶端的產(chǎn)品,對于數(shù)據(jù)的安全性就大大的提高,因為無需將數(shù)據(jù)發(fā)送到本地,前端可以將后端返回的數(shù)據(jù)進(jìn)行按需組合和可視化分析。關(guān)于turf的好處,這里不再贅述,感興趣的博主可以到其turf.js中文網(wǎng)和turf.js官網(wǎng),上面有更加詳細(xì)的介紹。
????????這里采用Turf.js的原因主要是其分析功能非常強(qiáng)大,同時其可以自動計算空間數(shù)據(jù)的bbox和最小外包多邊形(支持凸、凹兩種多邊形)。下面將采用實例的方式分別從bbox和外包多邊形的生成進(jìn)行說明。
二、原始數(shù)據(jù)展示
????????首先我們來看原始的數(shù)據(jù)在webgis中的展示效果是什么樣的。工程機(jī)械的軌跡數(shù)據(jù)如下,通過接口可以取到其gps位置信息。示例數(shù)據(jù)如下所示:
"lat": 28.0394672,
"lng": 112.9439207,
"cog": 0.0,
"p_distance": 49.0,
"img_url": "https://agri-static.holdingbyte.com/d-1000-awwwhqgwyxqe/3ecced35-e23f-4e91-ae34-4bef6294f4c0.jpg",
"t": 1693124829,
"agri_id": "d-1000-awwwhqgwyxqe-50-00",
"the_type": 301,
"__db_name__": "0",
"t_display": "2023-08-27 08:27"
序號 | 參數(shù) | 說明 |
1 | lng | 經(jīng)度,112.9439 |
2 | lat | 緯度,28.039 |
3 | t | 時間 |
4 | 其它參數(shù)忽略 | 其它參數(shù)不是很重要,暫時忽略 |
?????????在實際情況下,這些數(shù)據(jù)是連續(xù)的點(diǎn)位數(shù)據(jù),而不是孤立的點(diǎn)。上面為了將數(shù)據(jù)格式向朋友們描述清楚,所以進(jìn)行了示例數(shù)據(jù)的截取,完整的大致數(shù)據(jù)體如下所示:
1、點(diǎn)位數(shù)據(jù)展示?
????????為了將這些點(diǎn)位數(shù)據(jù)在空間上進(jìn)行展示,webgis可視化組件,我們依然選擇熟悉的leaflet。下面將簡單回顧一下,如何在leaflet中展示點(diǎn)位信息。
????????創(chuàng)建點(diǎn)位框架
????????新建index2.html頁面,在html網(wǎng)頁中輸入以下內(nèi)容:
<!DOCTYPE html>
<html>
<head>
<title>turf生成邊界凸多邊形實戰(zhàn)</title>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="./leaflet1.9.3/leaflet.css"/>
<script src="./leaflet1.9.3/leaflet.js"></script>
<style type="text/css">
body {
margin: 0;
padding: 0;
}
html, body, #map{
width: 100%;
height: 100%;
}
</style>
</head>
<body>
<div id="map"></div>
<script type="text/javascript" src="jquery.min.js"></script>
<!-- 使用unpkg -->
<script src="https://unpkg.com/@turf/turf/turf.min.js"></script>
<script>
</script>
</body>
</html>
????????定義地圖
????????在上面的html網(wǎng)頁中增加javascript腳本,進(jìn)行地圖的定義和初始化,關(guān)鍵代碼如下:
//聲明圖層組
var workPoints = L.layerGroup();
var wjLineGroup = L.layerGroup();
var baseLayer = L.tileLayer('./yxtile/{z}/{x}/{y}.png', {
minZoom: 14,
maxZoom: 21,
tms: false,
attribution: 'turf生成邊界凸多邊形實戰(zhàn)'
});
//聲明地圖并添加圖層
var map = L.map('map', {
center: [28.038387, 112.951566],
zoom: 16,
layers: [baseLayer,wjLineGroup]
});
//新建圖層控件的數(shù)據(jù)源-地圖
var baseLayers = {
'離線底圖': baseLayer
};
//新建圖層控件的數(shù)據(jù)源-城市
var overlays = {
'行駛軌跡': wjLineGroup
};
2、定義樣式
????????為了在程序中可以實現(xiàn)樣式的復(fù)用,這里將樣式的生成函數(shù)進(jìn)行了封裝,支持傳遞顏色進(jìn)行自定義設(shè)置。在需要使用的時候,傳入想要的顏色即可(溫馨提示:這里僅實現(xiàn)了顏色這個參數(shù)的自定義,其它參數(shù)的自定義可以模仿這種方法進(jìn)行)。
function getStyle(color){
return {
color: color,
weight: 3,
opacity: 1,
fillColor: color,
fillOpacity: 0.3,
fill: true,
stroke: true
}
}
3、定位數(shù)據(jù)初始化
????????定位數(shù)據(jù)采用后臺接口的方式提供,這里為了演示方便,將后臺接口的數(shù)據(jù)進(jìn)行了靜態(tài)臨時存儲。示例效果不變,不影響最終效果。關(guān)鍵代碼如下:
var lineArray = new Array();
var turfArray = new Array();
$(document).ready(function(){
$.ajax({
url: "data.json", //模擬從服務(wù)器獲取JSON數(shù)據(jù)的URL地址(請注意,URL必須與服務(wù)器上實際的文件名相同)
type: "GET", // 請求方法(POST或GET)
dataType: "json", // 響應(yīng)數(shù)據(jù)類型為JSON
success: function(data) {
// 成功獲取JSON數(shù)據(jù)后執(zhí)行的函數(shù)
var resData = data;
for(var i=0;i<resData.results.length;i++){
var item = resData.results[i];
lineArray.push([item.lat, item.lng]);
}
var polyline = L.polyline(lineArray, {color: 'blue'}).addTo(wjLineGroup);
map.fitBounds(polyline.getBounds());
},
error: function(xhr, status, error) {
// AJAX請求失敗時執(zhí)行的函數(shù)
console.log(xhr.responseText); // 輸出錯誤消息到控制臺
}
});
//新建圖層控件并添加到地圖
var layerControl = L.control.layers(baseLayers, overlays).addTo(map);
????????在瀏覽器中運(yùn)行以上的代碼,可以看到以下的效果,即完成了對軌跡數(shù)據(jù)的web展示。
三、Turfjs中bbox生成?
????????通過上面的例子可以看到,這里成功的把軌跡數(shù)據(jù)展示了出來。但我們怎么得到其邊界范圍呢?下面來深入講解。
1、官網(wǎng)講解
????????首先,我們來看一下,turfjs中文網(wǎng)對bbox生成的介紹。Takes a set of features, calculates the bbox of all input features, and returns a bounding box.獲取一組feature
,計算所有feature
的bbox
,并返回一個邊界框。
????????參數(shù)說明:
參數(shù) | 類型 | 描述 |
---|---|---|
geojson | GeoJSON | 任何 GeoJSON 對象 |
返回值如下:
????????BBox - bbox在minX, minY, maxX, maxY順序中的擴(kuò)展
????????來看一下官方的示例:
var line = turf.lineString([
[104.99467, 30.071677],
[107.13797, 36.550462],
[112.607082, 34.991467]
]);
var bbox = turf.bbox(line);
var bboxPolygon = turf.bboxPolygon(bbox);
2、軌跡bbox生成
????????首先,我們定義一個數(shù)組來接收數(shù)據(jù),var turfArray = new Array();在for循環(huán)中添加新的點(diǎn)。
for(var i=0;i<resData.results.length;i++){
var item = resData.results[i];
turfArray.push(turf.point([item.lng,item.lat]));
lineArray.push([item.lat, item.lng]);
}
var points = turf.featureCollection(turfArray);
var range = turf.bboxPolygon(turf.bbox(points));//turf生成最小外包框、bbox
L.geoJSON(range,{style:getStyle("red")}).addTo(map);
?????????可以看到,bbox生成的矩形范圍框,包含了許多的未到達(dá)的區(qū)域。下面我們再生成最小外包多邊形,來看看是否滿足效果。
四、Turfjs生成外包多邊形
1、官網(wǎng)例子
?????????Takes a Feature or a FeatureCollection and returns a convex hull Polygon.接受一個Feature
或FeatureCollection
,并返回凸多邊形。
????????參數(shù)說明:
參數(shù) | 類型 | 描述 |
---|---|---|
geojson | GeoJSON | Feature 或 FeatureCollection |
options | Object | 可選參數(shù):見下文 |
????????options選項
屬性 | 類型 | 默認(rèn)值 | 描述 |
---|---|---|---|
concavity | number | Infinity | 1 - thin shape. Infinity - 凸多邊形 |
var points = turf.featureCollection([
turf.point([10.195312, 43.755225]),
turf.point([10.404052, 43.8424511]),
turf.point([10.579833, 43.659924]),
turf.point([10.360107, 43.516688]),
turf.point([10.14038, 43.588348]),
turf.point([10.195312, 43.755225])
]);
var hull = turf.convex(points);
2、凸多邊形生成
var hull = turf.convex(points);//turf 生成凸多邊形最小外包框
L.geoJSON(hull,{style:getStyle("yellow")}).addTo(map);
?????????請注意這里的最小外包多邊形(黃色多邊形表示的區(qū)域),基本是滿足我們要求的,實現(xiàn)了范圍最小,更精準(zhǔn)的范圍覆蓋。文章來源:http://www.zghlxwxcb.cn/news/detail-839748.html
總結(jié)
????????以上就是本文的主要內(nèi)容。本文就將重點(diǎn)介紹這種實現(xiàn)的方式,主要講解Turf.js在求解范圍多邊形的兩種實現(xiàn)方式,通過代碼的方式讓讀者對實現(xiàn)過程更加的了解和掌握,可以快速的在學(xué)習(xí)和生產(chǎn)中進(jìn)行應(yīng)用,詳細(xì)對比了bbox和凸多邊形的生成過程,最后展示了兩個的實現(xiàn)效果。相信通過對比,能很明顯的看出區(qū)別。如果有興趣的,可以親自動手實踐一下。文章行文倉促,定有不當(dāng)之處,如有不當(dāng)之處,歡迎在評論區(qū)批評,非常感謝。文章來源地址http://www.zghlxwxcb.cn/news/detail-839748.html
到了這里,關(guān)于在Leaflet中使用Turf.js生成范圍多邊形的兩種實現(xiàn)方式的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!