9 Aug 2017
Enumerating leaf nodes on Viewer
When manipulating elements on the Viewer we often need to identify the leaf nodes on the hierarchy tree, meaning only the dbIds that are selectable on the model, or in other words, those who do not have children.
There are some samples around this, including this old blog post I wrote, but some of them rely on unsupported attributes. Ideally we should only use methods on the API, which are supported and not expected to change. Data structure may change from one version to the next.
Back to our topic, on a model like showing below, we're looking for "Basic Wall [123456]" leaf, not the parent nodes (e.g. STB 30.0, Basic Wall, or Walls).
To implement it we need to first .getObjectTree() of the model, then .getRootId() and check if is a leaf with .getChildCount(), if grater than 0 (zero), use .enumNodeChildren to check the next level on the hierarchy. As everything is based on callbacks, the code below uses a callback count to know when it's done.
function getAllLeafComponents(viewer, callback) {
var cbCount = 0; // count pending callbacks
var components = []; // store the results
var tree; // the instance tree
function getLeafComponentsRec(parent) {
cbCount++;
if (tree.getChildCount(parent) != 0) {
tree.enumNodeChildren(parent, function (children) {
getLeafComponentsRec(children);
}, false);
} else {
components.push(parent);
}
if (--cbCount == 0) callback(components);
}
viewer.getObjectTree(function (objectTree) {
tree = objectTree;
var allLeafComponents = getLeafComponentsRec(tree.getRootId());
});
}
To test it on the browser console, you can use something like:
getAllLeafComponents(NOP_VIEWER, function (dbIds) {
console.log('Found ' + dbIds.length + ' leaf nodes');
})