373 lines
10 KiB
TypeScript
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>
|
|
);
|
|
}
|