River Runner - その構築方法

見出し

これはレイアウト確認用のダミーテキストです。

オープンデータ、3D地形、およびカメラコントロールが組み合わさって、没入型の水文体験を実現します

オープンデータ、3D地形、およびカメラコントロールが組み合わさって、没入型の水文体験を実現します

今年の夏にSam Learnerによって作成されたRiver Runnerマップに感銘を受けました。そこで、Samにこの没入型3D体験をどのように構築したかについて詳しく教えてくれるように依頼しました。

数インチ離れて落ちる2つの雨滴が、数千マイル離れた場所にたどり着く可能性があることをご存知ですか?この仕組みに魅了された私は、水文学と流域データに飛び込み、2つの雨滴の発散する経路を視覚化しました。

雨滴のルーティング

USGSの水道データチームによる素晴らしい作業のおかげで、米国内のあらゆる小川、小川、川の流路パターンを追跡することが可能です。これは、プロジェクトの新しいビジョンにインスピレーションを与えました。裏庭からの水がどのように海に到達するかを人々が追跡できたらどうでしょうか?そして、あなたの水が流れるすべての流域とコミュニティを視覚化することで、私たちの行動が下流の人々に与える影響を明確にできるでしょうか?

USGSのNLDI APIからのデータは、プロジェクトの中核に必要な流路ルーティングデータを提供し、NHDPlusデータからのValue-Added Attributesは、河川パスを構成する流路の公式な親フィーチャー名を提供しました。ただし、そのデータにアクセスしやすく、ナビゲートしやすいインターフェースを設計することは、もう1つの課題であり、そこでMapboxが登場しました。 

3Dの旅

地図上にプロットされた流路を見るだけでなく、雨滴がその過程で触れるすべての場所や地形をより良く理解できるように、ユーザーがその下流への旅を観察できるようにしたいと考えました。以前のプロジェクトでMapboxの陰影処理機能を使用したことがあったので、地形の感覚をすぐに得られることはわかっていました。このプロジェクトを開始するまで知らなかったのは、Mapboxの3D機能とFreeCamera APIがどれほど強力で使いやすくなっているかということです。

わずか20行のコードで、地平線に穏やかな空のレイヤーを追加して、3Dタイルレイヤーを地図に追加しました。

export const addTopoLayer = ({ map }) => {
    map.addSource("mapbox-dem", {
        type: "raster-dem",
        url: "mapbox://mapbox.mapbox-terrain-dem-v1",
        tileSize: 512,
        maxzoom: 14,
    });

    // add the DEM source as a terrain layer with exaggerated height
    map.setTerrain({ source: "mapbox-dem", exaggeration: 1.7 });

    map.addLayer({
        id: "sky",
        type: "sky",
        paint: {
            "sky-type": "atmosphere",
            "sky-atmosphere-sun": [0.0, 0.0],
            "sky-atmosphere-sun-intensity": 15,
        },
    });
};

これで、視覚化の基盤はすでに整いました。

Mapbox のFreeCamera APIを使用すると、カメラの位置を細かく制御できます。これは、計算されたUSGSデータから得られた流路をトレースするために必要でした。私がしなければならなかったのは、USGSデータを返し、それを座標の配列に処理し、そのパスに沿ってポイントツーポイントでカメラを目的地まで移動させることだけでした。簡単ですよね?そうではありません。プロジェクトの初期のイテレーションは、信じられないほどでこぼこの乗り物になりました(乗り物酔いしやすい場合は、そのリンクをクリックしない方がよいかもしれません)。このツールを使用可能にするには、克服すべき重要な課題がいくつかありました。

補間と平滑化

FreeCamera APIを使用すると、3D空間での「カメラ」の位置決めと方向付けが非常に簡単になります。フローパスの座標配列を取得したら、最初にカメラを最初の座標に配置し、下流の座標を指し示し、turfjs along methodを使用してそれらを前進させることができると考えました。残念ながら、川の曲がりくねった部分は、風が強く方向感覚を失わせるような旅になりました。

この問題に対処するため、カメラが追従する人工的な滑らかなパスを作成しました。座標のグループの位置を平均化することで、小さな曲がりがパスに与える影響を軽減しました。カメラにこのパスを追従させ、元の滑らかでないパスを青い線としてプロットし、視聴者が追跡できるようにしました。

