1
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Draw.io でコスト0のデジタルツインを作る

Last updated at Posted at 2023-02-26
記事の前提:デジタルツインって何?

現実世界とリンクして、現実世界を再現するバーチャル空間のことです。
デジタルの双子(デジタルツイン)と呼ばれています。

ざっくりとしたジャンルを表す言葉ですので、同じ言葉でもまるで異なる技術のことを指します。

  • シミュレーションツールとしてのデジタルツイン
    目的:現実に起こっていないことをバーチャル空間で再現する
    例:NVIDIA Omniverse, 災害シミュレータ
  • 可視化ツールとしてのデジタルツイン
    目的:言語化が難しいものに 3D でラベル付けする
    例:AWS TwinMaker, Azure Digital Twins
  • などなど。ほかにもいろいろ

この記事では「デジタルツイン=現実とリンクした3Dの地図コンテンツ」の意味で扱います。
可視化ツールとして、「言語化の難しいものへのラベル付け」を目的とします。

記事の概要

  • Wiki や 5ch みたいに、誰もが簡単に編集できる3D地図

の作り方を紹介する記事です。

pagetop.png

記事が扱う開発環境とライブラリ

  • Draw.io
  • three.js
  • Cloudflare Workers

技術的なトピックを 3 行で

  • コストをかけずにデジタルツインを公開・運用する
  • 編集可能な Google Drive 上のファイルを、Web サイトからAjax参照する
  • Draw.io から 3D モデル(three.js) に変換するツールを筆者が作ったので紹介

デモサイトで触れる?

以下のサイトで実際に動いているものに触ることができます。
Google Map と同じ操作方法で閲覧できます。

compare.png

何が嬉しいの?

デジタルツインは何が嬉しいの?

デジタルツインのメリットに、『言語化できないもの』にラベル付けできることがあります。

needle.png

デジタルツインはデータを現実世界にひもづけて表現することで、名前がない、言葉で表現しにくい、名前を聞いてもピンとこないものに対して、ラベル付けやトピック付けをすることができます。

それを Draw.io で導入できると何が嬉しいの?

Draw.io で更新できるようになることで、

  • ツール不要で修正できるので、誰もがいつでも更新できる
  • データストレージも開発環境も不要になるので、安くなる

ようになります。

デジタルツインを Wiki 化できると何が嬉しいの?

オフィスが主体でデジタルツインをやるとしたら、

  • 空調のデジタルツイン
  • 会議中と人流のデジタルツイン

どうしても堅いプロジェクトになります。席替えやセンサーの入れ替えがあれば更新も手間がかかりますし、「毎回ダッシュボードを立ち上げるほど空調気にする?」があります。

Wiki なら、柔らかい情報をデジタルツインに書き込めます。

  • 寒い座席、サーバの音がうるさい座席
  • 推しのアニメの食玩が売っているコンビニの場所
  • 会社の裏の自販機のラインナップ
  • 明日休みますから飲み会の費用は〇〇さんに渡して、みたいなメモ書き

空調も人流に体感が入ることで双方向になりますし、使う人が見たい情報、見せたい情報、知りたい情報、比較的新鮮な情報が集まる場所になります。席替えをしてもすぐに更新できます。

構築してみる

構築の手順は以下の通りです。

  • Draw.ioのファイルを共有する
    • Draw.io のファイルを作って、 Google Drive に保存する
    • ファイル設定の「保存時の圧縮」を無効にする
    • 誰でもブラウザ上で編集できるように公開する
    • Ajax で Web サイトからDraw.ioの取れるようにするようにする
  • Draw.ioのファイルを3D化する
    • 読み込んだDraw.ioのファイルを、JavaScriptのライブラリで3D化する

以下のものが必要ですので、あらかじめ用意しておきます。

  • Google のアカウント
  • Cloudflare のアカウント

手順1:Draw.io のファイル共有する

[1:Draw.io のファイルを作って、 Google Drive に保存する]

Draw.io (https://app.diagrams.net/)をブラウザで開きます。
ファイルの保存先を尋ねられるので、「Google ドライブ」を選択します。

diagrams-1.png

Draw.io(diagrams.net)からGoogle ドライブへのアクセス権限を求められた場合は、3つともにチェックをつけて、Draw.ioからのアクセスを許可します。

diagrams-2.png

[2:ファイル設定の「保存時の圧縮」を無効にする]

初期設定では「属性」→「圧縮」が有効になっているのですが、これを無効にします。
「圧縮」のチェックを外すと保存時の圧縮が無効になります。

uncheck-element.png

[3:誰でもブラウザ上で編集できるようにする]

右上にある「共有」ボタンをクリックします。

share.png

ダイアログが出たら、「リンクを知っている全員」に対して「編集者」の権限を設定します。
「リンクをコピー」をクリックして、URLをコピーします。

share-dialog.png

コピーしたURLは(https)://drive.google.com/file/d/${ファイルID}/view?usp=sharingのようなフォーマットになっているのですが、末尾が/viewになっています。これを/editに置き換えた(https)://drive.google.com/file/d/${ファイルID}/edit?usp=sharingが編集用のURLになります。

編集用のURLを開くと、誰でもブラウザ上でDraw.ioファイルを編集することができますし、変更した内容はGoogle Driveに即時で反映されます。

この${ファイルID}は後で繰り返し出てくるため、コピーして手元のテキストエディタに置いておきます。

[4:Ajax で Web サイトから取れるようにする]

編集用のURLはあくまでプレビュー画面のURLですので、AjaxでWebアプリから参照するには直接のURLが必要です。直接参照するURL はhttps://drive.google.com/uc?export=download&id=${ファイルID}になります。

ただ、これをAjaxでウェブサイトから取得しようとするとエラーが出てしまいます。ドメインが違うためです。GoogleはこのURLから別のドメインにリダイレクトをかけているため、CloudfrontやAPI Gatewayの下にGoogle Driveを置くだけでは回避できません。

昔は CORS Anywhere(https://github.com/Rob--W/cors-anywhere )で簡単に解決できたのですが、悪用が多かったらしく、今ではサーバ側から厳しい制限がかけられています。Herokuも有料化したので、別の方法で対応します。

CORS Anywhereと同じものをCloudflare Workersの無料プランで自作します。
Cloudflare Workers(https://www.cloudflare.com/ja-jp/ )の「サービスを作成」で「HTTPハンドラ」のサービスを1つ作ります。

workers.png

作ったサービスを選んだら、右上の「クイック編集」のボタンを押します。

quick-edit.png

ソースコードをブラウザ上で編集できます。

worker-contents.png

ソースコードに以下のソースをコピペして、デプロイします。

CORS anywhareの簡単版
addEventListener("fetch", (event) => {
  event.respondWith(handleRequest(event.request));
});

async function handleRequest(request) {
  const url = new URL(request.url);
  const id = url.pathname.replace("/", "");
  const corsHeaders = {
    "Access-Control-Allow-Origin": "*",
    "Access-Control-Allow-Methods": "GET,OPTIONS",
  };
  const url_response = await fetch(
    "https://drive.google.com/uc?export=download&id=" + id
  );
  const body = await url_response.text();
  return new Response(body, {
    headers: corsHeaders,
  });
}

エディタの右側に検証ツールがあるので、URLの後ろに${ファイルID}をつけてリクエストします。

リクエスト先のURLはこんな感じになるはずです。
https://${workerの関数名}.${プロジェクト名}.workers.dev/${ファイルID}

リクエストに対して、xml形式のDraw.ioデータが返ってきたらOKです

Cloudflare Workers の無料プランには、

  • 実行時間(CPU runtime)が 10ms 以内であること
  • 1 日あたり 10 万リクエスト以内であること

の制限があります。
ピンとこない表現ですが、CPU runtime はプロセスの待ち時間(例:Google Driveに対してfetchしている間の通信時間など)を除いた時間になります。上記のソースなら 1ms 程度です。
ですので、このために有料プランを導入する必要はありません。

手順2:Draw.io で 3D に必要なデータを設定する

Draw.io は、座標や形、ラベルの文字列のほかに、自由なプロパティを持つことができます
※ショートカットはctrl+Mになります

property-drawio.png

Rectangle で好きな形を作成したら、プロパティに「type: x-building」を設定します
このデータをあとのライブラリで読み込むと、建物として立体化されます

property-building.png

ライブラリが読み込めるプロパティの例です

プロパティの値 できるもの
x-building 建物
x-street
street-label 道の上に表示するテキスト

手順3:取得した Draw.io のファイルを、3D化して表示する

以下のサンプルプロジェクトを参考にしてください。

【githubのプロジェクト】
https://github.com/fuyoneko/dio2town-contents

【index.htmlのソース】
https://github.com/fuyoneko/dio2town-contents/blob/master/docs/tobitamap/index.html

Draw.io を 3D に変換する Javascript のソースは以下の通りです。

ライブラリの読み込みをヘッダに書き込みます。

HTMLへの導入
<script
  src="https://cdn.jsdelivr.net/gh/fuyoneko/dio2town@v0.0.1/_bundles/dio-2-town-map.js"
  crossorigin="anonymous"
></script>

地図の表示場所にDIVタグを置きます。

HTMLのbodyには以下のタグを追加します
<!-- このDIVタグが3D地図に置き換わります。大きさは自由です -->
<div id="main" style="height: 100vh; width: 100vw"></div>

スクリプトで読み込みをします。

Draw.ioファイルの読み込み
<script>
  window.onload = function () {
    // カメラ、レンダラを作成して、mainタグの場所にマッピングする
    const core = new Dio2TownMap.Core(document.getElementById("main"));
    // DrawIoからデータを取得する
    new Dio2TownMap.DioParser()
      .parse({
        dioFile:
          "${先の手順で作ったCloudflare WorkersへのURL}", // Draw.ioファイルを取得する
        polygonFile: "./polygon.json", // 空のJSONファイルへのパス
      })
      .then((dataList) => {
        // Dioデータから3D画面を作成する
        new Dio2TownMap.MainField().basement(
          core.scene, // シーンオブジェクトを連携する
          dataList, // Dioデータを連携する
          (started, dataCount) => {} // オブジェクト化の完了通知
        );

        // 光源を初期化
        new Dio2TownMap.Light(core.scene);
      });
  };
</script>

既存のホームページに埋め込んでもいいですし、S3 や Cloudflare pages で公開してもいいですし、React や Vue に埋め込むのもよいと思います。

サンプルソースにはオブジェクトへのクリック操作を拾うソースも書いています。MainField がオブジェクトを持っているので、JavaScript で参照して操作することもできます。

これまでの展開と今後の展開

ここからは技術的な話を離れて雑記になります。

「Draw.io を 3D にするツール」は、飛田の地図のコア部分を切り出したものですので、「このツールで現状どこまでできるの?」は、飛田の地図を見ていただければと思います。
https://tobitamap.pages.dev

実装済みや一部実装した機能:

  • 建物をタップすると詳細を表示する
  • カメラ位置が下がると現実に近い表現(GLBデータの表示)になる
  • ルートに沿ってカメラが移動して、道案内をする
  • QRコードでカメラの状態を共有する

これらについてはドキュメントを整備します。

実装予定の機能:

  • 現実の雨に連動して、デジタルツイン空間内でも雨が降る
  • 「building」以外のプロパティ(「room」やデータ表示のオブジェクト)を整備する

これらについては引き続き対応をと考えています

まとめとか

コストゼロ、編集もブラウザだけで完結するデジタルツインの紹介でした。

画面をぐりぐりと操作してみて、

  • 3D の地図を、予算が用意できない商店街や学園祭でやったら?
  • QRコードのカメラ情報共有を、GPSの精度が下がる地下街やドーム球場でやったら?
  • iPhoneで3Dスキャンしたモデルをデジタルツイン上に表示したら?

「きっと楽しくなるだろう」「きっと便利になるだろう」と思ってもらえるのなら、色々な会社が出しているデジタルツインのサービスも含めて検討して、ぜひ導入してみてはと思います。

1
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?