In the post we introduce the properties of Navisworks objects. On the other hand, we often need to find objects by the properties. Finding items is a large part of the API. There are three main mechanisms.
1. Iteration
This is the basic way to get the items you are concerned with. However, it has a time cost with lower efficiency.
// Filter the model items from the selected items
foreach (ModelItem oItem in oDoc.CurrentSelection.SelectedItems)
{
//examine the item with property 'Entity Handle'
// and 'Value' is '187E2' and has geometry
if (oItem.HasGeometry &&
oItem.PropertyCategories.FindPropertyByDisplayName
("Entity Handle", "Value").Value.ToDisplayString() =
"187E2")
{
// found!
}
}
2. Search API
This corresponds to the Find Items functionality in Roamer. It is similar to the product functionality, but with further refined conditions. It is fast because it is happens in native code, but can only do what Roamer can do.
Selection: is what to search (i.e. Where to look).
Conditions: is what to find. A Condition is basically a test against an object property with quite flexible usage. It also has a few other options that are properties on the Search class.
The basic steps to use this API is as below:
// create a search class
Search search = new Search();
// add Selection and Conditions
// this code finds the item
// with Entity Handle >> value = "187E2"
search.Selection.SelectAll();
search.SearchConditions.Add(
SearchCondition.HasPropertyByDisplayName(
"Entity Handle",
"Value").EqualValue(VariantData.
FromDisplayString("187E2")));
// Execute Search
ModelItemCollection items = search.FindAll(
Application.ActiveDocument,false);
// highlight the items
Application.ActiveDocument.CurrentSelection.
CopyFrom(items);
We will introduce more usage of Search API in another blog.
3. LINQ
LINQ (Language Integrated Query) is a high level use, which allows much expression. Please refer to MSDN for more details on LINQ.
// in whole model items, find the items that has geometry
IEnumerable<ModelItem> items =
from x in doc.Models.GetRootItems().
DescendantsAndSelf
where x.HasGeometry
select x;
// highlight the items
doc.CurrentSelection.CopyFrom(items);
LINQ is slowest because it has to call back and forth between managed and native code. The Search API 'FindAll' method of the search class is internal to the Navisworks API and will usually return faster than the LINQ style method from before which, eventually, works in an iterative manner over the selection. One suggestion could be to use Search to select a subset of the model and then use LINQ to perform more sophisticated searches over the returned selection. e.g.
// assume we have had a search defined by Search API
// find the items which are more
// expensive than 100, on the basis of a search result
// assume a function 'ItemPrice'to check the ‘?price’ˉ
// information of the items
IEnumerable<ModelItem> expensive_items =
from item in search.FindAll(
Application.ActiveDocument, false);
where ItemPrice(item) > 100
select item;