Querying the Property Database
The Property Database contains all of the BIM data for a construction model and the manufacturing data for manufacturing models. The Property Database is kept on a dedicated web worker and accessing it is done via asynchronous messages.
In this example we’ll be writing a function that queries the Property Database of the model directly inside the web worker execution context.
Step 1: Writing a custom query function
The query function must be named userFunction
. Let’s start by writing a trivial query function for the Property Database.
function userFunction(pdb) {
return 42;
}
The trivial query function doesn’t interact with pdb
, the Property Database, yet. We’ll implement rhw interaction in Step 3. For now we’ll have it return a fixed 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 this code snippet, you’ll see the message retValue is: 42 in the browser’s developer console.
Step 3: Querying 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 is to return the ids of the heaviest 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 largest.
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 largest.
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 largest 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 you avoid 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?
To view an interactive example, see Querying Model Properties.
See Property Database for the instance methods available for your custom query function.