Skip to content

Commit

Permalink
feat(obc): display units in ElementProperties
Browse files Browse the repository at this point in the history
  • Loading branch information
HoyosJuan committed Aug 23, 2024
1 parent beddd8d commit bbf0c96
Show file tree
Hide file tree
Showing 4 changed files with 110 additions and 9 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/* eslint-disable import/no-extraneous-dependencies */
import * as FRAGS from "@thatopen/fragments";
import * as WEBIFC from "web-ifc";

const map: Record<string, any> = {
IFCLENGTHMEASURE: "LENGTHUNIT",
IFCAREAMEASURE: "AREAUNIT",
IFCVOLUMEMEASURE: "VOLUMEUNIT",
IFCPLANEANGLEMEASURE: "PLANEANGLEUNIT",
};

const ifcUnitSymbols: Record<string, { symbol: string; digits: number }> = {
MILLIMETRE: { symbol: "mm", digits: 0 },
METRE: { symbol: "m", digits: 2 },
KILOMETRE: { symbol: "km", digits: 2 },
SQUARE_METRE: { symbol: "m²", digits: 2 },
CUBIC_METRE: { symbol: "m³", digits: 2 },
DEGREE: { symbol: "°", digits: 2 },
RADIAN: { symbol: "rad", digits: 2 },
GRAM: { symbol: "g", digits: 0 },
KILOGRAM: { symbol: "kg", digits: 2 },
MILLISECOND: { symbol: "ms", digits: 0 },
SECOND: { symbol: "s", digits: 0 },
};

export const getModelUnit = async (
model: FRAGS.FragmentsGroup,
type: string,
) => {
const units = Object.values(
(await model.getAllPropertiesOfType(WEBIFC.IFCUNITASSIGNMENT))!,
)[0];
let unit: string | undefined;
for (const handle of units.Units) {
const unitAttrs = await model.getProperties(handle.value);
if (unitAttrs && unitAttrs.UnitType?.value === map[type]) {
unit = `${unitAttrs.Prefix?.value ?? ""}${unitAttrs.Name?.value ?? ""}`;
break;
}
}
if (unit) return ifcUnitSymbols[unit];
return null;
};
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,15 @@
import * as FRAGS from "@thatopen/fragments";
import * as BUI from "@thatopen/ui";
import * as WEBIFC from "web-ifc";
import { getModelUnit } from "./get-model-unit";
import { ElementPropertiesUI } from "./template";

