import { Grid, Environment } from '@react-three/drei';
import { ViewerOrbitControls as OrbitControls } from './ViewerOrbitControls';
import SceneCanvas from '../SceneCanvas';
import { WindArrow } from './WindArrow';
import { useCanvasTheme } from '@/lib/theme';
import type { PipeDef } from '../../lib/modules/piperack';
import FallbackDiagram from '../FallbackDiagram';
export interface Piperack3DInput {
width: number;
height: number;
elevation: number;
spacing: number;
numFrames: number;
pipes: PipeDef[];
phiTotal: number;
eta: number;
}
function PiperackModel({
width,
height,
elevation,
spacing,
numFrames,
pipes,
phiTotal,
}: Piperack3DInput) {
const theme = useCanvasTheme();
const isDark = theme === 'dark';
const halfW = width / 2;
const rackTop = elevation + height / 2;
const steelColor = isDark ? '#94a3b8' : '#64748b';
const pipeColors = ['#ef4444', '#3b82f6', '#f59e0b', '#10b981', '#8b5cf6'];
// 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 = -zOffset + i * spacing;
// Desenha apenas 2 colunas nas extremidades da largura do pórtico (conforme solicitado pelo usuário)
const numCols = 2;
for (let c = 0; c < numCols; c++) {
const colX = -halfW + (c / (numCols - 1)) * width;
frames.push(
);
}
// Viga Longitudinal da fileira (representando a face reticulada do pórtico)
frames.push(
{/* Opacidade ajustada para atingir 90% quando a solidez for 1.0 */}
);
}
// Gera as tubulações correndo longitudinalmente (ao longo de X)
// Agrupa tubos pela mesma elevação para evitar colisões e distribuí-los lado a lado (ao longo de Z)
const pipeMeshes: any[] = [];
const groups: Record = {};
pipes.forEach((pipe, idx) => {
// Arredondamos a elevação para agrupar valores muito próximos
const key = Math.round(pipe.elevationOffset * 100) / 100;
if (!groups[key]) groups[key] = [];
groups[key].push({pipe, idx});
});
Object.values(groups).forEach(group => {
const gap = 0.2; // 20cm de espaçamento entre tubos na mesma elevação
const totalDiam = group.reduce((sum, item) => sum + item.pipe.diameter, 0);
const totalGroupWidth = totalDiam + gap * (group.length - 1);
// Inicia a distribuição centralizada em Z=0
let currentZ = -totalGroupWidth / 2;
group.forEach((item) => {
const { pipe, idx } = item;
const zPos = currentZ + pipe.diameter / 2;
currentZ += pipe.diameter + gap;
const yPos = (elevation - height/2) + pipe.elevationOffset + pipe.diameter/2;
const color = pipeColors[idx % pipeColors.length];
pipeMeshes.push(
);
});
});
return (
{frames}
{pipeMeshes}
{/* Vento batendo lateralmente (transversal ao Pipe-rack) */}
);
}
export function Piperack3D(props: Piperack3DInput) {
const isDark = useCanvasTheme() === 'dark';
const fallback = (
);
return (
);
}