fix: inicializacao em cinza claro e amarração hierárquica assembly/peca no visualizador IFC

This commit is contained in:
2026-09-20 02:32:34 +00:00
parent 609f66c218
commit b29482b450
3 changed files with 140 additions and 66 deletions
+51 -21
View File
@@ -29,6 +29,7 @@ export interface PieceInfo {
pieceMark: string;
cleanMark?: string;
assemblyMark?: string;
cleanAssemblyMark?: string;
parentAssemblyID?: number;
phase?: string;
ofNumber?: string;
@@ -124,6 +125,14 @@ export function getCleanMarkValue(rawMark: string): string {
return cleaned;
}
// Helper: Identifica se uma marca é número de peça solta/corte (ex: 1000, 1001, 1002, 1010)
export function isSinglePartCutNumber(val: string): boolean {
if (!val) return false;
const clean = getCleanMarkValue(val);
const num = parseInt(clean, 10);
return !isNaN(num) && num >= 1000;
}
// Helper: Mapeamento de nome de material idêntico ao SteelXR
function getMaterialName(ifcApi: WebIFC.IfcAPI, modelID: number, matRef: any): string | null {
if (!matRef) return null;
@@ -440,6 +449,8 @@ export async function loadAndAuditIFC(
function extractBestMark(expressID: number): {
mark: string;
cleanMark: string;
assemblyMark: string;
cleanAssemblyMark: string;
section: string;
description: string;
} {
@@ -493,7 +504,10 @@ export async function loadAndAuditIFC(
}
}
if (!chosenMark && childToAssembly.has(expressID)) {
// Busca Assembly Mark no conjunto pai (IFCRELAGGREGATES)
let assemblyMark = '';
let cleanAssemblyMark = '';
if (childToAssembly.has(expressID)) {
const parentId = childToAssembly.get(expressID)!;
const parentProps = elementPropertiesMap.get(parentId) || {};
try {
@@ -512,13 +526,30 @@ export async function loadAndAuditIFC(
];
for (const pCand of parentCandidates) {
if (pCand && isValidMark(pCand)) {
chosenMark = String(pCand).trim();
assemblyMark = String(pCand).trim();
cleanAssemblyMark = getCleanMarkValue(assemblyMark);
break;
}
}
} catch {}
}
if (!assemblyMark && props.AssemblyMark && isValidMark(props.AssemblyMark)) {
assemblyMark = String(props.AssemblyMark).trim();
cleanAssemblyMark = getCleanMarkValue(assemblyMark);
}
// Em estruturas metálicas, a marca da peça apontada na produção é a marca do conjunto (Assembly Mark),
// a menos que a peça seja avulsa ou que não tenha conjunto pai
let finalMark = chosenMark;
if (assemblyMark && isValidMark(assemblyMark)) {
if (!finalMark || finalMark === 'indefinido' || isSinglePartCutNumber(finalMark)) {
finalMark = assemblyMark;
}
}
const clean = getCleanMarkValue(finalMark);
const section =
props.Section ||
props.Profile ||
@@ -528,11 +559,11 @@ export async function loadAndAuditIFC(
rawName ||
'';
const clean = getCleanMarkValue(chosenMark);
return {
mark: chosenMark || 'indefinido',
cleanMark: clean || chosenMark || 'indefinido',
mark: finalMark || 'indefinido',
cleanMark: clean || finalMark || 'indefinido',
assemblyMark: assemblyMark || finalMark || '',
cleanAssemblyMark: cleanAssemblyMark || clean || '',
section,
description: rawDesc
};
@@ -557,6 +588,8 @@ export async function loadAndAuditIFC(
type: 'IFCELEMENTASSEMBLY',
pieceMark: markInfo.mark,
cleanMark: markInfo.cleanMark,
assemblyMark: markInfo.assemblyMark,
cleanAssemblyMark: markInfo.cleanAssemblyMark,
childrenIDs: children,
connectedMeshIDs: children,
section: markInfo.section,
@@ -599,6 +632,8 @@ export async function loadAndAuditIFC(
ifcId: expressID,
pieceMark: markInfo.mark,
cleanMark: markInfo.cleanMark,
assemblyMark: markInfo.assemblyMark,
cleanAssemblyMark: markInfo.cleanAssemblyMark,
section: markInfo.section,
materialName,
connectedMeshIDs: connectedGroup
@@ -636,27 +671,22 @@ export async function loadAndAuditIFC(
geometry.setAttribute('normal', new THREE.BufferAttribute(normalArray, 3));
geometry.setIndex(new THREE.BufferAttribute(indices, 1));
// Cor original nativa do IFC igual ao SteelXR
// Padrão industrial solicitado: O modelo 3D IFC SEMPRE inicia com todas as peças 100% em cinza claro (#a1a1aa)
const color = placedGeometry.color;
const colorKey = (color.x * 255) << 16 | (color.y * 255) << 8 | (color.z * 255);
let material = materialsCache.get(colorKey);
if (!material) {
material = new THREE.MeshStandardMaterial({
color: new THREE.Color(color.x, color.y, color.z),
metalness: 0.25,
roughness: 0.65,
transparent: color.w < 1,
opacity: color.w,
side: THREE.DoubleSide,
});
materialsCache.set(colorKey, material);
}
const initialGrayMaterial = new THREE.MeshStandardMaterial({
color: new THREE.Color(0xa1a1aa),
metalness: 0.25,
roughness: 0.65,
side: THREE.DoubleSide,
});
const mesh3 = new THREE.Mesh(geometry, material);
const mesh3 = new THREE.Mesh(geometry, initialGrayMaterial);
mesh3.userData = {
ifcId: expressID,
pieceMark: markInfo.mark,
cleanMark: markInfo.cleanMark,
assemblyMark: markInfo.assemblyMark,
cleanAssemblyMark: markInfo.cleanAssemblyMark,
section: markInfo.section,
materialName,
nativeColor: new THREE.Color(color.x, color.y, color.z),