通常,基于Forge Viewer 开发的的朋友需要获取到模型的层次结构以及构件的DbId,用于在自己的流程中构造相关对象和处理。尤其DbId,大部分Forge Viewer对象的操作,参数是输入的DbId,而用来唯一确定构件的信息是一些其它的Id,例如ExternalId。所以,有时要做ID的映射,方便前端流程中,可以更快速的找到对应的构件。
一些朋友喜欢在Forge Viewer加载模型( 譬如在这个事件中Autodesk.Viewing.GEOMETRY_LOADED_EVENT)来遍历Viewer.InstanceTree (instanceTree.enumNodeChildren)获取DbId。对于简单模型,这个方法可用,而对于复杂模型,将造成较长时间才能完成遍历过程,影响流程的其它工作。
其实,在instanceTree的属性里,藏有DbId和模型节点的数组,只是没有现成的如同用户界面那样直接对应的映射表。
几个对象:
- instanceTree.nodeAccess.dbIdToIndex 含有所有dbId。不过这个数组是一个map,是dbId和instanceTree.nodeAccess.names数组的对应关系
- instanceTree.nodeAccess.names存放查询节点名字的序号
- instanceTree.nodeAccess.strings存放模型节点的名字,如果有特殊的后缀,则后缀需要从instanceTree.nodeAccess.nameSuffixes中拿到。例如本例中的 Surface[105545],中括号就是特殊的后缀
- instanceTree.nodeAccess.nameSuffixes,节点的特殊后缀
所以,假设我们知道一个dbId,以下代码将得到对应的节点名:
var dbid = 1854;
var it = NOP_VIEWER.model.getData().instanceTree;
var indexinNames = it.nodeAccess.dbIdToIndex[dbid];
var indexinStrings = it.nodeAccess.names[indexinNames];
var nodeMainString = it.nodeAccess.strings[indexinStrings];
var nodeSuffixString = it.nodeAccess.nameSuffixes[indexinStrings];
//最终的节点名字
var nodeFinalName = nodeMainString+nodeSuffixString;
其实,Forge Viewer API提供了一个直接的方法,通过dbId得到节点名。原理和上门是类似的。
var dbid = 1854;
var it = NOP_VIEWER.model.getData().instanceTree;
//最终的节点名字
var nodeFinalName = it.getNodeName(dbid);
反过来,假设知道了模型节点名,查询dbId,则可以先剔除后缀名,然后在it.nodeAccess.strings得到序号,接着从it.nodeAccess.names得到映射序号,最终在it.nodeAccess.dbIdToIndex得到dbId。但是:由于模型节点名是可以重复的,我还未找到一个有重复节点名的模型测试,而Forge Viewer增加一个后缀名,或许就是为了解决这种场景。有待进一步的测试。
在另外一篇文章中,介绍了无需前端的Forge Viewer API获取模型层次结构和DbId。