Skip to content

navara_three_api

navara_three_api is an API that provides utility functions for integrating Three.js with the Navara engine. It offers features necessary for 3D geospatial application development, including geospatial calculations, coordinate transformations, intersection tests, and RTE (Relative to Eye) rendering, all integrated with the Three.js type system.

Initializes the Navara API. You must call this function before using any other API functions.

Syntax:

async function initNavaraApi(): Promise<void>;

Returns:

A Promise that resolves when initialization is complete

Example:

import { initNavaraApi } from "@navaramap/three_api";
// Initialize at application startup
await initNavaraApi();

Functions for retrieving basic parameters of the WGS84 ellipsoid.

Gets the semi-major axis of the WGS84 ellipsoid.

Syntax:

function getWGS84SemiMajorAxis(): number;

Returns:

The semi-major axis of the WGS84 ellipsoid (meters)

Example:

const semiMajorAxis = getWGS84SemiMajorAxis();
console.log(`Semi-major axis: ${semiMajorAxis} m`); // Semi-major axis: 6378137 m

Gets the semi-minor axis of the WGS84 ellipsoid.

Syntax:

function getWGS84SemiMinorAxis(): number;

Returns:

The semi-minor axis of the WGS84 ellipsoid (meters)

Example:

const semiMinorAxis = getWGS84SemiMinorAxis();
console.log(`Semi-minor axis: ${semiMinorAxis} m`); // Semi-minor axis: 6356752.314245 m

Gets the eccentricity squared of the WGS84 ellipsoid.

Syntax:

function getWGS84EccentricitySquared(): number;

Returns:

The eccentricity squared of the WGS84 ellipsoid

Gets the flattening of the WGS84 ellipsoid.

Syntax:

function getWGS84Flattening(): number;

Returns:

The flattening of the WGS84 ellipsoid

Gets the eccentricity of the WGS84 ellipsoid.

Syntax:

function getWGS84Eccentricity(): number;

Returns:

The eccentricity of the WGS84 ellipsoid

Functions for transforming between coordinate systems. Integrated with the Three.js Vector3 type.

Converts geodetic coordinates (latitude, longitude, height) to a Three.js Vector3 (ECEF coordinate system).

Syntax:

function geodeticToVector3(lle: LatLngHeight): Vector3;

Parameters:

  • lle: The geodetic coordinates to convert
    • lat: Latitude (radians)
    • lng: Longitude (radians)
    • height: Height (meters)

Returns:

Position in the ECEF coordinate system (Three.js Vector3)

Example:

import { geodeticToVector3, degreeToRadian } from "@navaramap/three_api";
const lle = {
lat: degreeToRadian(35.6762), // Latitude of Tokyo
lng: degreeToRadian(139.6503), // Longitude of Tokyo
height: 100,
};
const position = geodeticToVector3(lle);
console.log(`Position: [${position.x}, ${position.y}, ${position.z}]`);

Converts a Three.js Vector3 (ECEF coordinate system) to geodetic coordinates (latitude, longitude, height).

Syntax:

function vector3ToGeodetic(xyz: Vector3): LatLngHeight;

Parameters:

  • xyz: The ECEF coordinates to convert (Three.js Vector3)

Returns:

Geodetic coordinates:

  • lat: Latitude (radians)
  • lng: Longitude (radians)
  • height: Height (meters)

Example:

import { vector3ToGeodetic, radianToDegree } from "@navaramap/three_api";
import { Vector3 } from "three";
const position = new Vector3(-3946416, 3364068, 3702654);
const lle = vector3ToGeodetic(position);
console.log(`Latitude: ${radianToDegree(lle.lat)}°`);
console.log(`Longitude: ${radianToDegree(lle.lng)}°`);
console.log(`Height: ${lle.height} m`);

Converts an angle from degrees to radians.

Syntax:

function degreeToRadian(degree: number): number;

