Overview
The ChartData component extracts building element data from loaded IFC models and prepares it for visualization using Chart.js. It provides methods to analyze elements by type, by building level, and generate chart-ready datasets.
Class Definition
export class ChartData extends OBC.Component {
enabled: boolean = true;
static uuid = OBC.UUID.create();
fragmentGroup = this.components.get(OBC.FragmentsManager);
constructor(components: OBC.Components) {
super(components);
components.add(ChartData.uuid, this);
}
}
Location: src/bim-components/ChartData/index.ts:28
Properties
Flag indicating whether the component is active
Dynamically generated UUID identifier for the component instance
fragmentGroup
OBC.FragmentsManager
required
Reference to the FragmentsManager containing all loaded building models
Interfaces
ChartData Interface
Represents a collection of building elements of a specific type.
export interface ChartData {
expressIds: number[],
elementType: string,
color: string,
}
Location: src/bim-components/ChartData/index.ts:7
Array of IFC Express IDs identifying specific building elements
Human-readable element type name (e.g., “IfcWall”, “Ground Floor”, “IfcSlab”)
RGB color string for chart visualization (e.g., “rgba(255, 0, 0, 0.5)“)
BarDataset Interface
Chart.js compatible dataset structure for bar and pie charts.
export interface BarDataset {
type: string,
data: {
labels: string[],
datasets: [{
label: string,
data: number[],
backgroundColor: string[],
borderWidth: number[],
borderRadius: number[],
borderColor: string[]
}]
}
}
Location: src/bim-components/ChartData/index.ts:13
Chart type (e.g., “bar”, “pie”, “doughnut”)
Array of label strings for each data point
Dataset label (e.g., “Quantity”)
Numeric values for each data point
data.datasets[0].backgroundColor
Background color for each bar/segment
data.datasets[0].borderWidth
Border width for each element
data.datasets[0].borderRadius
Border radius for rounded corners
data.datasets[0].borderColor
Border color for each element
Methods
getPropertiesOfSpecificLevel
Analyzes all building storeys (levels/floors) in loaded models and returns element counts per level.
getPropertiesOfSpecificLevel = async (): Promise<ChartData[]>
Location: src/bim-components/ChartData/index.ts:51
Array of ChartData objects, one per building level, containing all elements in that level
Process Flow:
- Iterates through all loaded models in FragmentsManager
- Extracts all
IFCBUILDINGSTOREY entities
- For each level, finds all contained elements using spatial relationships
- Generates unique colors for each level
- Returns array with expressIds, level name, and color
Example:
const chartData = components.get(ChartData);
const levelData = await chartData.getPropertiesOfSpecificLevel();
// Result:
// [
// {
// expressIds: [1234, 1235, 1236, ...],
// elementType: "Ground Floor",
// color: "rgb(142, 68, 173)"
// },
// {
// expressIds: [2234, 2235, 2236, ...],
// elementType: "First Floor",
// color: "rgb(52, 152, 219)"
// }
// ]
console.log(`${levelData[0].elementType} has ${levelData[0].expressIds.length} elements`);
// Output: "Ground Floor has 245 elements"
Implementation:
const indexer = this.components.get(OBC.IfcRelationsIndexer);
const usedColors = new Set<string>();
let levelsData: ChartData[] = [];
for (const [_, model] of this.fragmentGroup.groups) {
const levelOfModel = await model.getAllPropertiesOfType(WEBIFC.IFCBUILDINGSTOREY);
if (!levelOfModel) continue;
for (const [expressId, properties] of Object.entries(levelOfModel)) {
let pieData: ChartData = {
expressIds: [],
elementType: properties.Name.value,
color: this.generateUniqueRGB(usedColors)
};
const expressIdAsNUmber = parseInt(expressId) as number;
const allElementInThisLevel = indexer.getEntitiesWithRelation(
model,
"ContainedInStructure",
expressIdAsNUmber
);
allElementInThisLevel.forEach(item => pieData.expressIds.push(item));
levelsData.push(pieData);
}
}
return levelsData;
Source: src/bim-components/ChartData/index.ts:51-74
getPropertiesOfSpecificType
Extracts all elements of a specific IFC type from all loaded models.
getPropertiesOfSpecificType = async (
typeNumber: number,
elementTypeName: string,
color: string
): Promise<ChartData>
Location: src/bim-components/ChartData/index.ts:76
IFC entity type number (e.g., WEBIFC.IFCWALL, WEBIFC.IFCSLAB)
Human-readable name for the element type (e.g., “IfcWall”, “IfcSlab”)
RGBA color string for visualization (e.g., “rgba(255, 0, 0, 0.5)”)
ChartData object containing all expressIds of the specified type across all models
Example:
import * as WEBIFC from "web-ifc";
const chartData = components.get(ChartData);
// Get all walls
const walls = await chartData.getPropertiesOfSpecificType(
WEBIFC.IFCWALL,
"IfcWall",
"rgba(255, 0, 0, 0.5)"
);
// Get all slabs
const slabs = await chartData.getPropertiesOfSpecificType(
WEBIFC.IFCSLAB,
"IfcSlab",
"rgba(0, 150, 255, 0.5)"
);
console.log(`Found ${walls.expressIds.length} walls and ${slabs.expressIds.length} slabs`);
Implementation:
let bar: ChartData = {
expressIds: [],
elementType: elementTypeName,
color
};
for (var [id, model] of this.fragmentGroup.groups) {
const searchType = await model.getAllPropertiesOfType(typeNumber);
if (!searchType) continue;
for (var [expressId, properties] of Object.entries(searchType)) {
bar.expressIds.push(parseInt(expressId, 10));
}
}
return bar;
Source: src/bim-components/ChartData/index.ts:76-91
getAllEntitiesOfType
Convenience method that retrieves walls, slabs, and beams from all models.
getAllEntitiesOfType = async (): Promise<ChartData[]>
Location: src/bim-components/ChartData/index.ts:97
Array containing three ChartData objects: walls, slabs, and beams
Example:
const chartData = components.get(ChartData);
const entities = await chartData.getAllEntitiesOfType();
// Result:
// [
// { expressIds: [...], elementType: "IfcWall", color: "rgba(255, 0, 0, 0.5)" },
// { expressIds: [...], elementType: "IfcSlab", color: "rgba(0, 150, 255, 0.5)" },
// { expressIds: [...], elementType: "IfcBeam", color: "rgba(0, 255, 0, 0.5)" }
// ]
const [walls, slabs, beams] = entities;
console.log(`Building has ${walls.expressIds.length} walls, ${slabs.expressIds.length} slabs, and ${beams.expressIds.length} beams`);
Implementation:
let data: ChartData[] = [];
for (var [id, model] of this.fragmentGroup.groups) {
let walls = await this.getPropertiesOfSpecificType(
WEBIFC.IFCWALL,
"IfcWall",
"rgba(255, 0, 0, 0.5)"
);
// Fallback to IFCWALLSTANDARDCASE if no walls found
if (walls.expressIds.length == 0) {
walls = await this.getPropertiesOfSpecificType(
WEBIFC.IFCWALLSTANDARDCASE,
"IfcWallStandardCase",
"rgba(255, 0, 0, 0.5)"
);
}
const slabs = await this.getPropertiesOfSpecificType(
WEBIFC.IFCSLAB,
"IfcSlab",
"rgba(0, 150, 255, 0.5)"
);
const beams = await this.getPropertiesOfSpecificType(
WEBIFC.IFCBEAM,
"IfcBeam",
"rgba(0, 255, 0, 0.5)"
);
data.push(walls);
data.push(slabs);
data.push(beams);
}
return data;
Source: src/bim-components/ChartData/index.ts:97-110
chartData
Converts ChartData array into a Chart.js compatible dataset.
chartData = (data: ChartData[], chartType: string): BarDataset
Location: src/bim-components/ChartData/index.ts:112
Array of ChartData objects to convert
Chart.js chart type (“bar”, “pie”, “doughnut”, “line”, etc.)
Chart.js compatible dataset ready for rendering
Example:
import Chart from "chart.js/auto";
const chartData = components.get(ChartData);
// Get element data
const entities = await chartData.getAllEntitiesOfType();
// Convert to chart dataset
const dataset = chartData.chartData(entities, "bar");
// Create chart
const ctx = document.getElementById('myChart') as HTMLCanvasElement;
const myChart = new Chart(ctx, dataset);
// The dataset structure:
// {
// type: "bar",
// data: {
// labels: ["IfcWall", "IfcSlab", "IfcBeam"],
// datasets: [{
// label: "Quantity",
// data: [150, 45, 30],
// backgroundColor: ["rgba(255, 0, 0, 0.5)", "rgba(0, 150, 255, 0.5)", "rgba(0, 255, 0, 0.5)"],
// borderWidth: [2, 2, 2],
// borderRadius: [8, 8, 8],
// borderColor: ["darkred", "darkblue", "darkgreen"]
// }]
// }
// }
Implementation:
let singleDataset: BarDataset = {
type: chartType as ChartType,
data: {
labels: data.map(item => { return item.elementType }),
datasets: [
{
label: "Quantity",
data: data.map(item => { return item.expressIds.length }),
backgroundColor: data.map(item => { return item.color }),
borderWidth: [2, 2, 2],
borderRadius: [8, 8, 8],
borderColor: ["darkred", "darkblue", "darkgreen"]
}
]
}
};
return singleDataset;
Source: src/bim-components/ChartData/index.ts:112-132
generateUniqueRGB
Internal utility method to generate unique random RGB colors.
generateUniqueRGB = (usedColors: Set<string>): string
Location: src/bim-components/ChartData/index.ts:38
Set of already used color strings to ensure uniqueness
Unique RGB color string in format “rgb(r, g, b)“
Complete Usage Example
Building Analytics Dashboard
import * as OBC from "@thatopen/components";
import Chart from "chart.js/auto";
import { ChartData } from "./bim-components/ChartData";
import * as WEBIFC from "web-ifc";
// Initialize
const components = new OBC.Components();
const chartData = components.get(ChartData);
// Create bar chart of element types
async function createElementTypeChart() {
const entities = await chartData.getAllEntitiesOfType();
const dataset = chartData.chartData(entities, "bar");
const ctx = document.getElementById('elementChart') as HTMLCanvasElement;
new Chart(ctx, dataset);
}
// Create pie chart of elements per level
async function createLevelDistributionChart() {
const levelData = await chartData.getPropertiesOfSpecificLevel();
const dataset = chartData.chartData(levelData, "pie");
const ctx = document.getElementById('levelChart') as HTMLCanvasElement;
new Chart(ctx, dataset);
}
// Custom analysis: doors and windows
async function createOpeningsChart() {
const doors = await chartData.getPropertiesOfSpecificType(
WEBIFC.IFCDOOR,
"Doors",
"rgba(139, 69, 19, 0.5)"
);
const windows = await chartData.getPropertiesOfSpecificType(
WEBIFC.IFCWINDOW,
"Windows",
"rgba(135, 206, 235, 0.5)"
);
const dataset = chartData.chartData([doors, windows], "doughnut");
const ctx = document.getElementById('openingsChart') as HTMLCanvasElement;
new Chart(ctx, dataset);
}
// Execute all charts
await createElementTypeChart();
await createLevelDistributionChart();
await createOpeningsChart();
Element Highlighting from Chart
import * as OBF from "@thatopen/components-front";
// Get chart data
const levelData = await chartData.getPropertiesOfSpecificLevel();
const dataset = chartData.chartData(levelData, "bar");
// Create interactive chart
const ctx = document.getElementById('myChart') as HTMLCanvasElement;
const myChart = new Chart(ctx, {
...dataset,
options: {
onClick: (event, elements) => {
if (elements.length > 0) {
const index = elements[0].index;
const selectedLevel = levelData[index];
// Highlight elements in 3D viewer
const highlighter = components.get(OBF.Highlighter);
const fragmentsManager = components.get(OBC.FragmentsManager);
for (const [_, model] of fragmentsManager.groups) {
highlighter.highlightByID(
"select",
selectedLevel.expressIds,
true,
false,
model
);
}
}
}
}
});
IFC Entity Types Reference
Commonly used types:
WEBIFC.IFCWALL - Wall elements
WEBIFC.IFCWALLSTANDARDCASE - Standard wall elements
WEBIFC.IFCSLAB - Floor/slab elements
WEBIFC.IFCBEAM - Beam elements
WEBIFC.IFCDOOR - Door elements
WEBIFC.IFCWINDOW - Window elements
WEBIFC.IFCBUILDINGSTOREY - Building levels/floors
WEBIFC.IFCCOLUMN - Column elements
Dependencies
@thatopen/components - Fragment and model management
@thatopen/ui - UI components
chart.js - Chart rendering library
web-ifc - IFC entity type definitions