以前のこちらの記事で、Forge Viewewを使った2D図面と3Dモデルの連携方法についてご紹介をいたしました。
この記事では、2D シートと 3D モデルが 1 つのシードファイルに存在する場合に、Forge Viewerでの一意の識別子であるdbidが2D、3D双方で同一であることを利用して、相互に連携をする方法について、Revitのデータを例にしてご紹介をしています。
それでは、Inventorの2D図面と3Dモデルについても同様の手法で2D図面と3Dモデルを連携させられるでしょうか?
残念ながらInventorの2D図面(*.idw, .dwg)と、3Dモデル(*.iam, *.ipt)をForgeのModel Derivative API で変換した場合、変換されたSVFファイル中のdbidはそれぞれ別のidとなってしまいます。このため、ForgeのViewerで2D図面と3Dモデルを連携をする情報としてdbidを利用することが出来ません。
また、Inventorの2D図面(*.idw, .dwg)をSVFに変換した場合、図面上の図形の情報はSVFに渡りますが、図面を構成する元の3Dモデルに対応する情報はSVFに渡されず、パートやアセンブリに対応する図形がどれなのかが分からなくなってしまうため、dbid以外のパート、アセンブリ名等の情報を元に、3Dモデルと連携を行うこともできない状況です。
そこで、今回の記事では、Forge ViewerでInventorの2D図面 / 3Dモデルの連携を行う方法について解説をしたいと思います。
Inventorの2D図面 / 3Dモデルの連携アプリケーション
まず初めに、今回紹介する手法でInventorの2D図面/3Dモデル連携アプリケーションを紹介したいと思います。
左側のForge Viewerで表示されている2D図面で選択をすると、右側のViewer表示している3Dモデルの中で、対応するコンポーネントが選択・ズーム表示されていることが分かるかと思います。
また、右側の3Dモデルでコンポーネントを選択すると、選択したコンポーネントを含む図形が左側の2D図面で選択されていることが分かるかと思います。
なお、このアプリケーションの連携表示には、一点制限事項があります。
左側の2D図面で選択可能となるコンポーネントは、2D図面でViewとして配置したアセンブリの直下のコンポーネントとなるということです。つまり、トップアセンブリ配下に、アセンブリを配置していた場合、配置したアセンブリを構成するアセンブリやパートの単位では選択することが出来ません。
それでは、どのようにInventorの2D図面と3Dモデルを連携させるかについて解説をしたいと思います。
Inventor 2D図面の加工
前述したように、Inventor 2D図面をそのまま、ForgeのModel Derivative API で変換しても連携表示をするための情報が付加されません。
このため、Inventor 2D図面をAutoCAD図面に変換、Inventor図面でのコンポーネントをAutoCADでブロックとする加工を行うことで、連携表示に必要な情報がModel Derivative APIで変換後のSVFに渡るようにします。詳細な方法については、こちらのAutodesk Knowledge Networkの記事で紹介していますので、ご参照ください。
Forge Viewerでの連携
さて、HTML ページに 2D と 3D を表示する 2 つの <div> セクションが Forge Viewer カンバスとして用意されていて、Inventorの2D図面を加工したAutoCAD図面と、Inventorのアセンブリを表示すると仮定してください。
この時、前者カンバスのタグ id が viewer2ddiv、後者カンバスのタグ id が viewer3ddiv になっていて、それぞれの Viewer3D インスタンスを格納する JavaScript 変数が、viewer2dと viewer3dとします。
この状態で、viewer2d カンバスのドキュメント ロード成功時に、次のように、ジオメトリ選択 イベント SELECTION_CHANGED_EVENT をフックします。
viewer2d.addEventListener(Autodesk.Viewing.SELECTION_CHANGED_EVENT, function (event) {
if (onSync) {
return;
}
if (event.dbIdArray.length === 1) {
viewer2d.getProperties(event.dbIdArray[0], function (data) {
console.log('selected data name is ' + data.name);
var modelName = data.name.replace('Occurence_', '').replace(' [' + data.externalId + ']', '').replace(/#(\d+$)/, ':$1');
console.log('Search for [' + modelName + '] in 3d view.');
viewer3d.search(modelName, (dbIds) => {
// success
viewer3d.model.getBulkProperties(
dbIds,
['Name'],
(elements) => {
let dbIdsToSelect = [];
for (var i = 0; i < elements.length; i++) {
if (elements[i].properties[0].displayValue === modelName)
dbIdsToSelect.push(elements[i].dbId);
}
onSync = true;
viewer3d.select(dbIdsToSelect);
viewer3d.fitToView(dbIdsToSelect);
onSync = false;
},
(e) => {
// error, handle here...
},
['Name']);
});
})
}
});
SELECTION_CHANGED_EVENT イベントハンドラ関数のパラメータには、選択したジオメトリの dbId が格納されているので、dbidから選択されたモデルの名前を取得し、その名前を用いて、3dモデルを表示するカンバスで、その名前を持つモデルをsearch()及びgetBulkProperties()を用いて検索して、取得したジオメトリのdbidをselect() - 選択表示とfitToView()- 拡大 する をすることで、連携処理を実現することが出来るようになります。
同じく、viewer3d カンバスのドキュメント ロード成功時に、次のように、ジオメトリ選択 イベント SELECTION_CHANGED_EVENT をフックします。
viewer3d.addEventListener(Autodesk.Viewing.SELECTION_CHANGED_EVENT, function (event) {
if (onSync)
{
return;
}
if (event.dbIdArray.length === 1) {
viewer3d.getProperties(event.dbIdArray[0], function (data) {
console.log(data.name);
if (null == data.properties.find(prop => prop.attributeName == 'Component Name')) {
var instanceTree = viewer3d.model.getData().instanceTree;
var parentId = instanceTree.getNodeParentId(event.dbIdArray[0])
viewer3d.select([parentId]);
console.log("Selected ParentId is " + parentId + ".");
return;
}
})
}
var instanceTree = viewer3d.model.getData().instanceTree;
var selecteddbid = event.dbIdArray[0];
var dbids = [];
dbids.push(selecteddbid);
while (selecteddbid)
{
var parentId = instanceTree.getNodeParentId(selecteddbid);
dbids.push(parentId);
viewer3d.getProperties(parentId, function (data) {
console.log(data.name)
});
if (parentId == viewer3d.model.getRootId()) {
dbids.pop();
dbids.pop();
selecteddbid = dbids.pop();
break;
}
else
{
selecteddbid = parentId;
}
}
if (event.dbIdArray.length === 1) {
viewer3d.getProperties(selecteddbid, function (data) {
console.log('target data name is ' + data.name);
var modelName = 'Occurence_' + data.name.replace(' [' + data.externalId + ']', '').replace(/:(\d+$)/, '#$1');
console.log('Search for [' + modelName + '] in 2d view.');
viewer2d.search(modelName, (dbIds) => {
// success
viewer2d.model.getBulkProperties(
dbIds,
['Name'],
(elements) => {
let dbIdsToSelect = [];
for (var i = 0; i < elements.length; i++) {
if (elements[i].properties[0].displayValue.startsWith(modelName))
dbIdsToSelect.push(elements[i].dbId);
}
onSync = true;
viewer2d.select(dbIdsToSelect);
//viewer2d.fitToView(dbIdsToSelect);
onSync = false;
},
(e) => {
// error, handle here...
},
['Name']);
});
})
}
});
SELECTION_CHANGED_EVENT イベントハンドラ関数のパラメータには、選択したジオメトリの dbId が格納されているので、まず、選択したジオメトリの親で属性に’Component Name’を持つモデルを選択するようにします。これにより、3dモデル上では、Forge Viewerでプロパティを持つ(≒Inventorでのパートやアセンブリ)モデルが選択されるようになります。
次に、選択したモデルを親にさかのぼっていき、最上位のモデルの直下のモデルのdbidを取得します。これは、2D図面側では、Inventorでの最上位のアセンブリ直下のコンポーネントのみが、選択可能なモデルとなっているためです。
そして最後に、特定した最上位のモデルの直下のモデルのdbidから、モデルの名前を取得しsearch()及びgetBulkProperties()を用いて検索して、取得したジオメトリのdbidをselect() - 選択表示 をすることで、連携処理を実現することが出来るようになります。
なお、モデル名で検索をする際には、2D側のモデルでは、末尾の”:” + 数値が”#” + 数値に置き換える加工をしている事に合わせて、検索に使用する文字列を加工しています。
また、2D図面側ではモデル選択を容易にするためにBox選択ExtensionをロードしてBox選択をできるようにします。
viewer2d.addEventListener(
Autodesk.Viewing.EXTENSION_LOADED_EVENT,
(event) => {
if (event.extensionId != 'Autodesk.BoxSelection') return;
var viewer = event.target;
var boxSelExt = viewer.getExtension('Autodesk.BoxSelection');
boxSelExt.addToolbarButton(true); //!<<< Show the toolbar button for this extension
});
以上で、Inventorの2D図面と3DモデルをForge Viewerで連携表示することが出来るようになります。
まとめ
いかがでしたでしょうか?
Inventorの2D図面を加工し、AutoCADのブロックにする処理を行うことで、2D図面側でトップアセンブリ直下のオカレンスしか選択できないという制約事項はあるものの、Forge Viewerで2D図面と3Dモデルの連携表示ができることが確認できたかと思います。
今回の記事ではInventorの2D図面を手動で加工しましたが、Design Automationを用いて自動化することで、手作業での加工なしでForge Viewerで連携表示をさせることも可能かと思いますので、要件に合わせてご活用いただければと思います。
By Takehiro Kato
コメント