🗾

ポリラインを一定距離ごとにぶった切る turf.lineChunk

2020/10/06に公開

緯度経度群(LineString)を、一定距離ごとに分割したいというニッチな要求にも応えてくれる turfjs すごい。

例えば、東京-名古屋-大阪 を結ぶ LineString があるとします。

const line = turf.lineString([[139.76, 35.68], [136.90, 35.17], [135.51, 34.68]]);

これを、turf.lineChunk を使って「100km 毎に分割」します。

const chunk = turf.lineChunk(line, 100, { units: 'kilometers' }) as FeatureCollection;

100km ごとに分割された図形群は FeatureCollection として返却されます。
Feature 型は少々冗長なので、図形の座標群だけ抜き出すと次のように。

[
  [ 
    [ 139.76, 35.68 ],
    [ 138.67760192668752, 35.49567029653387 ] 
  ],
  [
    [ 138.67760192668752, 35.49567029653387], 
    [ 137.60028816204638, 35.30171921680228] 
  ],
  [ 
    [ 137.60028816204638, 35.30171921680228 ], 
    [ 136.9, 35.17 ], 
    [ 136.54843014074316, 35.04811131423963 ]
  ],
  [ 
    [ 136.54843014074316, 35.04811131423963 ], 
    [ 135.54211990949918, 34.69156812570359 ] 
  ],
  [ 
    [ 135.54211990949918, 34.69156812570359 ], 
    [ 135.51, 34.68 ] 
  ]
]

東京-名古屋-大阪 のポリラインを 100km ごとに分割したら、5つの LineString になった、ということです。
そして、3つ目の要素は経由地である名古屋の緯度経度を含んでいるため、ここだけ要素数が3になっています。純粋に 100km 間隔のポリラインを得たいならば、先頭の点だけ(終点は末端だけ)を抽出すればよいことになります。

次の例は、東京-名古屋-大阪 のポリラインを 300 等分して、それぞれの標高を取得し、断面図を作る処理です(elevationService は、地理院地図の標高タイルを使って標高APIを作る を見てね)。

const line = turf.lineString([[139.76, 35.68], [136.90, 35.17], [135.51, 34.68]]);
const len = turf.length(line, { units: 'kilometers' });

const chunk = turf.lineChunk(line, len / 300, { units: 'kilometers' }) as FeatureCollection;

const points = chunk.features.map((f, index) => {
  const ln = f.geometry as LineString;
  if (index < chunk.features.length - 1) {
    return ln.coordinates[0];
  } else {
    return ln.coordinates.slice(-1)[0];
  }
});

const elevations = await this.elevationService.getElevations(
  points.map(p => ({ lat: p[1], lng: p[0] }))
);

console.log(`elevations`, JSON.stringify(elevations));

elevations を EXCEL などを使ってプロットすると、次のようになります。

これは、地理院地図の 断面図作成 を模したものです。
地理院地図を使って、東京-名古屋-大阪の断面図を作ると、次のようになります。

ほぼ同じ見た目を再現できたんじゃあないかと思います。

ちなみに、「ポリラインの開始点から距離 x 進んだ座標(緯度経度)」を得るには、turf.along が便利です。

Discussion