🚀 Auto-deploy: BrainWind atualizado em 13/07/2026 18:25:51

This commit is contained in:
2026-07-13 18:25:51 +00:00
parent af49dc395d
commit 8b515847f8
2 changed files with 78 additions and 48 deletions
+50 -31
View File
@@ -35,44 +35,63 @@ function PiperackModel({
const steelColor = isDark ? '#94a3b8' : '#64748b';
const pipeColors = ['#ef4444', '#3b82f6', '#f59e0b', '#10b981', '#8b5cf6'];
// Gera os pórticos
// Gera os pórticos longitudinais (as fileiras de colunas)
const frames = [];
const totalSpacing = spacing * (numFrames > 1 ? numFrames - 1 : 0);
const zOffset = totalSpacing / 2;
for (let i = 0; i < numFrames; i++) {
const z = -i * spacing;
const z = -zOffset + i * spacing;
// Simplificando o visual: desenha 5 colunas distribuídas ao longo da largura (comprimento do pipe-rack)
const numCols = Math.max(2, Math.floor(width / 4) + 1);
for (let c = 0; c < numCols; c++) {
const colX = -halfW + (c / (numCols - 1)) * width;
frames.push(
<mesh key={`col-${i}-${c}`} position={[colX, rackTop / 2, z]} receiveShadow castShadow>
<boxGeometry args={[0.3, rackTop, 0.3]} />
<meshStandardMaterial color={steelColor} metalness={0.6} roughness={0.4} />
</mesh>
);
}
// Viga Longitudinal da fileira
frames.push(
<group key={`frame-${i}`} position={[0, 0, z]}>
{/* Coluna Esquerda */}
<mesh position={[-halfW, rackTop / 2, 0]} receiveShadow castShadow>
<boxGeometry args={[0.3, rackTop, 0.3]} />
<meshStandardMaterial color={steelColor} metalness={0.6} roughness={0.4} />
</mesh>
{/* Coluna Direita */}
<mesh position={[halfW, rackTop / 2, 0]} receiveShadow castShadow>
<boxGeometry args={[0.3, rackTop, 0.3]} />
<meshStandardMaterial color={steelColor} metalness={0.6} roughness={0.4} />
</mesh>
{/* Viga Transversal (Reticulado simplificado) */}
<mesh position={[0, elevation, 0]} receiveShadow castShadow>
<boxGeometry args={[width, height, 0.3]} />
<meshStandardMaterial color={steelColor} metalness={0.6} roughness={0.4} transparent opacity={phiTotal} />
</mesh>
</group>
<mesh key={`beam-${i}`} position={[0, elevation, z]} receiveShadow castShadow>
<boxGeometry args={[width, height, 0.3]} />
<meshStandardMaterial color={steelColor} metalness={0.6} roughness={0.4} transparent opacity={phiTotal} />
</mesh>
);
}
// Gera as tubulações correndo longitudinalmente
const rackLength = spacing * Math.max(numFrames - 1, 0.5); // Garante comprimento visual mesmo com 1 pórtico
const pipeZCenter = -(spacing * (numFrames - 1)) / 2;
// Vigas transversais conectando as fileiras nas pontas
if (numFrames > 1) {
frames.push(
<mesh key={`cross-1`} position={[-halfW, elevation, 0]} receiveShadow castShadow>
<boxGeometry args={[0.3, height, totalSpacing]} />
<meshStandardMaterial color={steelColor} metalness={0.6} roughness={0.4} transparent opacity={phiTotal} />
</mesh>
);
frames.push(
<mesh key={`cross-2`} position={[halfW, elevation, 0]} receiveShadow castShadow>
<boxGeometry args={[0.3, height, totalSpacing]} />
<meshStandardMaterial color={steelColor} metalness={0.6} roughness={0.4} transparent opacity={phiTotal} />
</mesh>
);
}
// Gera as tubulações correndo longitudinalmente (ao longo de X)
const pipeMeshes = pipes.map((pipe, idx) => {
// Distribui os tubos ao longo da largura do pórtico
const xPos = -halfW + 0.5 + (idx % Math.max(pipes.length, 1)) * (width - 1) / Math.max(pipes.length - 1, 1) || 0;
const yPos = elevation + (idx % 2 === 0 ? 0.2 : -0.2); // Leve variação de altura
// Distribui os tubos ao longo do espaçamento transversal (Z)
const zPos = numFrames > 1
? -zOffset + 0.5 + (idx % Math.max(pipes.length, 1)) * (totalSpacing - 1) / Math.max(pipes.length - 1, 1) || 0
: 0;
const yPos = elevation + height/2 + pipe.diameter/2 + (idx % 2 === 0 ? 0 : 0.2);
const color = pipeColors[idx % pipeColors.length];
return (
<mesh key={`pipe-${pipe.id}`} position={[xPos, yPos, pipeZCenter]} rotation={[Math.PI / 2, 0, 0]} receiveShadow castShadow>
<cylinderGeometry args={[pipe.diameter / 2, pipe.diameter / 2, rackLength + 1, 16]} />
<mesh key={`pipe-${pipe.id}`} position={[0, yPos, zPos]} rotation={[0, 0, Math.PI / 2]} receiveShadow castShadow>
<cylinderGeometry args={[pipe.diameter / 2, pipe.diameter / 2, width + 1, 16]} />
<meshStandardMaterial color={color} metalness={0.3} roughness={0.2} />
</mesh>
);
@@ -86,7 +105,7 @@ function PiperackModel({
{/* Vento batendo lateralmente (transversal ao Pipe-rack) */}
<WindArrow
direction={[0, 0, 1]}
target={[0, elevation, spacing * 0.5]}
target={[0, elevation, zOffset + 2]}
/>
</group>
);
@@ -121,8 +140,8 @@ export function Piperack3D(props: Piperack3DInput) {
minPolarAngle={0}
maxPolarAngle={Math.PI / 2 - 0.05}
minDistance={5}
maxDistance={50}
target={[0, props.elevation / 2, -(props.spacing * (props.numFrames - 1)) / 2]}
maxDistance={80}
target={[0, props.elevation / 2, 0]}
/>
</SceneCanvas>
);