2.12.2021, 9:00 - 11:00: Due to updates GitLab may be unavailable for some minutes between 09:00 and 11:00.

Commit 7664b98c authored by Daniel Lehmberg's avatar Daniel Lehmberg
Browse files

Merge branch 'master' into...

Merge branch 'master' into 241-new-flag-to-compute-metric-for-the-quality-of-the-stepcircleoptimizer
parents 08a3b8d0 415d81b2
......@@ -14,6 +14,13 @@
- import 'open' paths as polygons with a specified width. With this it is
possible to create walls or subway entrance
- add option to include osm ids into each obstacle created
`PostVis` added functionalities:
- the PostVis works now on the basis of simulation time instead of time steps. Agents' position will be interpolated.
- the user can jump to a specific simulation time
- the user can step forward by steps as small as 0.01s
- the user can make videos using also this new feature which results in very smooth movement
- the frames per seconds (FPS) is now more accurate
### Changed
......
......@@ -204,6 +204,7 @@ OutputprocessorsView.dataProcessor.text={Processor: ""}
AdjustPanel.lblVelocity.text=FPS
AdjustPanel.lblTime=Time
AdjustPanel.lblStep.text=Timestep
AdjustPanel.lblVisTime.text=Res.
ProjectView.warning.lwjgl.title=Warning
ProjectView.warning.opencl.title=Warning
......@@ -243,6 +244,7 @@ ProjectView.btnSnapshot.tooltip=Snapshot
ProjectView.btnPNGSnapshot.tooltip=PNG Snapshot
ProjectView.btnSVGSnapshot.tooltip=SVG Snapshot
ProjectView.btnTikZSnapshot.tooltip=TikZ Snapshot
ProjectView.btnPolySnapshot.tooltip=Poly Snapshot
PostVis.menuFile.title=File
PostVis.menuSettings.title=Setting
PostVis.menuRecentFiles.title=Recent Files
......
......@@ -209,6 +209,7 @@ OutputprocessorsView.dataProcessor.text={"Processor": ""}
AdjustPanel.lblVelocity.text=FPS
AdjustPanel.lblTime=Zeit
AdjustPanel.lblStep.text=Zeitschritt
AdjustPanel.lblVisTime.text=Aufl.
ProjectView.mntmOutputToSceneario.text=Generiere Szenario
ProjectView.mntmRunOutput.text=Offline erneut starten
......@@ -239,6 +240,7 @@ ProjectView.btnSnapshot.tooltip=Snapshot
ProjectView.btnPNGSnapshot.tooltip=PNG-Snapshot
ProjectView.btnSVGSnapshot.tooltip=SVG-Snapshot
ProjectView.btnTikZSnapshot.tooltip=TikZ-Snapshot
ProjectView.btnPolySnapshot.tooltip=Poly-Snapshot
PostVis.menuFile.title=Datei
PostVis.menuSettings.title=Einstellungen
PostVis.menuRecentFiles.title=K\u00FCrzlich verwendete Dateien
......
package org.vadere.gui.components.control.simulation;
import org.vadere.gui.components.model.DefaultSimulationConfig;
import org.vadere.gui.components.model.SimulationModel;
import org.vadere.gui.components.utils.Messages;
import org.vadere.gui.components.utils.Resources;
import org.vadere.gui.components.view.SimulationRenderer;
import org.vadere.gui.postvisualization.PostVisualisation;
import org.vadere.meshing.utils.io.poly.PSLGGenerator;
import org.vadere.state.scenario.Obstacle;
import org.vadere.util.geometry.shapes.VPolygon;
import org.vadere.util.geometry.shapes.VRectangle;
import org.vadere.util.logging.Logger;
import java.awt.event.ActionEvent;
import java.awt.geom.Rectangle2D;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.prefs.Preferences;
import java.util.stream.Collectors;
import javax.swing.*;
public class ActionGeneratePoly extends AbstractAction {
private static Logger logger = Logger.getLogger(ActionGeneratePNG.class);
private static Resources resources = Resources.getInstance("global");
private final SimulationModel<? extends DefaultSimulationConfig> model;
public ActionGeneratePoly(final String name, Icon icon, final SimulationRenderer renderer,
final SimulationModel<? extends DefaultSimulationConfig> model) {
super(name, icon);
this.model = model;
}
@Override
public void actionPerformed(final ActionEvent e) {
JFileChooser fileChooser = new JFileChooser(Preferences.userNodeForPackage(PostVisualisation.class).get("SettingsDialog.snapshotDirectory.path", "."));
Date todaysDate = new java.util.Date();
SimpleDateFormat formatter = new SimpleDateFormat(resources.getProperty("SettingsDialog.dataFormat"));
String formattedDate = formatter.format(todaysDate);
File outputFile = new File(Messages.getString("FileDialog.filenamePrefix") + formattedDate + ".poly");
fileChooser.setSelectedFile(outputFile);
int returnVal = fileChooser.showDialog(null, "Save");
if (returnVal == JFileChooser.APPROVE_OPTION) {
outputFile = fileChooser.getSelectedFile().toString().endsWith(".poly") ? fileChooser.getSelectedFile()
: new File(fileChooser.getSelectedFile().toString() + ".poly");
List<Obstacle> boundingObstacles = model.getTopography().getBoundaryObstacles();
Rectangle2D.Double boundWithBorder = model.getTopography().getBounds();
double boundWidth = model.getTopography().getBoundingBoxWidth();
VRectangle bound = new VRectangle(boundWithBorder.x + boundWidth, boundWithBorder.y + boundWidth, boundWithBorder.width - 2*boundWidth, boundWithBorder.height - 2*boundWidth);
List<Obstacle> obstacles = new ArrayList<>(model.getTopography().getObstacles());
obstacles.removeAll(model.getTopography().getBoundaryObstacles());
String polyString = PSLGGenerator.toPSLG(
new VPolygon(bound),
obstacles.stream()
.map(obs -> obs.getShape())
.map(shape -> new VPolygon(shape))
.collect(Collectors.toList()));
try {
outputFile.createNewFile();
Writer out = new OutputStreamWriter(new FileOutputStream(outputFile), "UTF-8");
out.write(polyString);
out.flush();
logger.info("generate new Poly.file: " + outputFile.getAbsolutePath());
} catch (IOException e1) {
logger.error(e1.getMessage());
e1.printStackTrace();
}
}
}
}
......@@ -135,8 +135,26 @@ public abstract class DefaultModel<T extends DefaultConfig> extends Observable i
@Override
public boolean setScale(final double scale) {
boolean hasChanged = true;
double oldScale = scaleFactor;
boolean hasChanged = setScaleWithoutChangingViewport(scale);
// update the viewport, since it depends on the scaleFactor
if (hasChanged) {
Rectangle2D.Double oldViewPort = getViewportBound();
Rectangle2D.Double newViewPort = new Rectangle2D.Double(
oldViewPort.getMinX(),
oldViewPort.getMinY(),
oldViewPort.getWidth() * oldScale / scaleFactor,
oldViewPort.getHeight() * oldScale / scaleFactor);
setViewportBound(newViewPort);
setChanged();
}
return hasChanged;
}
@Override
public boolean setScaleWithoutChangingViewport(double scale) {
boolean hasChanged = true;
if (scale < MIN_SCALE_FACTOR) {
this.scaleFactor = MIN_SCALE_FACTOR;
......@@ -148,17 +166,10 @@ public abstract class DefaultModel<T extends DefaultConfig> extends Observable i
hasChanged = false;
}
// update the viewport, since it depends on the scaleFactor
if (hasChanged) {
Rectangle2D.Double oldViewPort = getViewportBound();
Rectangle2D.Double newViewPort = new Rectangle2D.Double(
oldViewPort.getMinX(),
oldViewPort.getMinY(),
oldViewPort.getWidth() * oldScale / scaleFactor,
oldViewPort.getHeight() * oldScale / scaleFactor);
setViewportBound(newViewPort);
if(hasChanged) {
setChanged();
}
return hasChanged;
}
......@@ -254,7 +265,7 @@ public abstract class DefaultModel<T extends DefaultConfig> extends Observable i
}
@Override
public void setViewportBound(final Rectangle2D.Double viewportBound) {
public synchronized void setViewportBound(final Rectangle2D.Double viewportBound) {
Rectangle2D.Double oldViewportBound = this.viewportBound;
if (!oldViewportBound.equals(viewportBound)) {
......
......@@ -28,6 +28,8 @@ public interface IDefaultModel<T extends DefaultConfig> extends Iterable<Scenari
boolean setScale(final double scale);
boolean setScaleWithoutChangingViewport(final double scale);
void notifyScaleListeners();
Color getScenarioElementColor(final ScenarioElementType elementType);
......
......@@ -6,11 +6,8 @@ import java.util.function.Function;
import org.vadere.meshing.mesh.gen.PMesh;
import org.vadere.meshing.mesh.inter.IMesh;
import org.vadere.simulator.models.potential.solver.calculators.mesh.PotentialPoint;
import org.vadere.state.scenario.Agent;
import org.vadere.util.data.cellgrid.IPotentialPoint;
import org.vadere.util.geometry.shapes.IPoint;
import org.vadere.util.geometry.shapes.VPoint;
import org.vadere.util.geometry.shapes.VRectangle;
public abstract class SimulationModel<T extends DefaultSimulationConfig> extends DefaultModel {
......@@ -42,8 +39,8 @@ public abstract class SimulationModel<T extends DefaultSimulationConfig> extends
return config;
}
public IMesh<? extends IPotentialPoint, ?, ?, ?> getDiscretization() {
return new PMesh<IPotentialPoint>((x,y) -> new PotentialPoint(x,y));
public IMesh<?, ?, ?> getDiscretization() {
return new PMesh();
}
/*public double getPotential(final int x, final int y) {
......@@ -87,7 +84,7 @@ public abstract class SimulationModel<T extends DefaultSimulationConfig> extends
}*/
@Override
public void notifyObservers() {
public synchronized void notifyObservers() {
// synchronized (config) {
if (config.hasChanged()) {
setChanged();
......
......@@ -8,7 +8,6 @@ import org.vadere.state.scenario.Agent;
import org.vadere.state.scenario.MeasurementArea;
import org.vadere.state.scenario.ScenarioElement;
import org.vadere.state.scenario.Stairs;
import org.vadere.util.data.cellgrid.IPotentialPoint;
import org.vadere.util.geometry.shapes.Vector2D;
import org.vadere.util.geometry.shapes.VCircle;
import org.vadere.util.geometry.shapes.VLine;
......@@ -59,37 +58,45 @@ public abstract class DefaultRenderer {
* @param height
*/
public void render(final Graphics2D targetGraphics2D, final int width, final int height) {
render(targetGraphics2D, 0, 0, width, height);
synchronized (defaultModel) {
render(targetGraphics2D, 0, 0, width, height);
}
}
public void render(final Graphics2D targetGraphics2D, final int x, final int y, final int width, final int height) {
targetGraphics2D.drawImage(renderImage(width, height), x, y, null);
targetGraphics2D.dispose();
synchronized (defaultModel) {
targetGraphics2D.drawImage(renderImage(width, height), x, y, null);
targetGraphics2D.dispose();
}
}
public void renderGraphics(final Graphics2D targetGraphics2D, final int width, final int height) {
targetGraphics2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
synchronized (defaultModel) {
targetGraphics2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
// (1) clear background
targetGraphics2D.setColor(Color.GRAY);
//targetGraphics2D.fill();
targetGraphics2D.fillRect(0, 0, width, height);
// (1) clear background
targetGraphics2D.setColor(Color.GRAY);
//targetGraphics2D.fill();
targetGraphics2D.fillRect(0, 0, width, height);
// (2) render everything which can be rendered before the transformation
renderPreTransformation(targetGraphics2D, width, height);
// (2) render everything which can be rendered before the transformation
renderPreTransformation(targetGraphics2D, width, height);
// (3)
transformGraphics(targetGraphics2D);
// (3)
transformGraphics(targetGraphics2D);
// (4) render everything which can be rendered after the transformation
renderPostTransformation(targetGraphics2D, width, height);
// (4) render everything which can be rendered after the transformation
renderPostTransformation(targetGraphics2D, width, height);
}
}
public BufferedImage renderImage(final int width, final int height) {
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
Graphics2D bufferGraphics2D = (Graphics2D) image.getGraphics();
renderGraphics(bufferGraphics2D, width, height);
return image;
synchronized (defaultModel) {
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
Graphics2D bufferGraphics2D = (Graphics2D) image.getGraphics();
renderGraphics(bufferGraphics2D, width, height);
return image;
}
}
public void setLogo(final BufferedImage logo) {
......@@ -99,33 +106,36 @@ public abstract class DefaultRenderer {
protected void renderPreTransformation(final Graphics2D graphics2D, final int width, final int height) {}
protected void renderPostTransformation(final Graphics2D graphics2D, final int width, final int height) {
graphics2D.setColor(Color.WHITE);
Rectangle2D.Double topographyBound = defaultModel.getTopographyBound();
fill(new VRectangle(
topographyBound.getMinX() + defaultModel.getBoundingBoxWidth(),
topographyBound.getMinY() + defaultModel.getBoundingBoxWidth(),
(defaultModel.getTopographyBound().getWidth() - defaultModel.getBoundingBoxWidth() * 2),
(defaultModel.getTopographyBound().getHeight() - defaultModel.getBoundingBoxWidth() * 2)), graphics2D);
synchronized (defaultModel) {
graphics2D.setColor(Color.WHITE);
Rectangle2D.Double topographyBound = defaultModel.getTopographyBound();
fill(new VRectangle(
topographyBound.getMinX() + defaultModel.getBoundingBoxWidth(),
topographyBound.getMinY() + defaultModel.getBoundingBoxWidth(),
(defaultModel.getTopographyBound().getWidth() - defaultModel.getBoundingBoxWidth() * 2),
(defaultModel.getTopographyBound().getHeight() - defaultModel.getBoundingBoxWidth() * 2)), graphics2D);
}
}
protected void transformGraphics(final Graphics2D graphics2D) {
Rectangle2D.Double topographyBound = defaultModel.getTopographyBound();
mirrowHorizonzal(graphics2D, (int) (topographyBound.getHeight() * defaultModel.getScaleFactor()));
graphics2D.scale(defaultModel.getScaleFactor(), defaultModel.getScaleFactor());
synchronized (defaultModel) {
Rectangle2D.Double topographyBound = defaultModel.getTopographyBound();
mirrowHorizonzal(graphics2D, (int) (topographyBound.getHeight() * defaultModel.getScaleFactor()));
graphics2D.scale(defaultModel.getScaleFactor(), defaultModel.getScaleFactor());
//graphics2D.translate(-topographyBound.getMinX(), -topographyBound.getMinY());
//graphics2D.translate(-topographyBound.getMinX(), -topographyBound.getMinY());
/*
* This calculation we need since the viewport.y = 0 if the user scrolls to the bottom
*/
Rectangle2D.Double viewportBound = defaultModel.getViewportBound();
double dy = topographyBound.getHeight() - viewportBound.getHeight();
graphics2D.translate(-viewportBound.getX(), Math.max((dy - viewportBound.getY()), - viewportBound.getY()));
// graphics2D.translate(+viewportBound.getX(), -Math.max((dy - viewportBound.getY()), 0));
/*
* This calculation we need since the viewport.y = 0 if the user scrolls to the bottom
*/
Rectangle2D.Double viewportBound = defaultModel.getViewportBound();
double dy = topographyBound.getHeight() - viewportBound.getHeight();
graphics2D.translate(-viewportBound.getX(), Math.max((dy - viewportBound.getY()), - viewportBound.getY()));
// graphics2D.translate(+viewportBound.getX(), -Math.max((dy - viewportBound.getY()), 0));
}
}
protected void renderScenarioElement(final Iterable<? extends ScenarioElement> elements, final Graphics2D g,
......@@ -623,10 +633,10 @@ public abstract class DefaultRenderer {
protected void renderMesh(
@NotNull final Graphics2D g,
@NotNull final IMesh<? extends IPotentialPoint, ?, ?, ?> mesh,
@NotNull final IMesh<?, ?, ?> mesh,
@NotNull final VRectangle bound) {
MeshRenderer<? extends IPotentialPoint, ?, ?, ?> meshRenderer = new MeshRenderer<>(mesh);
meshRenderer.renderGraphics(g, bound);
MeshRenderer<?, ?, ?> meshRenderer = new MeshRenderer<>(mesh);
//meshRenderer.renderGraphics(g, bound);
}
protected void renderVoronoiDiagram(final Graphics2D g, final VoronoiDiagram voronoiDiagram) {
......
......@@ -13,7 +13,6 @@ import org.vadere.simulator.models.potential.fields.IPotentialField;
import org.vadere.simulator.models.potential.fields.IPotentialFieldTarget;
import org.vadere.state.scenario.Agent;
import org.vadere.state.scenario.Topography;
import org.vadere.util.data.cellgrid.IPotentialPoint;
import org.vadere.util.geometry.shapes.VRectangle;
import java.util.function.Function;
......@@ -32,7 +31,7 @@ public class OnlineVisualization implements PassiveCallback {
public final IPotentialField potentialFieldTarget;
public final Agent selectedAgent;
public final IPotentialField potentialField;
public final Function<Agent, IMesh<? extends IPotentialPoint, ?, ?, ?>> discretizations;
public final Function<Agent, IMesh<?, ?, ?>> discretizations;
public ObservationAreaSnapshotData(
final double simTimeInSec,
......@@ -40,7 +39,7 @@ public class OnlineVisualization implements PassiveCallback {
@Nullable final IPotentialField potentialFieldTarget,
@Nullable final IPotentialField potentialField,
@Nullable final Agent selectedAgent,
@Nullable final Function<Agent, IMesh<? extends IPotentialPoint, ?, ?, ?>> discretizations) {
@Nullable final Function<Agent, IMesh<?, ?, ?>> discretizations) {
this.simTimeInSec = simTimeInSec;
this.scenario = scenario;
this.potentialFieldTarget = potentialFieldTarget;
......@@ -124,7 +123,7 @@ public class OnlineVisualization implements PassiveCallback {
synchronized (model.getDataSynchronizer()) {
/* Push new snapshot of the observation area to the draw thread. */
IPotentialField pft = (model.config.isShowTargetPotentialField() && potentialFieldTarget != null) ? potentialFieldTarget.getSolution() : null;
Function<Agent, IMesh<? extends IPotentialPoint, ?, ?, ?>> discretizations = (model.config.isShowTargetPotentielFieldMesh() && potentialFieldTarget != null) ? potentialFieldTarget.getDiscretization() : null;
Function<Agent, IMesh<?, ?, ?>> discretizations = (model.config.isShowTargetPotentielFieldMesh() && potentialFieldTarget != null) ? potentialFieldTarget.getDiscretization() : null;
IPotentialField pedPotentialField = null;
Agent selectedAgent = null;
......
......@@ -14,9 +14,7 @@ import org.vadere.gui.onlinevisualization.OnlineVisualization;
import org.vadere.meshing.mesh.gen.PMesh;
import org.vadere.meshing.mesh.inter.IMesh;
import org.vadere.simulator.models.potential.fields.IPotentialField;
import org.vadere.simulator.models.potential.solver.calculators.mesh.PotentialPoint;
import org.vadere.state.scenario.*;
import org.vadere.util.data.cellgrid.IPotentialPoint;
import org.vadere.util.geometry.shapes.IPoint;
import org.vadere.util.voronoi.VoronoiDiagram;
......@@ -37,7 +35,7 @@ public class OnlineVisualizationModel extends SimulationModel<DefaultSimulationC
private IPotentialField potentialField = null;
private Function<Agent, IMesh<? extends IPotentialPoint, ?, ?, ?>> discretizations = null;
private Function<Agent, IMesh<?, ?, ?>> discretizations = null;
private Agent agent = null;
......@@ -209,12 +207,12 @@ public class OnlineVisualizationModel extends SimulationModel<DefaultSimulationC
}
@Override
public IMesh<? extends IPotentialPoint, ?, ?, ?> getDiscretization() {
public IMesh<?, ?, ?> getDiscretization() {
if(agent != null && discretizations != null && config.isShowTargetPotentielFieldMesh() && agent.equals(getSelectedElement())) {
return discretizations.apply(agent);
}
return new PMesh<IPotentialPoint>((x, y) -> new PotentialPoint(x, y));
return new PMesh();
}
@Override
......
......@@ -7,6 +7,7 @@ import org.vadere.gui.components.control.IViewportChangeListener;
import org.vadere.gui.components.control.JViewportChangeListener;
import org.vadere.gui.components.control.PanelResizeListener;
import org.vadere.gui.components.control.ViewportChangeListener;
import org.vadere.gui.components.control.simulation.ActionGeneratePoly;
import org.vadere.gui.components.utils.Messages;
import org.vadere.gui.components.utils.Resources;
import org.vadere.gui.components.utils.SwingUtils;
......@@ -174,7 +175,6 @@ public class OnlineVisualisationWindow extends JPanel implements Observer {
renderer,
model);
ActionGenerateSVG generateSVG = new ActionGenerateSVG(
Messages.getString("ProjectView.btnSVGSnapshot.tooltip"),
resources.getIcon("camera_svg.png", iconWidth, iconHeight),
......@@ -187,6 +187,12 @@ public class OnlineVisualisationWindow extends JPanel implements Observer {
renderer,
model);
ActionGeneratePoly generatePoly = new ActionGeneratePoly(
Messages.getString("ProjectView.btnPolySnapshot.tooltip"),
resources.getIcon("camera_poly.png", iconWidth, iconHeight),
renderer,
model);
ActionShowPotentialField showPotentialField = new ActionShowPotentialField(
"showPotentialField",
resources.getIcon("potentialField.png", iconWidth, iconHeight),
......@@ -222,6 +228,7 @@ public class OnlineVisualisationWindow extends JPanel implements Observer {
imgOptions.add(generatePNG);
imgOptions.add(generateSVG);
imgOptions.add(generateTikz);
imgOptions.add(generatePoly);
ActionOnlineVisMenu imgDialog = new ActionOnlineVisMenu(
"camera_menu",
......
......@@ -11,6 +11,7 @@ import org.vadere.gui.postvisualization.utils.ImageGenerator;
import org.vadere.gui.postvisualization.utils.SVGGenerator;
import org.vadere.gui.postvisualization.utils.TikzGenerator;
import org.vadere.gui.postvisualization.view.PostvisualizationRenderer;
import org.vadere.simulator.projects.Scenario;
import org.vadere.simulator.projects.io.IOOutput;
import org.vadere.simulator.projects.io.TrajectoryReader;
import org.vadere.util.io.IOUtils;
......@@ -22,7 +23,6 @@ import java.io.File;
import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.Locale;
import java.util.Optional;
......@@ -118,8 +118,9 @@ public class PostVisualizationConsole {
Optional<File> scenarioFile = IOUtils.getFirstFile(path.toFile(), IOUtils.SCENARIO_FILE_EXTENSION);
if (trajectoryFile.isPresent() && scenarioFile.isPresent()) {
TrajectoryReader reader = new TrajectoryReader(trajectoryFile.get().toPath());
model.init(reader.readFile(), IOOutput.readScenario(scenarioFile.get().toPath()), trajectoryFile.get().getParent());
Scenario scenario = IOOutput.readScenario(scenarioFile.get().toPath());
TrajectoryReader reader = new TrajectoryReader(trajectoryFile.get().toPath(), scenario);
model.init(reader.readFile(), scenario, trajectoryFile.get().getParent());
} else {
System.err.println("could not find trajectory or scenario file in: " + outputDirectoryPath);
}
......@@ -142,7 +143,7 @@ public class PostVisualizationConsole {
if (step != -1) {
model.setStep(step);
} else {
model.setTime(time);
model.setVisTime(time);
}
if (showGroups){
......
......@@ -2,13 +2,15 @@ package org.vadere.gui.postvisualization.control;
import org.vadere.gui.postvisualization.model.PostvisualizationModel;
import org.vadere.state.simulation.Step;
import org.vadere.util.logging.Logger;
import java.util.Optional;
public class Player implements Runnable {
private static Logger logger = Logger.getLogger(Player.class);
private static volatile Player instance;
private Thread currentThread;
private int currentStep;
enum State {
STOPPED, PAUSED, RUNNING
......@@ -29,7 +31,6 @@ public class Player implements Runnable {
private Player(final PostvisualizationModel model) {
this.model = model;
this.currentStep = 1;
this.currentThread = null;
state = State.STOPPED;
}
......@@ -41,7 +42,6 @@ public class Player implements Runnable {
public void stop() {
state = State.STOPPED;
running = false;
currentStep = 1;
if (currentThread != null) {
currentThread.interrupt();
......@@ -63,8 +63,6 @@ public class Player implements Runnable {
currentThread.start();
}
state = State.RUNNING;
model.getStep().ifPresent(s -> currentStep = s.getStepNumber());
synchronized (model) {
model.notifyAll();
}
......@@ -79,8 +77,8 @@ public class Player implements Runnable {
}
}
private boolean isRunable() {
return model.getStep().isPresent() && model.getFirstStep().isPresent() && model.getLastStep().isPresent();
private boolean isRunnable() {
return !model.isEmpty();
}
@Override
......@@ -91,17 +89,16 @@ public class Player implements Runnable {
// synchronized (model) {
switch (state) {
case RUNNING: {
if (isRunable()) {
if (model.getLastStep().get().getStepNumber() > model.getStep().get().getStepNumber()) {
currentStep = model.getStep().get().getStepNumber() + 1;