Parameters:

  • degree: Angle in degrees

Returns:

Angle in radians

Example:

const radians = degreeToRadian(90);
console.log(`90 degrees = ${radians} radians`); // 90 degrees = 1.5708 radians

Converts an angle from radians to degrees.

Syntax:

function radianToDegree(radian: number): number;

Parameters:

  • radian: Angle in radians

Returns:

Angle in degrees

Example:

const degrees = radianToDegree(Math.PI);
console.log(`π radians = ${degrees} degrees`); // π radians = 180 degrees

Functions for transforming between screen coordinates and world coordinates. Integrated with the Three.js PerspectiveCamera.

convertScreenToWorld(window, camera, vec2)

Section titled “convertScreenToWorld(window, camera, vec2)”

Converts screen coordinates to world coordinates.

Syntax:

function convertScreenToWorld(
windowObject: WindowObject,
camera: PerspectiveCamera,
vec2: Vector2
): Vector3 | undefined;

Parameters:

  • windowObject: Window information
    • width: Window width
    • height: Window height
    • pixelRatio: Device pixel ratio
  • camera: Three.js PerspectiveCamera
  • vec2: Screen coordinates (Three.js Vector2)

Returns:

Position in world coordinates, or undefined if no intersection

Example:

import { convertScreenToWorld } from "@navaramap/three_api";
import { Vector2 } from "three";
// Create window information object
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(`World coordinates: [${worldPos.x}, ${worldPos.y}, ${worldPos.z}]`);
}

convertWorldToScreen(window, camera, worldPos)

Section titled “convertWorldToScreen(window, camera, worldPos)”

Converts world coordinates to screen coordinates.

Syntax:

function convertWorldToScreen(
windowObject: WindowObject,
camera: PerspectiveCamera,
worldPos: Vector3
): Vector2 | undefined;

Parameters:

  • windowObject: Window information
  • camera: Three.js PerspectiveCamera
  • worldPos: Position in world coordinates (Three.js Vector3)

Returns:

Screen coordinates, or undefined if outside the field of view

Example:

import { convertWorldToScreen, geodeticToVector3 } from "@navaramap/three_api";
const lle = { lat: 0.622, lng: 2.435, height: 100 };
const worldPos = geodeticToVector3(lle);
const screenPos = convertWorldToScreen(window, camera, worldPos);
if (screenPos) {
console.log(`Screen coordinates: [${screenPos.x}, ${screenPos.y}]`);
}

Functions for intersection tests and ray casting.

Creates a plane from a point and a normal vector.

Syntax:

function getPlaneFromPointNormal(point: Vector3, normal: Vector3): Plane;

Parameters:

  • point: A point on the plane (Three.js Vector3)
  • normal: The plane’s normal vector (Three.js Vector3)

Returns:

The created plane

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-axis direction
const plane = getPlaneFromPointNormal(point, normal);

Generates a picking ray from screen coordinates.

Syntax:

function getPickRay(
windowObject: WindowObject,
camera: PerspectiveCamera,
vec2: Vector2
): Ray;

Parameters:

  • windowObject: Window information
  • camera: Three.js PerspectiveCamera
  • vec2: Screen coordinates (Three.js Vector2)

Returns:

The generated ray

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);

Calculates the intersection point of a ray and a plane.

Syntax:

function getRayPlaneIntersection(ray: Ray, plane: Plane): Vector3 | undefined;

Parameters:

  • ray: The ray for intersection testing
  • plane: The plane for intersection testing

Returns:

The intersection point coordinates (Three.js Vector3), or undefined if no intersection

Example:

