diff --git a/cura/LayerPolygon.py b/cura/LayerPolygon.py index 103703e594..e5fd307dc9 100644 --- a/cura/LayerPolygon.py +++ b/cura/LayerPolygon.py @@ -1,5 +1,6 @@ # Copyright (c) 2019 Ultimaker B.V. # Cura is released under the terms of the LGPLv3 or higher. +import math import numpy from typing import Optional, cast @@ -186,6 +187,11 @@ class LayerPolygon: def types(self): return self._types + @property + def lineLengths(self): + data_array = numpy.array(self._data) + return numpy.linalg.norm(data_array[1:] - data_array[:-1], axis=1) + @property def data(self): return self._data diff --git a/plugins/SimulationView/SimulationView.py b/plugins/SimulationView/SimulationView.py index 473948bc46..a659a6de97 100644 --- a/plugins/SimulationView/SimulationView.py +++ b/plugins/SimulationView/SimulationView.py @@ -78,6 +78,8 @@ class SimulationView(CuraView): self._minimum_path_num = 0 self.currentLayerNumChanged.connect(self._onCurrentLayerNumChanged) + self._current_feedrates = {} + self._lengths_of_polyline ={} self._busy = False self._simulation_running = False @@ -400,6 +402,15 @@ class SimulationView(CuraView): def getMaxFeedrate(self) -> float: return self._max_feedrate + def getSimulationTime(self, currentIndex) -> float: + try: + return (self._lengths_of_polyline[self._current_layer_num][currentIndex] / self._current_feedrates[self._current_layer_num][currentIndex])[0] + + except: + # In case of change in layers, currentIndex comes one more than the items in the lengths_of_polyline + # We give 1 second time for layer change + return 1.0 + def getMinThickness(self) -> float: if abs(self._min_thickness - sys.float_info.max) < 10: # Some lenience due to floating point rounding. return 0.0 # If it's still max-float, there are no measurements. Use 0 then. @@ -524,8 +535,10 @@ class SimulationView(CuraView): visible_indicies_with_extrusion = numpy.where(numpy.isin(polyline.types, visible_line_types_with_extrusion))[0] if visible_indices.size == 0: # No items to take maximum or minimum of. continue + self._lengths_of_polyline[layer_index] = polyline.lineLengths visible_feedrates = numpy.take(polyline.lineFeedrates, visible_indices) visible_feedrates_with_extrusion = numpy.take(polyline.lineFeedrates, visible_indicies_with_extrusion) + self._current_feedrates[layer_index] = polyline.lineFeedrates visible_linewidths = numpy.take(polyline.lineWidths, visible_indices) visible_linewidths_with_extrusion = numpy.take(polyline.lineWidths, visible_indicies_with_extrusion) visible_thicknesses = numpy.take(polyline.lineThicknesses, visible_indices) diff --git a/plugins/SimulationView/SimulationViewMainComponent.qml b/plugins/SimulationView/SimulationViewMainComponent.qml index a82d1e3db9..216095c15c 100644 --- a/plugins/SimulationView/SimulationViewMainComponent.qml +++ b/plugins/SimulationView/SimulationViewMainComponent.qml @@ -136,7 +136,7 @@ Item Timer { id: simulationTimer - interval: 100 + interval: UM.SimulationView.simulationTime running: false repeat: true onTriggered: diff --git a/plugins/SimulationView/SimulationViewProxy.py b/plugins/SimulationView/SimulationViewProxy.py index 669f7fdbcc..576281874c 100644 --- a/plugins/SimulationView/SimulationViewProxy.py +++ b/plugins/SimulationView/SimulationViewProxy.py @@ -2,6 +2,7 @@ # Cura is released under the terms of the LGPLv3 or higher. from typing import TYPE_CHECKING +import numpy from PyQt6.QtCore import QObject, pyqtSignal, pyqtProperty from UM.FlameProfiler import pyqtSlot from UM.Application import Application @@ -11,6 +12,11 @@ if TYPE_CHECKING: class SimulationViewProxy(QObject): + + S_TO_MS = 1000 + SPEED_OF_SIMULATION = 10 + FACTOR = S_TO_MS/SPEED_OF_SIMULATION + def __init__(self, simulation_view: "SimulationView", parent=None) -> None: super().__init__(parent) self._simulation_view = simulation_view @@ -54,6 +60,14 @@ class SimulationViewProxy(QObject): def currentPath(self): return self._simulation_view.getCurrentPath() + @pyqtProperty(int, notify=currentPathChanged) + def simulationTime(self): + # Extracts the currents paths simulation time (in seconds) for the current path from the dict of simulation time of the current layer. + # We multiply the time with 100 to make it to ms from s.(Should be 1000 in real time). This scaling makes the simulation time 10x faster than the real time. + simulationTimeOfpath = self._simulation_view.getSimulationTime(self._simulation_view.getCurrentPath()) * SimulationViewProxy.FACTOR + # Since the timer cannot process time less than 1 ms, we put a lower limit here + return int(max(1, simulationTimeOfpath)) + @pyqtProperty(int, notify=currentPathChanged) def minimumPath(self): return self._simulation_view.getMinimumPath()