frontend/src/cableEstimator/binSVGs/sideView.tsx

373 lines
10 KiB
TypeScript

import { colors } from "@mui/material";
import { jsonBin } from "common/DataImports/BinCables/BinCableImporter";
import { useEffect, useState } from "react";
import { distanceConversion } from "utils";
interface Props {
bin: jsonBin;
}
interface svgPoint {
x: number;
y: number;
}
export default function SideView(props: Props) {
const svgViewBoxSize = 250;
//percentage to of the svg to be the bin drawing from 0 to 1,
//NOTE: this is the percentage based on the longest side
//ie. if the bin is taller than it is wide the bin will be x percent of the height of the viewbox and the width will be scaled to the height and vice versa
const scaleMultiplier = 0.8;
const nodeSpacing = 4; //space in feet between the nodes
const dimensionFontSize = 7;
const gapSize = svgViewBoxSize * 0.05;
const { bin } = props;
const [scale, setScale] = useState(0); //the scale to multiply the bin dimension by in order to determine how long to draw the line
const [hopperHeight, setHopperHeight] = useState(0);
const [roofHeight, setRoofHeight] = useState(0);
useEffect(() => {
//get the peak height of the hopper
let h = (bin.Diameter / 2) * Math.tan(bin.HopperAngle * (Math.PI / 180));
setHopperHeight(h);
setRoofHeight(bin.Peak - bin.Sidewall);
let heightscale = svgViewBoxSize / (bin.Peak + h);
let widthscale = svgViewBoxSize / bin.Diameter;
//need to use the scale of the longer of the two dimensions
setScale((heightscale < widthscale ? heightscale : widthscale) * scaleMultiplier);
}, [bin, svgViewBoxSize]);
const binOutline = () => {
let startX = svgViewBoxSize / 2;
let startY = 0;
//let paddingVal = (padding * svgViewBoxSize)
return (
<path
strokeWidth={2}
stroke={colors.grey[400]}
fillOpacity={0}
d={
"M " +
startX +
" " +
startY + //starting point
" L " +
(startX + (bin.Diameter / 2) * scale) +
" " +
roofHeight * scale + //right side of the bin roof
" V " +
(roofHeight + bin.Sidewall) * scale + //right sidewall
(hopperHeight === 0
? " H " + (startX - (bin.Diameter / 2) * scale) //bin bottom if there is no hopper
: //else
" L " +
startX +
" " +
(roofHeight + hopperHeight + bin.Sidewall) * scale + //right side of the hopper
" L " +
(startX - (bin.Diameter / 2) * scale) +
" " +
(roofHeight + bin.Sidewall) * scale) + //left side of the hopper
" V " +
roofHeight * scale + //left sidewall
" Z " //left side of the bin roof (Z command draws the line from where you currently are back to the startign point)
}
/>
);
};
const cableLines = () => {
let cables: JSX.Element[] = [];
//let paddingVal = (padding * svgViewBoxSize)
// line for the roof at the top of the sidewall
// cables.push(
// <line
// key={"roof"}
// strokeWidth={2}
// stroke="yellow"
// x1={0}
// strokeDasharray={3}
// x2={svgViewBoxSize}
// y1={roofHeight*scale + paddingVal}
// y2={roofHeight*scale + paddingVal}
// />
// )
bin.CableSums.forEach(sum => {
let cableLength = 0;
bin.Cables.forEach(c => {
if (sum.Orbit === c.Orbit) {
//numNodes = c.Nodes
cableLength = c.Length;
}
});
let numNodes = Math.ceil(cableLength / nodeSpacing);
let xVal = svgViewBoxSize / 2 + sum.DistanceFromCenter * scale;
let cableStart = sum.DistanceFromCenter * Math.tan(bin.RoofAngle * (Math.PI / 180)) * scale;
//need to offset the padding to the top since we are now below the half mark as well as pad the bottom
let cableEnd = cableStart + cableLength * scale;
cables.push(
<line
key={"orbit" + sum.Orbit}
strokeWidth={2}
stroke="yellow"
x1={xVal}
y1={cableStart}
x2={xVal}
y2={cableEnd}
/>
);
let svgSpacing = (cableEnd - cableStart) / numNodes;
for (let i = 0; i < numNodes; i++) {
let nodeY = cableEnd - svgSpacing * i;
cables.push(
<circle key={"orbit" + sum.Orbit + "node" + i} cx={xVal} cy={nodeY} r={2} fill="blue" />
);
}
});
return cables;
};
const dimensionText = (key: string, x: number, y: number, text: string) => {
return (
<text
key={key}
style={{ fontSize: dimensionFontSize, fill: "white" }}
x={x}
y={y}
textAnchor="middle"
dominantBaseline={"middle"}>
{text}
</text>
);
};
const dimensionPath = (key: string, start: svgPoint, corner: svgPoint, end: svgPoint) => {
return (
//<line key={key} strokeWidth={1} stroke="white" x1={x1} x2={x2 ?? x1} y1={y1} y2={y2 ?? y1} />
<path
key={key}
strokeWidth={1}
stroke="white"
fillOpacity={0}
d={
"M " +
start.x +
" " +
start.y +
"L " +
corner.x +
" " +
corner.y +
"L " +
end.x +
" " +
end.y
}
/>
);
};
const bottomDiameter = () => {
let d: JSX.Element[] = [];
let x1 = svgViewBoxSize / 2 - (bin.Diameter / 2) * scale;
let x2 = svgViewBoxSize / 2 + (bin.Diameter / 2) * scale;
let y1 =
(roofHeight + bin.Sidewall + hopperHeight) * scale +
svgViewBoxSize * (1 - scaleMultiplier) * 0.1;
let y2 =
(roofHeight + bin.Sidewall + hopperHeight) * scale +
svgViewBoxSize * (1 - scaleMultiplier) * 0.25;
d.push(
dimensionText(
"bottomText",
svgViewBoxSize / 2,
y2,
distanceConversion(bin.Diameter).toFixed(1)
)
);
d.push(
dimensionPath(
"bottomDiameterLine1",
{ x: x1, y: y1 },
{ x: x1, y: y2 },
{ x: svgViewBoxSize / 2 - gapSize, y: y2 }
)
);
d.push(
dimensionPath(
"bottomDiameterLine2",
{ x: svgViewBoxSize / 2 + gapSize, y: y2 },
{ x: x2, y: y2 },
{ x: x2, y: y1 }
)
);
return d;
};
//height of the sidewall, on the left side - always used
const sidwallDimension = () => {
let d: JSX.Element[] = [];
let centerX = svgViewBoxSize / 2;
let x1 = centerX - (bin.Diameter / 2) * scale - svgViewBoxSize * (1 - scaleMultiplier) * 0.1;
let x2 = x1 - svgViewBoxSize * (1 - scaleMultiplier) * 0.15;
let midpoint = (roofHeight + bin.Sidewall / 2) * scale;
let y1 = roofHeight * scale;
let y2 = (roofHeight + bin.Sidewall) * scale;
d.push(
dimensionText("sidewallText", x2, midpoint, distanceConversion(bin.Sidewall).toFixed(1))
);
d.push(
dimensionPath(
"sidwallTopLine",
{ x: x1, y: y1 },
{ x: x2, y: y1 },
{ x: x2, y: midpoint - gapSize }
)
);
d.push(
dimensionPath(
"sidewallbottomLine",
{ x: x2, y: midpoint + gapSize },
{ x: x2, y: y2 },
{ x: x1, y: y2 }
)
);
return d;
};
//height of the bottom of the sidewall to the peak of the bin, on the left side - only used for hopper bins
const peakDimension = () => {
let d: JSX.Element[] = [];
let centerX = svgViewBoxSize / 2;
let xWall = centerX - (bin.Diameter / 2) * scale - svgViewBoxSize * (1 - scaleMultiplier) * 0.1;
let xPeak = svgViewBoxSize / 2 - svgViewBoxSize * (1 - scaleMultiplier) * 0.1;
let xText = xWall - svgViewBoxSize * (1 - scaleMultiplier) * 0.5;
let midpoint = ((roofHeight + bin.Sidewall) / 2) * scale;
let yTop = 0;
let yBottom = (roofHeight + bin.Sidewall) * scale;
d.push(
dimensionText(
"peakText",
xText,
midpoint,
distanceConversion(bin.Sidewall + roofHeight).toFixed(1)
)
);
d.push(
dimensionPath(
"peakTopLine",
{ x: xPeak, y: yTop },
{ x: xText, y: yTop },
{ x: xText, y: midpoint - gapSize }
)
);
d.push(
dimensionPath(
"peakbottomLine",
{ x: xText, y: midpoint + gapSize },
{ x: xText, y: yBottom },
{ x: xWall, y: yBottom }
)
);
return d;
};
//total height of the bin, on the right side - always used
const totalDimension = () => {
let d: JSX.Element[] = [];
let centerX = svgViewBoxSize / 2;
//let paddingVal = (padding* svgViewBoxSize)
let binRightX = centerX + (bin.Diameter / 2) * scale;
let xBinCenter = centerX + svgViewBoxSize * (1 - scaleMultiplier) * 0.1;
let xBinWall = binRightX + svgViewBoxSize * (1 - scaleMultiplier) * 0.1;
let x2 = binRightX + svgViewBoxSize * (1 - scaleMultiplier) * 0.2;
let midpoint = ((roofHeight + bin.Sidewall + hopperHeight) / 2) * scale;
let y1 = 0;
let y2 = (roofHeight + bin.Sidewall + hopperHeight) * scale;
d.push(
dimensionText(
"totalText",
x2,
midpoint,
distanceConversion(roofHeight + bin.Sidewall + hopperHeight).toFixed(1)
)
);
d.push(
dimensionPath(
"totalTopLine",
{ x: xBinCenter, y: y1 },
{ x: x2, y: y1 },
{ x: x2, y: midpoint - gapSize }
)
);
d.push(
dimensionPath(
"totalBottomLine",
{ x: x2, y: midpoint + gapSize },
{ x: x2, y: y2 },
{ x: hopperHeight > 0 ? xBinCenter : xBinWall, y: y2 }
)
);
return d;
};
const binDimensions = () => {
let dimensions: JSX.Element[] = [];
dimensions.push(...bottomDiameter());
// sidwall Height
dimensions.push(...sidwallDimension());
//total bin height
dimensions.push(...totalDimension());
if (hopperHeight > 0) {
//show the height of the peak + sidwall without the hopper
dimensions.push(...peakDimension());
}
return dimensions;
};
return (
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox={
"0 " +
(svgViewBoxSize * (scaleMultiplier - 1)) / 2 +
" " +
svgViewBoxSize +
" " +
svgViewBoxSize
}
height="100%"
width="100%">
{cableLines()}
{binOutline()}
{binDimensions()}
</svg>
);
}