navara_three_api
navara_three_api は、Three.js と Navara エンジンを統合するためのユーティリティ関数を提供する API です。地理空間計算、座標変換、交差判定、RTE(Relative to Eye)レンダリングなど、3D 地理空間アプリケーション開発に必要な機能を Three.js の型システムと統合して提供します。
initNavaraApi()
Section titled “initNavaraApi()”Navara API を初期化します。他の API 関数を使用する前に、必ずこの関数を呼び出してください。
Syntax:
async function initNavaraApi(): Promise<void>;Returns:
初期化完了時に解決される Promise
Example:
import { initNavaraApi } from "@navaramap/three-api";
// アプリケーション起動時に初期化await initNavaraApi();Ellipsoid Functions
Section titled “Ellipsoid Functions”WGS84 楕円体の基本パラメータを取得する関数群です。
getWGS84SemiMajorAxis()
Section titled “getWGS84SemiMajorAxis()”WGS84 楕円体の長半径を取得します。
Syntax:
function getWGS84SemiMajorAxis(): number;Returns:
WGS84 楕円体の長半径(メートル)
Example:
const semiMajorAxis = getWGS84SemiMajorAxis();console.log(`長半径: ${semiMajorAxis} m`); // 長半径: 6378137 mgetWGS84SemiMinorAxis()
Section titled “getWGS84SemiMinorAxis()”WGS84 楕円体の短半径を取得します。
Syntax:
function getWGS84SemiMinorAxis(): number;Returns:
WGS84 楕円体の短半径(メートル)
Example:
const semiMinorAxis = getWGS84SemiMinorAxis();console.log(`短半径: ${semiMinorAxis} m`); // 短半径: 6356752.314245 mgetWGS84EccentricitySquared()
Section titled “getWGS84EccentricitySquared()”WGS84 楕円体の離心率の二乗を取得します。
Syntax:
function getWGS84EccentricitySquared(): number;Returns:
WGS84 楕円体の離心率の二乗
getWGS84Flattening()
Section titled “getWGS84Flattening()”WGS84 楕円体の扁平率を取得します。
Syntax:
function getWGS84Flattening(): number;Returns:
WGS84 楕円体の扁平率
getWGS84Eccentricity()
Section titled “getWGS84Eccentricity()”WGS84 楕円体の離心率を取得します。
Syntax:
function getWGS84Eccentricity(): number;Returns:
WGS84 楕円体の離心率
Coordinate Transformation
Section titled “Coordinate Transformation”座標系間の変換を行う関数群です。Three.js の Vector3 型と統合されています。
geodeticToVector3(lle)
Section titled “geodeticToVector3(lle)”測地座標(緯度経度高度)を Three.js の Vector3(ECEF 座標系)に変換します。
Syntax:
function geodeticToVector3(lle: LatLngHeight): Vector3;Parameters:
lle: 変換する測地座標lat: 緯度(度)lng: 経度(度)height: 高度(メートル)
Returns:
ECEF 座標系での位置(Three.js Vector3)
Example:
import { geodeticToVector3 } from "@navaramap/three-api";
const lle = { lat: 35.6762, // 東京の緯度 lng: 139.6503, // 東京の経度 height: 100,};const position = geodeticToVector3(lle);console.log(`位置: [${position.x}, ${position.y}, ${position.z}]`);vector3ToGeodetic(xyz)
Section titled “vector3ToGeodetic(xyz)”Three.js の Vector3(ECEF 座標系)を測地座標(緯度経度高度)に変換します。
Syntax:
function vector3ToGeodetic(xyz: Vector3): LatLngHeight;Parameters:
xyz: 変換する ECEF 座標(Three.js Vector3)
Returns:
測地座標:
lat: 緯度(度)lng: 経度(度)height: 高度(メートル)
Example:
import { vector3ToGeodetic } from "@navaramap/three-api";import { Vector3 } from "three";
const position = new Vector3(-3946416, 3364068, 3702654);const lle = vector3ToGeodetic(position);console.log(`緯度: ${lle.lat}°`);console.log(`経度: ${lle.lng}°`);console.log(`高度: ${lle.height} m`);degreeToRadian(degree)
Section titled “degreeToRadian(degree)”角度を度からラジアンに変換します。Navara の API における緯度経度はすでに度単位のため、このヘルパーは Three.js の Euler rotation フィールドなどラジアンを取る計算にのみ必要です。
Syntax:
function degreeToRadian(degree: number): number;Parameters:
degree: 度単位の角度
Returns:
ラジアン単位の角度
Example:
const radians = degreeToRadian(90);console.log(`90度 = ${radians} ラジアン`); // 90度 = 1.5708 ラジアンradianToDegree(radian)
Section titled “radianToDegree(radian)”角度をラジアンから度に変換します。
Syntax:
function radianToDegree(radian: number): number;Parameters:
radian: ラジアン単位の角度
Returns:
度単位の角度
Example:
const degrees = radianToDegree(Math.PI);console.log(`π ラジアン = ${degrees}度`); // π ラジアン = 180度Screen-World Projection
Section titled “Screen-World Projection”スクリーン座標と世界座標間の変換を行う関数群です。Three.js の PerspectiveCamera と統合されています。
convertScreenToWorld(window, camera, vec2)
Section titled “convertScreenToWorld(window, camera, vec2)”スクリーン座標を世界座標に変換します。
Syntax:
function convertScreenToWorld( windowObject: WindowObject, camera: PerspectiveCamera, vec2: Vector2): Vector3 | undefined;Parameters:
windowObject: ウィンドウ情報width: ウィンドウの幅height: ウィンドウの高さpixelRatio: デバイスのピクセル比
camera: Three.js の PerspectiveCameravec2: スクリーン座標(Three.js Vector2)
Returns:
世界座標での位置、または交差しない場合は undefined
Example:
import { convertScreenToWorld } from "@navaramap/three-api";import { Vector2 } from "three";
// ウィンドウ情報オブジェクトを作成const windowObject = { width: canvas.clientWidth, height: canvas.clientHeight, pixelRatio: window.devicePixelRatio};
const screenPos = new Vector2(event.clientX, event.clientY);
const worldPos = convertScreenToWorld(windowObject, camera, screenPos);if (worldPos) { console.log(`世界座標: [${worldPos.x}, ${worldPos.y}, ${worldPos.z}]`);}convertWorldToScreen(window, camera, worldPos)
Section titled “convertWorldToScreen(window, camera, worldPos)”世界座標をスクリーン座標に変換します。
Syntax:
function convertWorldToScreen( windowObject: WindowObject, camera: PerspectiveCamera, worldPos: Vector3): Vector2 | undefined;Parameters:
windowObject: ウィンドウ情報camera: Three.js の PerspectiveCameraworldPos: 世界座標での位置(Three.js Vector3)
Returns:
スクリーン座標、または視野外の場合は undefined
Example:
import { convertWorldToScreen, geodeticToVector3 } from "@navaramap/three-api";
const lle = { lat: 35.6812, lng: 139.7671, height: 100 };const worldPos = geodeticToVector3(lle);
const screenPos = convertWorldToScreen(window, camera, worldPos);if (screenPos) { console.log(`スクリーン座標: [${screenPos.x}, ${screenPos.y}]`);}Intersection and Ray Casting
Section titled “Intersection and Ray Casting”交差判定とレイキャスティングを行う関数群です。
getPlaneFromPointNormal(point, normal)
Section titled “getPlaneFromPointNormal(point, normal)”点と法線ベクトルから平面を作成します。
Syntax:
function getPlaneFromPointNormal(point: Vector3, normal: Vector3): Plane;Parameters:
point: 平面上の点(Three.js Vector3)normal: 平面の法線ベクトル(Three.js Vector3)
Returns:
作成された平面
Example:
import { getPlaneFromPointNormal } from "@navaramap/three-api";import { Vector3 } from "three";
const point = new Vector3(0, 0, 0);const normal = new Vector3(0, 0, 1); // Z軸方向const plane = getPlaneFromPointNormal(point, normal);getPickRay(window, camera, vec2)
Section titled “getPickRay(window, camera, vec2)”スクリーン座標からピッキング用のレイを生成します。
Syntax:
function getPickRay( windowObject: WindowObject, camera: PerspectiveCamera, vec2: Vector2): Ray;Parameters:
windowObject: ウィンドウ情報camera: Three.js の PerspectiveCameravec2: スクリーン座標(Three.js Vector2)
Returns:
生成されたレイ
Example:
import { getPickRay } from "@navaramap/three-api";import { Vector2 } from "three";
const screenPos = new Vector2(event.clientX, event.clientY);const ray = getPickRay(window, camera, screenPos);getRayPlaneIntersection(ray, plane)
Section titled “getRayPlaneIntersection(ray, plane)”レイと平面の交点を計算します。
Syntax:
function getRayPlaneIntersection(ray: Ray, plane: Plane): Vector3 | undefined;Parameters:
ray: 交差判定を行うレイplane: 交差判定を行う平面
Returns:
交点の座標(Three.js Vector3)、または交差しない場合は undefined
Example:
import { getPickRay, getPlaneFromPointNormal, getRayPlaneIntersection,} from "@navaramap/three-api";import { Vector2, Vector3 } from "three";
// マウス位置からレイを生成const screenPos = new Vector2(event.clientX, event.clientY);const ray = getPickRay(window, camera, screenPos);
// 地面平面を定義const groundPlane = getPlaneFromPointNormal( new Vector3(0, 0, 0), new Vector3(0, 0, 1));
// 交点を計算const intersection = getRayPlaneIntersection(ray, groundPlane);if (intersection) { console.log( `クリック位置: [${intersection.x}, ${intersection.y}, ${intersection.z}]` );}getHeightFromEllipsoid(point)
Section titled “getHeightFromEllipsoid(point)”指定した点の楕円体からの高度を取得します。
Syntax:
function getHeightFromEllipsoid(point: Vector3): number;Parameters:
point: 高度を計算する点の ECEF 座標(Three.js Vector3)
Returns:
楕円体からの高度(メートル)
Example:
import { getHeightFromEllipsoid } from "@navaramap/three-api";import { Vector3 } from "three";
const position = new Vector3(-3946416, 3364068, 3702654);const height = getHeightFromEllipsoid(position);console.log(`高度: ${height} m`);Surface Normal and Reference Frames
Section titled “Surface Normal and Reference Frames”地表面の法線ベクトルと参照フレームを計算する関数群です。
geodeticSurfaceNormal(lle)
Section titled “geodeticSurfaceNormal(lle)”測地座標での地表面法線ベクトルを計算します。
Syntax:
function geodeticSurfaceNormal(lle: LatLngHeight): Vector3;Parameters:
lle: 測地座標
Returns:
正規化された地表面法線ベクトル(Three.js Vector3)
Example:
import { geodeticSurfaceNormal } from "@navaramap/three-api";
const lle = { lat: 35.6762, lng: 139.6503, height: 0,};const normal = geodeticSurfaceNormal(lle);console.log(`法線ベクトル: [${normal.x}, ${normal.y}, ${normal.z}]`);eastNorthUpToFixedFrame(origin)
Section titled “eastNorthUpToFixedFrame(origin)”East-North-Up 座標系から固定フレームへの変換行列を取得します。
Syntax:
function eastNorthUpToFixedFrame(origin: Vector3): Matrix4;Parameters:
origin: 原点の ECEF 座標(Three.js Vector3)
Returns:
4x4 変換行列(Three.js Matrix4)
Example:
import { eastNorthUpToFixedFrame, geodeticToVector3,} from "@navaramap/three-api";
const tokyoLle = { lat: 35.6762, lng: 139.6503, height: 0,};const origin = geodeticToVector3(tokyoLle);const matrix = eastNorthUpToFixedFrame(origin);
// オブジェクトに適用mesh.matrix.copy(matrix);mesh.matrixAutoUpdate = false;northEastDownToFixedFrame(origin)
Section titled “northEastDownToFixedFrame(origin)”North-East-Down 座標系から固定フレームへの変換行列を取得します。
Syntax:
function northEastDownToFixedFrame(origin: Vector3): Matrix4;Parameters:
origin: 原点の ECEF 座標(Three.js Vector3)
Returns:
4x4 変換行列(Three.js Matrix4)
northUpEastToFixedFrame(origin)
Section titled “northUpEastToFixedFrame(origin)”North-Up-East 座標系から固定フレームへの変換行列を取得します。
Syntax:
function northUpEastToFixedFrame(origin: Vector3): Matrix4;Parameters:
origin: 原点の ECEF 座標(Three.js Vector3)
Returns:
4x4 変換行列(Three.js Matrix4)
northWestUpToFixedFrame(origin)
Section titled “northWestUpToFixedFrame(origin)”North-West-Up 座標系から固定フレームへの変換行列を取得します。
Syntax:
function northWestUpToFixedFrame(origin: Vector3): Matrix4;Parameters:
origin: 原点の ECEF 座標(Three.js Vector3)
Returns:
4x4 変換行列(Three.js Matrix4)
westUpNorthToFixedFrame(origin)
Section titled “westUpNorthToFixedFrame(origin)”West-Up-North 座標系から固定フレームへの変換行列を取得します。
WUN は +Z 軸が北を指す唯一の右手系 Y-up 接線フレームであり、glTF 自身の規約(前方 +Z、上方 +Y、右方 -X)と3軸すべてで一致します。加工されていない glTF アセットをこのフレームに配置する場合、Rx(+90°) の軸補正は不要です。その補正は、オブジェクトごとに適用するのではなく、ここで一度だけフレームの定義自体に吸収されています。軸の向きの規約 を参照してください。
Syntax:
function westUpNorthToFixedFrame(origin: Vector3): Matrix4;Parameters:
origin: 原点の ECEF 座標(Three.js Vector3)
Returns:
WUN から ECEF への 4x4 変換行列(Three.js Matrix4)
Example:
import { westUpNorthToFixedFrame, geodeticToVector3,} from "@navaramap/three-api";
const origin = geodeticToVector3({ lat: 35.681236, lng: 139.767125, height: 0,});const matrix = westUpNorthToFixedFrame(origin);headingPitchRollToFixedFrame(placement)
Section titled “headingPitchRollToFixedFrame(placement)”地理的な位置に WUN 接線フレームを構築し、そこに heading・pitch・roll・scale を合成します。地理的な配置をワールド行列に変換する単一の呼び出しです。
lng/lat とここでのすべての角度は度単位です。これは geodeticToVector3(lle) や setCamera、geodetic メッシュ Descriptor フィールドと同じ規約です。
Syntax:
function headingPitchRollToFixedFrame( placement: Omit<GeodeticPlacement, "heightReference">): Matrix4;Parameters:
placement: 度とメートルで指定する地理的配置lng: 経度(度、必須)lat: 緯度(度、必須)height: 楕円体からの高さ(メートル、デフォルト0)heading: アセットの前方(glTF の+Z)が向く、北からの時計回りの角度(度、デフォルト0)pitch: ノーズアップを正とする角度(度、デフォルト0)roll: 右翼下げを正とする角度(度、デフォルト0)scale: フレームの一様または軸ごとのスケール(デフォルト1)
heightReference は、この型では意図的に受け付けていません。地形相対の高さの解決には view からのサンプリングが必要なため、これはメッシュ Descriptor の geodetic フィールドの役割です。
Returns:
配置されたローカルフレームから ECEF への 4x4 変換行列(Three.js Matrix4)
Example:
import { headingPitchRollToFixedFrame } from "@navaramap/three-api";
const matrix = headingPitchRollToFixedFrame({ lng: 138.036142, lat: 36.085621, height: 1, heading: 321,});heading はアセットの前方が向くコンパス方位で、前方とは glTF 自身の +Z です(setCamera と同じ規約です)。他の地球エンジンではアセットの前方として扱う軸が異なるため、他エンジンから移植したモデルでは heading に 90° の倍数を加える必要がある場合があります。
RTE (Relative to Eye) Rendering
Section titled “RTE (Relative to Eye) Rendering”大規模な座標系で高精度レンダリングを実現するための RTE レンダリング機能です。
encodePositionRTE(original, resultHigh?, resultLow?)
Section titled “encodePositionRTE(original, resultHigh?, resultLow?)”位置を RTE レンダリング用の高精度・低精度 Vector3 コンポーネントにエンコードします。位置を2つの float コンポーネントに分割することで、GPU 倍精度エミュレーションを実現します。
Syntax:
function encodePositionRTE( original: Vector3, resultHigh?: Vector3, resultLow?: Vector3,): { high: Vector3; low: Vector3 }Parameters:
original: エンコードする位置resultHigh: 高精度コンポーネントを格納するオプションの Vector3(GC 回避のため再利用可能)resultLow: 低精度コンポーネントを格納するオプションの Vector3(GC 回避のため再利用可能)
Returns:
high と low の Vector3 コンポーネントを持つオブジェクト
Example:
import { encodePositionRTE } from "@navaramap/three-api";import { Vector3 } from "three";
const position = new Vector3(6378137, 0, 0);const { high, low } = encodePositionRTE(position);// high + low ≈ 元の位置(GPU 精度が向上)calcModelMatrixRTE(objectMatrixWorld, matrixWorldInverse, result?)
Section titled “calcModelMatrixRTE(objectMatrixWorld, matrixWorldInverse, result?)”RTE レンダリング用のモデル行列を計算します。平行移動成分をゼロにした行列を返します。
Syntax:
function calcModelMatrixRTE( objectMatrixWorld: Matrix4, matrixWorldInverse: Matrix4, result?: Matrix4): Matrix4;Parameters:
objectMatrixWorld: オブジェクトのワールド行列(Three.js Matrix4)matrixWorldInverse: カメラのワールド逆行列(Three.js Matrix4)result: 結果を格納する行列(省略時は新規作成)
Returns:
RTE 用のモデル行列(Three.js Matrix4)
Example:
import { calcModelMatrixRTE } from "@navaramap/three-api";import { Matrix4 } from "three";
const rteMatrix = calcModelMatrixRTE( mesh.matrixWorld, camera.matrixWorldInverse);
// シェーダーで使用material.uniforms.modelMatrix.value = rteMatrix;calcCameraPosition(cameraPosition, modelMatrixWorld)
Section titled “calcCameraPosition(cameraPosition, modelMatrixWorld)”RTE レンダリング用のカメラ位置をエンコードします。高精度な位置情報を high と low の 2 つの Vector3 に分割します。
Syntax:
function calcCameraPosition( cameraPosition: Vector3, modelMatrixWorld: Matrix4): { high: Vector3; low: Vector3;};Parameters:
cameraPosition: カメラの位置(Three.js Vector3)modelMatrixWorld: モデルのワールド行列(Three.js Matrix4)
Returns:
エンコードされたカメラ位置:
high: 上位ビット(高精度成分)low: 下位ビット(低精度成分)
type EncodedPosition = { high: Vector3; low: Vector3;};Example:
import { calcCameraPosition } from "@navaramap/three-api";
const encodedCameraPos = calcCameraPosition(camera.position, mesh.matrixWorld);
// シェーダーで使用material.uniforms.cameraPositionHigh.value = encodedCameraPos.high;material.uniforms.cameraPositionLow.value = encodedCameraPos.low;composeWorldMatrixForRTE(frameMatrix, localMatrix)
Section titled “composeWorldMatrixForRTE(frameMatrix, localMatrix)”フレーム行列とローカル変換を合成し、結果を RTE レンダリング用の平行移動 Vector3 と回転・スケールのみの Matrix4 に分割します。平行移動は GPU 精度のために high/low の RTE uniform としてエンコードされ、回転・スケール行列はメッシュの matrixWorld に設定されてシェーダーの modelMatrix uniform となります。
Syntax:
function composeWorldMatrixForRTE( frameMatrix: Matrix4, localMatrix: Matrix4, resultPosition?: Vector3, resultRotationScale?: Matrix4): { position: Vector3; rotationScale: Matrix4;};Parameters:
frameMatrix: フレーム変換行列(例: NUE-to-ECEF)(Three.js Matrix4)localMatrix: フレーム内で合成するローカル T*R*S 変換(Three.js Matrix4)resultPosition(省略可): 抽出された平行移動を格納する Vector3(GC 回避のため再利用可能)resultRotationScale(省略可): 平行移動をゼロにした行列を格納する Matrix4(GC 回避のため再利用可能)
Returns:
RTE レンダリング用に分解された結果:
position: 合成行列から抽出されたワールド位置rotationScale: 平行移動がゼロにされた合成行列
type ComposeWorldMatrixForRTEResult = { position: Vector3; rotationScale: Matrix4;};Example:
import { composeWorldMatrixForRTE, encodePositionRTE } from "@navaramap/three-api";
// NUE-to-ECEF フレームとローカルオフセットを合成し、RTE 用に分割const { position, rotationScale } = composeWorldMatrixForRTE( nueToEcefMatrix, localTransformMatrix,);
// ワールド位置を high/low uniform としてエンコードconst posHigh = new Vector3();const posLow = new Vector3();encodePositionRTE(position, posHigh, posLow);
// 回転・スケールをメッシュに適用(平行移動は RTE uniform で処理)mesh.matrixAutoUpdate = false;mesh.matrixWorldAutoUpdate = false;mesh.matrixWorld.copy(rotationScale);EllipsoidGeodesic
Section titled “EllipsoidGeodesic”楕円体表面上の測地線計算を行うクラスです。2 点間の測地線距離、方位角、補間点の計算などを提供します。インスタンス生成時に共通変数を事前計算することで、最適化されたパフォーマンスを実現します。
constructor(start, end)
Section titled “constructor(start, end)”楕円体上の 2 点間の測地線を作成します。
Syntax:
constructor(start: LatLngHeight, end: LatLngHeight)Parameters:
start: 開始点の測地座標(緯度経度は度単位)end: 終了点の測地座標(緯度経度は度単位)
Example:
import { EllipsoidGeodesic } from "@navaramap/three-api";
const start = { lat: 35.6762, // 東京 lng: 139.6503, height: 0,};const end = { lat: 34.6937, // 大阪 lng: 135.5023, height: 0,};
const geodesic = new EllipsoidGeodesic(start, end);distance
Section titled “distance”開始点と終了点間の測地線距離(メートル)を取得します。
Syntax:
get distance(): numberReturns:
測地線距離(メートル)
Example:
const geodesic = new EllipsoidGeodesic(start, end);console.log(`距離: ${geodesic.distance} m`); // 距離: 401747.8... mconverged
Section titled “converged”測地線計算が収束したかどうかを取得します。開始点と終了点がほぼ対蹠点(地球の反対側)にある場合は最短経路を確実に求められないため false を返します。この場合 distance はおおよその推定値であり、補間メソッドは信頼できない経路をたどる代わりに端点にスナップします。
Syntax:
get converged(): booleanReturns:
計算が収束した場合は true、ほぼ対蹠点の場合は false
Example:
const geodesic = new EllipsoidGeodesic(start, end);
if (!geodesic.converged) { console.warn("ほぼ対蹠点のため距離は概算値です");}startHeading
Section titled “startHeading”開始点での方位角(度)を取得します。
Syntax:
get startHeading(): numberReturns:
開始点での方位角(度)
Example:
const geodesic = new EllipsoidGeodesic(start, end);console.log(`開始点方位角: ${geodesic.startHeading}°`);endHeading
Section titled “endHeading”終了点での方位角(度)を取得します。
Syntax:
get endHeading(): numberReturns:
終了点での方位角(度)
開始点の測地座標を取得します。
Syntax:
get start(): LatLngHeightReturns:
開始点の測地座標
終了点の測地座標を取得します。
Syntax:
get end(): LatLngHeightReturns:
終了点の測地座標
interpolatePoints(granularity?)
Section titled “interpolatePoints(granularity?)”測地線パスに沿って補間点を生成します。
Syntax:
interpolatePoints(granularity?: number): LatLngHeight[]Parameters:
granularity: 補間点間の距離(メートル)。省略時は WASM 側のデフォルト値が使用されます(測地線を適切に表現する粒度)
Returns:
補間された測地座標の配列。converged が false の場合は開始点と終了点のみを返します
Example:
const geodesic = new EllipsoidGeodesic(start, end);
// 1000m間隔で補間点を生成const points = geodesic.interpolatePoints(1000);console.log(`補間点数: ${points.length}`);
points.forEach((point, index) => { console.log(`点${index}: 緯度=${point.lat}°, 経度=${point.lng}°`);});interpolateDistance(distance)
Section titled “interpolateDistance(distance)”測地線パス上の指定距離の位置にある点を取得します。
Syntax:
interpolateDistance(distance: number): LatLngHeightParameters:
distance: 開始点からの距離(メートル)
Returns:
指定距離の位置の測地座標。converged が false の場合は近い方の端点を返します
Example:
const geodesic = new EllipsoidGeodesic(start, end);
// 中間点を取得const midpoint = geodesic.interpolateDistance(geodesic.distance / 2);console.log(`中間点: 緯度=${midpoint.lat}°, 経度=${midpoint.lng}°`);dispose()
Section titled “dispose()”WASM メモリを解放します。測地線オブジェクトが不要になったら呼び出してください。
Syntax:
dispose(): voidExample:
const geodesic = new EllipsoidGeodesic(start, end);
// 測地線計算を実行const distance = geodesic.distance;const points = geodesic.interpolatePoints(1000);
// 使用完了後にメモリを解放geodesic.dispose();完全な使用例
Section titled “完全な使用例”import { initNavaraApi, EllipsoidGeodesic, geodeticToVector3,} from "@navaramap/three-api";
await initNavaraApi();
// 東京から大阪への測地線を作成const tokyo = { lat: 35.6762, lng: 139.6503, height: 0,};const osaka = { lat: 34.6937, lng: 135.5023, height: 0,};
const geodesic = new EllipsoidGeodesic(tokyo, osaka);
// 距離と方位角を表示console.log(`距離: ${(geodesic.distance / 1000).toFixed(2)} km`);console.log(`開始方位角: ${geodesic.startHeading.toFixed(2)}°`);console.log(`終了方位角: ${geodesic.endHeading.toFixed(2)}°`);
// 10km間隔で補間点を生成し、3D座標に変換const points = geodesic.interpolatePoints(10000);const positions = points.map((point) => geodeticToVector3(point));
// Three.js でラインを描画const lineGeometry = new BufferGeometry().setFromPoints(positions);const lineMaterial = new LineBasicMaterial({ color: "#ff0000" });const line = new Line(lineGeometry, lineMaterial);scene.add(line);
// メモリを解放geodesic.dispose();LatLngHeight
Section titled “LatLngHeight”測地座標を表すインターフェースです。
interface LatLngHeight { lat: number; // 緯度(度) lng: number; // 経度(度) height: number; // 高度(メートル)}LatLng
Section titled “LatLng”緯度経度を表すインターフェースです。
interface LatLng { lat: number; // 緯度(度) lng: number; // 経度(度)}WindowObject
Section titled “WindowObject”ウィンドウ情報を表すインターフェースです。スクリーン座標変換関数に渡します。
interface WindowObject { width: number; // ウィンドウの幅(ピクセル) height: number; // ウィンドウの高さ(ピクセル) pixelRatio: number; // デバイスピクセル比}Usage Examples
Section titled “Usage Examples”@navaramap/three から API を使用する場合
Section titled “@navaramap/three から API を使用する場合”@navaramap/three を使用する場合は、@navaramap/three-api の API が @navaramap/three から再エクスポートされているため、そちらから直接 import することができます。
@navaramap/three から API を使用して、地球上でモデルを動的に移動させる例です:
import ThreeView, { geodeticToVector3, geodeticSurfaceNormal,} from "@navaramap/three";import { GLTFModelDesc } from "@navaramap/three-default-descs";import { Vector3, Quaternion, Euler, Matrix4 } from "three";
const view = new ThreeView({ container });
view.registerMesh("gltfModel", GLTFModelDesc);await view.init();
view.setCamera({ lng: 139.6503, lat: 35.6762, height: 1000,});
// 大阪の初期位置let longitude = 135.5023;const latitude = 34.6937;const altitude = 0;
// GLTFモデルを追加const modelDesc = view.addMesh<GLTFModelDesc>({ gltfModel: { url: "/path/to/model.glb" }, position: geodeticToVector3({ lat: latitude, lng: longitude, height: altitude, }),});
// アニメーションループ - 地球の周りをモデルを移動const animate = () => { // 経度を更新(地球の周りを移動) longitude += 0.01;
// 新しい位置を計算 const pos = geodeticToVector3({ lat: latitude, lng: longitude, height: altitude, });
// 地表面の法線を計算 const normal = geodeticSurfaceNormal({ lat: latitude, lng: longitude, height: altitude, });
// 移動方向を計算 const nextLongitude = longitude + 0.01; const nextPos = geodeticToVector3({ lat: latitude, lng: nextLongitude, height: altitude, }); const direction = new Vector3().subVectors(nextPos, pos).normalize();
// 回転を計算(法線を上方向として移動方向に向ける) const right = new Vector3().crossVectors(direction, normal).normalize(); const up = new Vector3().crossVectors(right, direction).normalize();
const rotationMatrix = new Matrix4(); rotationMatrix.makeBasis(right, up, direction.clone().negate());
const quaternion = new Quaternion(); quaternion.setFromRotationMatrix(rotationMatrix); const euler = new Euler().setFromQuaternion(quaternion);
// モデルの位置と回転を更新 modelDesc.update({ position: { x: pos.x, y: pos.y, z: pos.z }, rotation: { x: euler.x, y: euler.y, z: euler.z }, });
requestAnimationFrame(animate);};
animate();基本的な座標変換
Section titled “基本的な座標変換”import { initNavaraApi, geodeticToVector3, vector3ToGeodetic,} from "@navaramap/three-api";
// 初期化await initNavaraApi();
const tokyoLle = { lat: 35.6762, lng: 139.6503, height: 100,};
// 測地座標をECEF座標に変換const ecefPos = geodeticToVector3(tokyoLle);console.log(`ECEF座標: [${ecefPos.x}, ${ecefPos.y}, ${ecefPos.z}]`);
// ECEF座標を測地座標に戻すconst convertedLle = vector3ToGeodetic(ecefPos);console.log(`緯度: ${convertedLle.lat}°`);console.log(`経度: ${convertedLle.lng}°`);console.log(`高度: ${convertedLle.height} m`);スクリーンピッキング
Section titled “スクリーンピッキング”import { getPickRay, getPlaneFromPointNormal, getRayPlaneIntersection, getHeightFromEllipsoid,} from "@navaramap/three-api";import { Vector2, Vector3 } from "three";
// マウスクリックイベントハンドラcanvas.addEventListener("click", (event) => { const windowObject = { width: canvas.clientWidth, height: canvas.clientHeight, pixelRatio: window.devicePixelRatio };
// マウス位置 const screenPos = new Vector2(event.clientX, event.clientY);
// ピッキングレイを生成 const ray = getPickRay(windowObject, camera, screenPos);
// 地面平面(Z=0)を定義 const groundPlane = getPlaneFromPointNormal( new Vector3(0, 0, 0), new Vector3(0, 0, 1) );
// 交点を計算 const intersection = getRayPlaneIntersection(ray, groundPlane);
if (intersection) { console.log("クリックした地面の位置:", intersection);
// 交点の高度を確認 const height = getHeightFromEllipsoid(intersection); console.log("楕円体からの高度:", height); }});ローカル座標系の設定
Section titled “ローカル座標系の設定”import { geodeticToVector3, eastNorthUpToFixedFrame,} from "@navaramap/three-api";import { Mesh, BoxGeometry, MeshBasicMaterial } from "three";
// 東京の位置const tokyoLle = { lat: 35.6762, lng: 139.6503, height: 0,};
// ECEF座標を取得const origin = geodeticToVector3(tokyoLle);
// East-North-Up座標系の変換行列を取得const enuMatrix = eastNorthUpToFixedFrame(origin);
// メッシュを作成して配置const geometry = new BoxGeometry(100, 100, 100);const material = new MeshBasicMaterial({ color: "#ff0000" });const mesh = new Mesh(geometry, material);
// ENU座標系の変換行列を適用mesh.matrix.copy(enuMatrix);mesh.matrixAutoUpdate = false;
scene.add(mesh);スクリーン座標と世界座標の相互変換
Section titled “スクリーン座標と世界座標の相互変換”import { convertScreenToWorld, convertWorldToScreen, geodeticToVector3,} from "@navaramap/three-api";import { Vector2 } from "three";
const windowObject = { width: canvas.clientWidth, height: canvas.clientHeight, pixelRatio: window.devicePixelRatio};
// 世界座標をスクリーン座標に変換const worldPos = geodeticToVector3({ lat: 35.6762, lng: 139.6503, height: 100,});
const screenPos = convertWorldToScreen(windowObject, camera, worldPos);if (screenPos) { console.log(`スクリーン座標: [${screenPos.x}, ${screenPos.y}]`);
// HTMLエレメントを配置 const label = document.getElementById("label"); label.style.left = `${screenPos.x}px`; label.style.top = `${screenPos.y}px`;}
// スクリーン座標を世界座標に変換const mousePos = new Vector2(event.clientX, event.clientY);const pickedWorldPos = convertScreenToWorld(windowObject, camera, mousePos);if (pickedWorldPos) { console.log( `世界座標: [${pickedWorldPos.x}, ${pickedWorldPos.y}, ${pickedWorldPos.z}]` );}