UP | HOME

Mapray Nodeでの開発方法

1. 構成について

https://mapray.com の Document ページに説明があります。

1.1. Mapray Cloud と Mapray JS

maprayjs-and-mapraycloud.png

1.2. リソースの種類とライセンス

Maprayで利用することができるサーバリソースには、静的リソース、データセットの2種類のデータがあります。

1.2.1. 静的リソース

地図画像
地図画像タイルです。 任意の外部地図タイルサービスを利用することができます。
DEMデータ
地図形状タイルです。 Mapray Cloudで配信されるMapray独自形式のタイルを利用します。 タイルにアクセスするにはアクセストークンが必要です。

1.2.2. データセット

ユーザが任意のデータをアップロードし、簡単に地図上に表示することができます。

  • 2Dデータ: GeoJson
  • 3Dデータ: glTF, obj
  • 点群データ: las
  • (建物データ: CityGML)

1.3. コアライブラリ・UIライブラリ

2つのレベルで開発を行うことができます。

コアライブラリ(@mapray/mapray-js
レンダリングに必要な最小構成のライブラリとなっています。 コアライブラリを直接利用する場合は、マウス操作やカメラ操作など基本機能から実装する必要があります。 ソースコードAPI
UIライブラリ(@mapray/ui
コアライブラリに加えて、一般的な地図アプリケーションのベースとなる機能が実装されたライブラリとなっています。 マウス操作やキーボード操作などが実装されているため、簡単にアプリケーションを実装することができます。 ソースコード、API(準備中です)。

この文章では、UIライブラリを使った開発について説明します。

2. NodeでのMapray開発

2.1. 事前準備

2.1.1. アカウントとトークン

Mapray Cloud アカウント
アカウント作成方法については解説ページをご参照ください。 ※ユーザIDを確認します。2Dデータや3Dデータなどのユーザデータにアクセスする際に利用します。
Mapray Cloud アクセストークン
トークン作成方法については解説ページをご参照ください。 Mapray Cloudへアップロードしない場合でもアクセストークンが必要になります。

2.1.2. ツール

  • node
  • npm
  • yarn( yarn を使った例について説明しますが、 npm でも動作します)

2.2. 最小構成

ここでは、最小構成(地図を表示するだけ)の例を示します。

2.2.1. プロジェクト作成

本説明では、最終的に下記のようなフォルダ構成となります。

フォルダ 説明
dist ビルド後のjsが出力されるディレクトリ
package.json Node の設定ファイル
src ソースファイル
webpack.config.js ビルド設定ファイル
node_modules Node の依存ライブラリが保存されるディレクトリ
yarn.lock yarnのファイル

空のディレクトリを作成し、ディレクトリ内で下記を実行します。

yarn add -D webpack webpack-cli
yarn add @mapray/mapray-js @mapray/ui

webpack.config.jsを作成します( webpack の設定ファイル)。

const path = require('path');

module.exports = {
  entry: './src/index.js',
  output: {
    filename: 'main.js',
    path: path.resolve(__dirname, 'dist'),
  },
};

src/index.js を作成します。 ACCESS_TOKEN に取得したMapray Cloudトークンを指定します。

import maprayui from "@mapray/ui";

const ACCESS_TOKEN = "MTU*************************************";

window.startApp = id => {
  const stdViewer = new maprayui.StandardUIViewer(id, ACCESS_TOKEN);
  // stdViewer...
};

package.json を下記のように、scripts要素を追加します。

{
    :
  "scripts": {
    "build": "webpack"
  },
    :
}

ビルドします。

yarn run build

dist/index.html を作成します。 ビルドした js ファイルを読み込み startApp() を呼び出します。

<html>
<head>
<meta charset="utf-8"/>
<script type="text/javascript" src="./main.js"></script>
</head>
<body onload="window.startApp('mapray-container')">
<div id="mapray-container" style="width:1024px;height:768px"></div>
</body>
</html>

2.2.2. Nodeで開発用サーバを作成する

ここでは st(Node製サーバ)をインストールします。

yarn add -D st

(上記コマンドを実行すると package.json が書き変わりますのでご注意ください。)

サーバ起動コマンドを登録します。 ここでは、ポート7777、公開ディレクトリ dist として公開するように設定しています。

{
    :
  "scripts": {
    "build": "webpack",
    "server": "st --no-cache -H 0.0.0.0 --port 7777 --index index.html -d dist"
  },
    :
}

サーバを起動します。

npm run server

http://localhost:7777 へアクセスします。

2.2.3. 実行結果

demo-basic.png

2.3. エンティティ

基本機能の使い方の説明については、MaprayホームページのExamplesをご覧ください。 ここでは、簡単なカメラ操作やエンティティの追加方法について説明します。

window.startApp = id => {
  const stdViewer = new maprayui.StandardUIViewer(id, ACCESS_TOKEN);

  const mtFujiPosition = new mapray.GeoPoint(138.72884, 35.36423, 0);

  // カメラ視点の変更
  stdViewer.setCameraPosition({
    longitude: mtFujiPosition.longitude,
    latitude: mtFujiPosition.latitude - 0.05,
    height: mtFujiPosition.altitude + 6000
  });

  // カメラ視線先の変更
  stdViewer.setLookAtPosition({
    longitude: mtFujiPosition.longitude,
    latitude: mtFujiPosition.latitude,
    height: mtFujiPosition.altitude + 3000
  });

  const pin = new mapray.PinEntity(stdViewer.viewer.scene)
  pin.altitude_mode = mapray.AltitudeMode.RELATIVE;
  pin.addMakiIconPin( "car-15", mtFujiPosition );
  stdViewer.addEntity(pin);
};

2.3.1. 実行結果

demo-entities.png

2.3.2. 関連するAPI

2.4. マウス操作のカスタマイズ

StandardUIViewerのマウス操作をカスタマイズする例を示します。

import mapray from "@mapray/mapray-js";
import maprayui from "@mapray/ui";

const ACCESS_TOKEN = "MTU*************************************";


class CustomViewer extends maprayui.StandardUIViewer {
  onMouseDown( point, event ) {
    if ( event.shiftKey ) {
      const pickResult = this.viewer.pick(point);

      if ( pickResult.entity ) {
        console.log( "Entity: ", pickResult.entity );
      }
      else if (pickResult.point) {
        const pin = new mapray.PinEntity( this.viewer.scene );
        const p = new mapray.GeoPoint();
        p.setFromGocs( pickResult.point );
        pin.addMakiIconPin( "car-15", p );
        this.addEntity( pin );
      }
    }
    else {
      super.onMouseDown( point, event );
    }
  }
}


window.startApp = id => {
    new CustomViewer( id, ACCESS_TOKEN );
};

2.4.1. 実行結果

shiftを押しながらクリックするとピンが配置されます。

demo-mouse.png

shiftを押しながらピン上でクリックするとコンソールにクリックしたピンの情報が出力されます。

demo-mouse-dev.png

より詳細な例はデバッグ用コードをご参照ください。

2.4.2. 関連するAPI

2.5. 3Dデータ

ここでは、Mapray Cloudにアップロードした3Dデータを表示する例を示します。

2.5.1. 3Dデータのアップロード

Mapray Cloudの3Dデータセットページからアップロードします(解説ページ)。 現在 glTFobj 形式に対応しています。 複数テクスチャには対応していおりませんのでご注意ください。

アップロードする方法は下記2種類あります。

Portable Data
3Dモデルを任意の位置に配置するモードです。 座標値の単位はメートルで、原点周辺に分布しているようなデータです。
Geographic Data
モデルデータ自体が地理情報(位置情報)を持っているデータを配置するモードです。 現在、平面直角座標のみ対応しています。

今回は、Portable Data のモデルをアップロードします。

2.5.2. 3Dデータの表示

src/index.js を下記のように修正します。 ACCESS_TOKEN に取得したMapray Cloudトークンを指定します。 USER_ID にユーザIDを指定します。 datasetId にアップロードしたデータセットのIDを指定します。

import mapray from "@mapray/mapray-js";
import maprayui from "@mapray/ui";

const ACCESS_TOKEN = "MTU*************************************";
const USER_ID = "567*************";

window.startApp = id => {
    const stdViewer = new maprayui.StandardUIViewer(id, ACCESS_TOKEN);

    const maprayApi = new mapray.MaprayApi({
            basePath: "https://cloud.mapray.com",
            version: "v1",
            userId: USER_ID,
            token: ACCESS_TOKEN,
    });

    const datasetId = "576*************";
    const resource = maprayApi.get3DDatasetAsResource( [ datasetId ] );
    const loader = new mapray.SceneLoader( stdViewer.viewer.scene, resource, {
      onEntity: (loader, entity, prop) => {
        // リソースが 3Dデータセットなので、entity は ModelEntityクラスとなります。
        // onEntityを指定した場合は、entityの追加を手動で行う必要があります。
        stdViewer.addEntity(entity);

        // モデル位置にカメラを移動します
        const bounds = entity.getBounds();
        const length = bounds.getLatitudeDistance();
        stdViewer.startFlyCamera({
          time: 3.0,
          iscs_end: bounds.getCenter(),
          end_altitude: 5 * length,
          end_from_lookat: 5 * length,
        });
      }
    } );
    loader.load();
};

2.5.3. 実行結果

demo-3d.png

2.5.4. 関連するAPI

2.6. 点群(Mapray Cloud)

Mapray Cloudへファイルをアップロードして点群を表示する方法について説明します。

2.6.1. 点群のアップロード

Mapray Cloudの点群データセットページからアップロードします(解説ページ)。 現在 las 形式に対応しています。 バージョン1.2, 1.3の色付き点群に対応しています。

2.6.2. 点群の表示

src/index.js を下記のように修正します。 ACCESS_TOKEN に取得したMapray Cloudトークンを指定します。 USER_ID にユーザIDを指定します。 datasetId にアップロードしたデータセットのIDを指定します。

import mapray from "@mapray/mapray-js";
import maprayui from "@mapray/ui";

const ACCESS_TOKEN = "MTU*************************************";
const USER_ID = "567*************";

window.startApp = id => {
  const stdViewer = new maprayui.StandardUIViewer(id, ACCESS_TOKEN);

  const maprayApi = new mapray.MaprayApi({
    basePath: "https://cloud.mapray.com",
    version: "v1",
    userId: USER_ID,
    token: ACCESS_TOKEN,
  });

  const datasetId = "573*************";
  const resource = maprayApi.getPointCloudDatasetAsResource( datasetId );

  const pointCloudProvider = new mapray.RawPointCloudProvider( resource );
  const pointCloud = stdViewer.viewer.point_cloud_collection.add( pointCloudProvider );

  // 点群位置にカメラを移動します
  maprayApi.getPointCloudDataset( datasetId )
    .then(dataset => {
      const bbox = dataset.bbox;
      stdViewer.startFlyCamera({
        time: 3.0,
        iscs_end: new mapray.GeoPoint(
          (bbox[0] + bbox[3])/2,
          (bbox[1] + bbox[4])/2,
          (bbox[2] + bbox[5])/2,
        ),
        end_altitude: 100,
        end_from_lookat: 100,
      });
    });
};

2.6.3. 実行結果

demo-point-cloud.png

2.6.4. 点群表示の変更

読み込む点群を細かくする例(デフォルトは 0.7 です)。

pointCloud.setPointsPerPixel(1.0);

読み込む点群の描画形状やサイズを変更する例。

pointCloud.setPointShape(mapray.PointCloud.PointShapeType.GRADIENT_CIRCLE);
pointCloud.setPointSizeType(mapray.PointCloud.PointSizeType.PIXEL);
pointCloud.setPointSize(10);

より詳細な例はデバッグ用コードをご参照ください。

2.6.5. 点群が地形と重なる問題について

点群が地形より下にある場合に点群を確認することができなくなることがあります。 暫定的な対処方法として地形を非表示にすることで点群を見える状態にすることができます。

stdViewer.viewer.render_mode = mapray.Viewer.RenderMode.WIREFRAME;
demo-point-cloud-without-dem.png

2.7. 点群(Static File Server)

Mapray Cloudを使わず、ファイルサーバに点群データをアップロードして点群を表示する方法について説明します。 (現時点でこの方法は一般的に公開されている方法ではないため、通常のドキュメントには記載されていない方法となります。)

2.7.1. 点群データの準備

点群データの生成方法については別途資料をご確認ください。 点群データは下記のような構成になっています。

- Root
  |-- info.json
  |-- 0
  |-- 1
  |-- 2
  |-- 3
  |   :
  '-- 4

ルートディレクトリに info.json があり点群タイルに関する情報が含まれています。 この構成のままサーバへアップロードします。

下記のURLにアクセスすることで上記 info.json へアクセスできるものとして以降の説明をします。

http://localhost:8888/point-data/info.json

2.7.2. 点群の表示

src/index.js を下記のように修正します。 ACCESS_TOKEN に取得したMapray Cloudトークンを指定します。

import mapray from "@mapray/mapray-js";
import maprayui from "@mapray/ui";

const ACCESS_TOKEN = "MTU*************************************";

window.startApp = id => {
  const stdViewer = new maprayui.StandardUIViewer(id, ACCESS_TOKEN);

  const resource = new mapray.URLResource("http://localhost:8888/point-data/info.json");

  const pointCloudProvider = new mapray.RawPointCloudProvider( resource );
  const pointCloud = stdViewer.viewer.point_cloud_collection.add( pointCloudProvider );

  // 点群位置にカメラを移動します
  resource.load({ type: mapray.Resource.ResourceType.JSON })
    .then(info => {
      const bbox = info.bbox;
      stdViewer.startFlyCamera({
        time: 3.0,
        iscs_end: new mapray.GeoPoint(
          (bbox[0] + bbox[3])/2,
          (bbox[1] + bbox[4])/2,
          (bbox[2] + bbox[5])/2,
        ),
        end_altitude: 300,
        end_from_lookat: 100,
      });
    });
};

2.7.3. 実行結果

MaprayCloudを使う場合と同様に下記のように表示されます。

demo-point-cloud-static-file.png

pointCloud への操作はMaprayCloudを使う場合と同様に行うことができます。