const pathSmoother = (coordinateSet, smoothingCoefficient = 1) => {
    const setLength = coordinateSet.length;
    const smoothedCoordinatePath = coordinateSet.map((coordinate, index) => {
        const coordinateGroup = coordinateSet.slice(
            Math.max(0, index - smoothingCoefficient),
            index + 1 + smoothingCoefficient
        );

        const lng =
            coordinateGroup
                .map((d) => d[0])
                .reduce((a, b) => a + b, 0) / coordinateGroup.length;

        const lat =
            coordinateGroup
                .map((d) => d[1])
                .reduce((a, b) => a + b, 0) / coordinateGroup.length;

        return [lng, lat];
    });

    return smoothedCoordinatePath;
};

速度、ピッチ、ズーム

川の経路が流れる速度のバランスを取るのが難しいことはわかっていました。誰も、ツールがミシシッピ川下流を20分かけて移動するのを見たいとは思わないでしょう。しかし、速すぎると吐き気を催します。Mapboxのカメラが流路座標を移動する速度を制御するのは簡単でしたが、カメラの仰角とピッチによって影響を受ける真の速度と知覚的な速度の違いがすぐに明らかになりました。

作用する力を理解するために、時速500マイルで移動する飛行機に乗っている自分を想像してください。数千フィート上空にいて、地平線を見つめている場合、自分がどれだけ速く移動しているかにほとんど気づかないかもしれません。地上すれすれにいて、真下を見つめている場合は、目が回るほど速く移動しているように感じるでしょう。地面からの距離と見下ろす角度の両方が、移動速度の認識に影響を与えます。これは、速度、カメラの高さ、カメラのピッチのバランスを見つける際に私が対処しなければならなかったことです。

快適な視聴体験(約70度の角度)を実現するカメラピッチと、かなり長い走行(秒速約4km)を可能にする基本速度が見つかるまで実験することにしました。次に、知覚速度が適切に感じられるまで、カメラの仰角を調整しました。高校の三角法の教科書を引っ張り出した後、仰角とピッチを使用して、ターゲットポイントからカメラを正しい位置に戻すことができました。

プロジェクトにおけるフィードバックと課題の一貫した源泉は、河川での走行時にユーザーがカメラをどれだけ制御できるかという点でした。再生コントロールを提供できたことは良かったのですが、速度、高度、ピッチの相互作用によって、ユーザーが不快な体験をする機会が非常に多いため、これらの要素に対するユーザーの制御にいくつかの制約を設けることは理にかなっていると感じました。最終的には譲歩して、ある種のズームコントロールを提供しましたが、知覚速度を妥当な範囲内に保つために、カメラの速度に固定されています。また、パススムーザーの係数にも関連付けられており、乗り物酔いを避けるために、高速時にはよりスムーズで近似的なパスが生成されます。

標高

多くのツールと同様に、カメラの位置をより細かく制御できるようになったことと引き換えに、内部の「魔法」の一部が失われます。カメラの仰角を手動で設定できることは、私が構築したかった機能にとって非常に重要でしたが、山から海面に向かって流れる経路に意図しない影響がありました。カメラは同じ仰角にとどまりましたが、地面が遠ざかってしまったのです。

カメラと地面の間の距離を一定に保つために、queryTerrainElevationメソッドを使用してルートに沿って標高をサンプリングしました。その標高配列をアニメーション関数に渡し、サンプリングされた標高を補間し、カメラの標高を地上からの一定の距離に維持します。

流域を活性化する

プロジェクトを開始して以来、多くの方から、分水界の概念と河川や小川の相互接続性が、このように流れの経路を視覚化することで本当に理解できたという声を聞いています。分水界を理解することで、水路の保護に対する緊急性が高まり、水路に投棄されたり、取り出されたりするものに対する意識が高まることを願っています。私たちのほとんどは、他の多くの人よりも上流に住んでいます。

このプロジェクトは、Mapbox、USGS Water チーム、Geoconnex および NLDI API の背後にあるチームに多大な恩恵を受けています。特に、USGS の Dave Blodgett 氏の多大なご協力に感謝いたします。これらの人々は現在、私がグローバル River Runner を作成するために使用したデータ製品を拡張するために多くの作業を行っています!

Sam、あなたのイノベーションを共有してくれてありがとう!River Runnerやその他のプロジェクトについてSamと連絡を取りたい場合は、ご連絡ください

科学コミュニケーション、環境保護、またはその他の社会貢献のためのツールを構築している場合は、Community チームにご連絡ください。また、ワンクリックで Mapbox 3D 地形を今すぐ始めましょう。

これはレイアウト確認用のダミーテキストです。

これはレイアウト確認用のダミーテキストです。

関連記事