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:
@@ -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 && (
|
||||
|
||||
@@ -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() {
|
||||
@@ -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 = () => {
|
||||
@@ -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());
|
||||
@@ -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]);
|
||||
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
// },
|
||||
// }))
|
||||
// );
|
||||
|
||||
Reference in New Issue
Block a user