1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

山の位置をARで表示する技術ブログ:ロケーションARの基本

Posted at

はじめに

現実世界にデジタル情報を重ね合わせる技術、ロケーションAR。今回は、ユーザーの位置情報を基に山の位置をリアルタイムで表示する方法について説明します。この技術を使えば、観光や登山の際に周囲の山々を簡単に識別することができます。

使用技術とライブラリ

このプロジェクトでは、以下の技術とライブラリを使用します:

  • AFRAME:3DおよびARコンテンツをウェブ上で作成するフレームワーク
  • AR.js:ウェブベースのARライブラリ
  • Geolib:地理座標の計算を簡単にするライブラリ
  • JavaScript:クライアントサイドのスクリプティング
  • HTML:ウェブページの構造を定義

HTMLの基本構造

以下は、HTMLの基本構造です。AR.jsとAFRAMEを使用して、ユーザーのカメラビューに方角を示す矢印を配置します。

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
  <title>AR Planet Locator</title>
  <link rel="stylesheet" href="./css/styles.css">
  <script src="https://aframe.io/releases/1.6.0/aframe.min.js"></script>
  <script src="https://raw.githack.com/AR-js-org/AR.js/master/aframe/build/aframe-ar-nft.js"></script>
  <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
  <script src="https://cdn.jsdelivr.net/npm/geolib@3.3.4/lib/index.min.js"></script>
  <script src="./js/ar.js"></script>
  <style>
    body, html { margin: 0; overflow: hidden; }
  </style>
</head>
<body>
  <a-scene embedded arjs="sourceType: webcam;">
    <a-camera gps-camera rotation-reader id="camera"></a-camera>
    <!-- 方角の矢印を表示 -->
    <a-entity id="north-arrow" position="0 0 -10.5">
      <a-cone color="red" radius-bottom="0.5" height="2" position="0 1 0" rotation="0 0 0"></a-cone>
      <a-text value="北" scale="4 4 1" position="-0.5 2.8 0" rotation="0 0 0"></a-text>
    </a-entity>
  </a-scene>
</body>
</html>

JavaScriptによる位置計算と表示

ar.jsファイルでは、ユーザーの現在位置と山の位置を基に、AR表示を行うための位置計算と描画を行います。

AFRAME.registerComponent("rotation-reader", {
  tick: function () {
    const cameraRotation = this.el.object3D.rotation;
    // カメラの回転情報を利用した処理
  },
});

function calculatePosition(targetLatitude, targetLongitude, userLatitude, userLongitude) {
  const distance = 10; // 固定距離(メートル)
  const userPosition = { latitude: userLatitude, longitude: userLongitude };
  const targetPosition = { latitude: targetLatitude, longitude: targetLongitude };
  let bearing = geolib.getRhumbLineBearing(userPosition, targetPosition);
  bearing -= 90; // 方位が90度ずれているため修正
  const x = distance * Math.cos((bearing * Math.PI) / 180);
  const z = distance * Math.sin((bearing *Math.PI) / 180);
  return { x, y: 1, z, bearing };
}

function updateARPosition(userLatitude, userLongitude, mountains) {
  mountains.forEach((mountain) => {
    const { lat, lng, name } = mountain;
    const targetPosition = calculatePosition(lat, lng, userLatitude, userLongitude);
    const pointerEntity = document.createElement("a-entity");
    pointerEntity.setAttribute("position", `${targetPosition.x} ${targetPosition.y} ${targetPosition.z}`);
    const circleEntity = document.createElement("a-entity");
    circleEntity.setAttribute("geometry", "primitive: circle; radius: 0.1");
    circleEntity.setAttribute("material", "color: white");
    circleEntity.setAttribute("position", "0 1 0");
    const lineEntity = document.createElement("a-entity");
    lineEntity.setAttribute("line", `start: 0, 1, 0; end: 0, 3, -2; color: white; linewidth: 20`);
    const textEntity = document.createElement("a-text");
    textEntity.setAttribute("value", name);
    textEntity.setAttribute("color", "white");
    textEntity.setAttribute("position", "0 3.1 -2");
    textEntity.setAttribute("rotation", `0 ${-targetPosition.bearing - 90} 90`);
    textEntity.setAttribute("scale", "3 3 3");
    pointerEntity.appendChild(circleEntity);
    pointerEntity.appendChild(lineEntity);
    pointerEntity.appendChild(textEntity);
    document.querySelector("a-scene").appendChild(pointerEntity);
  });
}

// 初期処理としてupdateARPositionを呼び出す
document.addEventListener("DOMContentLoaded", () => {
  const userLatitude = 35.6895;  // モックデータ
  const userLongitude = 139.6917; // モックデータ
  const mountains = [
    { lat: 35.3606, lng: 138.7274, name: "Mt. Fuji" }, // モックデータ
    { lat: 36.2048, lng: 137.2529, name: "Mt. Yari" }   // モックデータ
  ];
  updateARPosition(userLatitude, userLongitude, mountains);
});

結論

ロケーションAR技術を活用すれば、ユーザーの位置情報を基に現実世界にデジタル情報を重ね合わせることが可能です。このブログでは、その基本的な実装方法を紹介しました。AR技術を用いることで、観光や登山の際に周囲の山々を簡単に識別でき、ユーザーに新しい体験を提供することができます。

1
0
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
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?