import { usePileCapStore } from '../../store/pileCapStore'; import type { PileReaction } from '../../types/pileCap'; import { DraggableLabel } from './DraggableLabel'; interface OneWayShearDiagramProps { direction: 'X' | 'Y'; criticalSectionDist: number; // in inches (e.g., d or 0) piles: PileReaction[]; } export const OneWayShearDiagram = ({ direction, criticalSectionDist, piles }: OneWayShearDiagramProps) => { const geometry = usePileCapStore(state => state.geometry); // Global Diagram State const isLocked = usePileCapStore(state => state.diagramState.isLocked); const labelPositions = usePileCapStore(state => state.diagramState.labelPositions); const setDiagramLocked = usePileCapStore(state => state.setDiagramLocked); const updateLabelPosition = usePileCapStore(state => state.updateLabelPosition); const getLabelPos = (id: string, defaultX: number, defaultY: number) => { return labelPositions[id] || { x: defaultX, y: defaultY }; }; // Dimensions const width = 300; const height = 300; const padding = 40; // Scale factors const scaleX = (width - 2 * padding) / geometry.length; const scaleZ = (height - 2 * padding) / geometry.width; const scale = Math.min(scaleX, scaleZ); // Center offsets const offsetX = (width - geometry.length * scale) / 2; const offsetZ = (height - geometry.width * scale) / 2; // Helper to transform coordinates const toPx = (x: number, z: number) => ({ x: offsetX + x * scale, y: offsetZ + z * scale }); // Column dimensions in ft const colLenFt = geometry.columnLength / 12; const colWidthFt = geometry.columnWidth / 12; const colX = (geometry.length - colLenFt) / 2 + geometry.columnOffsetX; const colZ = (geometry.width - colWidthFt) / 2 + geometry.columnOffsetZ; // Critical Section Lines // direction 'X' means shear force Vy (checking along X axis? No, One-Way Shear X usually means shear across the width, checking sections along length) // Wait, "One-Way Shear X" typically means Vux (shear force in X direction), so critical planes are perpendicular to X axis. // Let's assume direction 'X' means we are checking sections at x = ... // Critical section positions (in ft from left/bottom edge) const distFt = criticalSectionDist / 12; let critLine1 = 0; let critLine2 = 0; let shadeRects: { x: number, y: number, w: number, h: number }[] = []; if (direction === 'X') { // Critical planes are vertical lines // Col center X const colCenterX = colX + colLenFt / 2; // Planes at center +/- (colLen/2 + dist) const leftPlaneX = colCenterX - (colLenFt / 2 + distFt); const rightPlaneX = colCenterX + (colLenFt / 2 + distFt); critLine1 = leftPlaneX; critLine2 = rightPlaneX; // Shade outer regions // Left region: 0 to leftPlaneX if (leftPlaneX > 0) { shadeRects.push({ x: 0, y: 0, w: leftPlaneX, h: geometry.width }); } // Right region: rightPlaneX to length if (rightPlaneX < geometry.length) { shadeRects.push({ x: rightPlaneX, y: 0, w: geometry.length - rightPlaneX, h: geometry.width }); } } else { // Direction Y (Z in geometry) // Critical planes are horizontal lines const colCenterZ = colZ + colWidthFt / 2; const bottomPlaneZ = colCenterZ - (colWidthFt / 2 + distFt); const topPlaneZ = colCenterZ + (colWidthFt / 2 + distFt); critLine1 = bottomPlaneZ; critLine2 = topPlaneZ; // Shade outer regions // Bottom region: 0 to bottomPlaneZ if (bottomPlaneZ > 0) { shadeRects.push({ x: 0, y: 0, w: geometry.length, h: bottomPlaneZ }); } // Top region: topPlaneZ to width if (topPlaneZ < geometry.width) { shadeRects.push({ x: 0, y: topPlaneZ, w: geometry.length, h: geometry.width - topPlaneZ }); } } return (
{/* Controls (Mini version since this is usually embedded in a list) */}
{/* Pile Cap Outline */} {/* Shaded Failure Areas */} {shadeRects.map((r, i) => ( ))} {/* Critical Section Lines */} {direction === 'X' ? ( <> ) : ( <> )} {/* Piles */} {piles.map((p, i) => { const pos = toPx(p.x, p.y); // Note: PileReaction uses y for Z direction const pileSizePx = (geometry.pileSize / 12) * scale; // Check if pile is in shaded region (contributing to shear) let isContributing = false; if (direction === 'X') { if (p.x < critLine1 || p.x > critLine2) isContributing = true; } else { if (p.y < critLine1 || p.y > critLine2) isContributing = true; } const pileColor = isContributing ? "#ffcccc" : "#eee"; // Highlight contributing piles const strokeColor = isContributing ? "#cc0000" : "#999"; if (geometry.pileType === 'Round') { return ( ); } else { return ( ); } })} {/* Column */} {/* Axes */} {/* Critical Section Label */}
); };