add useHeatMapStore for managing monitoring of vehicles and humans in HeatMap component

This commit is contained in:
2025-09-05 15:00:16 +05:30
parent bef1b3dcee
commit 77dc821431
2 changed files with 126 additions and 35 deletions

View File

@@ -6,6 +6,7 @@ import { useSceneContext } from "../../modules/scene/sceneContext";
import * as CONSTANTS from "../../types/world/worldConstants";
import { determineExecutionMachineSequences } from "../../modules/simulation/simulator/functions/determineExecutionMachineSequences";
import { useAnimationPlaySpeed, usePauseButtonStore, usePlayButtonStore, useResetButtonStore } from "../../store/usePlayButtonStore";
import { useHeatMapStore } from "../../store/simulation/useHeatMapStore";
const DECAY_RATE = 0.01;
const GROWTH_TIME_MULTIPLIER = 20;
@@ -32,6 +33,7 @@ const HeatMap = () => {
const { getProductById, products } = productStore();
const { selectedProductStore } = useProductContext();
const { selectedProduct } = selectedProductStore();
const { hasHuman, hasVehicle, monitoringHuman, monitoringVehicle, addMonitoringHuman, addMonitoringVehicle } = useHeatMapStore();
const { isPlaying } = usePlayButtonStore();
const { isReset } = useResetButtonStore();
const { isPaused } = usePauseButtonStore();
@@ -62,6 +64,11 @@ const HeatMap = () => {
}
}, [isReset, isPlaying]);
useEffect(() => {
addMonitoringVehicle("26770368-55e8-4d40-87f7-8eacb48dc236");
addMonitoringHuman("264a51e7-d8b9-4093-95ac-fa7e2dc49cfa");
}, []);
useEffect(() => {
const selectedProductData = getProductById(selectedProduct.productUuid);
const newEvents: EventsSchema[] = [];
@@ -70,21 +77,26 @@ const HeatMap = () => {
determineExecutionMachineSequences([selectedProductData]).then((sequences) => {
sequences.forEach((sequence) => {
sequence.forEach((event) => {
if (event.type === "human" || event.type === "vehicle") {
newEvents.push(event);
if (event.type === "human") {
if (hasHuman(event.modelUuid)) {
newEvents.push(event);
}
} else if (event.type === "vehicle") {
if (hasVehicle(event.modelUuid)) {
newEvents.push(event);
}
}
});
});
setEvents(newEvents);
});
}
}, [selectedProduct, products]);
}, [selectedProduct, products, monitoringHuman, monitoringVehicle]);
useFrame((state) => {
if (!scene || !isPlaying || isReset) return;
const now = state.clock.elapsedTime;
if (isPaused || speed === 0) {
lastFrameTime.current = now;
return;
@@ -95,16 +107,13 @@ const HeatMap = () => {
delta = now - lastFrameTime.current;
}
lastFrameTime.current = now;
if (delta <= 0) return;
const updateInterval = UPDATE_INTERVAL / Math.max(speed, 0.1);
if (now - lastUpdateTime.current < updateInterval) return;
lastUpdateTime.current = now;
const scaledDelta = delta * speed;
let updatedPoints = [...points];
events.forEach((event) => {
@@ -113,35 +122,23 @@ const HeatMap = () => {
const pos = isUsingBBOX
? (() => {
const box = new THREE.Box3().setFromObject(model);
const { min, max } = box;
return new THREE.Vector3((min.x + max.x) / 2, 0, (min.z + max.z) / 2);
})()
const box = new THREE.Box3().setFromObject(model);
const { min, max } = box;
return new THREE.Vector3((min.x + max.x) / 2, 0, (min.z + max.z) / 2);
})()
: model.position;
updatedPoints.push({
x: pos.x,
y: pos.z,
strength: 0.3,
lastUpdated: now,
});
updatedPoints.push({ x: pos.x, y: pos.z, strength: 0.3, lastUpdated: now });
});
updatedPoints = updatedPoints
.map((p) => ({
...p,
strength: Math.max(0, p.strength - DECAY_RATE * scaledDelta),
}))
.filter((p) => p.strength > 0.01);
updatedPoints = updatedPoints.map((p) => ({ ...p, strength: Math.max(0, p.strength - DECAY_RATE * scaledDelta) })).filter((p) => p.strength > 0.01);
setPoints(updatedPoints);
});
const pointTexture = useMemo(() => {
if (points.length === 0) return null;
const data = new Float32Array(points.length * 4);
points.forEach((p, i) => {
const index = i * 4;
data[index] = (p.x + width / 2) / width;
@@ -150,13 +147,7 @@ const HeatMap = () => {
data[index + 3] = 0.0;
});
const texture = new THREE.DataTexture(
data,
points.length,
1,
THREE.RGBAFormat,
THREE.FloatType
);
const texture = new THREE.DataTexture(data, points.length, 1, THREE.RGBAFormat, THREE.FloatType);
texture.needsUpdate = true;
return texture;
}, [points, width, height]);
@@ -234,7 +225,7 @@ const HeatMap = () => {
float adjustedIntensity = intensity * u_growthRate;
// Normalize intensity between 0-1
float normalized = clamp(intensity / max(u_growthRate, 0.0001), 0.0, 1.0);
float normalized = clamp(intensity / max(u_growthRate, 0.0001), 0.0, 1.0);
vec3 color = vec3(0.0);
if (normalized < 0.33) {
@@ -254,4 +245,4 @@ const HeatMap = () => {
);
};
export default HeatMap;
export default HeatMap;

View File

@@ -0,0 +1,100 @@
import { create } from "zustand";
import { immer } from "zustand/middleware/immer";
interface HeatMapState {
monitoringVehicle: string[];
monitoringHuman: string[];
setMonitoringVehicle: (vehiclesUuid: string[]) => void;
addMonitoringVehicle: (vehicleUuid: string) => void;
removeMonitoringVehicle: (vehicleUuid: string) => void;
clearMonitoringVehicle: () => void;
setMonitoringHuman: (humansUuid: string[]) => void;
addMonitoringHuman: (humanUuid: string) => void;
removeMonitoringHuman: (humanUuid: string) => void;
clearMonitoringHuman: () => void;
clearAllMonitors: () => void;
hasVehicle: (vehicleUuid: string) => boolean;
hasHuman: (humanUuid: string) => boolean;
}
export const useHeatMapStore = create<HeatMapState>()(
immer((set, get) => ({
monitoringVehicle: [],
monitoringHuman: [],
setMonitoringVehicle: (vehiclesUuid) =>
set((state) => {
state.monitoringVehicle = vehiclesUuid;
}),
addMonitoringVehicle: (vehicleUuid) =>
set((state) => {
if (!state.monitoringVehicle.includes(vehicleUuid)) {
state.monitoringVehicle.push(vehicleUuid);
}
}),
removeMonitoringVehicle: (vehicleUuid) =>
set((state) => {
state.monitoringVehicle = state.monitoringVehicle.filter((v) => v !== vehicleUuid);
}),
clearMonitoringVehicle: () =>
set((state) => {
state.monitoringVehicle = [];
}),
setMonitoringHuman: (humansUuid) =>
set((state) => {
state.monitoringHuman = humansUuid;
}),
addMonitoringHuman: (humanUuid) =>
set((state) => {
if (!state.monitoringHuman.includes(humanUuid)) {
state.monitoringHuman.push(humanUuid);
}
}),
removeMonitoringHuman: (humanUuid) =>
set((state) => {
state.monitoringHuman = state.monitoringHuman.filter((h) => h !== humanUuid);
}),
clearMonitoringHuman: () =>
set((state) => {
state.monitoringHuman = [];
}),
clearAllMonitors: () =>
set((state) => {
state.monitoringVehicle = [];
state.monitoringHuman = [];
}),
hasVehicle: (vehicleUuid) => get().monitoringVehicle.includes(vehicleUuid),
hasHuman: (humanUuid) => get().monitoringHuman.includes(humanUuid),
}))
);
// useEffect(() => {
// const selectedProductData = getProductById(selectedProduct.productUuid);
// const newEvents: EventsSchema[] = [];
// if (selectedProductData) {
// determineExecutionMachineSequences([selectedProductData]).then((sequences) => {
// sequences.forEach((sequence) => {
// sequence.forEach((event) => {
// if (event.type === "human" || event.type === "vehicle") {
// newEvents.push(event);
// }
// });
// });
// setEvents(newEvents);
// });
// }
// }, [selectedProduct, products, monitoringHuman, monitoringVehicle]);