Autodesk Forge Viewer, Search - autodesk-forge

I am using Autodesk Forge Viewer.
viewer.search('"' + keyword +'"', function(e)
{
viewer.select(e);
viewer.fitToView(e);
}
I am searching like this.
The problem is that it searches for both "SG-100" and "SSG-100".
I only want to search for SG-100.
How can I do this?
Help!

My suggestion would be to do a second filter inside the search:
viewer.search(keyword, (dbIds) => {
// success
viewer.getBulkProperties(dbIds, ['AttributeName'], (elements) => {
let dbIdsToSelect = [];
for(var i=0; i<elements.length; i++){
if (elements[i].properties[0].displayValue===keyword)
dbIdsToSelect.push(elements[i].dbId;
}
viewer.select(dbIdsToSelect);
viewer.fitToView(dbIdsToSelect);
}
}, (e) => {
// error, handle here...
}, ['AttributeName']);

I agree with Augusto's suggestion that you'd need to limit the search scope to specific properties only to avoid partial matches. According to the search function description it's supposed to do just that if you provide the list of property names in the 4th argument that is called 'attributeNames'. Unfortunately, from my experience, that does not work, so you need a second level filtering by using a getBulkProperties function that will reduce the list of dbIds from the search to only those that have specific properties defined. Pay attention, that the search method belong to the viewer object but the getBulkProperties method belongs to the viewer.model object.

Related

How can I filter only on elements in the Autodesk Forge Viewer API that are relevant for quantity take off?

For BIM model quantity take off I need to filter on all elements that are relevant for quantity take off. Below are some visual examples of the element I need (green circled) and which elements I don't need (red cross)
Example 1
Example 2
How can I filter only on elements in the Autodesk Forge API that are relevant for quantity take off?
When I use the API I get all levels and I didn't manage to get the level I need.
First of all, you'll need to define the logic to filter these elements.
From the images you've shared, the hierarchy tree of your model seems to be organized in a way that you're interested in the nodes in the 5th level from the root node.
So, if that's the case, you could use something like the snippet below to find the nodes' paths and then filter it to retrieve the 5th-level nodes' dbids:
var findfifthNodes = function (model) {
return new Promise(function (resolve, reject) {
model.getObjectTree(function (tree) {
let nodes = {};
tree.enumNodeChildren(tree.getRootId(), function (dbid) {
let nodepath = [dbid];
if(!!nodes[tree.getNodeParentId(dbid)]){
nodepath = nodepath.concat(nodes[tree.getNodeParentId(dbid)]);
}
nodes[dbid] = nodepath;
}, true /* recursively enumerate children's children as well */);
let fifthNodes = Object.values(nodes).filter(p => p.length == 5).map(a => a[0]);
resolve(fifthNodes);
}, reject);
});
}
You can also add your own custom tree view that might be more suitable to your workflow.
To achieve that, please refer to https://aps.autodesk.com/blog/custom-tree-views

Get Property Name of Part that is Selected

I am currently making a web page that uses the forge viewer. How can I make a function that will return the value from the "Properties" tab inside the viewer. I need to be able to get the value of the 'name' property inside the viewer, when a part is selected by the user. Any help is much appreciated!
Cheers!
viewer.addEventListener(Autodesk.Viewing.SELECTION_CHANGED_EVENT, onSelectionChanged)
function onSelectionChanged(dbids){
console.log(dbids)
viewer.getProperties(dbIds, props => {
props.properties.forEach(prop => {
// any custom action with data?
//prop.displayName
//prop.displayValue
//prop.displayCategory
// etc
});
}
Blog: https://forge.autodesk.com/blog/property-inspector-viewer

Getting selected elements properties in forge viewer when more then one model loaded

I have have a viewer app with 8 models loaded
I have a plugin looking for the "AGGREGATE_SELECTION_CHANGED_EVENT" event
this.viewer.addEventListener(Autodesk.Viewing.AGGREGATE_SELECTION_CHANGED_EVENT, this.onSelectionBinded);
I need to be able to get access to the selected elements properties
this.viewer.getProperties(_dbId, (result) => { })
but it seams the viewer is only looking at the last loaded model not all of them.
do i have to load/switch to the other models ? and if so how.
The viewer.model is always pointed to the first loaded model with my experience. If you want to access other loaded models, you can obtain them via calling viewer.impl.modelQueue().getModels(). Afterward, call Viewer properties APIs in this way:
var allModels = viewer.impl.modelQueue().getModels();
var model = allModels[1];
model.getProperties( dbId, onSuccessCallback, onErrorCallback );
Besides, you can obtain the model instance in the function argument event of your onSelectionBinded callback. So, your onSelectionBinded can be modified to this based on the above logic:
this.onSelectionBinded = function( event ) {
var selSet = event.selections;
var firstSel = selSet[0];
var model = firstSel.model;
var dbIds = firstSel.dbIdArray;
var firstDbId = dbIds[0];
model.getProperties( firstDbId, onSuccessCallback, onErrorCallback );
}
Hope it helps!
I know this is a little late...
Another way to get properties for multi-model, is to use the aggregated method.
var DBids = viewer.impl.selector.getAggregateSelection();
I have a blog post and sample website that goes through the details:
https://forge.autodesk.com/blog/highlighting-clashes-multi-model

Set marker visible with knockout JS ko.utils.arrayFilter

Hello guys I am trying to create an app that sets the appropriate markers visible when a knockout search is being done.
Basically the app is.
When someone does a search the list that is bellow it, filters the list and makes only the markers that are associated with the filter list visible on the map.
I have created a ko.utils.arrayFilter and I am trying to set only the item.marker.setVisible(true)
My Github link is https://github.com/Aimpotis/map3
Thank you again and much respect to the community it is helping me learn a lot
All you need is to set the visibility of the marker to match whether it is found:
if (!filter) {
// this is new
ko.utils.arrayForEach(self.listLoc(), function (item) {
item.marker.setVisible(true);
});
return self.listLoc();
} else {
return ko.utils.arrayFilter(self.listLoc(), function(item) {
var result = (item.title.toLowerCase().search(filter) >= 0)
item.marker.setVisible(result); // this is a new line
return result;
});
}
Working fiddle.
Note: unless you're supporting particularly old browsers, you can use the Array filter method rather than Knockout's arrayFilter util, and .foreach instead of arrayForEach.

Highlight an array of nodes in Autodesk Viewer

Problem:
I have an array of nodes that I would like to highlight when an action happens.
My Attempted Solution
I have tried using code from the model browser, but it seems to only accept one dbId at a time. I have tried to iterate over my array and call it, but the highlighting doesn't work when that is done.
for (var i = 0; i < dbIdsArray.length; i++) {
viewerApp.getCurrentViewer().impl.rolloverObjectNode(dbIdsArray[i]);
}
Any advice on how to implement this correctly would be a great help.
Thanks
If you want to highlight a couple of dbids, there are some different ways depending on your requirement.
Maybe you can use the API Viewer3D.isolate() to highlight the
selected objects by isolating them, you can just input dbId array as
follow, also, you can zoom the selected items to the viewer window
use the API Viewer3D.fitToView() to focus on them:
viewer.isolate(dbIdArray);
viewer.fitToView(dbIdArray);
If you want to highlight the selected objects with different color,
maybe you can try the new API Viewer3D.setThemingColor(), here is the
simple code sample. Remember you need to clear the color using
Viewer3D.clearThemingColors(). The simple code sample should be like:
I'm able to highlight components using following code:
viewer.addEventListener(
Autodesk.Viewing.SELECTION_CHANGED_EVENT,
function (e) {
if(e.dbIdArray.length) {
var dbId = e.dbIdArray[0];
viewer.impl.highlightObjectNode(
viewer.model, dbId, true, false)
viewer.select([])
viewer.impl.sceneUpdated(true)
}
})
This is using function:
viewer.impl.highlightObjectNode = function(model, dbId, value, simpleHighlight)