turf.js で Bスプライン曲線

飛行機の航跡データをturf.jsでBスプライン曲線に変換して地図で描画してみました。

調べたところ、Bスプライン曲線は渡した実際の座標からはずれた座標にも線を引くので、業務用としては不向きかと思いますが、今回実装してみたアプリについては業務用途では使われないので、気にしなくてよいかと思います。

APIドキュメント

[ コード例 ]

ラッパークラスを使ってます。

GoogleMap 呼び出し側


const geojsonfnm = "geojson/SimpleLine.json";

$.getJSON(geojsonfnm, function (data) {

      const geomes = data["geometry"]["coordinates"];
      
      let applyData = data;

      // -- スプライン指定している場合、turf.jsでスプライン変換 -- //
      if (isSpline) {
        //console.log("--- Splined");
        // -C 自作ラッパークラス //
        const myturf = new MyTurf({resolution: 20000, sharpness: 2});
        applyData = myturf.getSplinedGeometries(geomes);
      }
      
      // GeoJSON を描画 //
      let lines = gmapS.data.addGeoJson(applyData);
});

ラッパークラス

/**
 * turf.js用ラッパークラス
 * @type type
 */
class MyTurf {

  /**
   * コンストラクタ
   * @param {type} optionmap オプション値
   * @returns {MyTurf}
   */
  constructor(optionmap) {
    this.optionmap = optionmap;
  }

  /**
   * Bスプライン曲線
   * @param {type} line Feature  [[lat,lon], [lat,lon], [lat,lon]]
   * @returns {undefined} Feature  - curved line
   */
  getSplinedGeometries(geomes) {
    let line = turf.lineString(geomes);
    return turf.bezierSpline(line, this.optionmap);
  }
  
  /**
   * 中心点取得
   * @param {type} geomes
   * @returns {unresolved}
   */
  getCenter (geomes) {
    let features = turf.points(geomes);
    return turf.center(features);
  }

  /**
   * 2点位置指定方向取得
   * @param {type} p1
   * @param {type} p2
   * @returns {unresolved}
   */
  getBeaing(p1, p2) {
    return turf.bearing(p1, p2);
  }
  
   /**
   * 方向角配列
   * @returns {Array|drawMapLAFlightSP.splinedBearingArray.barray}
   */
  getSplinedBearingArray(coordinates) {


    let barray = [];
    let prevll;
    let tmpbearing;

    const myturf = new MyTurf();
    const pushToArray = (ll, idx) => {

      if (idx > 0) {

        prevll = coordinates[idx - 1];
        // turf.jsで方向角を求める //
        tmpbearing = myturf.getBeaing(prevll, ll);
        // 時計式角度を航空式角度に変換 //
        tmpbearing = tmpbearing < 0 ? Number(tmpbearing) + Number(360) : tmpbearing; // アイコン用整数に四捨五入 // tmpbearing = Math.round(tmpbearing); barray.push(tmpbearing); } }; coordinates.forEach((ll, idx) => pushToArray(ll, idx));

    //console.log("--- barray");
    //console.log(barray);
    return barray;

  }

}

[ 利用例 ]

実はあまり変わり映えないばかりか、小半径な旋回が見受けられます。
アクチャル座標データが少ない曲線表現では有効かも知れませんが、多い場合、逆効果です。

スプライン未適用

スプライン適用