Refactor heatmap components and restructure simulation heatmap logic

- Deleted obsolete heatmapPreview and realTimeHeatMap components.
- Moved heatmap logic into a new structure under modules/simulation/heatMap.
- Introduced HeatMap and HeatMapRenderer components to manage heatmap rendering based on comparison state.
- Updated imports and adjusted state management for heatmap data.
- Enhanced heatmap preview functionality to handle image loading and rendering.
- Improved performance and organization of heatmap data handling in the simulation context.
This commit is contained in:
2025-10-17 15:56:45 +05:30
parent 1465043faf
commit 0d84f6527f
7 changed files with 211 additions and 117 deletions

View File

@@ -1,11 +1,4 @@
import {
useCompareProductDataStore,
useLoadingProgress,
useIsComparing,
useCreateNewWindow,
useLimitDistance,
useRenderDistance,
} from "../../../store/builder/store";
import { useCompareProductDataStore, useLoadingProgress, useIsComparing, useCreateNewWindow, useLimitDistance, useRenderDistance } from "../../../store/builder/store";
import { useSimulationState } from "../../../store/simulation/useSimulationStore";
import { usePlayButtonStore } from "../../../store/ui/usePlayButtonStore";
import { useEffect, useState } from "react";
@@ -45,22 +38,13 @@ export interface CompareProduct {
efficiencyScore?: number;
};
}
export const createCompareProduct = (
productUuid: string,
productName: string,
assets: AssetData[]
): CompareProduct => ({
productUuid,
productName,
simulationData: calculateSimulationData(assets),
});
function ComparisonScene() {
const { isPlaying } = usePlayButtonStore();
const { productStore, versionStore } = useSceneContext();
const { versionHistory, selectedVersion, setSelectedVersion } = versionStore();
const { products, selectedProduct } = productStore();
const { isComparing, setIsComparing } = useIsComparing();
const { isComparing } = useIsComparing();
const { activeModule } = useModuleStore();
const { mainScene, comparisonScene, setComparisonState } = useSimulationState();
const { loadingProgress } = useLoadingProgress();
@@ -69,10 +53,8 @@ function ComparisonScene() {
const { setCompareProductsData } = useCompareProductDataStore();
const [shouldShowComparisonResult, setShouldShowComparisonResult] = useState(false);
const { addSimulationRecord } = useSimulationManager();
const { createNewWindow, setCreateNewWindow } = useCreateNewWindow();
const { clearComparisonState } = useSimulationState();
const { setRenderDistance } = useRenderDistance();
const { setLimitDistance } = useLimitDistance();
const { createNewWindow } = useCreateNewWindow();
const handleSelectVersion = (option: string) => {
const version = versionHistory.find((version) => version.versionName === option);
if (version) {
@@ -86,22 +68,12 @@ function ComparisonScene() {
echo.log(getData.message);
const getSimulate = getData?.data?.existingSimulatedData;
if (!getSimulate) return;
if (
!selectedVersion?.versionId ||
!projectId ||
getSimulate === undefined ||
!selectedProduct.productUuid
) {
if (!selectedVersion?.versionId || !projectId || getSimulate === undefined || !selectedProduct.productUuid) {
echo.warn("No prebacked Data found");
alert("Please run the simulation before comparing.");
return;
}
addSimulationRecord(
projectId,
selectedVersion?.versionId || "",
selectedProduct.productUuid || "",
getSimulate.data
);
addSimulationRecord(projectId, selectedVersion?.versionId || "", selectedProduct.productUuid || "", getSimulate.data);
});
}
};
@@ -124,45 +96,26 @@ function ComparisonScene() {
echo.warn(getData.message);
const getSimulate = getData?.data?.existingSimulatedData;
if (!getSimulate) return;
addSimulationRecord(
projectId,
selectedVersion?.versionId || "",
product.productUuid || "",
getSimulate.data
);
addSimulationRecord(projectId, selectedVersion?.versionId || "", product.productUuid || "", getSimulate.data);
});
setComparisonState(data);
}
};
const createCompareProduct = (productUuid: string, productName: string, assets: AssetData[]): CompareProduct => ({
productUuid,
productName,
simulationData: calculateSimulationData(assets),
});
useEffect(() => {
if (mainScene && comparisonScene && selectedVersion) {
const mainVersion = useSimulationManager
.getState()
.getProductById(
projectId,
mainScene.version.versionUuid,
mainScene.product.productUuid
);
const mainVersion = useSimulationManager.getState().getProductById(projectId, mainScene.version.versionUuid, mainScene.product.productUuid);
const compareVersion = useSimulationManager
.getState()
.getProductById(
projectId,
comparisonScene.version.versionUuid,
comparisonScene.product.productUuid
);
const compareVersion = useSimulationManager.getState().getProductById(projectId, comparisonScene.version.versionUuid, comparisonScene.product.productUuid);
const mainVompareversion = createCompareProduct(
mainVersion?.productId ?? "",
mainScene.product.productName,
mainVersion?.simulateData || []
);
const compareProduct2 = createCompareProduct(
compareVersion?.productId ?? "",
comparisonScene.product.productName,
compareVersion?.simulateData || []
);
const mainVompareversion = createCompareProduct(mainVersion?.productId ?? "", mainScene.product.productName, mainVersion?.simulateData || []);
const compareProduct2 = createCompareProduct(compareVersion?.productId ?? "", comparisonScene.product.productName, compareVersion?.simulateData || []);
const comparedArray = [mainVompareversion, compareProduct2];
@@ -175,26 +128,8 @@ function ComparisonScene() {
} else {
setShouldShowComparisonResult(false);
}
}, [
mainScene,
comparisonScene,
selectedVersion,
projectId,
setCompareProductsData,
simulationRecords,
]);
}, [mainScene, comparisonScene, selectedVersion, projectId, setCompareProductsData, simulationRecords]);
const handleExit = () => {
setIsComparing(false);
setCreateNewWindow(false);
clearComparisonState();
if (!projectId) return;
findEnvironment(projectId).then((data) => {
if (!data) return;
setRenderDistance(data.renderDistance);
setLimitDistance(data.limitDistance);
});
};
return (
<>
{isComparing && activeModule === "simulation" && selectedProduct && (

View File

@@ -1,5 +1,5 @@
import RealTimeHeatMap from "./realTime/realTimeHeatMap";
import { useIsComparing } from "../../store/builder/store";
import { useIsComparing } from "../../../store/builder/store";
import HeatMapRenderer from "./heatMapRenderer";
function HeatMap() {

View File

@@ -1,7 +1,7 @@
import React, { useMemo } from "react";
import { useSceneContext } from "../../modules/scene/sceneContext";
import { useSimulationManager } from "../../store/rough/useSimulationManagerStore";
import { useSimulationState } from "../../store/simulation/useSimulationStore";
import { useMemo } from "react";
import { useSceneContext } from "../../scene/sceneContext";
import { useSimulationManager } from "../../../store/rough/useSimulationManagerStore";
import { useSimulationState } from "../../../store/simulation/useSimulationStore";
import HeatmapPreview from "./heatmapPreview";
const HeatMapRenderer = () => {

View File

@@ -1,7 +1,7 @@
import { useState, useEffect } from "react";
import { TextureLoader, Texture, DoubleSide } from "three";
import * as CONSTANTS from "../../types/world/worldConstants";
import { useHeatmapTypeStore } from "../../store/builder/store";
import * as CONSTANTS from "../../../types/world/worldConstants";
import { useHeatmapTypeStore } from "../../../store/builder/store";
interface HeatmapPreviewProps {
image: string | Blob | null;
@@ -41,9 +41,7 @@ const HeatmapPreview: React.FC<HeatmapPreviewProps> = ({ image, type }) => {
// Handle string URL input
if (typeof image === "string") {
const fixedImage = image.includes(":undefined")
? image.replace(":undefined", ":8400")
: image;
const fixedImage = image.includes(":undefined") ? image.replace(":undefined", ":8400") : image;
// Only load if it ends with a valid image extension
const isValidImage = /\.(png|jpg|jpeg|webp|gif)$/i.test(fixedImage.trim());

View File

@@ -1,16 +1,11 @@
import * as THREE from "three";
import { useEffect, useMemo, useRef, useState } from "react";
import { useFrame, useThree } from "@react-three/fiber";
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/ui/usePlayButtonStore";
import { useHeatMapStore } from "../../../store/simulation/useHeatMapStore";
import { useSceneContext } from "../../../scene/sceneContext";
import * as CONSTANTS from "../../../../types/world/worldConstants";
import { determineExecutionMachineSequences } from "../../simulator/functions/determineExecutionMachineSequences";
import { useAnimationPlaySpeed, usePauseButtonStore, usePlayButtonStore, useResetButtonStore } from "../../../../store/ui/usePlayButtonStore";
import { useHeatMapStore } from "../../../../store/simulation/useHeatMapStore";
const DECAY_RATE = 0.01;
const GROWTH_TIME_MULTIPLIER = 20;
@@ -33,8 +28,7 @@ const RealTimeHeatMap = () => {
const debugModeMap = { solid: 0, grayscale: 1, normal: 2 } as const;
const { productStore } = useSceneContext();
const { getProductById, products, selectedProduct } = productStore();
const { monitoringHuman, monitoringVehicle, clearBakedPoints, addBakedPoint } =
useHeatMapStore();
const { monitoringHuman, monitoringVehicle, clearBakedPoints, addBakedPoint } = useHeatMapStore();
const { isPlaying } = usePlayButtonStore();
const { isReset } = useResetButtonStore();
const { isPaused } = usePauseButtonStore();
@@ -159,9 +153,7 @@ const RealTimeHeatMap = () => {
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);
});
@@ -177,13 +169,7 @@ const RealTimeHeatMap = () => {
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]);

View File

@@ -14,7 +14,7 @@ import Trigger from "./triggers/trigger";
import useModuleStore from "../../store/ui/useModuleStore";
import SimulationAnalysis from "./analysis/simulationAnalysis";
import { useSceneContext } from "../scene/sceneContext";
import HeatMap from "../../components/heatMapGenerator/heatMap";
import HeatMap from "./heatMap/heatMap";
function Simulation() {
const { activeModule } = useModuleStore();

View File

@@ -242,4 +242,179 @@ export const useSimulationManager = create<SimulationManagerStore>((set, get) =>
return version?.products.find((p: ProductSimulation) => p.productId === productId);
},
}));
///////////////////////////
// import { create } from "zustand";
// import { immer } from "zustand/middleware/immer";
// interface SimulationUsageRecord {
// activeTime: number;
// isActive: boolean;
// idleTime: number;
// type: "roboticArm" | "vehicle" | "transfer" | "storageUnit" | "crane" | "human" | "machine";
// assetId: string;
// }
// type image = string | Blob | null;
// // Product → holds multiple usage records
// interface ProductSimulation {
// productId: string;
// simulateData: SimulationUsageRecord[];
// heatMaps?: { type: string; image: image }[];
// }
// // Version → holds multiple products
// interface VersionSimulation {
// versionId: string;
// products: ProductSimulation[];
// }
// // Project → holds multiple versions
// interface ProjectSimulation {
// projectId: string | undefined;
// versions: VersionSimulation[];
// }
// interface SimulationManagerStore {
// simulationRecords: ProjectSimulation[];
// // Main operations
// addSimulationRecord: (projectId: string | undefined, versionId: string, productId: string, record: SimulationUsageRecord) => void;
// addSimulationRecords: (projectId: string | undefined, versionId: string, productId: string, records: SimulationUsageRecord[], heatMaps?: { type: string; image: image }[]) => void;
// resetProductRecords: (projectId: string | undefined, versionId: string | null, productId: string) => void;
// // Getter helpers
// getProjectById: (projectId: string | undefined) => ProjectSimulation | undefined;
// getVersionById: (projectId: string | undefined, versionId: string | null) => VersionSimulation | undefined;
// getProductById: (projectId: string | undefined, versionId: string | null, productId: string) => ProductSimulation | undefined;
// getSimulationRecordById: (projectId: string | undefined, versionId: string, productId: string, assetId: string) => SimulationUsageRecord | undefined;
// getHeatMapsById: (projectId: string | undefined, versionId: string, productId: string) => { type: string; image: image }[] | undefined;
// // Helper functions for internal use
// findOrCreateProject: (projectId: string | undefined) => ProjectSimulation;
// findOrCreateVersion: (project: ProjectSimulation, versionId: string) => VersionSimulation;
// findOrCreateProduct: (version: VersionSimulation, productId: string) => ProductSimulation;
// findOrUpdateSimulationRecord: (product: ProductSimulation, record: SimulationUsageRecord) => void;
// }
// export const useSimulationManager = create<SimulationManagerStore>()(
// immer((set, get) => ({
// simulationRecords: [],
// // Helper functions
// findOrCreateProject: (projectId) => {
// let project = get().simulationRecords.find((p) => p.projectId === projectId);
// if (!project) {
// project = { projectId, versions: [] };
// set((state) => {
// state.simulationRecords.push(project!);
// });
// }
// return project!;
// },
// findOrCreateVersion: (project, versionId) => {
// let version = project.versions.find((v) => v.versionId === versionId);
// if (!version) {
// version = { versionId, products: [] };
// set((state) => {
// const targetProject = state.simulationRecords.find((p) => p.projectId === project.projectId);
// if (targetProject) {
// targetProject.versions.push(version!);
// }
// });
// }
// return version!;
// },
// findOrCreateProduct: (version, productId) => {
// let product = version.products.find((p) => p.productId === productId);
// if (!product) {
// product = { productId, simulateData: [] };
// set((state) => {
// const targetProject = state.simulationRecords.find((p) => p.versions.some((v) => v.versionId === version.versionId));
// const targetVersion = targetProject?.versions.find((v) => v.versionId === version.versionId);
// if (targetVersion) {
// targetVersion.products.push(product!);
// }
// });
// }
// return product!;
// },
// findOrUpdateSimulationRecord: (product, record) => {
// const existingIndex = product.simulateData.findIndex((r) => r.assetId === record.assetId);
// if (existingIndex !== -1) {
// set((state) => {
// const targetRecord = product.simulateData[existingIndex];
// Object.assign(targetRecord, record);
// });
// } else {
// set((state) => {
// product.simulateData.push(record);
// });
// }
// },
// // Main operations
// addSimulationRecord: (projectId, versionId, productId, record) =>
// set((state) => {
// const project = get().findOrCreateProject(projectId);
// const version = get().findOrCreateVersion(project, versionId);
// const product = get().findOrCreateProduct(version, productId);
// get().findOrUpdateSimulationRecord(product, record);
// }),
// addSimulationRecords: (projectId, versionId, productId, records, heatMaps) =>
// set((state) => {
// const project = get().findOrCreateProject(projectId);
// const version = get().findOrCreateVersion(project, versionId);
// const product = get().findOrCreateProduct(version, productId);
// // Add all records
// records.forEach((record) => {
// get().findOrUpdateSimulationRecord(product, record);
// });
// // Update heatmaps if provided
// if (heatMaps) {
// product.heatMaps = heatMaps;
// }
// }),
// resetProductRecords: (projectId, versionId, productId) =>
// set((state) => {
// const product = get().getProductById(projectId, versionId, productId);
// if (product) {
// product.simulateData = [];
// }
// }),
// // Getter helpers
// getProjectById: (projectId) => {
// return get().simulationRecords.find((p) => p.projectId === projectId);
// },
// getVersionById: (projectId, versionId) => {
// const project = get().getProjectById(projectId);
// return project?.versions.find((v) => v.versionId === versionId);
// },
// getProductById: (projectId, versionId, productId) => {
// const version = get().getVersionById(projectId, versionId);
// return version?.products.find((p) => p.productId === productId);
// },
// getSimulationRecordById: (projectId, versionId, productId, assetId) => {
// const product = get().getProductById(projectId, versionId, productId);
// return product?.simulateData.find((record) => record.assetId === assetId);
// },
// getHeatMapsById: (projectId, versionId, productId) => {
// const product = get().getProductById(projectId, versionId, productId);
// return product?.heatMaps;
// },
// }))
// );