Property Database Queries
The Property Database contains all of the BIM data for a construction model, or manufacturing details for manufacturing models. The Property Database is kept on a dedicated web worker and accessing it is done via asynchronous messages.
In this tutorial we’ll be writing a functions that queries the model’s Property Database directly inside the web worker execution context.
Before You Begin
Makes sure to be using Viewer version 6.5.0 or later.
Instantiate a ViewingApplication before moving ahead; it provides a solid starting point.
Step 1: Writing a custom query function
The query function must be named userFunction
. Let’s start by writing a trivial query function.
function userFunction(pdb) {
return 42;
}
The trivial query function doesn’t interact with pdb
, the Property Database, yet. We’ll expand on its implementation on Step 3, but for now we’ll have it return a fix value of 42
.
Step 2: Executing the custom query function
Use viewer.model.getPropertyDb().executeUserFunction(userFunction)
which returns a Promise
that resolves with the return value of userFunction
.
var thePromise = viewer.model.getPropertyDb().executeUserFunction( userFunction );
thePromise.then(function(retValue){
console.log('retValue is: ', retValue); // prints 'retValue is: 42'
}).catch(function(err){
console.log("Something didn't go right...")
console.log(err);
});
After executing the above code snippet, you’ll see the message retValue is: 42 in the browser’s developer console.
Step 3: Quering the Property Database
Now it’s time to modify our userFunction
to have it interact with the Property Database.
The objective of the custom query function will be to return the id of the most massive parts in the model. To do this, we’ll iterate over all part-ids in the model and check their Mass property value.
Due to the Property Database data layout, we’ll first need to identify the index for the “Mass” property. Update the custom query function as follows:
function userFunction(pdb) {
//return 42;
var attrIdMass = -1;
// Iterate over all attributes and find the index to the one we are interested in
pdb.enumAttributes(function(i, attrDef, attrRaw){
var name = attrDef.name;
if (name === 'Mass') {
attrIdMass = i;
return true; // to stop iterating over the remaining attributes.
}
});
}
If the value of attrIdMass
is different than -1
, then we know that the model’s Property Database contains “Mass” data for its parts. Next we’ll have the function iterate over all parts and their properties, to find out which one is the most massive.
function userFunction(pdb) {
//return 42;
var attrIdMass = -1;
// Iterate over all attributes and find the index to the one we are interested in
pdb.enumAttributes(function(i, attrDef, attrRaw){
var name = attrDef.name;
if (name === 'Mass') {
attrIdMass = i;
return true; // to stop iterating over the remaining attributes.
}
});
// Early return is the model doesn't contain data for "Mass".
if (attrIdMass === -1)
return null;
// Now iterate over all parts to find out which one is the most massive.
var maxValue = 0;
var maxValId = -1;
pdb.enumObjects(function(dbId){
// For each part, iterate over their properties.
pdb.enumObjectProperties(dbId, function(attrId, valId){
// Only process 'Mass' property.
// The word "Property" and "Attribute" are used interchangeably.
if (attrId === attrIdMass) {
var value = pdb.getAttrValue(attrId, valId);
if (value > maxValue) {
maxValue = value;
maxValId = dbId;
}
// Stop iterating over additional properties when "Mass" is found.
return true;
}
});
});
// Return results
return {
id: maxValId,
mass: maxValue
}
}
And finally, the Promise’s resolve
function from Step 2 will have to be updated, too. In this case, we’ll have the viewer select and focus (zoom) on the most massive part.
var thePromise = viewer.model.getPropertyDb().executeUserFunction( userFunction );
thePromise.then(function(retValue){
//if (retValue === 42) {
// console.log('We got the expected value back.');
//}
if (!retValue) {
console.log("Model doesn't contain property 'Mass'.");
return;
}
var mostMassiveId = retValue.id;
viewer.select(mostMassiveId);
viewer.fitToView([mostMassiveId]);
console.log('Most massive part is', mostMassiveId, 'with Mass:', retValue.mass);
});
Final thoughts
When writing your own userFunction
, make sure that it avoids referencing objects that live outside the function’s scope. This is because the function gets serialized when messaged to the web worker.
What’s next?
Check out all the Property Database instance methods available to your custom query function.