鐵人賽Day 18- Turf.js:空間資料運算及分析

web
  1. 1. 前言
  2. 2. 幾何運算-pointsWithinPolygon
    1. 2.1. 範例目的:
    2. 2.2. 說明:
  3. 3. 空間分析-clustersKmeans
    1. 3.1. 範例目的:
    2. 3.2. 說明:
  4. 4. 幾何運算-找出Polygon的中心點與計算最鄰近的POI
    1. 4.1. 範例目的:
    2. 4.2. 說明:
  5. 5. 後記

前言

今天要介紹turf.js,
前兩天的網球地圖完成了基本的地圖功能及版面,並在地圖上展示、查詢了GIS資料,今天想進一步對資料做空間資料分析,使用的是turf.js

本文是參加鐵人賽的文章,同步發表於 “2018鐵人賽-30天打造我的WebGIS系列”

turf.js是Mapbox公司提出用來處理空間資料分析的開源函式庫,打開turf.js的說明文件,可以看到其功能非常的多:

要處理空間資料的手段有很多,常見的方法是使用QGIS等軟體做資料處理,也可以使用其他程式語言的函式庫輔助或手刻,而turf.js是一個十分方便輕巧的工具,最棒的是可以用在webGIS中,client端空間資料處理

至於什麼是空間資料分析呢?主要像是空間資料幾何運算、內插、資料聚合等都算,廢話不多說,我們就先來實作幾個案例。

幾何運算-pointsWithinPolygon

範例目的:

產生隨機的POI,利用新北市polygon,切出新北市內的POI

說明:

首先,先new一個layer

1
2
3
4
5
6
7
8
9
10
11
var ramdomLayer = L.geoJson(null, {
pointToLayer: function (feature, latlng) {
return L.marker(latlng, {
icon: L.icon({
iconUrl: "./dist/assets/img/icon-black.png",
iconSize: [36, 36],
iconAnchor: [0, 18]
}),
});
}
});

利用 turf.randomPoint 產生隨機點,設定隨機點的範圍在[121.41, 24.9, 121.8, 25.19] 方框中。

1
2
3
4
var ramdompts = turf.randomPoint(25, { bbox: [121.41, 24.9, 121.8, 25.19] });
//把成果放入圖層
ramdomLayer.addData(ramdompts);
ramdomLayer.addTo(map);

接著,放入新北市geojson

1
2
3
4
var ntp = L.geoJson(null);
$.getJSON("./dist/assets/data/ntp.geojson", function (data) {
ntp.addData(data);
});

在沒有屬性欄位的狀態下,我們用幾何取出新北市範圍內的POI
那就使用turf.pointsWithinPolygon~

1
2
3
4
//ramdompts為前面產生的隨機點
//data為新北市geojson
var ptsWithin = turf.pointsWithinPolygon(ramdompts, data);
//成果為geojson points

ps.成果跟後面一起展示喔

空間分析-clustersKmeans

範例目的:

對新北市範圍的POI做距離分群

說明:

這邊使用的群聚(cluster)演算法是Kmeans,Kmeans是非監督式學習的分類演算法,
這個演算法要設定分群的數量,流程概述如下:
1.根據預先設定的目標群數n,隨機給n個點作為n群資料的群聚中心
2.資料中距離(空間距離)哪個群聚中心最近,就屬哪類
3.各群以平均值重新計算各群中心點
4.反覆1~3,直到中心點移動量低於設定值或是達到迭代次數而停止

利用turfclustersKmeans為資料作分群,設定分五類:

1
2
var clustered_kmeans = turf.clustersKmeans(ptsWithin, { numberOfClusters: 5 });
//結果是geojson points

幾何運算-找出Polygon的中心點與計算最鄰近的POI

範例目的:

找出新北市幾何中心及距離該點最近的poi

說明:

turf.js有很多幾何的計算,以下是計算Polygon中心點,及找群POI中距離這個中心點最近的一個,
直接看程式碼:

1
2
3
4
//中心
//data是新北市polygon geojson
var center = turf.center(data);
L.geoJson(center).addTo(map).bindPopup('這是新北幾何中心').openPopup();

最短距離:

1
2
var nearest = turf.nearestPoint(center, ptsWithin);
L.geoJson(center).addTo(map).bindPopup('這是距離新北中心最近的點').openPopup();

成果:
隨機給定POI(黑色),使用空間選取前
(ps.,另有不同icon顯示中心點及最近點。)

只顯示新北市內的poi,並依空間分佈分群(不同顏色為不同群)

後記

turf.js除了今天介紹的功能,還有很多是在webGIS常用的,例如buffer,intersect等等,很多GIS軟體工具提供的功能,turf.js都可以引用參考,非常方便,另外,turf.js相關介紹可以參考這個youtube喔^^。

明天會繼續介紹turf.js比較進階的空間分析功能,除了今天的基本運算外,希望能多觸及進階的分析方法!
今天的程式碼一樣放在github(day18的commit)。