91 lines
No EOL
2.8 KiB
TypeScript
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>
|
|
)
|
|
} |