changed the heatmap limit to use the grain height
This commit is contained in:
parent
b1c676987e
commit
874be1d8b7
3 changed files with 489 additions and 525 deletions
|
|
@ -1,3 +1,4 @@
|
|||
|
||||
import OrbitCameraControls from "3dModels/CameraControls/OrbitCameraControls";
|
||||
import { Canvas } from "@react-three/fiber";
|
||||
import { Bin } from "models";
|
||||
|
|
@ -10,53 +11,56 @@ import { BuildCableData, CableData } from "../Data/BuildCableData";
|
|||
import { BuildNodeData, NodeData } from "../Data/BuildNodeData";
|
||||
import { pond } from "protobuf-ts/pond";
|
||||
import GrainCableFill from "../Systems/Inventory/GrainCableFill";
|
||||
import TempHeatMap from "../Systems/Heatmap/TempHeatMap"; //grain heat map
|
||||
import NodePointCloud from "../Systems/Heatmap/NodePointCloud"; //hot spots
|
||||
|
||||
import TempHeatMap from "../Systems/Heatmap/TempHeatMap";
|
||||
import NodePointCloud from "../Systems/Heatmap/NodePointCloud";
|
||||
|
||||
interface Props {
|
||||
/**
|
||||
* The bin to generate a 3D model of
|
||||
*/
|
||||
bin: Bin
|
||||
/**
|
||||
* The scale to apply to the bin dimensions
|
||||
* ie 100 would make the bin 1:100 scale
|
||||
* @default 100
|
||||
*/
|
||||
scale: number
|
||||
/**
|
||||
* optional: the percent of the bin to fill using a level top, this will be used with manual and lidar controls
|
||||
*/
|
||||
fillPercent?: number
|
||||
nodeClick?: (node: NodeData, cable: CableData) => void
|
||||
/**
|
||||
* toggles the grain in the bin
|
||||
*/
|
||||
showGrain?: boolean
|
||||
/**
|
||||
* toggles the heatmap overlay
|
||||
*/
|
||||
showHeatmap?: boolean
|
||||
/**
|
||||
* toggles the hotspots in the bin
|
||||
*/
|
||||
showHotspots?: boolean
|
||||
}
|
||||
|
||||
export default function Bin3dView(props: Props){
|
||||
//this function will generate a 3D model of a bin based on its settings using multiple meshes, cylinder for the body, cone for the roof
|
||||
// and either a cone for the hopper or circle for flat bottom, it is possible to also use lathe geometry for this as well,
|
||||
// it might even work better because we can control the smoothness easier with it being only one mesh rather than 3
|
||||
const {bin, scale = 100, fillPercent, nodeClick, showHeatmap, showGrain, showHotspots} = props
|
||||
|
||||
export default function Bin3dView(props: Props) {
|
||||
const { bin, scale = 100, fillPercent, nodeClick, showHeatmap, showGrain, showHotspots } = props
|
||||
|
||||
const binCenter = useMemo(() => new Vector3(0, 0, 0), []);
|
||||
const cableData = useMemo(() => BuildCableData(bin), [bin]);
|
||||
const nodeData = useMemo(() => BuildNodeData(cableData), [cableData]);
|
||||
|
||||
const nodeData = useMemo(() => BuildNodeData(cableData), [cableData]);
|
||||
|
||||
const isCableInventory =
|
||||
bin.inventoryControl() === pond.BinInventoryControl.BIN_INVENTORY_CONTROL_AUTOMATIC ||
|
||||
bin.inventoryControl() === pond.BinInventoryControl.BIN_INVENTORY_CONTROL_HYBRID_CABLE;
|
||||
|
||||
// For cable inventory, TempHeatMap derives the wavy surface directly from
|
||||
// the top nodes in nodeData — no scalar needed.
|
||||
//
|
||||
// For flat fill percent, we convert the fill percent to a Y coordinate
|
||||
// using the same volume math as GrainFillFlat and pass it as flatMaxY.
|
||||
const flatMaxY = useMemo(() => {
|
||||
if (isCableInventory || fillPercent === undefined) return undefined;
|
||||
|
||||
const radius = bin.diameter() / 2;
|
||||
const sidewallH = bin.sidewallHeight();
|
||||
const hopperH = bin.hopperHeight() ?? 0;
|
||||
const cylVolume = Math.PI * radius * radius * sidewallH;
|
||||
const hopperVol = hopperH > 0 ? (1 / 3) * Math.PI * radius * radius * hopperH : 0;
|
||||
const filled = (cylVolume + hopperVol) * fillPercent;
|
||||
|
||||
const cylinderFillH = hopperH > 0 && filled <= hopperVol
|
||||
? 0
|
||||
: Math.max(0, (filled - hopperVol) / (Math.PI * radius * radius));
|
||||
|
||||
return -sidewallH / 2 + cylinderFillH;
|
||||
}, [isCableInventory, fillPercent, bin]);
|
||||
|
||||
const grainInventory = () => {
|
||||
if(bin.inventoryControl() === pond.BinInventoryControl.BIN_INVENTORY_CONTROL_AUTOMATIC ||
|
||||
bin.inventoryControl() === pond.BinInventoryControl.BIN_INVENTORY_CONTROL_HYBRID_CABLE){
|
||||
if (isCableInventory) {
|
||||
return (
|
||||
<GrainCableFill
|
||||
<GrainCableFill
|
||||
diameter={bin.diameter()}
|
||||
nodes={nodeData}
|
||||
sidewallHeight={bin.sidewallHeight()}
|
||||
|
|
@ -65,25 +69,27 @@ export default function Bin3dView(props: Props){
|
|||
grainOpacity={0.3}
|
||||
/>
|
||||
)
|
||||
}else if (fillPercent){
|
||||
<GrainFillFlat
|
||||
diameter={bin.diameter()}
|
||||
sidewallHeight={bin.sidewallHeight()}
|
||||
hopperHeight={bin.hopperHeight()}
|
||||
fillPercent={fillPercent}
|
||||
grainOpacity={0.3}
|
||||
/>
|
||||
} else if (fillPercent) {
|
||||
return (
|
||||
<GrainFillFlat
|
||||
diameter={bin.diameter()}
|
||||
sidewallHeight={bin.sidewallHeight()}
|
||||
hopperHeight={bin.hopperHeight()}
|
||||
fillPercent={fillPercent}
|
||||
grainOpacity={0.3}
|
||||
/>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return (
|
||||
<Canvas>
|
||||
<group scale={[1/scale, 1/scale, 1/scale]}>
|
||||
<BinShell
|
||||
binBodyColour="#fff"
|
||||
radialSegments={20}
|
||||
binMetalness={0.5}
|
||||
binRoughness={0.7}
|
||||
<Canvas>
|
||||
<group scale={[1 / scale, 1 / scale, 1 / scale]}>
|
||||
<BinShell
|
||||
binBodyColour="#fff"
|
||||
radialSegments={20}
|
||||
binMetalness={0.5}
|
||||
binRoughness={0.7}
|
||||
binOpacity={0.2}
|
||||
diameter={bin.diameter()}
|
||||
sidewallHeight={bin.sidewallHeight()}
|
||||
|
|
@ -91,30 +97,37 @@ export default function Bin3dView(props: Props){
|
|||
hopperHeight={bin.hopperHeight()}
|
||||
renderOrder={4}
|
||||
/>
|
||||
|
||||
{/* grain - cylinder*/}
|
||||
|
||||
{showGrain && grainInventory()}
|
||||
{/* cables */}
|
||||
<BinCables cableData={cableData} nodeData={nodeData} bin={bin} binCenter={binCenter}
|
||||
|
||||
<BinCables
|
||||
cableData={cableData}
|
||||
nodeData={nodeData}
|
||||
bin={bin}
|
||||
binCenter={binCenter}
|
||||
onNodeClick={(node, cable) => {
|
||||
// console.log(node)
|
||||
// console.log(cable)
|
||||
if(nodeClick){
|
||||
nodeClick(node, cable)
|
||||
}
|
||||
if (nodeClick) nodeClick(node, cable)
|
||||
}}
|
||||
renderOrder={1}/>
|
||||
{showHotspots && <NodePointCloud bin={bin} nodes={nodeData} /> }
|
||||
{showHeatmap && <TempHeatMap bin={bin} nodes={nodeData}/>}
|
||||
</group>
|
||||
|
||||
{/* lighting */}
|
||||
<ambientLight intensity={0.2} color={"white"}/>
|
||||
<directionalLight intensity={0.2} color={"white"} position={[0,0,5]}/>
|
||||
<directionalLight intensity={0.2} color={"white"} position={[0,0,-5]}/>
|
||||
<directionalLight intensity={0.2} color={"white"} position={[5,0,0]}/>
|
||||
<directionalLight intensity={0.2} color={"white"} position={[-5,0,0]}/>
|
||||
<OrbitCameraControls clampVerticalRotation />
|
||||
</Canvas>
|
||||
renderOrder={1}
|
||||
/>
|
||||
|
||||
{showHotspots && <NodePointCloud bin={bin} nodes={nodeData} />}
|
||||
|
||||
{showHeatmap && (
|
||||
<TempHeatMap
|
||||
bin={bin}
|
||||
nodes={nodeData}
|
||||
flatMaxY={flatMaxY}
|
||||
/>
|
||||
)}
|
||||
</group>
|
||||
|
||||
<ambientLight intensity={0.2} color={"white"} />
|
||||
<directionalLight intensity={0.2} color={"white"} position={[0, 0, 5]} />
|
||||
<directionalLight intensity={0.2} color={"white"} position={[0, 0, -5]} />
|
||||
<directionalLight intensity={0.2} color={"white"} position={[5, 0, 0]} />
|
||||
<directionalLight intensity={0.2} color={"white"} position={[-5, 0, 0]} />
|
||||
<OrbitCameraControls clampVerticalRotation />
|
||||
</Canvas>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue