Turf.jsを使ったマップグリッド配置とセルごとのステータス管理
公開日: 2026/03/04 / 更新日: 2026/03/04
植林の作業進捗を管理するためのアプリに使うロジックを考えた。
- 管理者が作業者ごとに担当範囲を地図上にグリッドで指定
- 作業者は植林を完了したセルを報告
管理者がポリゴンからセルを生成する計算は、Turf.jsを使ってクライアントサイドで実行する。
マップ上に正n角形(今回は3角形)を表示させる。
//中心点と半径と頂点の数を設定
const center = turf.point([139.7671, 35.6812]);
const radius = 5;
const vertexCount = 3;
const angleStep = 360 / vertexCount;
//頂点座標格納用にリストを用意
const co0rdinates = [];
//頂点の回数分だけ角度をずらしながらそれぞれの頂点の座標をリストに格納していく
for (let i = 0; i < vertexCount; i++) {
const bearing = i * angleStep;
const destPoint = turf.destination(center, radius, bearing, { units: "kilometers" });
coordinates.push(destPoint.geometry.coordinates); }
//GeoJSONのルールで、図形を完成させるためにリストの最後に1個めの頂点座標(coordinates[0])をもう一度追加する必要がある
coordinates.push(coordinates[0]);
// 5. Polygon(面)データとして完成!
const polygon = turf.polygon([coordinates]);管理者は各頂点をドラッグ&ドロップで植林依頼範囲をマスクすることができる。
(このロジックはLeafLetなどの描画側の処理も絡むためコードは割愛)
生成されたn角形からグリッドを生成する
//せるのサイズを10m四方で指定
const gridSizeKm = Math.sqrt(100) / 1000;
//外接する長方形を計算する
const bounds = turf.bbox(trianglePolygon) as [minLng, minLat, maxLng, maxLat];
//その長方形全体にgridSizeKmで指定したようなグリッドを追加
const generated = turf.squareGrid(bounds, gridSizeKm, { units: "kilometers" });
//作った全セルの中から、前に生成した図形にかかっているセルだけ残す
const maskedCells = generated.features.filter((cell) =>
turf.booleanIntersects(cell, polygon)
); 生成されたセルにgrid-keyを付与する。(セルの座標配列を文字列化して作成。)
このgrid-keyと作業進捗ステータスをAPIに送信してDBを更新する仕組み。
現状、DBが保持するのはポリゴンの頂点座標と進捗ありのセルの情報だけだが、進捗が進むにつれてデータが膨らみ読み込みに時間がかかる可能性がある。
最初に思いつく対策は、全ポリゴンのうち半数以上が進捗した点を境に、逆に進捗なしのセルをDBに保存するように切り替える作戦だ。確かに、この対策により平均データ量は1/2になるが、大きな削減とは言い難い。
次に思いついたのは、進捗済みセルのgrid-keyをうまいこと計算して個別のセルをいくつかの長方形として処理してから保存させるということだ。この方法ならばデータ量を大きく削減できるが今回の場合は困難だ。なぜなら、実際には各セルの植林ステータスに完了日時の情報も含まれるからだ。
実際の運用を見据えるとまだ検討する箇所が多いが、植林の進捗管理コミュニケーションツールとしてTurf.jsを使って計算する際のロジックについて簡単にまとめた。