APS Viewer を使ったプログラミング作業をしていると、特定の要素の最小、あるいは最大位置を把握したい場合があります。そのような場面では、デスクトップで利用する CAD のアドイン開発でよく見られる境界ボックス(Bounding Box や Boundary Box)を、同様に取得、利用することが出来ます。
境界ボックスは、要素を囲む最小座標と最大座標を返すのが一般的です。APS Viewer では、現在、画面上でマウス左ボタンを使って選択している要素、またはモデル ブラウザなどで選択した「現在」の要素について、ViewingUtilities.getBoundingBox メソッドが Three.js の THREE.Box3 を返します。
Forge Viewer:オーバーレイとシーン ビルダー でご紹介した方法と、要素の選択時に発生する SELECTION_CHANGED_EVENT イベントを併用すると、Viewer 上に境界ボックスを描画して可視化するようなことも可能です。
_viewer.addEventListener(Autodesk.Viewing.SELECTION_CHANGED_EVENT, onSelectedByPick);
…
function onSelectedByPick(event) {
let dbIdArray = event.dbIdArray;
boundingBox(dbIdArray);
}
…
function boundingBox(dbIdArray) {
let bbox;
if (dbIdArray.length > 0) {
for (i = 0; i < dbIdArray.length; i++) {
var node = dbIdArray[i];
bbox = _viewer.utilities.getBoundingBox();
}
const min = JSON.parse(JSON.stringify(bbox.min));
const max = JSON.parse(JSON.stringify(bbox.max));
const xw = max.x – min.x;
const yw = max.y – min.y;
const zh = max.z – min.z;
if (_viewer.overlays.hasScene('custom-scene')) {
_viewer.overlays.removeMesh(_scene.mesh, 'custom-scene');
_viewer.overlays.removeScene('custom-scene');
_scene.material.dispose();
_scene.geom.dispose();
_scene = null;
}
_scene = new sceneMember(
new THREE.BoxGeometry(xw, yw, zh),
new THREE.MeshBasicMaterial({
color: 0x000000,
wireframe: true,
wireframeLinewidth: 1
})
);
_scene.mesh = new THREE.Mesh(_scene.geom, _scene.material);
_scene.mesh.position.set(min.x + xw / 2, min.y + yw / 2, min.z + zh / 2);
if (!_viewer.overlays.hasScene('custom-scene')) {
_viewer.overlays.addScene('custom-scene');
}
_viewer.overlays.addMesh(_scene.mesh, 'custom-scene');
}
}

APS Viewer v7 では、モデルブラウザ上の要素選択は要素自身を選択状態にしません。このため、画面上の選択操作時と異なり、SELECTION_CHANGED_EVENT イベントが発生しません。代わりに、モデルブラウザ上で選択した要素は、選択表示(孤立表示、独立表示、ISOLATE 表示)の状態に遷移します。
選択状態になる際には ISOLATE_EVENT イベントが発生するので、このイベントを使うと、モデルブラウザ上の選択を利用することも出来ます。
_viewer.addEventListener(Autodesk.Viewing.ISOLATE_EVENT, onSelectedByMBrowser);
…
function onSelectedByMBrowser(event) {
let dbIdArray = event.nodeIdArray;
_viewer.select(dbIdArray); // force to be 'current'
_viewer.clearSelection(); //
boundingBox(dbIdArray);
}

この方法を使うと、POST job エンドポイントを generateMasterViews advanced オプションを指定して変換した Revit モデルに対して、部屋の境界ボックスを得ることも出来ます。

getBoundingBox メソッドは単一要素だけでなく、ノード全体の境界ボックスも返す点にご注意ください。[Shift] キーを押しながら、画面上で複数の要素を直接選択した場合も同様です。

By Toshiaki Isezaki

Leave a Reply