// Initialize viewer component
let viewerConfigs = {
domElementId: "viewer",
showUI: true
};
let viewer = new bimU.Viewer(viewerConfigs);
viewer.initialize();
// Register selection event
let selectedElementIndices;
viewer.addEventListener(bimU.EventsEnum.ON_SELECTION_CHANGED, (e) => {
// Cache selected element indices
selectedElementIndices = e.selectedElementIndices;
});
// Add custom button for calculating the sum of selected perimeters
viewer.addCustomButton("button1", "chart-donut", "#e91e63", "Calculate Total Perimeter", () => {
if (!selectedElementIndices || selectedElementIndices.length === 0) {
viewer.showDialog("Warning", "No element is selected.", "Close", null, null, true);
return;
}
// Filter out selected floor elements
let propertyFilter1 = new bimU.PropertyFilter("Element", "Category", "Floors");
let propertyFilter2 = new bimU.PropertyFilter(null, "eIdx", selectedElementIndices);
propertyFilter2.operator = bimU.OperatorsEnum.IN;
// Calculate total perimeter
let propertySelector = new bimU.PropertySelector("Dimensions", "Perimeter");
propertySelector.dataType = bimU.DataTypesEnum.FLOAT;
let func = bimU.AggregateFunctionsEnum.SUM;
// Send query to BIM database
viewer.aggregateElementProperty([propertyFilter1, propertyFilter2], propertySelector, func, (data) => {
viewer.showDialog("Total Perimeter:", String(data[0].Perimeter), "Close", null, null, true);
}, onError);
});
// Add custom button for calculating the sum of selected areas
viewer.addCustomButton("button2", "grid", "#e91e63", "Calculate Total Area", () => {
if (!selectedElementIndices || selectedElementIndices.length === 0) {
viewer.showDialog("Warning", "No element is selected.", "Close", null, null, true);
return;
}
// Filter out selected floor elements
let filterExpression = `"Element:Category" = 'Floors' AND eIdx IN ('${selectedElementIndices.join(`', '`)}')`;
// The property value of "Area" includes a unit (e.g., 100 m²) and is therefore not stored as a number.
// So we have to extract it from the text string and put together a raw query to aggregate the values.
let propertyName = `Dimensions:Area`;
// Work out character length for the number to be extracted
let length = `CHAR_LENGTH("${propertyName}") - 3`;
// Note that the first character of the string has index 1 rather than 0
let extractedNumber = `SUBSTRING("${propertyName}", 1, ${length})`;
// Convert string to floating number and calculate the sum
let selectExpression = `SUM( CAST( ${extractedNumber} AS FLOAT) ) AS "TotalArea"`;
viewer.getElementDataByQuery(filterExpression, selectExpression, 1000, (data) => {
viewer.showDialog("Total Area:", String(data[0].TotalArea) + " m²", "Close", null, null, true);
}, onError);
});
// Callbacks
let onPorgress = (e) => {
console.log(e);
viewer.showDialog("Loading...", "Progress:" + e.progress, "Close", null, null, true);
};
let onLoaded = (e) => {
console.log(e);
viewer.closeDialog();
};
let onError = (e) => console.error(e);
// Load model
let modelConfigs = {
modelId: "5dffdeb8cb9115000420d21f",
password: "123456",
};
viewer.loadModel(modelConfigs, onPorgress, onLoaded, onError);
<div id="viewer" style="width:600px;height:400px;background-color:black;border:5px solid gray;"></div>
.image {
width: 60px;
height: 40px;
margin: 5px;
border: 2px solid gray;
}
External resources loaded into this fiddle: