ドキュメント / リファレンス
API リファレンス
@mirgrid/web-sdk の公開 API を、分類ごとにすべて載せます。使い方の流れは はじめに や各ガイドで説明しているので、ここでは関数ごとの引数・戻り値・例外の条件をまとめます。
SDK には 4 つの入口があります。
| import 先 | 中身 |
|---|---|
@mirgrid/web-sdk |
初期化、位置と空間アドレス、セルの集合、voxel 化、配信データ、低レベルの LOD |
@mirgrid/web-sdk/render.mjs |
露出面を WebGL2 で描く描画器 |
@mirgrid/web-sdk/creation.mjs |
作図面に描いた多角形を押し出して、形を作る関数 |
@mirgrid/web-sdk/lod.mjs |
LOD の核を wasm のメモリ越しに呼ぶための層 |
例の出力は、Node で実行したときにそのまま表示されたものです。
目次
- 共通の約束
- 初期化: init・initSync
- 位置と空間アドレス
- レベル: spatial_voxel_size_m
- 緯度経度と ECEF: spatial_geodetic_to_ecef・spatial_ecef_to_llh_rad・spatial_ecef_height
- ENU: spatial_ecef_to_enu・spatial_enu_to_ecef・spatial_ecef_to_enu_many・spatial_enu_to_ecef_many
- セルと空間アドレス: spatial_ecef_to_voxel・spatial_voxel_to_ecef・spatial_voxel_bounds・spatial_hilbert_cellid_hex・spatial_hilbert_cellid_decode・spatial_cellid_to_ecef
- 平面直角座標系: spatial_plane_rect_to_ecef・spatial_ecef_to_plane_rect・spatial_llh_to_plane_rect・spatial_llh_to_plane_rect_many・spatial_plane_rect_to_llh_deg・spatial_plane_rect_scale_factor
- 現場基準の格子の向き: spatial_yaw_from_deg
- セルの集合: CellSetJs・ROI の書き方・ops_cells_in_roi・ops_cell_relation・ops_diff3・ops_extrude_polygon_to_cells
- voxel 化: VoxelizerJs・FrameJs・voxel_faces_from_packet・VoxelizeInputSpec・VoxelizeReadSummary・VoxelCellInfo・VoxelFaces・VoxelFacesOptions
- 配信データ: encode_voxel_packet・packet_metadata・decode_voxel_packet・decode_voxel_packet_lod・decode_voxel_packet_in_frame・DecodedVoxels
- 描画 (render.mjs): createVoxelRenderer・VoxelRendererOptions・VoxelRenderer・VoxelView・VoxelViewSpec・VoxelLayerOptions・VoxelPick・RenderableFaces
- 形を作る (creation.mjs): defineViewPlane・View・createView・projectToPlane・createPolygon・extrude・planeAxisOf・extrusionCandidateOf・メタデータの関数・creation.mjs の型・creation_ で始まる wasm の関数
- 低レベルの LOD
共通の約束
単位と座標
- 長さの単位は m、角度の単位は度です。ラジアンを返すのは spatial_ecef_to_llh_rad だけです。
- 緯度経度は、経度・緯度の順に並べます。高さは楕円体高 [m] です。楕円体は WGS84 です(日本の測地系 JGD2011 が使う GRS80 との差は、日本の範囲で 0.2 mm 未満です)。
- ECEF は、地球の中心を原点にした直交座標 [m] です。
- ENU は、ある地点(原点)から見た東・北・上の直交座標 [m] です。
- 平面直角座標系は、JGD2011 の 1〜19 系(EPSG 6669〜6687)に対応しています。easting は東向きの座標(測量でいう Y)、northing は北向きの座標(測量でいう X)です。
レベルとセル
空間を立方体のセルに分けて扱います。セルの細かさをレベルと呼びます。レベルは 1〜30 の整数で、数が大きいほど細かくなります。レベルを L とすると、セルの一辺は 2^(24−L) m です。
| レベル | セルの一辺 |
|---|---|
| 1 | 8,388,608 m |
| 16 | 256 m |
| 20 | 16 m |
| 24 | 1 m |
| 26 | 0.25 m |
| 30 | 0.015625 m (1/64 m) |
セルの位置は、各軸の番号 (voxel index) vx, vy, vz で表します。番号は 0 以上 2^レベル 未満の整数です。JavaScript の Number のまま正確に表せるので、BigInt は使いません。範囲の外の番号や整数でない番号を渡すと、どの関数も Error を投げます。
空間アドレスは、セルを表す 32 桁の 16 進の文字列です。レベルと位置の両方を含むので、文字列だけで 1 つのセルが決まります。
格子の種類
セルを切る格子には 2 種類あります。
- 地球基準の格子 (ECEF): ECEF の軸に沿った格子です。地球全体で 1 つなので、どこでも同じ番号の付け方になります。ふだんはこちらを使います。
- 現場基準の格子 (site): 現場の 1 点 (anchor) での東・北・上に沿った格子です。セルが現場で水平な立方体になります。使える範囲は anchor の中心から各軸 2048 m 未満です。
格子は次の形の object(記述子)で表せます。JSON にして保存できます。
{ kind: 'ecef' }
{ kind: 'site', datum: 'JGD2011', epoch: 2011.4, anchor: '0000000002e9380374bc9c0000000000', yaw: 0 }
datum は測地系の名前で、'JGD2011'・'ITRF2014'・'unspecified' のどれかです(大文字と小文字は区別しません)。epoch は測地系ごとに決まった値です(JGD2011 は 2011.4、ITRF2014 は 2010、unspecified には無し)。anchor はレベル 16 のセルの空間アドレスです。yaw は格子の向きで、0〜65535 の整数(1 周 = 65536)です。度からの換算は spatial_yaw_from_deg を使います。
エラー
不正な入力を受けると、関数は Error を投げます。error.message に理由が入ります。黙って別のセルや既定値に置き換えることはしません。
init の前に wasm の関数を呼ぶと TypeError になります。
free() が要るもの
次の 4 つのクラスは、データを wasm のメモリに持っています。使い終わったら free() を呼んでください。
| クラス | 作る関数 |
|---|---|
| CellSetJs | new CellSetJs・from_indices・from_ecef_points・集合演算・ops_*・VoxelizerJs.toCellSet |
| DecodedVoxels | decode_voxel_packet・decode_voxel_packet_lod・decode_voxel_packet_in_frame |
| FrameJs | FrameJs.ecef・FrameJs.site・FrameJs.fromDescriptor |
| VoxelizerJs | new VoxelizerJs・VoxelizerJs.siteAuto |
ガベージコレクションでもいずれ解放されますが、いつになるかは決まっていません。free() を呼んだ後にそのオブジェクトを使ったり、もう一度 free() を呼んだりすると Error になります。4 つのクラスは [Symbol.dispose]() も持っているので、using 宣言に対応した環境では、ブロックを抜けるときに自動で解放できます。
これ以外の関数が返す値(型付き配列や普通の object)は JavaScript 側の値なので、free() は要りません。
初期化
init
export default function init(
module_or_path?: { module_or_path: InitInput | Promise<InitInput> },
): Promise<InitOutput>;
type InitInput = RequestInfo | URL | Response | BufferSource | WebAssembly.Module;
wasm を読み込んで、SDK を使える状態にします。ほかの関数より先に 1 回だけ await してください。2 回目以降の呼び出しは何もせず、1 回目と同じ結果を返します。
- ブラウザやバンドラ(Vite など)では、引数を省いて
await init()と書きます。パッケージの隣にあるvoxel_core_bg.wasmをnew URL('voxel_core_bg.wasm', import.meta.url)で読み込みます。 - wasm の置き場所を変えたときや Node で使うときは、
module_or_pathに URL・Response・バイト列・コンパイル済みのWebAssembly.Moduleを渡します。 { module_or_path }で包まずに直接渡す古い書き方も動きますが、コンソールに警告が出ます。- 戻り値の
InitOutputは wasm の exports です。ふだんは使いません。低レベルの LOD で使います。
Node では、wasm のバイト列を読んで渡します。
import { readFileSync } from 'node:fs';
import init, { spatial_voxel_size_m } from '@mirgrid/web-sdk';
const wasmUrl = new URL('voxel_core_bg.wasm', import.meta.resolve('@mirgrid/web-sdk'));
await init({ module_or_path: readFileSync(wasmUrl) });
console.log(spatial_voxel_size_m(24));
1
initSync
export function initSync(module: { module: SyncInitInput }): InitOutput;
type SyncInitInput = BufferSource | WebAssembly.Module;
init と同じ初期化を、同期で行います。wasm のバイト列か WebAssembly.Module を、すでに手元に持っているときに使います。2 回目以降の呼び出しは何もしません。{ module } で包まずに直接渡すと、警告が出ます。
import { readFileSync } from 'node:fs';
import { initSync, spatial_voxel_size_m } from '@mirgrid/web-sdk';
const wasmUrl = new URL('voxel_core_bg.wasm', import.meta.resolve('@mirgrid/web-sdk'));
initSync({ module: readFileSync(wasmUrl) });
console.log(spatial_voxel_size_m(30));
0.015625
位置と空間アドレス
緯度経度・ECEF・ENU・平面直角座標系のあいだの変換と、セルの番号・空間アドレスの計算をする関数です。どれも @mirgrid/web-sdk から import します。
緯度経度から空間アドレスを求めて、元に戻す例です。
import init, {
spatial_geodetic_to_ecef, spatial_ecef_to_voxel, spatial_hilbert_cellid_hex,
spatial_hilbert_cellid_decode, spatial_cellid_to_ecef,
} from '@mirgrid/web-sdk';
await init();
const ecef = spatial_geodetic_to_ecef(139.7671, 35.6812, 40);
const [vx, vy, vz] = spatial_ecef_to_voxel(ecef[0], ecef[1], ecef[2], 24);
const id = spatial_hilbert_cellid_hex(vx, vy, vz, 24);
console.log(vx, vy, vz);
console.log(id);
console.log(spatial_hilbert_cellid_decode(id));
console.log(spatial_cellid_to_ecef(id));
4428917 11738705 12088148
0000000002e9380374bc9e7cc1940000
{ vx: 4428917, vy: 11738705, vz: 12088148, level: 24 }
Float64Array(3) [ -3959690.5078125, 3350097.4921875, 3699540.4921875 ]
spatial_voxel_size_m
function spatial_voxel_size_m(level: number): number;
レベル level のセルの一辺 [m] を返します。レベル 24 なら 1、レベル 30 なら 0.015625 です。level が 1〜30 の外なら Error を投げます。
spatial_geodetic_to_ecef
function spatial_geodetic_to_ecef(lon_deg: number, lat_deg: number, height: number): Float64Array;
経度・緯度 [度] と楕円体高 height [m] を、ECEF の [x, y, z] [m] に変換します。入力は検査しません。NaN を渡すと NaN を含む配列が返ります。
spatial_ecef_to_llh_rad
function spatial_ecef_to_llh_rad(x: number, y: number, z: number): { lon: number; lat: number };
ECEF [m] を経度・緯度に変換します。戻り値の単位はラジアンです。度にするには 180 / Math.PI を掛けます。高さは spatial_ecef_height で求めます。
spatial_ecef_height
function spatial_ecef_height(x: number, y: number, z: number): number;
ECEF [m] の点の楕円体高 [m] を返します。地表付近では誤差は 1 mm 未満です。
spatial_ecef_to_enu
function spatial_ecef_to_enu(
x: number, y: number, z: number,
origin_lon_deg: number, origin_lat_deg: number, origin_height: number,
): Float64Array;
ECEF の点 (x, y, z) [m] を、原点(経度 [度]・緯度 [度]・楕円体高 [m])から見た ENU の [east, north, up] [m] に変換します。画面に描くときは、ECEF のままではなく、この関数で手元の座標にしてから GPU に渡してください。
import init, { spatial_geodetic_to_ecef, spatial_ecef_to_enu } from '@mirgrid/web-sdk';
await init();
const p = spatial_geodetic_to_ecef(139.768, 35.6812, 40);
console.log(spatial_ecef_to_enu(p[0], p[1], p[2], 139.7671, 35.6812, 40));
Float64Array(3) [
81.47317089525853,
0.00037323128506372427,
-0.0005197661007088072
]
spatial_enu_to_ecef
function spatial_enu_to_ecef(
east: number, north: number, up: number,
origin_lon_deg: number, origin_lat_deg: number, origin_height: number,
): Float64Array;
spatial_ecef_to_enu の逆です。原点から見た東・北・上 [m] を、ECEF の [x, y, z] [m] に変換します。
spatial_ecef_to_enu_many
function spatial_ecef_to_enu_many(
ecef: Float64Array,
origin_lon_deg: number, origin_lat_deg: number, origin_height: number,
): Float64Array;
spatial_ecef_to_enu を多くの点にまとめて行います。ecef は [x, y, z, x, y, z, …] と並べた配列で、戻り値も同じ並びの [e, n, u, …] です。数十万点でも 1 回の呼び出しで済みます。ecef の長さが 3 の倍数でなければ Error を投げます。
spatial_enu_to_ecef_many
function spatial_enu_to_ecef_many(
enu: Float64Array,
origin_lon_deg: number, origin_lat_deg: number, origin_height: number,
): Float64Array;
spatial_enu_to_ecef の一括版です。enu は [e, n, u, e, n, u, …] と並べます。長さが 3 の倍数でなければ Error を投げます。
spatial_ecef_to_voxel
function spatial_ecef_to_voxel(x: number, y: number, z: number, level: number): Float64Array;
ECEF の点 [m] を含む、レベル level のセルの番号 [vx, vy, vz] を返します。点がセルの境界にちょうど乗っているときの扱いも含めて、SDK のほかの関数と同じ規則で決まります。
level が 1〜30 の外なら Error を投げます。座標は検査しません。各軸の座標は有限で、絶対値が 8,388,608 m (2^23 m) 未満の値を渡してください。NaN や範囲の外の値を渡しても Error にはならず、意味の無い番号が返ります。
spatial_voxel_to_ecef
function spatial_voxel_to_ecef(vx: number, vy: number, vz: number, level: number): Float64Array;
セル (vx, vy, vz, level) の中心を、ECEF の [x, y, z] [m] で返します。level が 1〜30 の外のときや、番号が 0〜2^level − 1 の整数でないときは Error を投げます。
spatial_voxel_bounds
function spatial_voxel_bounds(vx: number, vy: number, vz: number, level: number): Float64Array;
セルが占める範囲を、ECEF の軸に沿った箱 [min_x, min_y, min_z, max_x, max_y, max_z] [m] で返します。min の面はセルに含まれ、max の面は含まれません。例外の条件は spatial_voxel_to_ecef と同じです。
spatial_hilbert_cellid_hex
function spatial_hilbert_cellid_hex(vx: number, vy: number, vz: number, level: number): string;
セルの番号から、地球基準の格子の空間アドレス(32 桁の 16 進)を作ります。空間アドレスは、セルを 3 次元のヒルベルト曲線の順に並べた番号です。近いセルほど似た値になりやすくなります。spatial_ecef_to_voxel が返した番号を、そのまま渡せます。例外の条件は spatial_voxel_to_ecef と同じです。
spatial_hilbert_cellid_decode
function spatial_hilbert_cellid_decode(cell_hex: string): { vx: number; vy: number; vz: number; level: number };
空間アドレスを、セルの番号とレベルに戻します。英字の大文字と小文字は区別しません。32 桁でない文字列や 16 進でない文字を含む文字列を渡すと、Error を投げます。
spatial_cellid_to_ecef
function spatial_cellid_to_ecef(cell_hex: string): Float64Array;
空間アドレスが表すセルの中心を、ECEF の [x, y, z] [m] で返します。空間アドレスが壊れていれば Error を投げます。
spatial_plane_rect_to_ecef
function spatial_plane_rect_to_ecef(easting: number, northing: number, height: number, epsg: number): Float64Array;
平面直角座標系の点(easting・northing [m] と楕円体高 height [m])を、ECEF の [x, y, z] [m] に変換します。epsg は 6669〜6687 のどれかで、ほかの値なら Error を投げます。標高しか分からないときは、ジオイド高を足して楕円体高にしてから渡してください。
spatial_ecef_to_plane_rect
function spatial_ecef_to_plane_rect(x: number, y: number, z: number, epsg: number): Float64Array;
ECEF [m] を平面直角座標系の [easting, northing, height] に変換します。height は楕円体高 [m] です。epsg が 6669〜6687 の外なら Error を投げます。
spatial_llh_to_plane_rect
function spatial_llh_to_plane_rect(lon_deg: number, lat_deg: number, epsg: number): Float64Array;
経度・緯度 [度] を、平面直角座標系の [easting, northing] [m] に変換します。高さや ECEF を経由しない、直接の変換です。epsg が 6669〜6687 の外なら Error を投げます。
import init, { spatial_llh_to_plane_rect, spatial_plane_rect_to_llh_deg } from '@mirgrid/web-sdk';
await init();
const [easting, northing] = spatial_llh_to_plane_rect(139.7671, 35.6812, 6677);
console.log(easting, northing);
console.log(spatial_plane_rect_to_llh_deg(easting, northing, 6677));
-5995.185165976924 -35367.23013254245
Float64Array(2) [ 139.76710000000006, 35.6811999999441 ]
spatial_llh_to_plane_rect_many
function spatial_llh_to_plane_rect_many(lonlat: Float64Array, epsg: number): Float64Array;
spatial_llh_to_plane_rect の一括版です。lonlat は [lon, lat, lon, lat, …] と並べ、戻り値は [easting, northing, …] です。矩形の 4 隅のように、いくつかの点をまとめて変換するときに使います。長さが 2 の倍数でないときや、epsg が 6669〜6687 の外のときは Error を投げます。
spatial_plane_rect_to_llh_deg
function spatial_plane_rect_to_llh_deg(easting: number, northing: number, epsg: number): Float64Array;
spatial_llh_to_plane_rect の逆です。平面直角座標系の点 [m] を、[lon_deg, lat_deg] [度] に変換します。epsg が 6669〜6687 の外なら Error を投げます。
spatial_plane_rect_scale_factor
function spatial_plane_rect_scale_factor(easting: number, northing: number, epsg: number): number;
平面直角座標系のその点での縮尺係数 k を返します。平面上の距離 = 実際の距離 × k の関係です。epsg が 6669〜6687 の外なら Error を投げます。
spatial_yaw_from_deg
function spatial_yaw_from_deg(deg: number): number;
現場基準の格子の向き [度](真北から東回り)を、格子の記述子に書く yaw の値(0〜65535 の整数。1 周 = 65536)に換算します。端数は偶数への丸めで整数にし、範囲の外の角度は 1 周ぶん回して収めます。戻り値は FrameJs.site と VoxelizerJs.siteAuto に渡します。deg が有限でなければ Error を投げます。
import init, { spatial_yaw_from_deg } from '@mirgrid/web-sdk';
await init();
console.log(spatial_yaw_from_deg(90), spatial_yaw_from_deg(-90), spatial_yaw_from_deg(360));
16384 49152 0
セルの集合
セルの集合を作り、和・積・差や範囲での切り出しをする API です。どれも @mirgrid/web-sdk から import します。
CellSetJs
class CellSetJs {
constructor(level: number);
static from_indices(level: number, flat: Float64Array): CellSetJs;
static from_ecef_points(level: number, flat: Float64Array): CellSetJs;
readonly level: number;
readonly size: number;
indices(): Float64Array;
contains(vx: number, vy: number, vz: number): boolean;
cell_ids(): string[];
bounds_ecef(): Float64Array;
centers_enu(lon_deg: number, lat_deg: number, h: number): Float32Array;
area_m2(): number;
distance_m(other: CellSetJs, max_steps: number): number | null;
union(other: CellSetJs): CellSetJs;
intersect(other: CellSetJs): CellSetJs;
difference(other: CellSetJs): CellSetJs;
shared_with(other: CellSetJs, tolerance: number): CellSetJs;
downshift(to_level: number): CellSetJs;
clip(roi: Roi, mode: 'touching' | 'inside'): CellSetJs;
free(): void;
[Symbol.dispose](): void;
}
同じレベルのセルを集めた集合です。同じセルは 1 つにまとまり、入れた順番を保ちます。データは wasm のメモリにあるので、使い終わったら free() を呼んでください。集合を返すメソッドは、どれも新しい CellSetJs を返します。元の集合は変わりません。
コンストラクタと from_indices・from_ecef_points で作る集合は、地球基準の格子のセルです。現場基準の格子の集合は VoxelizerJs.toCellSet で作ります。
import init, { CellSetJs } from '@mirgrid/web-sdk';
await init();
const a = CellSetJs.from_indices(24, Float64Array.of(4428917, 11738705, 12088148, 4428918, 11738705, 12088148));
const b = CellSetJs.from_indices(24, Float64Array.of(4428918, 11738705, 12088148, 4428919, 11738705, 12088148));
const shared = a.intersect(b);
console.log(a.size, shared.size, shared.indices());
console.log(a.area_m2(), a.distance_m(b, 10));
console.log(a.cell_ids());
a.free();
b.free();
shared.free();
2 1 Float64Array(3) [ 4428918, 11738705, 12088148 ]
10 0
[
'0000000002e9380374bc9e7cc1940000',
'0000000002e9380374bc9e7cc06c0000'
]
constructor
new CellSetJs(level) は、レベル level の空の集合を作ります。level が 1〜30 の外なら Error を投げます。
from_indices
CellSetJs.from_indices(level, flat) は、[vx, vy, vz, vx, vy, vz, …] と並べた番号から集合を作ります。同じセルが何度出てきても、最初の 1 つだけが残ります。flat の長さが 3 の倍数でないときや、番号が 0〜2^level − 1 の整数でないときは Error を投げます。
from_ecef_points
CellSetJs.from_ecef_points(level, flat) は、[x, y, z, …] と並べた ECEF の点 [m] から、それぞれの点を含むセルの集合を作ります。セルの決め方は spatial_ecef_to_voxel と同じです。長さが 3 の倍数でなければ Error を投げます。座標は検査しないので、NaN や範囲の外の点を入れないでください。
level と size
level は集合のレベル、size はセルの数です。どちらも読み取り専用のプロパティです。
indices
入れた順のセルの番号を、[vx, vy, vz, …] と並べた Float64Array で返します。
contains
contains(vx, vy, vz) は、そのセルが集合に入っていれば true を返します。番号が 0〜2^level − 1 の整数でなければ Error を投げます。
cell_ids
入れた順のセルの空間アドレス(32 桁の 16 進)を、文字列の配列で返します。
bounds_ecef
すべてのセルを囲む、ECEF の軸に沿った箱 [min_x, min_y, min_z, max_x, max_y, max_z] [m] を返します。空の集合では 6 つとも NaN です。
centers_enu
centers_enu(lon_deg, lat_deg, h) は、セルの中心を原点(経度・緯度 [度]・楕円体高 [m])から見た ENU [m] にして、[e, n, u, …] の Float32Array で返します。そのまま GPU に渡せる形です。
area_m2
集合の表面積 [m²] を返します。隣り合うセルどうしが接している面は数えません。空の集合では 0 です。
distance_m
distance_m(other, max_steps) は、2 つの集合のすき間の距離 [m] を返します。セル単位で測るので、結果はセルの一辺の整数倍です。
- 重なっているか、すき間なく接していれば
0です。 max_stepsセルぶん広げても届かないときや、どちらかが空の集合のときはnullです。0とは意味が違うので、区別してください。- 2 つの集合のレベルが違うときや、
max_stepsが負のときは Error を投げます。
union・intersect・difference
union(other) は和、intersect(other) は積(両方にあるセル)、difference(other) は差(自分にあって other に無いセル)を返します。2 つの集合のレベルが違うと Error を投げます。先に downshift でレベルを揃えてください。
shared_with
shared_with(other, tolerance) は、自分のセルのうち、前後・左右・上下に ±tolerance セルの立方体の範囲に other のセルがあるものを返します。tolerance は 0〜8 の整数です。範囲の外の値やレベルの違う集合を渡すと、Error を投げます。
downshift
downshift(to_level) は、レベル to_level に粗くした集合を返します。それぞれのセルは、それを含む粗いセルに置き換わり、同じセルは 1 つにまとまります。to_level が今のレベルより細かいときは、今のレベルのまま写しを返します。to_level が 1〜30 の外なら Error を投げます。
clip
clip(roi, mode) は、ROI(関心のある範囲)に入るセルだけを残した集合を返します。ROI の書き方は ROI の書き方 を見てください。
modeが'touching'なら、ROI と少しでも重なるセルを残します。modeが'inside'なら、全体が ROI に入るセルだけを残します。
ROI の形が正しくないときや、mode がこの 2 つのどちらでもないときは Error を投げます。
現場基準の格子の集合で使えるもの
VoxelizerJs.toCellSet で作った現場基準の格子の集合では、使えるメソッドが限られます。
- 使えるもの:
level・size・indices・contains・area_m2・downshift、それに同じ格子の集合どうしのunion・intersect・difference・shared_with・distance_mと ops_diff3。 - 使えないもの:
cell_ids・bounds_ecef・centers_enuは、番号を地球基準の格子のものとして計算するので、正しい値になりません。clipと、地球基準の格子の集合との演算は、unreachableという Error になります。
現場基準の格子のセルの空間アドレスと中心は、VoxelizerJs.cellInfo か FrameJs.cellAt で求めてください。
ROI の書き方
CellSetJs.clip・ops_cells_in_roi・ops_cell_relation は、範囲を ROI という object で受け取ります。座標はすべて ECEF [m] です。ROI は、次の 6 種類を入れ子にして組み立てます。
| 書き方 | 意味 |
|---|---|
{ aabb: { min: [x, y, z], max: [x, y, z] } } |
ECEF の軸に沿った箱(境界を含む) |
{ sphere: { center: [x, y, z], radius_m: r } } |
中心 center、半径 r [m] の球(境界を含む) |
{ slab: { origin: [x, y, z], normal: [x, y, z], half_thickness_m: t } } |
origin を通り normal に垂直な平面から、両側に t [m] までの板 |
{ not: roi } |
roi の外側 |
{ and: [roi, …] } |
すべての roi に入る範囲 |
{ or: [roi, …] } |
どれかの roi に入る範囲 |
normalは長さ 1 でなくてもかまいません。長さが 0 なら Error になります。radius_mやhalf_thickness_mが負なら、空の範囲として扱います。- 中身の無い
{ and: [] }は空間全体、{ or: [] }は空の範囲です。
ops_cells_in_roi は、範囲を囲む有限の箱が求まる ROI だけを受け付けます。slab だけの ROI や not は使えません。and には有界な子を 1 つ以上入れ、or の子はすべて有界にしてください。
次の例は、半径 5 m の球と、厚さ 1 m の水平な板が重なる範囲のセルを集めます。板の向きは、その地点の真上の向き(ECEF で表したもの)にしています。
import init, { ops_cells_in_roi, spatial_geodetic_to_ecef } from '@mirgrid/web-sdk';
await init();
const c = spatial_geodetic_to_ecef(139.7671, 35.6812, 40);
const above = spatial_geodetic_to_ecef(139.7671, 35.6812, 41);
const up = [above[0] - c[0], above[1] - c[1], above[2] - c[2]];
const roi = {
and: [
{ sphere: { center: Array.from(c), radius_m: 5 } },
{ slab: { origin: Array.from(c), normal: up, half_thickness_m: 0.5 } },
],
};
const cells = ops_cells_in_roi(roi, 24, 10000);
console.log(cells.size);
cells.free();
280
ops_cells_in_roi
function ops_cells_in_roi(roi: Roi, level: number, max_cells: number): CellSetJs;
レベル level のセルのうち、ROI と少しでも重なるものをすべて集めます。セルは番号の小さい順(vx、vy、vz の順に比べる)に並びます。戻り値は CellSetJs なので、使い終わったら free() を呼んでください。
max_cells は、調べるセルの数の上限です。調べ始める前に数を見積もり、上限を超えるなら Error を投げます。ほかに、ROI を囲む有限の箱が求まらないとき(slab だけ、not など)と、level が 1〜30 の外のときも Error を投げます。
import init, { ops_cells_in_roi, ops_cell_relation, spatial_geodetic_to_ecef } from '@mirgrid/web-sdk';
await init();
const center = Array.from(spatial_geodetic_to_ecef(139.7671, 35.6812, 40));
const roi = { sphere: { center, radius_m: 1.5 } };
const cells = ops_cells_in_roi(roi, 24, 1000);
console.log(cells.size);
console.log(ops_cell_relation(roi, 4428917, 11738705, 12088148, 24));
cells.free();
45
inside
ops_cell_relation
function ops_cell_relation(roi: Roi, vx: number, vy: number, vz: number, level: number): 'outside' | 'intersects' | 'inside';
1 つのセルと ROI の関係を返します。
'outside': セルは ROI と重なりません。'intersects': セルの一部が ROI に入ります。'inside': セル全体が ROI に入ります。
and・or・not を組み合わせた ROI では、判定は安全側に倒します。本当は外にあるセルでも 'intersects' になることがありますが、'outside' のセルが ROI に入ることはありません。ROI の形が正しくないとき、level が 1〜30 の外のとき、番号が 0〜2^level − 1 の整数でないときは Error を投げます。
ops_diff3
function ops_diff3(before: CellSetJs, after: CellSetJs, compare_level: number, tolerance: number): {
level: number;
removed: Float64Array;
added: Float64Array;
unchanged: Float64Array;
removedCount: number;
addedCount: number;
unchangedCount: number;
};
2 つの時点の集合を比べて、セルを「無くなった」「増えた」「変わらない」の 3 つに分けます。
- 両方の集合をレベル
compare_levelに粗くしてから比べます。compare_levelは、どちらの集合のレベルより細かくしてはいけません。細かいと Error を投げます。 tolerance(0〜8 の整数)は、ずれを許すセルの数です。beforeのセルの ±toleranceセルの範囲にafterのセルがあれば、「変わらない」と数えます。同じ位置のセルどうしを先に対応させ、1 つのafterのセルは 1 回しか使いません。範囲の外の値なら Error を投げます。removed・unchangedはbefore側のセル、addedはafter側のセルで、どれも[vx, vy, vz, …]の並びです。levelはcompare_levelと同じ値です。
戻り値は普通の object なので free() は要りません。before と after は呼び出しの後もそのまま使えます。
import init, { CellSetJs, ops_diff3 } from '@mirgrid/web-sdk';
await init();
const before = CellSetJs.from_indices(24, Float64Array.of(100, 200, 300, 101, 200, 300));
const after = CellSetJs.from_indices(24, Float64Array.of(101, 200, 300, 102, 200, 300));
console.log(ops_diff3(before, after, 24, 0));
console.log(ops_diff3(before, after, 24, 2).unchangedCount);
before.free();
after.free();
{
level: 24,
removed: Float64Array(3) [ 100, 200, 300 ],
added: Float64Array(3) [ 102, 200, 300 ],
unchanged: Float64Array(3) [ 101, 200, 300 ],
removedCount: 1,
addedCount: 1,
unchangedCount: 1
}
2
ops_extrude_polygon_to_cells
function ops_extrude_polygon_to_cells(
level: number,
origin_lon_deg: number, origin_lat_deg: number, origin_h_m: number,
polygon_flat: Float64Array,
min_height_m: number, max_height_m: number,
max_cells: number,
normal_axis: 'east' | 'north' | 'up',
): CellSetJs;
床や壁の多角形を、ENU の 1 つの軸の向きに押し出した立体を、地球基準の格子のセルの集合にします。中心がその立体に入るセルを集めます。そのため、多角形の縁にセルの半分より少ししか掛からないところは、入らないことがあります。
origin_*は ENU の原点(経度・緯度 [度]・楕円体高 [m])です。normal_axisは押し出す向きです。polygon_flatは多角形の頂点を[a, b, a, b, …]と並べた配列です。a・bは、normal_axisを除いた ENU の 2 軸を東・北・上の順に並べたものです。'up'なら(東, 北)、'north'なら(東, 上)、'east'なら(北, 上)です。単位は m です。min_height_m・max_height_mは、押し出す範囲をnormal_axisの向きの座標 [m] で表したものです。max_cellsは、調べるセルの数の上限です。
次のときは Error を投げます。
- 頂点が 3 つ未満のときや、面積がほぼ 0 のとき。
min_height_m > max_height_mのときや、値が有限でないとき。normal_axisが 3 つのどれでもないとき。- 調べるセルの数が
max_cellsを超えるとき。 levelが 1〜30 の外のとき。
creation.mjs で作った形から、この関数の引数を作れます。
import init, { ops_extrude_polygon_to_cells } from '@mirgrid/web-sdk';
await init();
const cells = ops_extrude_polygon_to_cells(
24, 139.7671, 35.6812, 40,
Float64Array.of(0, 0, 4, 0, 4, 3, 0, 3),
0, 2.4, 10000, 'up',
);
console.log(cells.size, cells.level);
cells.free();
26 24
voxel 化
点群やメッシュをセルにする API と、格子を扱う API です。どれも @mirgrid/web-sdk から import します。
VoxelizerJs
class VoxelizerJs {
constructor(level: number, frame?: FrameJs | object | null);
static siteAuto(level: number, datum?: string | null, yaw?: number | null): VoxelizerJs;
readonly level: number;
readonly cellCount: number;
setInput(spec: VoxelizeInputSpec): void;
setSurfaceDensity(points_per_m2: number): void;
setMaxCells(max?: number | null): void;
pushPoints(xyz: Float64Array, rgb?: Uint8Array | null): void;
pushTriangles(xyz: Float64Array, indices?: Uint32Array | null, rgb?: Uint8Array | null): number;
pushFile(bytes: Uint8Array, format: string): VoxelizeReadSummary;
frameDescriptor(): object | null;
indices(): Float64Array;
colors(): Uint8Array;
counts(): Float64Array;
cellInfo(i: number): VoxelCellInfo;
toCellSet(): CellSetJs;
toPacket(): Uint8Array;
faces(origin?: [number, number, number] | null, options?: VoxelFacesOptions | null): VoxelFaces;
free(): void;
[Symbol.dispose](): void;
}
点・三角形・ファイルを積んで、セルにまとめます。セルの色は、そのセルに入った点の色の平均です。レベルと格子は作るときに決まり、後から変えられません。使い終わったら free() を呼んでください。
結果を読むメソッド(indices・colors・counts・cellInfo・faces など)は、セルを番号の小さい順(vx、vy、vz の順に比べる)に並べて返します。この並びでの位置を「セル番号」と呼びます。
import init, { VoxelizerJs } from '@mirgrid/web-sdk';
await init();
const voxelizer = new VoxelizerJs(24);
voxelizer.setInput({ coordSystem: 'latlon' });
voxelizer.pushPoints(
Float64Array.of(139.7671, 35.6812, 40, 139.76711, 35.6812, 40, 139.7672, 35.6812, 40),
Uint8Array.of(255, 0, 0, 0, 0, 255, 0, 255, 0),
);
console.log(voxelizer.cellCount);
console.log(voxelizer.cellInfo(0));
const faces = voxelizer.faces();
console.log(faces.faceCount, faces.originLlh);
voxelizer.free();
3
{
index: [ 4428911, 11738698, 12088148 ],
cellId: '0000000002e9380374bc9e7d880c0000',
rgb: [ 0, 255, 0 ],
count: 1,
centerEcef: [ -3959696.5078125, 3350090.4921875, 3699540.4921875 ],
sourceType: 2
}
18 [ 139.76714888785557, 35.68120374573367, 40.05131894722581 ]
constructor
new VoxelizerJs(level, frame?) は、レベル level(1〜30)の voxel 化を始めます。frame には FrameJs か格子の記述子を渡します。省くと地球基準の格子になります。入力の座標系は、最初は ECEF です。level が範囲の外のときや、記述子が正しくないときは Error を投げます。
渡した FrameJs は中身を読むだけなので、呼び出しの後も使えます。
siteAuto
VoxelizerJs.siteAuto(level, datum?, yaw?) は、現場基準の格子で voxel 化を始めます。格子の anchor は、最初に積んだ点を含むレベル 16 のセルに決まります。格子の軸はその地点の東・北・上なので、セルが現場で水平な立方体になります。
datumは測地系の名前で、既定は'JGD2011'です。知らない名前なら Error を投げます。yawは格子の向き(0〜65535 の整数)で、既定は 0(格子が東西南北に揃う)です。度からは spatial_yaw_from_deg で換算します。- 積む点は、anchor の中心から各軸 2048 m 未満に収めてください。外の点を積むと Error を投げます。
決まった格子は frameDescriptor で読めます。同じ格子に別のファイルを重ねるときは、その記述子を new VoxelizerJs(level, descriptor) に渡してください。
setInput
setInput(spec) は、この後に積む点・三角形・ファイルの座標系と置き場所を決めます。すでに積んだセルは変わりません。spec の形は VoxelizeInputSpec です。知らないキーがあるとき、必要な値が足りないとき、値が正しくないときは Error を投げます。
setSurfaceDensity
setSurfaceDensity(points_per_m2) は、三角形の表面から点を拾う密度の下限 [点/m²] を決めます。既定は 16 です。実際の密度は、レベルに合わせて必要なだけ上がります。0 以下か有限でない値なら Error を投げます。
setMaxCells
setMaxCells(max) は、セルの数の上限を決めます。null か 0 なら上限はありません(既定)。積んでいる途中でセルの数が上限を超えると、push* が Error を投げます。0 以上の整数でも null でもなければ Error を投げます。
pushPoints
pushPoints(xyz, rgb?) は、点を積みます。xyz は入力の座標系での [x, y, z, …] です。rgb は 1 点 3 バイトの色で、省くと灰色 (180, 180, 180) になります。
次のときは Error を投げます。
xyzの長さが 3 の倍数でないとき。rgbの長さが、点の数 × 3 でないとき。- 変換した ECEF 座標が有限でないか、範囲の外のとき。
- セルの数が上限を超えたとき。
pushTriangles
pushTriangles(xyz, indices?, rgb?) は、三角形を積みます。三角形の表面から点を拾い、その点を積みます。戻り値は拾った点の数です。
xyzは頂点の座標[x, y, z, …]です。indicesは 1 三角形 3 個の頂点番号です。省くと、頂点を 3 個ずつ使って三角形にします。rgbは 1 三角形 3 バイトの色です。省くと (180, 190, 205) になります。
配列の長さが合わないとき、indices に頂点の数以上の番号があるとき、そのほか pushPoints と同じ条件で Error を投げます。
pushFile
pushFile(bytes, format) は、ファイルのバイト列を読んで積みます。戻り値は VoxelizeReadSummary です。
- 対応する形式は PLY・LAS・LAZ・glTF・GLB・OBJ・STL です。
formatには形式名('laz'など)かファイル名('scan.laz'など)を渡します。 - PLY は binary_little_endian だけに対応しています。ASCII の PLY は読めません。
- glTF は、外部のファイルを参照しないもの(GLB か、data: URI に埋め込んだもの)だけを読めます。
- LAS・LAZ のヘッダに EPSG が書いてあっても、入力の座標系は切り替わりません。座標系は
setInputで決めてください。
対応していない形式や壊れたファイルのとき、そのほか pushPoints と同じ条件で Error を投げます。ファイル全体を一度に wasm のメモリへ写すので、大きなファイルは Web Worker の中で読むと、画面が止まりません。
level と cellCount
level はレベル、cellCount は今のセルの数です。どちらも読み取り専用のプロパティです。
frameDescriptor
今の格子の記述子を返します(格子の種類 を参照)。siteAuto でまだ点を積んでいないときは、格子が決まっていないので null を返します。
indices, colors, counts
indices() はセルの番号 [vx, vy, vz, …]、colors() はセルの色(1 セル 3 バイト)、counts() はセルに入った点の数を返します。どれもセル番号の順です。現場基準の格子では、番号は現場基準の格子のものです。
cellInfo
cellInfo(i) は、セル番号 i のセルの情報を VoxelCellInfo で返します。i が 0〜cellCount − 1 の整数でないときや、セルがまだ無いときは Error を投げます。
toCellSet
セルを CellSetJs にして返します。格子はこの voxel 化と同じです。使い終わったら free() を呼んでください。現場基準の格子の集合で使えるメソッドには制限があります(現場基準の格子の集合で使えるもの を参照)。
toPacket
セルを配信データ (packet) のバイト列にして返します。セルの色と、メッシュ・点群のどちら由来かを保ちます。面の向きの情報はすべての向き (63) になります。セルが無ければ Error を投げます。
packet には格子の情報が入りません。現場基準の格子で作った packet を後で読むときのために、frameDescriptor も一緒に保存してください。
faces
faces(origin?, options?) は、セルの露出面(ほかのセルに隠れていない面)を VoxelFaces で返します。結果は JavaScript 側の型付き配列だけでできているので、Web Worker から transfer できます。free() は要りません。
originは描画空間の原点[lon, lat, h](度・楕円体高 m)です。省くと、地球基準の格子ではセルを囲む箱の中心、現場基準の格子では anchor の真上(anchor の中心の経度・緯度と、セルを囲む箱の中心の高さ)になります。- 1 つの描画器に重ねるレイヤは、同じ原点で作ってください。2 つ目からは
faces(renderer.originLlh)と書きます。 optionsは VoxelFacesOptions です。
次のときは Error を投げます。
- セルが無いとき。
originが有限でないか、緯度が −90〜90 の外のとき。optionsに知らないキーがあるとき。- 最初のセルから各軸 2^23 セル以上離れたセルがあるとき(レベル 24 で 8,388,608 m)。広い範囲は、レベルを粗くするか、分けて作ってください。
FrameJs
class FrameJs {
static ecef(): FrameJs;
static site(datum: string, anchor_hex: string, yaw: number): FrameJs;
static fromDescriptor(descriptor: object): FrameJs;
kind(): 'ecef' | 'site';
toDescriptor(): object;
matrix(): Float64Array;
cellAt(ix: number, iy: number, iz: number, level: number): { cellId: string; centerEcef: Float64Array };
free(): void;
[Symbol.dispose](): void;
}
セルを切る格子を表します(格子の種類 を参照)。VoxelizerJs・voxel_faces_from_packet・decode_voxel_packet_in_frame に渡して使います。使い終わったら free() を呼んでください。
FrameJs.ecef()は、地球基準の格子を返します。FrameJs.site(datum, anchor_hex, yaw)は、現場基準の格子を返します。anchor_hexはレベル 16 のセルの空間アドレスです。yawは 0〜65535 の整数です。度の値は spatial_yaw_from_deg で換算してから渡してください。datumが知らない名前のときや、anchor_hexがレベル 16 の空間アドレスでないときは Error を投げます。FrameJs.fromDescriptor(descriptor)は、記述子から格子を作ります。必要なキーが無いとき、型が合わないとき、epochが測地系の値と違うときは Error を投げます。kind()は'ecef'か'site'を返します。toDescriptor()は記述子を返します。地球基準の格子では{ kind: 'ecef' }です。matrix()は、格子の座標から ECEF [m] への 4×4 の変換行列を、列優先の 16 要素で返します。[0..3]が東の列、[4..7]が北の列、[8..11]が上の列、[12..15]が平行移動です。three.js のMatrix4.fromArrayにそのまま渡せます。地球基準の格子では単位行列です。cellAt(ix, iy, iz, level)は、この格子のセルの空間アドレスと、中心の ECEF [m] を返します。現場基準の格子では、空間アドレスは現場基準の格子のものになります。levelが 1〜30 の外のときや、番号が 0〜2^level − 1 の整数でないときは Error を投げます。
import init, {
FrameJs, spatial_geodetic_to_ecef, spatial_ecef_to_voxel, spatial_hilbert_cellid_hex,
} from '@mirgrid/web-sdk';
await init();
const c = spatial_geodetic_to_ecef(139.7671, 35.6812, 40);
const [ax, ay, az] = spatial_ecef_to_voxel(c[0], c[1], c[2], 16);
const frame = FrameJs.site('JGD2011', spatial_hilbert_cellid_hex(ax, ay, az, 16), 0);
console.log(frame.kind());
console.log(frame.toDescriptor());
frame.free();
site
{
kind: 'site',
datum: 'JGD2011',
epoch: 2011.4,
anchor: '0000000002e9380374bc9c0000000000',
yaw: 0
}
voxel_faces_from_packet
function voxel_faces_from_packet(
bytes: Uint8Array,
xor_key: number,
frame?: FrameJs | object | null,
origin?: [number, number, number] | null,
): VoxelFaces;
配信データ (packet) を読んで、露出面を VoxelFaces で返します。色は packet のセルの色で、面の向きの情報を使って陰影を付けます。free() は要りません。
xor_keyは packet を隠すときに使った 1 バイトの鍵(0〜255)です。隠していなければ 0 です。frameは、packet をどの格子のものとして読むかです。FrameJsか記述子を渡します。省くと地球基準の格子です。packet には格子の情報が入っていないので、現場基準の格子の packet では必ず渡してください。渡さないと、別の場所のセルとして読まれます。originは描画空間の原点[lon, lat, h]です。省いたときの決まり方は faces と同じです。
faces.cells の値は、packet の中のセルの順番です。packet が壊れているとき、セルが無いとき、そのほか faces と同じ条件で Error を投げます。
import init, { VoxelizerJs, voxel_faces_from_packet } from '@mirgrid/web-sdk';
await init();
const voxelizer = VoxelizerJs.siteAuto(26);
voxelizer.setInput({ coordSystem: 'local', origin: [139.7671, 35.6812, 40] });
voxelizer.pushPoints(Float64Array.of(0, 0, 0, 1, 0, 0, 0, 1, 0));
const descriptor = voxelizer.frameDescriptor();
const packet = voxelizer.toPacket();
console.log(descriptor);
const faces = voxel_faces_from_packet(packet, 0, descriptor);
console.log(faces.frameKind, faces.cellCount, faces.faceCount);
voxelizer.free();
{
kind: 'site',
datum: 'JGD2011',
epoch: 2011.4,
anchor: '0000000002e9380374bc9c0000000000',
yaw: 0
}
site 3 18
VoxelizeInputSpec
interface VoxelizeInputSpec {
coordSystem: string;
origin?: [number, number, number] | null;
utmZone?: number | null;
utmHemisphere?: 'north' | 'south' | null;
unitScale?: number | null;
geoidHeightM?: number | null;
rotationDeg?: number | null;
translation?: [number, number, number] | null;
pivot?: [number, number, number] | null;
}
setInput に渡す、入力の座標系と置き場所です。
| キー | 意味 |
|---|---|
coordSystem |
入力の座標系。下の表のどれか(必須) |
origin |
'local' の原点 [lon, lat, h](度・楕円体高 m) |
utmZone |
'utm' のゾーン番号(1〜60) |
utmHemisphere |
'utm' の半球('north' か 'south') |
unitScale |
入力の 1 単位が何 m か。mm なら 0.001。既定 1 |
geoidHeightM |
入力の高さが標高のときのジオイド高 [m]。楕円体高 = 標高 + この値。既定 0 |
rotationDeg |
鉛直軸まわりの回転 [度]。正の値で反時計回り。既定 0 |
translation |
平行移動 [東, 北, 上] [m]。既定 [0, 0, 0] |
pivot |
回転の中心。入力の単位で書く。既定 [0, 0, 0] |
coordSystem に書ける値は次のとおりです。
| 値 | 入力の座標 |
|---|---|
'ecef' |
ECEF [x, y, z] [m](最初はこれ) |
'latlon' |
[経度, 緯度, 楕円体高](度・m) |
'utm' |
UTM の [easting, northing, 楕円体高] [m]。utmZone と utmHemisphere が必要 |
'local' |
origin から見た ENU [東, 北, 上] [m]。origin が必要 |
'6669'〜'6687' |
平面直角座標系の [easting, northing, 楕円体高] [m] |
入力の点には、回転(pivot まわり)、平行移動、unitScale の倍率の順に掛けてから、座標系に沿って ECEF に変換します。回転と平行移動は、ローカル座標や平面直角座標系のように、軸が東・北・上に近い座標系で使うものです。
VoxelizeReadSummary
interface VoxelizeReadSummary {
format: 'ply' | 'las' | 'laz' | 'gltf' | 'glb' | 'obj' | 'stl';
points: number;
triangles: number;
samples: number;
declaredEpsg: number | null;
}
pushFile の結果です。format は読んだ形式、points は点の数、triangles は三角形の数、samples は三角形の表面から拾った点の数です。declaredEpsg は、LAS・LAZ のヘッダに書いてある EPSG です。書いていなければ null です。
VoxelCellInfo
interface VoxelCellInfo {
index: [number, number, number];
cellId: string;
rgb: [number, number, number];
count: number;
centerEcef: [number, number, number];
sourceType: number;
}
cellInfo が返す、1 つのセルの情報です。
| キー | 意味 |
|---|---|
index |
セルの番号。現場基準の格子では、その格子の番号 |
cellId |
空間アドレス(32 桁の 16 進)。現場基準の格子では、その格子の空間アドレス |
rgb |
セルの色(入った点の色の平均) |
count |
セルに入った点の数(三角形から拾った点を含む) |
centerEcef |
セルの中心の ECEF [m] |
sourceType |
由来。1 = メッシュ、2 = 点群、3 = 両方 |
VoxelFaces
interface VoxelFaces {
level: number;
cellSizeM: number;
cellCount: number;
faceCount: number;
sorted: boolean;
start: Uint32Array;
coords: Int16Array | Float32Array;
colors: Uint8Array;
cells: Uint32Array;
gridToRender: Float64Array;
index0: [number, number, number];
frameKind: 'ecef' | 'site';
originLlh: [number, number, number];
boundsRender: [number, number, number, number, number, number];
}
faces と voxel_faces_from_packet が返す露出面です。そのまま setLayer に渡して描けます。すべて JavaScript 側の値なので、free() は要りません。
| キー | 意味 |
|---|---|
level・cellSizeM |
レベルと、セルの一辺 [m] |
cellCount・faceCount |
セルの数と面の数 |
coords |
1 面 4 要素。格子の座標 x, y, z(最初のセルからのセル数。整数がセルの中心)と、面の向き d(0〜5 = +X, −X, +Y, −Y, +Z, −Z) |
sorted |
true なら coords は Int16Array で、面が向きごとにまとまっています。false なら Float32Array です |
start |
7 要素。向き d の面は start[d] 以上 start[d + 1] 未満の番号です |
colors |
1 面 4 バイト。陰影を付けた r, g, b と 255 |
cells |
面ごとのセル番号。faces では cellInfo の引数、voxel_faces_from_packet では packet の中の順番 |
gridToRender |
格子の座標から描画空間(originLlh から見た ENU [m])への 4×4 の行列。列優先 |
index0 |
格子の座標が 0 のセル(最初のセル)の番号 |
frameKind |
格子の種類 |
originLlh |
描画空間の原点 [lon, lat, h] |
boundsRender |
描画空間でセルを囲む箱 [minE, minN, minU, maxE, maxN, maxU] [m] |
面の格子の座標からセルの番号を求めるには、index0 に格子の座標を足します。その番号を FrameJs.cellAt に渡すと、空間アドレスが分かります。
VoxelFacesOptions
interface VoxelFacesOptions {
occlusion?: boolean;
}
faces の選択肢です。occlusion を false にすると、隣のセルに塞がれた面も残します。既定は true です。
配信データ
配信データ (packet) は、セルの番号・色・由来・面の向き・地物の ID をまとめたバイト列です。1 つの packet には 1 つのレベルのセルが入ります。ここの関数はどれも @mirgrid/web-sdk から import します。
import init, { encode_voxel_packet, packet_metadata, decode_voxel_packet } from '@mirgrid/web-sdk';
await init();
const packet = encode_voxel_packet([
{ vx: 4428917, vy: 11738705, vz: 12088148, r: 255, g: 0, b: 0 },
{ vx: 4428918, vy: 11738705, vz: 12088148, r: 0, g: 0, b: 255, sourceType: 2, featureIdPrimary: 7 },
], 24);
console.log(packet_metadata(packet, 0));
const decoded = decode_voxel_packet(packet, 0, 139.7671, 35.6812, 40);
console.log(decoded.count, decoded.positions);
console.log(decoded.colors, decoded.feature_ids_primary);
decoded.free();
{
voxelLevel: 24,
columnMask: 31,
headerLength: 40,
byteLength: 87,
vxBase: 4428917,
vyBase: 11738705,
vzBase: 12088148,
count: 2
}
2 Float32Array(6) [
-0.18406754732131958,
0.4328923225402832,
0.027242183685302734,
-0.8299636840820312,
0.8781789541244507,
-0.5928690433502197
]
Uint8Array(8) [
255, 0, 0, 0,
0, 0, 255, 2
] Uint32Array(2) [ 4294967295, 7 ]
encode_voxel_packet
function encode_voxel_packet(
voxels: Array<{
vx: number; vy: number; vz: number;
r?: number; g?: number; b?: number;
sourceType?: number;
normalMask?: number;
featureIdPrimary?: number;
featureIdSecondary?: number;
}>,
voxel_level: number,
): Uint8Array;
セルの配列から packet を 1 つ作ります。vx・vy・vz 以外は省けます。
| キー | 意味 | 省いたとき |
|---|---|---|
vx・vy・vz |
セルの番号(整数) | 省けません |
r・g・b |
色(0〜255) | 0 |
sourceType |
由来(下位 4 ビット。1 = メッシュ、2 = 点群、3 = 両方) | 0 |
normalMask |
露出面の向きのビット(下の表) | 63(すべて) |
featureIdPrimary・featureIdSecondary |
地物の ID(0〜4294967294) | 無し (4294967295) |
normalMask のビットは、1 = +X、2 = −X、4 = +Y、8 = −Y、16 = +Z、32 = −Z です。軸は格子の軸です。
キーの名前は camelCase です。知らないキーは読み飛ばすので、綴りに気を付けてください。配列が空のとき、voxel_level が 1〜30 の外のとき、必須のキーが無いときや値の型が合わないとき(小数の番号、256 以上の色など)は Error を投げます。番号が 0〜2^level − 1 に収まっているかは確かめないので、正しい番号を渡してください。
packet_metadata
function packet_metadata(packet_data: Uint8Array, xor_key: number): {
voxelLevel: number;
columnMask: number;
headerLength: number;
byteLength: number;
vxBase: number;
vyBase: number;
vzBase: number;
count: number;
};
packet のヘッダだけを読みます。セルを展開しないので軽い処理です。
| キー | 意味 |
|---|---|
voxelLevel |
セルのレベル |
columnMask |
入っている列のビット。1 = 番号、2 = 色、4 = 由来、8 = 面の向き、16 = 地物の ID(主)、32 = 地物の ID(副) |
headerLength |
ヘッダの長さ(バイト) |
byteLength |
packet 全体の長さ(バイト) |
vxBase・vyBase・vzBase |
番号の基準(各軸の最小値) |
count |
セルの数 |
xor_key は packet を隠すときに使った 1 バイトの鍵(0〜255)です。隠していなければ 0 です。鍵が違うときや packet が壊れているときは Error を投げます。
decode_voxel_packet
function decode_voxel_packet(
packet_data: Uint8Array,
xor_key: number,
origin_lon: number, origin_lat: number, origin_height: number,
clamp_level?: number | null,
): DecodedVoxels;
packet を展開して、セルの中心を原点(経度・緯度 [度]・楕円体高 [m])から見た ENU [m] にします。結果は DecodedVoxels で、使い終わったら free() を呼んでください。地球基準の格子の packet 用です。現場基準の格子の packet には decode_voxel_packet_in_frame を使います。
clamp_levelを渡すと、それより細かいセルをレベルclamp_levelに粗くしてから返します。1〜30 の値にしてください(0 を渡すとunreachableという Error になります)。packet のレベル以上の値なら、何も変わりません。- 同じセルになった複数のセルは 1 つにまとめ、最初に出てきた位置に置きます。面の向きのビットは OR を取ります。メッシュ由来と点群由来が重なったときは、由来を 3 にして点群の色を使います。地物の ID は、主と副の 2 つまで残します。
鍵が違うときや packet が壊れているときは Error を投げます。
decode_voxel_packet_lod
function decode_voxel_packet_lod(
packet_data: Uint8Array,
xor_key: number,
origin_lon: number, origin_lat: number, origin_height: number,
center_lon: number, center_lat: number,
r1: number, r2: number, r3: number, r4: number,
shape_mode: number,
height_scale: number,
is_paid: boolean,
): DecodedVoxels;
decode_voxel_packet と同じように展開しますが、注目点から遠いセルほど粗いレベルにまとめます。注目点は(center_lon、center_lat、origin_height)です。結果の位置は、原点(origin_lon、origin_lat、origin_height)から見た ENU [m] です。
セルごとに、注目点からの距離でレベルを選びます。距離の測り方は shape_mode で決まります。
shape_modeが 1 なら円柱で測ります。水平の距離が r 以下で、高さの差が r ×height_scale以下のとき、半径 r の内側とみなします。height_scaleが負なら 0 として扱います。- それ以外なら球で測ります。3 次元の距離が r 以下のとき、半径 r の内側とみなします。
is_paid は、細かいレベルをどこまで許すかです。false なら最も細かくてレベル 24、true なら最も細かくてレベル 30 です。どちらも、最も粗いのはレベル 17 です。
| 注目点からの距離 | is_paid: false |
is_paid: true |
|---|---|---|
| r1 / 32 以内 | 24 | 30 |
| r1 / 16 以内 | 24 | 29 |
| r1 / 8 以内 | 24 | 28 |
| r1 / 4 以内 | 24 | 27 |
| r1 / 2 以内 | 24 | 26 |
| r1 × 0.75 以内 | 23 | 25 |
| r1 以内 | 23 | 24 |
| r2 以内 | 22 | 22 |
| r3 以内 | 21 | 21 |
| r4 以内 | 20 | 20 |
| r4 × 1.5 以内 | 19 | 19 |
| r4 × 3 以内 | 18 | 18 |
| それより遠い | 17 | 17 |
packet のレベルより細かくはなりません。セルの colors の 4 バイト目には、上位 4 ビットに(選んだレベル − 17)、下位 4 ビットに由来が入ります。鍵が違うときや packet が壊れているときは Error を投げます。
decode_voxel_packet_in_frame
function decode_voxel_packet_in_frame(
packet_data: Uint8Array,
xor_key: number,
frame: FrameJs,
origin_x: number, origin_y: number, origin_z: number,
clamp_level?: number | null,
): DecodedVoxels;
格子を指定して packet を展開します。現場基準の格子の packet を読むときに使います。結果の位置は、セルの中心を格子の座標で表し、そこから原点 (origin_x, origin_y, origin_z) [m] を引いた値です。現場基準の格子ではセルが軸に沿った箱になるので、そのまま描けます。
- 原点は、格子の座標で表します。現場基準の格子なら現場の座標 [m]、地球基準の格子なら ECEF [m] です。位置は 32 ビットの小数 (
Float32Array) になるので、原点はデータの近くに置いてください。ECEF の値をそのまま 32 ビットにすると、0.5 m 刻みに丸まってしまいます。 - 地球基準の格子でも呼べますが、位置は ECEF の軸のまま原点を移しただけの座標です。decode_voxel_packet の ENU とは別のものです。
clamp_levelの意味と例外の条件は decode_voxel_packet と同じです。
渡した frame は中身を読むだけなので、呼び出しの後も使えます。
DecodedVoxels
class DecodedVoxels {
readonly count: number;
readonly positions: Float32Array;
readonly colors: Uint8Array;
readonly normal_masks: Uint8Array;
readonly feature_ids_primary: Uint32Array;
readonly feature_ids_secondary: Uint32Array;
free(): void;
[Symbol.dispose](): void;
}
packet を展開した結果です。データは wasm のメモリにあるので、使い終わったら free() を呼んでください。直接 new では作れません。
| プロパティ | 意味 |
|---|---|
count |
セルの数 |
positions |
セルの中心。1 セル 3 要素 [m] |
colors |
1 セル 4 バイト。r, g, b と、由来(下位 4 ビット。decode_voxel_packet_lod では上位 4 ビットにレベルも入る) |
normal_masks |
1 セル 1 バイト。露出面の向きのビット(encode_voxel_packet の表を参照) |
feature_ids_primary・feature_ids_secondary |
1 セル 1 要素。地物の ID。無いときは 4294967295 |
型付き配列のプロパティは、読むたびに wasm のメモリから新しい配列を写して作ります。何度も使うときは、一度変数に入れてください。
描画 (render.mjs)
露出面 (VoxelFaces) を WebGL2 で描く描画器です。ほかのライブラリに依存しません。@mirgrid/web-sdk/render.mjs から import します。
import するだけなら DOM や WebGL に触れないので、Node でも import できます。描くにはブラウザの WebGL2 が要ります。
import init, { VoxelizerJs } from '@mirgrid/web-sdk';
import { createVoxelRenderer } from '@mirgrid/web-sdk/render.mjs';
await init();
const voxelizer = new VoxelizerJs(24);
voxelizer.setInput({ coordSystem: 'latlon' });
voxelizer.pushPoints(Float64Array.of(139.7671, 35.6812, 40, 139.76711, 35.6812, 40, 139.7672, 35.6812, 40));
const canvas = document.querySelector('canvas');
const renderer = createVoxelRenderer(canvas);
renderer.setLayer('points', voxelizer.faces());
canvas.addEventListener('click', (event) => {
const hit = renderer.pick(event.clientX, event.clientY);
if (hit) console.log(voxelizer.cellInfo(hit.cell));
});
描画空間は、originLlh から見た ENU [m] です。z 軸が上を向きます。マウスとタッチで視点を動かせます。
| 操作 | 動き |
|---|---|
| 左ドラッグ・1 本指 | 回転 |
| 右ドラッグ・中ボタンのドラッグ・Shift + ドラッグ | 平行移動 |
| ホイール | 拡大・縮小 |
| 2 本指 | つまんで拡大・縮小と平行移動 |
画面に変化があったときだけ、requestAnimationFrame で描き直します。canvas の大きさは ResizeObserver と devicePixelRatio に合わせます。
createVoxelRenderer
function createVoxelRenderer(canvas: HTMLCanvasElement, options?: VoxelRendererOptions): VoxelRenderer;
canvas に描く描画器を作ります。options は VoxelRendererOptions です。canvas でないものを渡したときや、WebGL2 が使えないときは Error を投げます。
VoxelRendererOptions
interface VoxelRendererOptions {
background?: [number, number, number, number];
lightDirection?: [number, number, number];
ambient?: number;
fovDeg?: number;
azimuthDeg?: number;
elevationDeg?: number;
pixelRatio?: number;
onContextLost?: () => void;
onContextRestored?: () => void;
onRender?: (view: VoxelView) => void;
}
| キー | 意味 | 既定 |
|---|---|---|
background |
背景色 [r, g, b, a](各 0〜1) |
[0.96, 0.97, 0.98, 1] |
lightDirection |
光が来る向き(描画空間の ENU。長さは 1 でなくてよい) | [0.35, -0.5, 1] |
ambient |
光が当たらない面の明るさ(0〜1) | 0.55 |
fovDeg |
縦の視野角 [度] | 45 |
azimuthDeg |
最初の視点の方位角 [度]。東から反時計回り | −60 |
elevationDeg |
最初の視点の仰角 [度] | 35 |
pixelRatio |
描く解像度の倍率 | devicePixelRatio |
onContextLost |
WebGL の context を失ったときに呼ぶ関数。この間は描画が止まります | 無し |
onContextRestored |
context が戻ったときに呼ぶ関数。GPU の資源は作り直してあります | 無し |
onRender |
描くたびに、今の視点 (VoxelView) を渡して呼ぶ関数。方位の印などを重ねて描くのに使います | 無し |
VoxelRenderer
interface VoxelRenderer {
setLayer(id: string, faces: RenderableFaces, options?: VoxelLayerOptions): void;
removeLayer(id: string): boolean;
setVisible(id: string, visible: boolean): void;
fitView(): void;
render(): void;
pick(clientX: number, clientY: number): VoxelPick | null;
setView(view: VoxelViewSpec): void;
dispose(): void;
readonly view: VoxelView;
readonly originLlh: [number, number, number] | null;
readonly contextLost: boolean;
readonly layerIds: string[];
}
createVoxelRenderer が返す描画器です。
| メソッド・プロパティ | 動き |
|---|---|
setLayer(id, faces, options?) |
露出面をレイヤとして置きます。同じ id があれば置き換えます。最初のレイヤを置いたときに、視点をそのレイヤに合わせます。options は VoxelLayerOptions です |
removeLayer(id) |
レイヤを取り除きます。取り除いたら true、そのレイヤが無ければ false を返します |
setVisible(id, visible) |
レイヤを表示するか隠すかを切り替えます |
fitView() |
見えているレイヤ全体が収まるように、視点を合わせます |
render() |
すぐに描きます。ふだんは変化のたびに自動で描くので、呼ばなくてかまいません |
pick(clientX, clientY) |
画面の座標(MouseEvent.clientX・clientY)の下にある面を VoxelPick で返します。何も無ければ null です |
setView(view) |
視点を VoxelViewSpec で決めます。書かなかった項目は今のままです |
dispose() |
操作の listener、ResizeObserver、GPU の資源を外します。2 回目以降は何もしません |
view |
今の視点 (VoxelView) |
originLlh |
レイヤの描画空間の原点。レイヤが無ければ null |
contextLost |
WebGL の context を失っている間は true |
layerIds |
置いてあるレイヤの id の配列 |
1 つの描画器に重ねるレイヤは、同じ originLlh で作ってください。2 つ目からは voxelizer.faces(renderer.originLlh) や voxel_faces_from_packet(bytes, 0, frame, renderer.originLlh) と書きます。
次のときは Error を投げます。
setLayer:facesの形が正しくないとき、ほかのレイヤと原点が違うとき、dispose()の後のとき、新しいidでレイヤを置いた回数が 65535 を超えたとき(取り除いたレイヤの分も数えます)。setVisible: そのidのレイヤが無いとき。setView: 値が有限でないとき、distanceMが 0 以下のとき。
setView で targetEnu か distanceM を決めると、最初のレイヤでの自動の視点合わせはしなくなります。向き(azimuthDeg・elevationDeg)だけを決めたときは、自動で合わせます。
VoxelView
interface VoxelView {
targetEnu: [number, number, number];
distanceM: number;
azimuthDeg: number;
elevationDeg: number;
axesOnScreen: { east: [number, number]; north: [number, number]; up: [number, number] };
}
今の視点です。VoxelRenderer の view と、onRender の引数で受け取ります。
| キー | 意味 |
|---|---|
targetEnu |
視点が回る中心 [e, n, u] [m] |
distanceM |
中心から目までの距離 [m] |
azimuthDeg |
目の方位角 [度]。東から反時計回りで、−90 なら南から北を見ます |
elevationDeg |
目の仰角 [度]。±89.94 度までで、90 に近いほど真上から見ます |
axesOnScreen |
東・北・上の単位ベクトルが画面で向く方向 [x 右, y 下]。長さは 1 以下で、視線に沿う軸ほど短くなります。方位の印を描くのに使います |
VoxelViewSpec
interface VoxelViewSpec {
targetEnu?: [number, number, number];
distanceM?: number;
azimuthDeg?: number;
elevationDeg?: number;
}
setView に渡す視点です。意味は VoxelView の同じ名前のキーと同じです。真上から見るなら elevationDeg: 90、南から見るなら azimuthDeg: -90 を渡します。elevationDeg は ±89.94 度に収めます。
VoxelLayerOptions
interface VoxelLayerOptions {
visible?: boolean;
}
setLayer の選択肢です。visible の既定は true です。同じ id のレイヤを置き換えるときに省くと、前の値を引き継ぎます。
VoxelPick
interface VoxelPick {
layerId: string;
face: number;
cell: number;
direction: number;
}
pick の結果です。layerId はレイヤの id、face はレイヤの中の面の番号です。cell はセル番号 (faces.cells[face]) で、cellInfo にそのまま渡せます。direction は面の向き(0〜5 = +X, −X, +Y, −Y, +Z, −Z。格子の軸)です。
RenderableFaces
interface RenderableFaces {
faceCount: number;
coords: Int16Array | Float32Array;
colors: Uint8Array;
cells: Uint32Array;
gridToRender: ArrayLike<number>;
originLlh: ArrayLike<number>;
boundsRender: ArrayLike<number>;
}
描画器が読む露出面のキーです。VoxelFaces の一部なので、faces() や voxel_faces_from_packet() の結果をそのまま渡せます。キーの意味は VoxelFaces と同じです。
形を作る (creation.mjs)
作図面 (View) の上に 2 次元の多角形を描き、面の法線に沿って押し出して、立体を作ります。@mirgrid/web-sdk/creation.mjs から import します。
- 長さの単位は m です。座標は、利用者が決めた手元の
[x, y, z][m] です(x が東、y が北、z が上)。 - 幾何の計算は wasm で行うので、init の後に呼んでください。前に呼ぶと Error を投げます。メタデータの関数だけは、init の前でも使えます。
- 作図面の軸 u・v は直交する単位ベクトルになり、法線は u × v です。作図面の上で反時計回りに描いた多角形は、符号付きの面積が正になります。
import init, { ops_extrude_polygon_to_cells } from '@mirgrid/web-sdk';
import { createView, createPolygon, extrude, extrusionCandidateOf } from '@mirgrid/web-sdk/creation.mjs';
await init();
const view = createView({ plane: 'XY', origin: [0, 0, 0] });
const room = extrude(createPolygon(view, [[0, 0], [4, 0], [4, 3], [0, 3]]), 2.4);
console.log(room.volumeM3, room.bbox);
const candidate = extrusionCandidateOf(room);
console.log(candidate);
const cells = ops_extrude_polygon_to_cells(
24, 139.7671, 35.6812, 40,
Float64Array.from(candidate.polygon.flat()), candidate.min, candidate.max, 10000, candidate.normalAxis,
);
console.log(cells.size);
cells.free();
28.8 { min: [ 0, 0, 0 ], max: [ 4, 3, 2.4 ] }
{
normalAxis: 'up',
polygon: [ [ 0, 0 ], [ 4, 0 ], [ 4, 3 ], [ 0, 3 ] ],
min: 0,
max: 2.4
}
26
defineViewPlane
function defineViewPlane(spec?: ViewPlaneSpec): PlaneGeometry;
作図面の幾何だけを求めます。戻り値は { origin, u, v, normal, scaleU, scaleV } で、ID やメタデータは付きません。spec (ViewPlaneSpec) では、面の向きを次のどれか 1 つで決めます。
| 書き方 | 面 |
|---|---|
plane: 'XY' |
u = 東、v = 北、法線 = 上 |
plane: 'XZ' |
u = 東、v = 上、法線 = 南 |
plane: 'YZ' |
u = 北、v = 上、法線 = 東 |
u と v |
面内の 2 軸。v は u に直交するように直します |
direction と normal |
面内の 1 軸と法線。direction は normal に直交するように直します |
ほかに次のキーを書けます。
origin: 面の原点。[x, y, z][m] か、{ longitude, latitude, height? }です。緯度経度で書くときは、fromLlhメソッドを持つ object をframeに渡してください。fromLlh({ longitude, latitude, height })が返す[x, y, z]を原点にします。既定は[0, 0, 0]です。scale: 作図の 1 単位が何 m か。数か[scaleU, scaleV]です。mm で描くなら 0.001 にします。既定は 1 です。
次のときは Error を投げます。
- 向きの指定が 0 個か、2 個以上のとき。
uとv(またはdirectionとnormal)の片方しか無いとき。planeが 3 つのどれでもないとき。scaleが正の数でないとき。- 緯度経度の
originにframeが無いとき。
View
class View implements PlaneGeometry, CreationMetadata {
constructor(spec?: ViewSpec);
id: string;
kind: 'view';
origin: Vec3; u: Vec3; v: Vec3; normal: Vec3;
scaleU: number; scaleV: number;
confidence: number | null;
source: string | null;
reconstructionState: ReconstructionState;
toWorld(point: Vec2): Vec3;
projectToPlane(point: Vec3): { u: number; v: number; distanceM: number };
}
ID とメタデータを持つ作図面です。幾何は defineViewPlane と同じです。spec には defineViewPlane のキーに加えて id を書けます。省くと 'view-1' のような ID が付きます。
toWorld([u, v])は、作図の座標を[x, y, z][m] にします。projectToPlane([x, y, z])は、projectToPlane と同じです。
createView
function createView(spec?: ViewSpec): View;
new View(spec) と同じです。
import init from '@mirgrid/web-sdk';
import { createView, setConfidence, setSource, setReconstructionState } from '@mirgrid/web-sdk/creation.mjs';
await init();
const view = setConfidence(createView({ plane: 'XZ', id: 'north-wall' }), 0.8);
setSource(view, 'manual');
setReconstructionState(view, 'inferred');
console.log(view.id, view.normal, view.confidence, view.source, view.reconstructionState);
north-wall [ 0, -1, 0 ] 0.8 manual inferred
projectToPlane
function projectToPlane(view: PlaneGeometry, point: Vec3): { u: number; v: number; distanceM: number };
3 次元の点を作図面に垂直に下ろします。u・v は作図の座標で、view.toWorld で元に戻せます。distanceM は、法線の向きを正とした、面からの距離 [m] です。view には View も defineViewPlane の結果も渡せます。点が有限の数でなければ Error を投げます。
createPolygon
function createPolygon(view: View, points: Vec2[], options?: { id?: string }): Polygon;
作図面の上に描いた環(作図の座標 [u, v] の配列)を、3 次元の多角形にします。戻り値は Polygon です。signedArea は符号付きの面積 [m²] で、作図面の上で反時計回りなら正です。areaM2 は面積 [m²]、vertices3d は頂点の [x, y, z] [m] です。options.id を省くと 'polygon-1' のような ID が付きます。
view が View でないとき、点が 3 つ未満のとき、面積が 0 のときは Error を投げます。
extrude
function extrude(polygon: Polygon, distanceM: number, options?: { id?: string }): Space;
多角形を、作図面から法線に沿って distanceM [m] 押し出した立体にします。distanceM が負なら、法線と逆の向きに押し出します。0 なら Error を投げます。戻り値は Space です。
| キー | 意味 |
|---|---|
distanceM |
押し出した距離(符号付き) [m] |
heightM |
押し出した距離の大きさ [m] |
baseVertices3d・topVertices3d |
底面と上面の頂点 [x, y, z] [m] |
volumeM3 |
体積 [m³] |
bbox |
立体を囲む箱 { min, max } [m] |
options.id を省くと 'space-1' のような ID が付きます。polygon が createPolygon の結果でなければ Error を投げます。
planeAxisOf
function planeAxisOf(view: PlaneGeometry): 'east' | 'north' | 'up' | null;
作図面の法線がそろっている ENU の軸を返します。向きの符号は問いません。斜めの面では null を返します。
extrusionCandidateOf
function extrusionCandidateOf(space: Space): ExtrusionCandidate;
extrude の立体を、ops_extrude_polygon_to_cells の引数の形 { normalAxis, polygon, min, max } にします。polygon は、normalAxis を除いた ENU の 2 軸を東・北・上の順に並べた頂点です。min・max は押し出した範囲です。座標の原点は、ops_extrude_polygon_to_cells に渡す経度・緯度・楕円体高になります。
space が extrude の結果でないときや、作図面が ENU の軸にそろっていない(斜めの面の)ときは Error を投げます。
メタデータの関数
function setConfidence<T extends CreationEntity>(entity: T, value: number | null): T;
function getConfidence(entity: CreationEntity): number | null;
function setSource<T extends CreationEntity>(entity: T, value: string | null): T;
function getSource(entity: CreationEntity): string | null;
function setReconstructionState<T extends CreationEntity>(entity: T, state: ReconstructionState): T;
function getReconstructionState(entity: CreationEntity): ReconstructionState;
const RECONSTRUCTION_STATES: readonly ReconstructionState[]; // ['confirmed', 'inferred', 'unknown']
View・Polygon・Space に、どれだけ確かか・どこから来たか・どう作ったかを書き込みます。set* は渡したオブジェクトを書き換えて、そのオブジェクトを返します。作ったばかりのオブジェクトは、confidence: null、source: null、reconstructionState: 'unknown' です。どれも wasm を使わないので、init の前でも呼べます。
setConfidenceのvalueは 0〜1 の数かnullです。範囲の外なら Error を投げます。nullで未設定に戻します。setSourceのvalueは出どころを書く自由な文字列です。nullで消します。setReconstructionStateのstateは'confirmed'(確かめた)・'inferred'(推定した)・'unknown'(不明)のどれかです。大文字で書いてもかまいません。ほかの値なら Error を投げます。RECONSTRUCTION_STATESは、この 3 つを並べた配列です。
creation.mjs の型
type Vec3 = [number, number, number];
type Vec2 = [number, number];
type ViewPlanePreset = 'XY' | 'XZ' | 'YZ';
type ReconstructionState = 'confirmed' | 'inferred' | 'unknown';
type ExtrusionNormalAxis = 'east' | 'north' | 'up';
type CreationEntity = View | Polygon | Space;
interface GeodeticOrigin { longitude: number; latitude: number; height?: number }
interface FrameLike { fromLlh(origin: { longitude: number; latitude: number; height: number }): number[] }
interface CreationMetadata { confidence: number | null; source: string | null; reconstructionState: ReconstructionState }
interface ViewPlaneSpec {
plane?: ViewPlanePreset;
origin?: Vec3 | GeodeticOrigin;
frame?: FrameLike;
u?: Vec3; v?: Vec3;
direction?: Vec3; normal?: Vec3;
scale?: number | [number, number];
}
interface ViewSpec extends ViewPlaneSpec { id?: string }
interface PlaneGeometry { origin: Vec3; u: Vec3; v: Vec3; normal: Vec3; scaleU: number; scaleV: number }
interface Polygon extends CreationMetadata {
id: string; kind: 'polygon'; view: View; points: Vec2[];
signedArea: number; areaM2: number; vertices3d: Vec3[];
}
interface Space extends CreationMetadata {
id: string; kind: 'space'; polygon: Polygon; view: View;
distanceM: number; heightM: number;
baseVertices3d: Vec3[]; topVertices3d: Vec3[];
volumeM3: number; bbox: { min: Vec3; max: Vec3 };
}
interface ExtrusionCandidate { normalAxis: ExtrusionNormalAxis; polygon: Vec2[]; min: number; max: number }
Vec3 は [x, y, z] [m](x が東、y が北、z が上)、Vec2 は作図の座標 [u, v](作図の単位)です。
creation_ で始まる wasm の関数
@mirgrid/web-sdk には、creation.mjs が中で呼ぶ次の 7 つの関数もあります。ふだんは creation.mjs の関数を使ってください。plane には View か defineViewPlane の結果を渡します。
function creation_view_plane(spec: ViewPlaneSpec): PlaneGeometry;
function creation_to_world(plane: PlaneGeometry, point: Vec2): Vec3;
function creation_project_to_plane(plane: PlaneGeometry, point: Vec3): { u: number; v: number; distanceM: number };
function creation_polygon(plane: PlaneGeometry, points: Vec2[]): { points: Vec2[]; signedArea: number; areaM2: number; vertices3d: Vec3[] };
function creation_extrude(plane: PlaneGeometry, points: Vec2[], distance_m: number): { distanceM: number; heightM: number; baseVertices3d: Vec3[]; topVertices3d: Vec3[]; volumeM3: number; bbox: { min: Vec3; max: Vec3 } };
function creation_plane_axis(plane: PlaneGeometry): 'east' | 'north' | 'up' | null;
function creation_extrusion_candidate(plane: PlaneGeometry, points: Vec2[], distance_m: number): ExtrusionCandidate;
| 関数 | 対応する creation.mjs の関数 |
|---|---|
creation_view_plane |
defineViewPlane(緯度経度の origin は受け付けません) |
creation_to_world |
View.toWorld |
creation_project_to_plane |
projectToPlane |
creation_polygon |
createPolygon の幾何の部分 |
creation_extrude |
extrude の幾何の部分 |
creation_plane_axis |
planeAxisOf |
creation_extrusion_candidate |
extrusionCandidateOf |
例外の条件は、対応する creation.mjs の関数と同じです。
低レベルの LOD
LOD(遠くを粗く、近くを細かく表示する仕組み)の核と露出面の抽出を、wasm のメモリ越しに直接呼ぶための API です。表示するタイルやレベルを自前で決める、描画エンジンの作者向けのものです。セルを描くだけなら、voxel_faces_from_packet と 描画 (render.mjs) で足ります。
核の関数は、init が返す InitOutput に mg_ で始まる名前で入っています。引数の構造体は wasm のメモリに置き、その位置(数)を渡します。構造体の配置は lod_layout() の表から読みます。
@mirgrid/web-sdk の関数:
| 関数 | 中身 |
|---|---|
lod_layout(): string |
構造体の配置の表 (JSON) |
lod_api_version(): number |
核の API の版 |
lod_alloc(size: number, align: number): number |
wasm のメモリを確保して、位置を返す |
lod_dealloc(ptr: number, size: number, align: number): void |
lod_alloc で確保したメモリを返す |
@mirgrid/web-sdk/lod.mjs の関数:
| 関数 | 中身 |
|---|---|
parseLayout(json: string): Map<string, StructLayout> |
lod_layout() の表を、構造体の名前ごとの配置に直す |
createLodAbi(sdk: LodSdk, wasm: LodWasm): LodAbi |
構造体の読み書きと mg_* の呼び出しをまとめたオブジェクトを作る。sdk は import * as sdk from '@mirgrid/web-sdk'、wasm は await init() の戻り値 |
lod.mjs の型: FieldKind・LayoutField・StructLayout・FieldValue・FieldWriter・FieldReader・LodAbi・LodSdk・LodWasm。