🚀 Auto-deploy: BrainWind atualizado em 13/07/2026 15:33:59
This commit is contained in:
@@ -510,6 +510,47 @@ function DynamicsDiagram({ height, freq, scruton, sectionShape, sectionSize, sho
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface PiperackProps {
|
||||||
|
width: number;
|
||||||
|
height: number;
|
||||||
|
elevation: number;
|
||||||
|
spacing: number;
|
||||||
|
numFrames: number;
|
||||||
|
phiTotal: number;
|
||||||
|
eta: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
function PiperackDiagram({ width, height, elevation, spacing, numFrames, phiTotal, eta }: PiperackProps) {
|
||||||
|
const vw = 400, vh = 300;
|
||||||
|
const s = Math.min((vw - 80) / width, (vh - 80) / (elevation + height));
|
||||||
|
const cx = vw / 2, ground = vh - 40;
|
||||||
|
const w = width * s;
|
||||||
|
const h = height * s;
|
||||||
|
const elev = elevation * s;
|
||||||
|
|
||||||
|
void spacing;
|
||||||
|
void eta;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<svg viewBox={`0 0 ${vw} ${vh}`} className="w-full h-full">
|
||||||
|
<rect width={vw} height={vh} fill="none" />
|
||||||
|
<line x1={cx - w - 20} y1={ground} x2={cx + w + 20} y2={ground} stroke="#94a3b8" strokeWidth={1} />
|
||||||
|
{/* Colunas */}
|
||||||
|
<line x1={cx - w / 2} y1={ground} x2={cx - w / 2} y2={ground - elev - h} stroke="#475569" strokeWidth={3} />
|
||||||
|
<line x1={cx + w / 2} y1={ground} x2={cx + w / 2} y2={ground - elev - h} stroke="#475569" strokeWidth={3} />
|
||||||
|
{/* Viga */}
|
||||||
|
<rect x={cx - w / 2} y={ground - elev - h} width={w} height={h} fill="#3b82f6" opacity={Math.max(0.2, phiTotal)} stroke="#334155" strokeWidth={1.5} />
|
||||||
|
|
||||||
|
{/* Seta de vento */}
|
||||||
|
<defs><marker id="parrow" markerWidth={8} markerHeight={6} refX={8} refY={3} orient="auto"><polygon points="0,0 8,3 0,6" fill="#22c55e" /></marker></defs>
|
||||||
|
<line x1={30} y1={ground - elev - h / 2} x2={Math.max(35, cx - w / 2 - 20)} y2={ground - elev - h / 2} stroke="#22c55e" strokeWidth={2} markerEnd="url(#parrow)" />
|
||||||
|
<text x={(30 + Math.max(35, cx - w / 2 - 20)) / 2} y={ground - elev - h / 2 - 8} textAnchor="middle" fontSize={8} fill="#22c55e">Vento</text>
|
||||||
|
|
||||||
|
<text x={cx} y={ground + 18} textAnchor="middle" fontSize={9} fill="#475569">b = {width}m | h = {height}m | z = {elevation}m | φ = {phiTotal.toFixed(2)} | n = {numFrames}</text>
|
||||||
|
</svg>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
export type FallbackDiagramProps =
|
export type FallbackDiagramProps =
|
||||||
| { type: 'warehouse'; props: WarehouseProps }
|
| { type: 'warehouse'; props: WarehouseProps }
|
||||||
| { type: 'cylinder'; props: CylinderProps }
|
| { type: 'cylinder'; props: CylinderProps }
|
||||||
@@ -520,7 +561,8 @@ export type FallbackDiagramProps =
|
|||||||
| { type: 'bridge'; props: BridgeProps }
|
| { type: 'bridge'; props: BridgeProps }
|
||||||
| { type: 'tower'; props: TowerProps }
|
| { type: 'tower'; props: TowerProps }
|
||||||
| { type: 'isolatedRoof'; props: IsolatedRoofProps }
|
| { type: 'isolatedRoof'; props: IsolatedRoofProps }
|
||||||
| { type: 'dynamics'; props: DynamicsProps };
|
| { type: 'dynamics'; props: DynamicsProps }
|
||||||
|
| { type: 'piperack'; props: PiperackProps };
|
||||||
|
|
||||||
export default function FallbackDiagram(input: FallbackDiagramProps) {
|
export default function FallbackDiagram(input: FallbackDiagramProps) {
|
||||||
return (
|
return (
|
||||||
@@ -536,6 +578,7 @@ export default function FallbackDiagram(input: FallbackDiagramProps) {
|
|||||||
{input.type === 'tower' && <TowerDiagram {...input.props} />}
|
{input.type === 'tower' && <TowerDiagram {...input.props} />}
|
||||||
{input.type === 'isolatedRoof' && <IsolatedRoofDiagram {...input.props} />}
|
{input.type === 'isolatedRoof' && <IsolatedRoofDiagram {...input.props} />}
|
||||||
{input.type === 'dynamics' && <DynamicsDiagram {...input.props} />}
|
{input.type === 'dynamics' && <DynamicsDiagram {...input.props} />}
|
||||||
|
{input.type === 'piperack' && <PiperackDiagram {...input.props} />}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import SceneCanvas from '../SceneCanvas';
|
|||||||
import { WindArrow } from './WindArrow';
|
import { WindArrow } from './WindArrow';
|
||||||
import { useCanvasTheme } from '@/lib/theme';
|
import { useCanvasTheme } from '@/lib/theme';
|
||||||
import type { PipeDef } from '../../lib/modules/piperack';
|
import type { PipeDef } from '../../lib/modules/piperack';
|
||||||
|
import FallbackDiagram from '../FallbackDiagram';
|
||||||
|
|
||||||
export interface Piperack3DInput {
|
export interface Piperack3DInput {
|
||||||
width: number;
|
width: number;
|
||||||
@@ -94,8 +95,15 @@ function PiperackModel({
|
|||||||
export function Piperack3D(props: Piperack3DInput) {
|
export function Piperack3D(props: Piperack3DInput) {
|
||||||
const isDark = useCanvasTheme() === 'dark';
|
const isDark = useCanvasTheme() === 'dark';
|
||||||
|
|
||||||
|
const fallback = (
|
||||||
|
<FallbackDiagram
|
||||||
|
type="piperack"
|
||||||
|
props={props}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<SceneCanvas moduleId="piperack" fallback={<div />}>
|
<SceneCanvas moduleId="piperack" fallback={fallback}>
|
||||||
<ambientLight intensity={isDark ? 0.3 : 0.6} />
|
<ambientLight intensity={isDark ? 0.3 : 0.6} />
|
||||||
<directionalLight position={[10, 15, 10]} intensity={isDark ? 1 : 1.5} castShadow shadow-bias={-0.001} />
|
<directionalLight position={[10, 15, 10]} intensity={isDark ? 1 : 1.5} castShadow shadow-bias={-0.001} />
|
||||||
<Environment preset="city" />
|
<Environment preset="city" />
|
||||||
|
|||||||
Reference in New Issue
Block a user