export const createPsetsRow = async (
model: FRAGS.FragmentsGroup,
psets: { [attribute: string]: any }[],
uiState: ElementPropertiesUI,
) => {
const { displayUnits } = uiState;
const row: BUI.TableGroupData = { data: { Name: "PropertySets" } };
for (const pset of psets) {
const setRow: BUI.TableGroupData = {
Expand All @@ -21,10 +25,22 @@ export const createPsetsRow = async (
attr.includes("Value"),
);
if (!(valueKey && propAttrs[valueKey])) continue;
let value = propAttrs[valueKey].value;
let symbol = "";
if (displayUnits) {
const { name } = propAttrs[valueKey];
const units: Record<string, any> =
(await getModelUnit(model, name)) ?? {};
symbol = units.symbol;
value = propAttrs[valueKey].value;
if (typeof value === "number" && units.digits) {
value = value.toFixed(units.digits);
}
}
const propRow: BUI.TableGroupData = {
data: {
Name: propAttrs.Name.value,
Value: propAttrs[valueKey].value,
Value: `${value} ${symbol ?? ""}`,
},
};
if (!setRow.children) setRow.children = [];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,15 @@
import * as FRAGS from "@thatopen/fragments";
import * as BUI from "@thatopen/ui";
import * as WEBIFC from "web-ifc";
import { getModelUnit } from "./get-model-unit";
import { ElementPropertiesUI } from "./template";

export const createQsetsRow = async (
model: FRAGS.FragmentsGroup,
qsets: { [attribute: string]: any }[],
uiState: ElementPropertiesUI,
) => {
const { displayUnits } = uiState;
const row: BUI.TableGroupData = { data: { Name: "QuantitySets" } };
for (const qset of qsets) {
const setRow: BUI.TableGroupData = { data: { Name: qset.Name.value } };
Expand All @@ -15,14 +19,27 @@ export const createQsetsRow = async (
const { value: propID } = qtoHandle;
const propAttrs = await model.getProperties(propID);
if (!propAttrs) continue;

const valueKey = Object.keys(propAttrs).find((attr) =>
attr.includes("Value"),
);
if (!(valueKey && propAttrs[valueKey])) continue;
let value = propAttrs[valueKey].value;
let symbol = "";
if (displayUnits) {
const { name } = propAttrs[valueKey];
const units: Record<string, any> =
(await getModelUnit(model, name)) ?? {};
symbol = units.symbol;
value = propAttrs[valueKey].value;
if (typeof value === "number" && units.digits) {
value = value.toFixed(units.digits);
}
}
const propRow: BUI.TableGroupData = {
data: {
Name: propAttrs.Name.value,
Value: propAttrs[valueKey].value,
Value: `${value} ${symbol ?? ""}`,
},
};
if (!setRow.children) setRow.children = [];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,19 +11,35 @@ import { createQsetsRow } from "./qsets-row";
import { createAttributesRow } from "./attributes-row";

/**
* Heloooooooooo
* UI State to render an element properties table
*/
export interface ElementPropertiesUI {
/**
* The main entry point of @thatopen/components in your app
*/
components: OBC.Components;
/**
* The selection of elements to show its properties in the table
*/
fragmentIdMap: FRAGS.FragmentIdMap;
/**
* Display a warning instead of the table in case there is no selection
* @default true
*/
emptySelectionWarning?: boolean;
/**
* Display units (m, mm, m², etc) in numeric values when apply
* @remarks It can be expensive (temporal)
* @default false
*/
displayUnits?: boolean;
// dataToDisplay?: (
// | "Attributes"
// | "PropertySets"
// | "QuantitySets"
// | "Classifications"
// | "Tasks"
// | "SpatialContainers"
// | "SpatialContainer"
// )[];
}

Expand All @@ -40,6 +56,7 @@ const processDefinedByRelations = async (
model: FRAGS.FragmentsGroup,
expressID: number,
row: BUI.TableGroupData,
uiState: ElementPropertiesUI,
) => {
const indexer = components.get(OBC.IfcRelationsIndexer);
const definedByRelations = indexer.getEntityRelations(
Expand All @@ -59,11 +76,11 @@ const processDefinedByRelations = async (
if (attrs.type === WEBIFC.IFCELEMENTQUANTITY) qsets.push(attrs);
}

const psetRow = await createPsetsRow(model, psets);
const psetRow = await createPsetsRow(model, psets, uiState);
if (psetRow.children) addRowChildren(row, psetRow);

const qsetRow = await createQsetsRow(model, qsets);
if (qsetRow.children) addRowChildren(row, psetRow);
const qsetRow = await createQsetsRow(model, qsets, uiState);
if (qsetRow.children) addRowChildren(row, qsetRow);
}
};

Expand Down Expand Up @@ -167,6 +184,7 @@ let processedElements: { [modelID: string]: Map<number, BUI.TableGroupData> } =
const computeTableData = async (
components: OBC.Components,
fragmentIdMap: FRAGS.FragmentIdMap,
uiState: ElementPropertiesUI,
) => {
const indexer = components.get(OBC.IfcRelationsIndexer);
const fragments = components.get(OBC.FragmentsManager);
Expand Down Expand Up @@ -212,7 +230,13 @@ const computeTableData = async (
const elementRelations = modelRelations.get(expressID);
if (!elementRelations) continue;

await processDefinedByRelations(components, model, expressID, elementRow);
await processDefinedByRelations(
components,
model,
expressID,
elementRow,
uiState,
);
await processAssociateRelations(components, model, expressID, elementRow);
await processAssignmentRelations(
components,
Expand Down Expand Up @@ -243,7 +267,8 @@ export const elementPropertiesTemplate = (state: ElementPropertiesUI) => {
const table = e as BUI.Table;
table.columns = [{ name: "Name", width: "12rem" }];
table.headersHidden = true;
table.loadFunction = () => computeTableData(components, fragmentIdMap);
table.loadFunction = () =>
computeTableData(components, fragmentIdMap, state);
const loaded = await table.loadData(true);
if (loaded) table.dispatchEvent(new Event("datacomputed"));
};
Expand Down

0 comments on commit bbf0c96

Please sign in to comment.