From 0d84f6527f5fce3e0fb079cd6e48cd25baa22327 Mon Sep 17 00:00:00 2001 From: Jerald-Golden-B Date: Fri, 17 Oct 2025 15:56:45 +0530 Subject: [PATCH] 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. --- .../layout/scenes/ComparisonScene.tsx | 101 ++-------- .../simulation/heatMap}/heatMap.tsx | 2 +- .../simulation/heatMap}/heatMapRenderer.tsx | 8 +- .../simulation/heatMap}/heatmapPreview.tsx | 8 +- .../heatMap}/realTime/realTimeHeatMap.tsx | 30 +-- app/src/modules/simulation/simulation.tsx | 2 +- .../store/rough/useSimulationManagerStore.ts | 177 +++++++++++++++++- 7 files changed, 211 insertions(+), 117 deletions(-) rename app/src/{components/heatMapGenerator => modules/simulation/heatMap}/heatMap.tsx (81%) rename app/src/{components/heatMapGenerator => modules/simulation/heatMap}/heatMapRenderer.tsx (90%) rename app/src/{components/heatMapGenerator => modules/simulation/heatMap}/heatmapPreview.tsx (90%) rename app/src/{components/heatMapGenerator => modules/simulation/heatMap}/realTime/realTimeHeatMap.tsx (91%) diff --git a/app/src/components/layout/scenes/ComparisonScene.tsx b/app/src/components/layout/scenes/ComparisonScene.tsx index fb0d382..323c5a8 100644 --- a/app/src/components/layout/scenes/ComparisonScene.tsx +++ b/app/src/components/layout/scenes/ComparisonScene.tsx @@ -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 && ( diff --git a/app/src/components/heatMapGenerator/heatMap.tsx b/app/src/modules/simulation/heatMap/heatMap.tsx similarity index 81% rename from app/src/components/heatMapGenerator/heatMap.tsx rename to app/src/modules/simulation/heatMap/heatMap.tsx index 89fad23..bcdbfd9 100644 --- a/app/src/components/heatMapGenerator/heatMap.tsx +++ b/app/src/modules/simulation/heatMap/heatMap.tsx @@ -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() { diff --git a/app/src/components/heatMapGenerator/heatMapRenderer.tsx b/app/src/modules/simulation/heatMap/heatMapRenderer.tsx similarity index 90% rename from app/src/components/heatMapGenerator/heatMapRenderer.tsx rename to app/src/modules/simulation/heatMap/heatMapRenderer.tsx index 2e6925f..aee6a8b 100644 --- a/app/src/components/heatMapGenerator/heatMapRenderer.tsx +++ b/app/src/modules/simulation/heatMap/heatMapRenderer.tsx @@ -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 = () => { diff --git a/app/src/components/heatMapGenerator/heatmapPreview.tsx b/app/src/modules/simulation/heatMap/heatmapPreview.tsx similarity index 90% rename from app/src/components/heatMapGenerator/heatmapPreview.tsx rename to app/src/modules/simulation/heatMap/heatmapPreview.tsx index 442b67e..40607b1 100644 --- a/app/src/components/heatMapGenerator/heatmapPreview.tsx +++ b/app/src/modules/simulation/heatMap/heatmapPreview.tsx @@ -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 = ({ 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()); diff --git a/app/src/components/heatMapGenerator/realTime/realTimeHeatMap.tsx b/app/src/modules/simulation/heatMap/realTime/realTimeHeatMap.tsx similarity index 91% rename from app/src/components/heatMapGenerator/realTime/realTimeHeatMap.tsx rename to app/src/modules/simulation/heatMap/realTime/realTimeHeatMap.tsx index 255e8f6..87e076c 100644 --- a/app/src/components/heatMapGenerator/realTime/realTimeHeatMap.tsx +++ b/app/src/modules/simulation/heatMap/realTime/realTimeHeatMap.tsx @@ -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]); diff --git a/app/src/modules/simulation/simulation.tsx b/app/src/modules/simulation/simulation.tsx index 3bb6f1e..65fa29b 100644 --- a/app/src/modules/simulation/simulation.tsx +++ b/app/src/modules/simulation/simulation.tsx @@ -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(); diff --git a/app/src/store/rough/useSimulationManagerStore.ts b/app/src/store/rough/useSimulationManagerStore.ts index 91dd114..ee061bf 100644 --- a/app/src/store/rough/useSimulationManagerStore.ts +++ b/app/src/store/rough/useSimulationManagerStore.ts @@ -242,4 +242,179 @@ export const useSimulationManager = create((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()( +// 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; +// }, +// })) +// );