frontend/src/bin/3dView/BinCables/GrainCable.tsx

91 lines
No EOL
2.8 KiB
TypeScript

import Cylinder, { CylinderGeometry } from "3dModels/Shapes/3D/Cylinder"
import { pond } from "protobuf-ts/pond"
import React from "react"
import { Vector3 } from "three"
import CableNode, { NodeData } from "./CableNode"
import { Bin } from "models"
export interface CableData {
radius: number
topPosition: Vector3
bottomPosition: Vector3
grainCable: pond.GrainCable
radialSegments?: number
heightSegments?: number
}
interface Props {
cable: CableData
bin: Bin
binCenter: Vector3
}
export default function GrainCable(props: Props) {
const {cable, bin, binCenter} = props
const calculateHeight = () => {
return cable.topPosition.distanceTo(cable.bottomPosition)
}
const calculateCenter = () => {
return cable.bottomPosition.clone()
.add(
cable.topPosition.clone()
.sub(cable.bottomPosition)
.multiplyScalar(0.5)
);
};
const buildCableNodes = () => {
const nodeRadius = 20
const grainCable = cable.grainCable
const nodeCount = grainCable.celcius.length;
if (nodeCount === 0) return [];
const bottomY = cable.bottomPosition.y;
const topY = cable.topPosition.y;
const height = topY - bottomY;
const spacing = height / nodeCount;
let nodeData: NodeData[] = []
grainCable.celcius.forEach((celcius,i) => {
const nodeY = bottomY + (i * spacing);
const humidity = grainCable.relativeHumidity[i] || undefined;
const moisture = grainCable.moisture[i] || undefined;
nodeData.push({
radius: nodeRadius,
position: new Vector3(cable.bottomPosition.x, nodeY, cable.bottomPosition.z),
celcius: celcius,
humidity: humidity,
moisture: moisture,
topNode: grainCable.topNode === i+1, //top node tracking starts at 1 not 0 so add one to the index
excluded: grainCable.excludedNodes.includes(i),
inGrain: i+1 <= grainCable.topNode
})
})
return nodeData
}
const geometry = React.useMemo(() => ({
radiusTop: cable.radius,
radiusBottom: cable.radius,
height: calculateHeight(),
radialSegments: cable.radialSegments ?? 10,
heightSegments: cable.heightSegments ?? 2
} as CylinderGeometry), [cable]);
return (
<React.Fragment>
<Cylinder geometry={geometry} position={calculateCenter()} opacity={0.5}/>
{buildCableNodes().map((node, i) => (
<CableNode key={"node " + i} node={node} binCenter={binCenter} lowerThreshold={bin.lowerTempThreshold()} upperThreshold={bin.upperTempThreshold()}/>
))}
</React.Fragment>
)
}