import {
getPickRay,
getPlaneFromPointNormal,
getRayPlaneIntersection,
} from "@navaramap/three_api";
import { Vector2, Vector3 } from "three";
// Generate a ray from the mouse position
const screenPos = new Vector2(event.clientX, event.clientY);
const ray = getPickRay(window, camera, screenPos);
// Define the ground plane
const groundPlane = getPlaneFromPointNormal(
new Vector3(0, 0, 0),
new Vector3(0, 0, 1)
);
// Calculate the intersection
const intersection = getRayPlaneIntersection(ray, groundPlane);
if (intersection) {
console.log(
`Click position: [${intersection.x}, ${intersection.y}, ${intersection.z}]`
);
}

Gets the height above the ellipsoid for a given point.

Syntax:

function getHeightFromEllipsoid(point: Vector3): number;

Parameters:

  • point: ECEF coordinates of the point to calculate height for (Three.js Vector3)

Returns:

Height above the ellipsoid (meters)

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: ${height} m`);

Functions for calculating surface normal vectors and reference frames.

Calculates the geodetic surface normal vector.

Syntax:

function geodeticSurfaceNormal(lle: LatLngHeight): Vector3;

Parameters:

  • lle: Geodetic coordinates

Returns:

Normalized surface normal vector (Three.js Vector3)

Example:

import { geodeticSurfaceNormal, degreeToRadian } from "@navaramap/three_api";
const lle = {
lat: degreeToRadian(35.6762),
lng: degreeToRadian(139.6503),
height: 0,
};
const normal = geodeticSurfaceNormal(lle);
console.log(`Normal vector: [${normal.x}, ${normal.y}, ${normal.z}]`);

Gets the transformation matrix from the East-North-Up coordinate system to the fixed frame.

Syntax:

function eastNorthUpToFixedFrame(origin: Vector3): Matrix4;

Parameters:

  • origin: Origin ECEF coordinates (Three.js Vector3)

Returns:

4x4 transformation matrix (Three.js Matrix4)

Example:

import {
eastNorthUpToFixedFrame,
geodeticToVector3,
degreeToRadian,
} from "@navaramap/three_api";
const tokyoLle = {
lat: degreeToRadian(35.6762),
lng: degreeToRadian(139.6503),
height: 0,
};
const origin = geodeticToVector3(tokyoLle);
const matrix = eastNorthUpToFixedFrame(origin);
// Apply to an object
mesh.matrix.copy(matrix);
mesh.matrixAutoUpdate = false;

Gets the transformation matrix from the North-East-Down coordinate system to the fixed frame.

Syntax:

function northEastDownToFixedFrame(origin: Vector3): Matrix4;

Parameters:

  • origin: Origin ECEF coordinates (Three.js Vector3)

Returns:

4x4 transformation matrix (Three.js Matrix4)

Gets the transformation matrix from the North-Up-East coordinate system to the fixed frame.

Syntax:

function northUpEastToFixedFrame(origin: Vector3): Matrix4;

Parameters:

  • origin: Origin ECEF coordinates (Three.js Vector3)

Returns:

4x4 transformation matrix (Three.js Matrix4)

Gets the transformation matrix from the North-West-Up coordinate system to the fixed frame.

Syntax:

function northWestUpToFixedFrame(origin: Vector3): Matrix4;

Parameters:

  • origin: Origin ECEF coordinates (Three.js Vector3)

Returns:

4x4 transformation matrix (Three.js Matrix4)

RTE rendering functionality for achieving high-precision rendering in large-scale coordinate systems.

encodePositionRTE(original, resultHigh?, resultLow?)

Section titled “encodePositionRTE(original, resultHigh?, resultLow?)”

Encodes a position into high and low precision Vector3 components for RTE rendering. This enables GPU double precision emulation by splitting a position into two float components.

Syntax:

function encodePositionRTE(
original: Vector3,
resultHigh?: Vector3,
resultLow?: Vector3,
): { high: Vector3; low: Vector3 }

Parameters:

  • original: Position to encode
  • resultHigh: Optional Vector3 to store the high precision component (reused to avoid GC)
  • resultLow: Optional Vector3 to store the low precision component (reused to avoid GC)

Returns:

Object with high and low Vector3 components

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 ≈ original position with improved GPU precision

calcModelMatrixRTE(objectMatrixWorld, matrixWorldInverse, result?)

Section titled “calcModelMatrixRTE(objectMatrixWorld, matrixWorldInverse, result?)”

Calculates the model matrix for RTE rendering. Returns a matrix with the translation component zeroed out.

Syntax:

function calcModelMatrixRTE(
objectMatrixWorld: Matrix4,
matrixWorldInverse: Matrix4,
result?: Matrix4
): Matrix4;

Parameters:

  • objectMatrixWorld: Object’s world matrix (Three.js Matrix4)
  • matrixWorldInverse: Camera’s world inverse matrix (Three.js Matrix4)
  • result: Matrix to store the result (creates a new one if omitted)

Returns:

Model matrix for RTE (Three.js Matrix4)

Example:

import { calcModelMatrixRTE } from "@navaramap/three_api";
import { Matrix4 } from "three";
const rteMatrix = calcModelMatrixRTE(
mesh.matrixWorld,
camera.matrixWorldInverse
);
// Use in shader
material.uniforms.modelMatrix.value = rteMatrix;

calcCameraPosition(cameraPosition, modelMatrixWorld)

Section titled “calcCameraPosition(cameraPosition, modelMatrixWorld)”

Encodes the camera position for RTE rendering. Splits high-precision position information into two Vector3 values: high and low.

Syntax:

function calcCameraPosition(
cameraPosition: Vector3,
modelMatrixWorld: Matrix4
): {
high: Vector3;
low: Vector3;
};

Parameters:

  • cameraPosition: Camera position (Three.js Vector3)
  • modelMatrixWorld: Model’s world matrix (Three.js Matrix4)

Returns:

Encoded camera position:

  • high: High bits (high-precision component)
  • low: Low bits (low-precision component)
type EncodedPosition = {
high: Vector3;
low: Vector3;
};

Example:

import { calcCameraPosition } from "@navaramap/three_api";
const encodedCameraPos = calcCameraPosition(camera.position, mesh.matrixWorld);
// Use in shader
material.uniforms.cameraPositionHigh.value = encodedCameraPos.high;
material.uniforms.cameraPositionLow.value = encodedCameraPos.low;

composeWorldMatrixForRTE(frameMatrix, localMatrix)

Section titled “composeWorldMatrixForRTE(frameMatrix, localMatrix)”

Composes a frame matrix with a local transform, then splits the result into a translation Vector3 and a rotation/scale-only Matrix4 for RTE rendering. The translation is intended to be encoded as high/low RTE uniforms for GPU precision, while the rotation/scale matrix is assigned to the mesh’s matrixWorld so it becomes the shader’s modelMatrix uniform.

Syntax:

function composeWorldMatrixForRTE(
frameMatrix: Matrix4,
localMatrix: Matrix4,
resultPosition?: Vector3,
resultRotationScale?: Matrix4
): {
position: Vector3;
rotationScale: Matrix4;
};

Parameters:

  • frameMatrix: The frame transformation matrix (e.g. NUE-to-ECEF) (Three.js Matrix4)
  • localMatrix: The local T*R*S transform to compose within the frame (Three.js Matrix4)
  • resultPosition (optional): Vector3 to store the extracted translation (reused to avoid GC)
  • resultRotationScale (optional): Matrix4 to store the translation-zeroed matrix (reused to avoid GC)

Returns:

The decomposed result for RTE rendering:

  • position: World position extracted from the composed matrix
  • rotationScale: The composed matrix with translation zeroed out
type ComposeWorldMatrixForRTEResult = {
position: Vector3;
rotationScale: Matrix4;
};

Example:

import { composeWorldMatrixForRTE, encodePositionRTE } from "@navaramap/three_api";
// Compose an NUE-to-ECEF frame with a local offset, then split for RTE
const { position, rotationScale } = composeWorldMatrixForRTE(
nueToEcefMatrix,
localTransformMatrix,
);
// Encode the world position as high/low uniforms
const posHigh = new Vector3();
const posLow = new Vector3();
encodePositionRTE(position, posHigh, posLow);
// Apply rotation/scale to the mesh (translation is handled by RTE uniforms)
mesh.matrixAutoUpdate = false;
mesh.matrixWorldAutoUpdate = false;
mesh.matrixWorld.copy(rotationScale);

A class for geodesic calculations on the ellipsoid surface. Provides geodesic distance, azimuth, and interpolation point calculations between two points. Achieves optimized performance by pre-computing common variables when the instance is created.

Creates a geodesic between two points on the ellipsoid.

Syntax:

constructor(start: LatLngHeight, end: LatLngHeight)

Parameters:

  • start: Geodetic coordinates of the start point (latitude and longitude in radians)
  • end: Geodetic coordinates of the end point (latitude and longitude in radians)

Example:

import { EllipsoidGeodesic, degreeToRadian } from "@navaramap/three_api";
const start = {
lat: degreeToRadian(35.6762), // Tokyo
lng: degreeToRadian(139.6503),
height: 0,
};
const end = {
lat: degreeToRadian(34.6937), // Osaka
lng: degreeToRadian(135.5023),
height: 0,
};
const geodesic = new EllipsoidGeodesic(start, end);

Gets the geodesic distance between the start and end points (meters).

Syntax:

get distance(): number

Returns:

Geodesic distance (meters)

Example:

const geodesic = new EllipsoidGeodesic(start, end);
console.log(`Distance: ${geodesic.distance} m`); // Distance: 401747.8... m

Gets the azimuth at the start point (radians).

Syntax:

get startHeading(): number

Returns:

Azimuth at the start point (radians)

Example:

import { radianToDegree } from "@navaramap/three_api";
const geodesic = new EllipsoidGeodesic(start, end);
console.log(`Start heading: ${radianToDegree(geodesic.startHeading)}°`);

Gets the azimuth at the end point (radians).

Syntax:

get endHeading(): number

Returns:

Azimuth at the end point (radians)

Gets the geodetic coordinates of the start point.

Syntax:

get start(): LatLngHeight

Returns:

Geodetic coordinates of the start point

Gets the geodetic coordinates of the end point.

Syntax:

get end(): LatLngHeight

Returns:

Geodetic coordinates of the end point

Generates interpolation points along the geodesic path.

Syntax:

interpolatePoints(granularity?: number): LatLngHeight[]

Parameters:

  • granularity: Distance between interpolation points (meters). When omitted, the WASM-side default value is used (a granularity that adequately represents the geodesic)

Returns:

An array of interpolated geodetic coordinates

Example:

const geodesic = new EllipsoidGeodesic(start, end);
// Generate interpolation points at 1000m intervals
const points = geodesic.interpolatePoints(1000);
console.log(`Number of interpolation points: ${points.length}`);
points.forEach((point, index) => {
console.log(`Point ${index}: lat=${radianToDegree(point.lat)}°, lng=${radianToDegree(point.lng)}°`);
});

Gets the point at a specified distance along the geodesic path.

Syntax:

interpolateDistance(distance: number): LatLngHeight

Parameters:

  • distance: Distance from the start point (meters)

Returns:

Geodetic coordinates at the specified distance

Example:

const geodesic = new EllipsoidGeodesic(start, end);
// Get the midpoint
const midpoint = geodesic.interpolateDistance(geodesic.distance / 2);
console.log(`Midpoint: lat=${radianToDegree(midpoint.lat)}°, lng=${radianToDegree(midpoint.lng)}°`);

Releases WASM memory. Call this when the geodesic object is no longer needed.

Syntax:

dispose(): void

Example:

const geodesic = new EllipsoidGeodesic(start, end);
// Perform geodesic calculations
const distance = geodesic.distance;
const points = geodesic.interpolatePoints(1000);
// Release memory after use
geodesic.dispose();
import {
initNavaraApi,
EllipsoidGeodesic,
degreeToRadian,
radianToDegree,
geodeticToVector3,
} from "@navaramap/three_api";
await initNavaraApi();
// Create a geodesic from Tokyo to Osaka
const tokyo = {
lat: degreeToRadian(35.6762),
lng: degreeToRadian(139.6503),
height: 0,
};
const osaka = {
lat: degreeToRadian(34.6937),
lng: degreeToRadian(135.5023),
height: 0,
};
const geodesic = new EllipsoidGeodesic(tokyo, osaka);
// Display distance and azimuth
console.log(`Distance: ${(geodesic.distance / 1000).toFixed(2)} km`);
console.log(`Start heading: ${radianToDegree(geodesic.startHeading).toFixed(2)}°`);
console.log(`End heading: ${radianToDegree(geodesic.endHeading).toFixed(2)}°`);
// Generate interpolation points at 10km intervals and convert to 3D coordinates
const points = geodesic.interpolatePoints(10000);
const positions = points.map((point) => geodeticToVector3(point));
// Draw a line in Three.js
const lineGeometry = new BufferGeometry().setFromPoints(positions);
const lineMaterial = new LineBasicMaterial({ color: "#ff0000" });
const line = new Line(lineGeometry, lineMaterial);
scene.add(line);
// Release memory
geodesic.dispose();

An interface representing geodetic coordinates.

interface LatLngHeight {
lat: number; // Latitude (radians)
lng: number; // Longitude (radians)
height: number; // Height (meters)
}

An interface representing latitude and longitude.

interface LatLng {
lat: number; // Latitude (radians)
lng: number; // Longitude (radians)
}

An interface representing window information. Passed to screen coordinate transformation functions.

interface WindowObject {
width: number; // Window width (pixels)
height: number; // Window height (pixels)
pixelRatio: number; // Device pixel ratio
}

When using @navaramap/three, the @navaramap/three_api APIs are re-exported from @navaramap/three, so you can import them directly from there.

An example of using the API from @navaramap/three to dynamically move a model around the globe:

import ThreeView, {
geodeticToVector3,
degreeToRadian,
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,
});
// Initial position in Osaka
let longitude = 135.5023;
const latitude = 34.6937;
const altitude = 0;
// Add a GLTF model
const modelDesc = view.addMesh<GLTFModelDesc>({
gltfModel: { url: "/path/to/model.glb" },
position: geodeticToVector3({
lat: degreeToRadian(latitude),
lng: degreeToRadian(longitude),
height: altitude,
}),
});
// Animation loop - move the model around the globe
const animate = () => {
// Update longitude (move around the globe)
longitude += 0.01;
// Calculate new position
const pos = geodeticToVector3({
lat: degreeToRadian(latitude),
lng: degreeToRadian(longitude),
height: altitude,
});
// Calculate surface normal
const normal = geodeticSurfaceNormal({
lat: degreeToRadian(latitude),
lng: degreeToRadian(longitude),
height: altitude,
});
// Calculate movement direction
const nextLongitude = longitude + 0.01;
const nextPos = geodeticToVector3({
lat: degreeToRadian(latitude),
lng: degreeToRadian(nextLongitude),
height: altitude,
});
const direction = new Vector3().subVectors(nextPos, pos).normalize();
// Calculate rotation (orient towards movement direction with normal as up)
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);
// Update model position and rotation
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();
import {
initNavaraApi,
degreeToRadian,
geodeticToVector3,
vector3ToGeodetic,
radianToDegree,
} from "@navaramap/three_api";
// Initialize
await initNavaraApi();
const tokyoLle = {
lat: degreeToRadian(35.6762),
lng: degreeToRadian(139.6503),
height: 100,
};
// Convert geodetic coordinates to ECEF coordinates
const ecefPos = geodeticToVector3(tokyoLle);
console.log(`ECEF coordinates: [${ecefPos.x}, ${ecefPos.y}, ${ecefPos.z}]`);
// Convert ECEF coordinates back to geodetic coordinates
const convertedLle = vector3ToGeodetic(ecefPos);
console.log(`Latitude: ${radianToDegree(convertedLle.lat)}°`);
console.log(`Longitude: ${radianToDegree(convertedLle.lng)}°`);
console.log(`Height: ${convertedLle.height} m`);
import {
getPickRay,
getPlaneFromPointNormal,
getRayPlaneIntersection,
getHeightFromEllipsoid,
} from "@navaramap/three_api";
import { Vector2, Vector3 } from "three";
// Mouse click event handler
canvas.addEventListener("click", (event) => {
const windowObject = {
width: canvas.clientWidth,
height: canvas.clientHeight,
pixelRatio: window.devicePixelRatio
};
// Mouse position
const screenPos = new Vector2(event.clientX, event.clientY);
// Generate picking ray
const ray = getPickRay(windowObject, camera, screenPos);
// Define ground plane (Z=0)
const groundPlane = getPlaneFromPointNormal(
new Vector3(0, 0, 0),
new Vector3(0, 0, 1)
);
// Calculate intersection
const intersection = getRayPlaneIntersection(ray, groundPlane);
if (intersection) {
console.log("Clicked ground position:", intersection);
// Check the height at the intersection
const height = getHeightFromEllipsoid(intersection);
console.log("Height from ellipsoid:", height);
}
});
import {
geodeticToVector3,
eastNorthUpToFixedFrame,
degreeToRadian,
} from "@navaramap/three_api";
import { Mesh, BoxGeometry, MeshBasicMaterial } from "three";
// Tokyo location
const tokyoLle = {
lat: degreeToRadian(35.6762),
lng: degreeToRadian(139.6503),
height: 0,
};
// Get ECEF coordinates
const origin = geodeticToVector3(tokyoLle);
// Get East-North-Up coordinate system transformation matrix
const enuMatrix = eastNorthUpToFixedFrame(origin);
// Create and place a mesh
const geometry = new BoxGeometry(100, 100, 100);
const material = new MeshBasicMaterial({ color: "#ff0000" });
const mesh = new Mesh(geometry, material);
// Apply ENU coordinate system transformation matrix
mesh.matrix.copy(enuMatrix);
mesh.matrixAutoUpdate = false;
scene.add(mesh);

Converting Between Screen and World Coordinates

Section titled “Converting Between Screen and World Coordinates”
import {
convertScreenToWorld,
convertWorldToScreen,
geodeticToVector3,
degreeToRadian,
} from "@navaramap/three_api";
import { Vector2 } from "three";
const windowObject = {
width: canvas.clientWidth,
height: canvas.clientHeight,
pixelRatio: window.devicePixelRatio
};
// Convert world coordinates to screen coordinates
const worldPos = geodeticToVector3({
lat: degreeToRadian(35.6762),
lng: degreeToRadian(139.6503),
height: 100,
});
const screenPos = convertWorldToScreen(windowObject, camera, worldPos);
if (screenPos) {
console.log(`Screen coordinates: [${screenPos.x}, ${screenPos.y}]`);
// Position an HTML element
const label = document.getElementById("label");
label.style.left = `${screenPos.x}px`;
label.style.top = `${screenPos.y}px`;
}
// Convert screen coordinates to world coordinates
const mousePos = new Vector2(event.clientX, event.clientY);
const pickedWorldPos = convertScreenToWorld(windowObject, camera, mousePos);
if (pickedWorldPos) {
console.log(
`World coordinates: [${pickedWorldPos.x}, ${pickedWorldPos.y}, ${pickedWorldPos.z}]`
);
}