refactor: clean up comments and improve code readability in heatmap components
This commit is contained in:
@@ -18,9 +18,6 @@ const BakedHeatMap = () => {
|
|||||||
const height = CONSTANTS.gridConfig.size;
|
const height = CONSTANTS.gridConfig.size;
|
||||||
const width = CONSTANTS.gridConfig.size;
|
const width = CONSTANTS.gridConfig.size;
|
||||||
|
|
||||||
/**
|
|
||||||
* Helper: Create a DataTexture from filtered baked points
|
|
||||||
*/
|
|
||||||
const createPointTexture = useCallback(
|
const createPointTexture = useCallback(
|
||||||
(filteredPoints: typeof bakedPoints) => {
|
(filteredPoints: typeof bakedPoints) => {
|
||||||
if (filteredPoints.length === 0) return null;
|
if (filteredPoints.length === 0) return null;
|
||||||
@@ -30,8 +27,8 @@ const BakedHeatMap = () => {
|
|||||||
const index = i * 4;
|
const index = i * 4;
|
||||||
data[index] = (p.points.x + width / 2) / width;
|
data[index] = (p.points.x + width / 2) / width;
|
||||||
data[index + 1] = (p.points.y + height / 2) / height;
|
data[index + 1] = (p.points.y + height / 2) / height;
|
||||||
data[index + 2] = 0.3; // heat strength
|
data[index + 2] = 0.3;
|
||||||
data[index + 3] = 0.0; // unused
|
data[index + 3] = 0.0;
|
||||||
});
|
});
|
||||||
|
|
||||||
const texture = new THREE.DataTexture(
|
const texture = new THREE.DataTexture(
|
||||||
@@ -55,25 +52,20 @@ const BakedHeatMap = () => {
|
|||||||
u_growthRate: { value: GROWTH_RATE },
|
u_growthRate: { value: GROWTH_RATE },
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
|
||||||
* Render the heatmap to a base64 PNG for a specific type (human/vehicle)
|
|
||||||
*/
|
|
||||||
const renderHeatmapToImage = useCallback(
|
const renderHeatmapToImage = useCallback(
|
||||||
(type: string) => {
|
(type: string) => {
|
||||||
if (!meshRef.current) return null;
|
if (!meshRef.current) return null;
|
||||||
|
|
||||||
// Filter points by type first
|
|
||||||
const filteredPoints = bakedPoints.filter((p) => p.type === type);
|
const filteredPoints = bakedPoints.filter((p) => p.type === type);
|
||||||
if (filteredPoints.length === 0) return null;
|
if (filteredPoints.length === 0) return null;
|
||||||
|
|
||||||
// Create texture for these points
|
|
||||||
const pointTexture = createPointTexture(filteredPoints);
|
const pointTexture = createPointTexture(filteredPoints);
|
||||||
if (!pointTexture) return null;
|
if (!pointTexture) return null;
|
||||||
|
|
||||||
uniformsRef.current.u_points.value = pointTexture;
|
uniformsRef.current.u_points.value = pointTexture;
|
||||||
uniformsRef.current.u_count.value = filteredPoints.length;
|
uniformsRef.current.u_count.value = filteredPoints.length;
|
||||||
|
|
||||||
// Temporary top-down orthographic camera
|
|
||||||
const exportCamera = new THREE.OrthographicCamera(
|
const exportCamera = new THREE.OrthographicCamera(
|
||||||
width / -2,
|
width / -2,
|
||||||
width / 2,
|
width / 2,
|
||||||
@@ -85,26 +77,23 @@ const BakedHeatMap = () => {
|
|||||||
exportCamera.position.set(0, 1, 0);
|
exportCamera.position.set(0, 1, 0);
|
||||||
exportCamera.lookAt(0, 0, 0);
|
exportCamera.lookAt(0, 0, 0);
|
||||||
|
|
||||||
// Offscreen render target
|
|
||||||
const renderTarget = new THREE.WebGLRenderTarget(1024, 1024, {
|
const renderTarget = new THREE.WebGLRenderTarget(1024, 1024, {
|
||||||
format: THREE.RGBAFormat,
|
format: THREE.RGBAFormat,
|
||||||
type: THREE.UnsignedByteType,
|
type: THREE.UnsignedByteType,
|
||||||
});
|
});
|
||||||
|
|
||||||
// Temporary scene with only this mesh
|
|
||||||
const tempScene = new THREE.Scene();
|
const tempScene = new THREE.Scene();
|
||||||
tempScene.add(meshRef.current);
|
tempScene.add(meshRef.current);
|
||||||
|
|
||||||
// Render to texture
|
|
||||||
gl.setRenderTarget(renderTarget);
|
gl.setRenderTarget(renderTarget);
|
||||||
gl.render(tempScene, exportCamera);
|
gl.render(tempScene, exportCamera);
|
||||||
gl.setRenderTarget(null);
|
gl.setRenderTarget(null);
|
||||||
|
|
||||||
// Read pixels
|
|
||||||
const pixels = new Uint8Array(1024 * 1024 * 4);
|
const pixels = new Uint8Array(1024 * 1024 * 4);
|
||||||
gl.readRenderTargetPixels(renderTarget, 0, 0, 1024, 1024, pixels);
|
gl.readRenderTargetPixels(renderTarget, 0, 0, 1024, 1024, pixels);
|
||||||
|
|
||||||
// Convert pixels to base64 PNG
|
|
||||||
const canvas = document.createElement("canvas");
|
const canvas = document.createElement("canvas");
|
||||||
canvas.width = 1024;
|
canvas.width = 1024;
|
||||||
canvas.height = 1024;
|
canvas.height = 1024;
|
||||||
@@ -116,30 +105,38 @@ const BakedHeatMap = () => {
|
|||||||
ctx.putImageData(imageData, 0, 0);
|
ctx.putImageData(imageData, 0, 0);
|
||||||
return canvas.toDataURL("image/png");
|
return canvas.toDataURL("image/png");
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
},
|
},
|
||||||
[gl, width, height, bakedPoints, createPointTexture]
|
[gl, width, height, bakedPoints, createPointTexture]
|
||||||
);
|
);
|
||||||
|
|
||||||
/**
|
|
||||||
* Export both human and vehicle heatmaps and log them
|
const downloadImage = (base64: string, filename: string) => {
|
||||||
*/
|
const link = document.createElement("a");
|
||||||
|
link.href = base64;
|
||||||
|
link.download = filename;
|
||||||
|
document.body.appendChild(link);
|
||||||
|
link.click();
|
||||||
|
document.body.removeChild(link);
|
||||||
|
};
|
||||||
|
|
||||||
const exportHeatmapAsPNG = useCallback(() => {
|
const exportHeatmapAsPNG = useCallback(() => {
|
||||||
const types = ["human", "vehicle"];
|
const types = ["human", "vehicle"];
|
||||||
|
|
||||||
const result = types.map((type) => {
|
const result = types.map((type) => {
|
||||||
const image = renderHeatmapToImage(type);
|
const image = renderHeatmapToImage(type);
|
||||||
return {
|
if (image) {
|
||||||
type,
|
downloadImage(image, `${type}-heatmap.png`);
|
||||||
image,
|
}
|
||||||
};
|
return { type, image };
|
||||||
});
|
});
|
||||||
|
|
||||||
console.log("Exported Heatmaps:", result);
|
console.log("Exported Heatmaps:", result);
|
||||||
return result;
|
return result;
|
||||||
}, [renderHeatmapToImage]);
|
}, [renderHeatmapToImage]);
|
||||||
|
|
||||||
// Create default texture for initial rendering
|
|
||||||
const pointTexture = useMemo(() => createPointTexture(bakedPoints), [bakedPoints, createPointTexture]);
|
const pointTexture = useMemo(() => createPointTexture(bakedPoints), [bakedPoints, createPointTexture]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -149,6 +146,7 @@ const BakedHeatMap = () => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
|
||||||
<mesh ref={meshRef} rotation={[Math.PI / 2, 0, 0]} position={[0, 0.025, 0]}>
|
<mesh ref={meshRef} rotation={[Math.PI / 2, 0, 0]} position={[0, 0.025, 0]}>
|
||||||
<planeGeometry args={[width, height]} />
|
<planeGeometry args={[width, height]} />
|
||||||
<shaderMaterial
|
<shaderMaterial
|
||||||
@@ -211,7 +209,6 @@ const BakedHeatMap = () => {
|
|||||||
/>
|
/>
|
||||||
</mesh>
|
</mesh>
|
||||||
|
|
||||||
{/* Button to export */}
|
|
||||||
<Html>
|
<Html>
|
||||||
<button
|
<button
|
||||||
style={{
|
style={{
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ function HeatMap() {
|
|||||||
const { bakedPoints, setBakedPoints } = useHeatMapStore();
|
const { bakedPoints, setBakedPoints } = useHeatMapStore();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
console.log("bakedPoints: ", bakedPoints);
|
// console.log("bakedPoints: ", bakedPoints);
|
||||||
}, [bakedPoints]);
|
}, [bakedPoints]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -1,11 +1,10 @@
|
|||||||
import * as THREE from "three";
|
import * as THREE from "three";
|
||||||
import { useEffect, useMemo, useRef, useState } from "react";
|
import { useEffect, useMemo, useRef, useState } from "react";
|
||||||
import { useFrame, useThree } from "@react-three/fiber";
|
import { useFrame, useThree } from "@react-three/fiber";
|
||||||
import { useProductContext } from "../../../modules/simulation/products/productContext";
|
|
||||||
import { useSceneContext } from "../../../modules/scene/sceneContext";
|
import { useSceneContext } from "../../../modules/scene/sceneContext";
|
||||||
import * as CONSTANTS from "../../../types/world/worldConstants";
|
import * as CONSTANTS from "../../../types/world/worldConstants";
|
||||||
import { determineExecutionMachineSequences } from "../../../modules/simulation/simulator/functions/determineExecutionMachineSequences";
|
import { determineExecutionMachineSequences } from "../../../modules/simulation/simulator/functions/determineExecutionMachineSequences";
|
||||||
import { useAnimationPlaySpeed, usePauseButtonStore, usePlayButtonStore, useResetButtonStore } from "../../../store/usePlayButtonStore";
|
import { useAnimationPlaySpeed, usePauseButtonStore, usePlayButtonStore, useResetButtonStore } from "../../../store/ui/usePlayButtonStore";
|
||||||
import { useHeatMapStore } from "../../../store/simulation/useHeatMapStore";
|
import { useHeatMapStore } from "../../../store/simulation/useHeatMapStore";
|
||||||
|
|
||||||
const DECAY_RATE = 0.01;
|
const DECAY_RATE = 0.01;
|
||||||
@@ -28,9 +27,7 @@ const RealTimeHeatMap = () => {
|
|||||||
const debugMode: "solid" | "grayscale" | "normal" = "normal";
|
const debugMode: "solid" | "grayscale" | "normal" = "normal";
|
||||||
const debugModeMap = { solid: 0, grayscale: 1, normal: 2 } as const;
|
const debugModeMap = { solid: 0, grayscale: 1, normal: 2 } as const;
|
||||||
const { productStore } = useSceneContext();
|
const { productStore } = useSceneContext();
|
||||||
const { getProductById, products } = productStore();
|
const { getProductById, products, selectedProduct } = productStore();
|
||||||
const { selectedProductStore } = useProductContext();
|
|
||||||
const { selectedProduct } = selectedProductStore();
|
|
||||||
const { hasHuman, hasVehicle, monitoringHuman, monitoringVehicle, addMonitoringHuman, addMonitoringVehicle, addBakedPoint } = useHeatMapStore();
|
const { hasHuman, hasVehicle, monitoringHuman, monitoringVehicle, addMonitoringHuman, addMonitoringVehicle, addBakedPoint } = useHeatMapStore();
|
||||||
const { isPlaying } = usePlayButtonStore();
|
const { isPlaying } = usePlayButtonStore();
|
||||||
const { isReset } = useResetButtonStore();
|
const { isReset } = useResetButtonStore();
|
||||||
@@ -51,7 +48,7 @@ const RealTimeHeatMap = () => {
|
|||||||
u_radius: { value: RADIUS },
|
u_radius: { value: RADIUS },
|
||||||
u_opacity: { value: OPACITY },
|
u_opacity: { value: OPACITY },
|
||||||
u_debugMode: { value: debugModeMap[debugMode] },
|
u_debugMode: { value: debugModeMap[debugMode] },
|
||||||
u_growthRate: { value: GROWTH_TIME_MULTIPLIER }, // NEW
|
u_growthRate: { value: GROWTH_TIME_MULTIPLIER },
|
||||||
});
|
});
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|||||||
Reference in New Issue
Block a user