🚀 Auto-deploy: melhoria no snap e medição AR em 01/06/2026 00:41:59
This commit is contained in:
+158
-3
@@ -7,6 +7,53 @@ const WASM_PATH = 'https://unpkg.com/web-ifc@0.0.57/';
|
||||
/**
|
||||
* Convert an IFC file (ArrayBuffer) into a GLB Blob using web-ifc + GLTFExporter.
|
||||
*/
|
||||
function getMaterialName(ifcApi: WebIFC.IfcAPI, modelID: number, matRef: any): string | null {
|
||||
if (!matRef) return null;
|
||||
const matId = matRef.value;
|
||||
if (!matId) return null;
|
||||
try {
|
||||
const matLine = ifcApi.GetLine(modelID, matId);
|
||||
if (!matLine) return null;
|
||||
|
||||
if (matLine.Name && matLine.Name.value) {
|
||||
return matLine.Name.value;
|
||||
}
|
||||
|
||||
if (matLine.Materials) {
|
||||
for (const mRef of matLine.Materials) {
|
||||
const name = getMaterialName(ifcApi, modelID, mRef);
|
||||
if (name) return name;
|
||||
}
|
||||
}
|
||||
|
||||
if (matLine.MaterialConstituents) {
|
||||
for (const mcRef of matLine.MaterialConstituents) {
|
||||
const mcLine = ifcApi.GetLine(modelID, mcRef.value);
|
||||
if (mcLine && mcLine.Material) {
|
||||
const name = getMaterialName(ifcApi, modelID, mcLine.Material);
|
||||
if (name) return name;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (matLine.MaterialProfileSet) {
|
||||
return getMaterialName(ifcApi, modelID, matLine.MaterialProfileSet);
|
||||
}
|
||||
if (matLine.MaterialProfiles) {
|
||||
for (const mpRef of matLine.MaterialProfiles) {
|
||||
const mpLine = ifcApi.GetLine(modelID, mpRef.value);
|
||||
if (mpLine && mpLine.Material) {
|
||||
const name = getMaterialName(ifcApi, modelID, mpLine.Material);
|
||||
if (name) return name;
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
// Silencia erros de atributos inexistentes
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
export async function parseIFCtoThree(buffer: ArrayBuffer): Promise<THREE.Scene> {
|
||||
const ifcApi = new WebIFC.IfcAPI();
|
||||
ifcApi.SetWasmPath(WASM_PATH, true);
|
||||
@@ -15,6 +62,87 @@ export async function parseIFCtoThree(buffer: ArrayBuffer): Promise<THREE.Scene>
|
||||
const data = new Uint8Array(buffer);
|
||||
const modelID = ifcApi.OpenModel(data);
|
||||
|
||||
// Mapeamento de materiais
|
||||
const elementMaterialMap = new Map<number, string>();
|
||||
try {
|
||||
const rels = ifcApi.GetLineIDsWithType(modelID, WebIFC.IFCRELASSOCIATESMATERIAL);
|
||||
for (let i = 0; i < rels.size(); i++) {
|
||||
const relId = rels.get(i);
|
||||
const rel = ifcApi.GetLine(modelID, relId);
|
||||
if (rel && rel.RelatedObjects && rel.RelatingMaterial) {
|
||||
const matName = getMaterialName(ifcApi, modelID, rel.RelatingMaterial);
|
||||
if (matName) {
|
||||
for (const objRef of rel.RelatedObjects) {
|
||||
elementMaterialMap.set(objRef.value, matName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
console.warn('[IFC Parser] Falha ao mapear materiais:', err);
|
||||
}
|
||||
|
||||
// Mapeamento de propriedades adicionais
|
||||
const elementPropertiesMap = new Map<number, Record<string, string>>();
|
||||
try {
|
||||
const relsProp = ifcApi.GetLineIDsWithType(modelID, WebIFC.IFCRELDEFINESBYPROPERTIES);
|
||||
for (let i = 0; i < relsProp.size(); i++) {
|
||||
const relId = relsProp.get(i);
|
||||
const rel = ifcApi.GetLine(modelID, relId);
|
||||
if (rel && rel.RelatedObjects && rel.RelatingPropertyDefinition) {
|
||||
const propDefId = rel.RelatingPropertyDefinition.value;
|
||||
const propDef = ifcApi.GetLine(modelID, propDefId);
|
||||
|
||||
if (propDef) {
|
||||
const props: Record<string, string> = {};
|
||||
|
||||
if (propDef.HasProperties) {
|
||||
for (const pRef of propDef.HasProperties) {
|
||||
const pLine = ifcApi.GetLine(modelID, pRef.value);
|
||||
if (pLine && pLine.Name) {
|
||||
const name = pLine.Name.value;
|
||||
let value = '';
|
||||
if (pLine.NominalValue) {
|
||||
value = String(pLine.NominalValue.value);
|
||||
}
|
||||
if (name && value) {
|
||||
props[name] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (propDef.Quantities) {
|
||||
for (const qRef of propDef.Quantities) {
|
||||
const qLine = ifcApi.GetLine(modelID, qRef.value);
|
||||
if (qLine && qLine.Name) {
|
||||
const name = qLine.Name.value;
|
||||
let value = '';
|
||||
if (qLine.LengthValue !== undefined) value = `${qLine.LengthValue.toFixed(1)} mm`;
|
||||
else if (qLine.AreaValue !== undefined) value = `${qLine.AreaValue.toFixed(1)} m²`;
|
||||
else if (qLine.VolumeValue !== undefined) value = `${qLine.VolumeValue.toFixed(2)} m³`;
|
||||
else if (qLine.NominalValue) value = String(qLine.NominalValue.value);
|
||||
|
||||
if (name && value) {
|
||||
props[name] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (Object.keys(props).length > 0) {
|
||||
for (const objRef of rel.RelatedObjects) {
|
||||
const existing = elementPropertiesMap.get(objRef.value) ?? {};
|
||||
elementPropertiesMap.set(objRef.value, { ...existing, ...props });
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
console.warn('[IFC Parser] Falha ao mapear propriedades:', err);
|
||||
}
|
||||
|
||||
const scene = new THREE.Scene();
|
||||
const materials: Map<number, THREE.MeshStandardMaterial> = new Map();
|
||||
|
||||
@@ -22,11 +150,38 @@ export async function parseIFCtoThree(buffer: ArrayBuffer): Promise<THREE.Scene>
|
||||
const placedGeometries = mesh.geometries;
|
||||
const expressID = (mesh as unknown as { expressID?: number }).expressID ?? 0;
|
||||
|
||||
// One Group per IfcProduct → represents a single "element" (beam, plate…).
|
||||
// userData is preserved by GLTFExporter as `extras` and survives reload.
|
||||
let name = '';
|
||||
let tag = '';
|
||||
let objectType = '';
|
||||
let description = '';
|
||||
try {
|
||||
const elementLine = ifcApi.GetLine(modelID, expressID);
|
||||
if (elementLine) {
|
||||
name = elementLine.Name?.value ?? '';
|
||||
tag = elementLine.Tag?.value ?? '';
|
||||
objectType = elementLine.ObjectType?.value ?? '';
|
||||
description = elementLine.Description?.value ?? '';
|
||||
}
|
||||
} catch (e) {}
|
||||
|
||||
const materialName = elementMaterialMap.get(expressID) ?? '';
|
||||
const extraProps = elementPropertiesMap.get(expressID) ?? {};
|
||||
|
||||
const elementGroup = new THREE.Group();
|
||||
elementGroup.name = `ifc_${expressID}`;
|
||||
elementGroup.userData = { ifcElement: true, ifcId: expressID };
|
||||
elementGroup.userData = {
|
||||
ifcElement: true,
|
||||
ifcId: expressID,
|
||||
materialName,
|
||||
properties: {
|
||||
name,
|
||||
tag,
|
||||
objectType,
|
||||
description,
|
||||
material: materialName,
|
||||
...extraProps
|
||||
}
|
||||
};
|
||||
|
||||
for (let i = 0; i < placedGeometries.size(); i++) {
|
||||
const placedGeometry = placedGeometries.get(i);
|
||||
|
||||
Reference in New Issue
Block a user