Commit 0d0a4a27 authored by Benedikt Zoennchen's avatar Benedikt Zoennchen
Browse files

resolve merge conflicts with master branch.

parents 1c5e5874 7c87c7cd
......@@ -2,6 +2,7 @@
target/
*.out
*.preferences.xml
swing-inspector-linux-1.2.3/
#Tools and build utils
bin/
......
......@@ -43,7 +43,7 @@ unit_tests_with_coverage:
script:
- Documentation/version-control/git-hook-vadere-software
- mvn clean
- mvn -Dtest=!TestConvolution,!TestBitonicSort,!TestCLLinkedList test
- mvn -Dtest=!TestConvolution,!TestBitonicSort,!TestCLLinkedList,!TestCLOptimalStepsModel test
- python3 Tools/ContinuousIntegration/collect_line_and_branch_coverage.py
run_scenario_files:
......
**Note:** Before writing into this file, read the guidelines in [Writing Changelog Entries.md](Documentation/contributing/Writing Changelog Entries.md).
# In Progress: v0.7
# In Progress: v0.7
## Added
- Two new outputprocessors - mainly for the BHM - to evaluaet queueWidth
(QueueWidthProcessor) and behavior (PedestrianBehaviorProcessor)
- In package `org.vadere.simulator.utils`, added `TopographyChecker` to show
user if the current topography contains problems. The `TopographyChecker`
will check for overlapping `ScenarioElements` and check for inconsistence
settings such as missing TargetIDs for sources or inconsistenct speed ranges
for pedestrians. See this
[table](Documentation/changelLogImages/TopographyCheckerMessages.md) for
supported warnings and erros as well as this
[picture](Documentation/changelLogImages/TopographyChecker.png) to see which
kind of overlap produces erros or warnings.
- Add `--output-dir [on, off]` (default: `on`) switch to `scenario-run`
sub-command. This will will turn the ScenarioChecker on or off for the command
line. If the Checker detects an error the simulation will not be executed.
# v0.6 (2018-09-07)
......@@ -12,7 +30,7 @@
- VadereConsole.jar migrate will migrate all scenario files within the specified directory and all child directories. (37fde165: Simulator)
* To exclude specific sub-trees or only specific directories the igonoreDirs List can be expanded.
* DO_NOT_MIGRATE or .DO_NOT_MIGRATE: Ignore current directory but continue with existing child directories.
* DO_NOT_MIGRATE_TREE or .DO_NOT_MIGRATE_TREE: Ignore the directories and the complete sub-tree.
* DO_NOT_MIGRATE_TREE or .DO_NOT_MIGRATE_TREE: Ignore the directories and the complete sub-tree.
- Added a new OutputProcessor, NumberOverlapsProcessor. This processor saves the number of overlaps that occurred during a simulation run. It needs the PedestrianOverlapProcessor. (57d90e93: Simulator, State)
- Added sub commands to "VadereConsole": project-run, scenario-run, suq, migrate (c7e0538c: GUI)
- In the onlinevisualization it is now possible to display the target potential field of a selected pedestrian. (123457aa: GUI)
......
# TopographyChecker Messages
## Overlapping ScenarioElements
|Type of Elemetns | TotalOvelrap/ contained in | PartialOverlap |
|--------------------|:----------------:|:----------------:|
|Obstacle / Obstacle | WARN | ./. |
|Obstacle / Source | ERROR | ERROR |
|Obstacle / Target | ERROR | WARN |
|Obstacle / Stairs | ERROR | WARN |
|Obstacle / Ped. | ERROR | ERROR |
|Source / Source | WARN | WARN |
|Source / Target | WARN | WARN |
|Source / Stairs | WARN | WARN |
|Target / Target | WARN | WARN |
|Target / Stairs | WARN | WARN |
|Stairs / Stairs | ERROR | ERROR |
Legend:
WARN Warning but simulation is possible
ERROR Error and simulation is not possible
./. Nothing to do all good
## Misc Tests
### Errors
- A Source has no targetId set but is setup to spawn pedestrians. Solution: Set targetId
- A Source has a targetId set but the target does not exist. Solution: Create target or remove unused targetId from Source.
- If the SpeedDistributionMean of a pedestrian ist not between min/max speed.
### Warnings
- A Source has no targetId set and does not spawn pedestrians. Solution: Possible error
- A Target is never used by any Source. Solution: Possible error and this will cost performance.
- The Stairs model only works for 'normal' one-step-stairs. If the tread is outside of
the range of 10cm < x < 35cm. The simulation does not make sense.
- If the speed setup of a pedestrian is bigger then 12.0 m/s (world record). This is possible an error.
......@@ -47,7 +47,7 @@ For this project, GPGPU with OpenCL is used to speed up some computations. There
### Run the Application
1. Get the Source: Run `git clone https://gitlab.lrz.de/vadere/vadere.git`.
2. Build the Application: Go to the project directory and run `mvn clean package` (or `mvn clean package -DskipTests` if you want to skip the unit tests). This will build `vadere.jar`and `postvis.jar`.
2. Build the Application: Go to the project directory and run `mvn clean package` (or `mvn clean package -Dmaven.test.skip` if you want to skip the unit tests). This will build `vadere.jar`and `postvis.jar`.
3. Start the Application: After building the application, you can start Vadere by running `java -jar VadereGui/target/vadere.jar`.
4. (If you only want to use the Postvisualization-Tool you can do so by running `java -jar VadereGui/target/postvis.jar`).
......@@ -77,6 +77,9 @@ Follow the **installation instructions** above i.e. install all required softwar
- select `pom.xml` > *Next* > *Next* > *Next* > *Finish*
- open *VadereGui (gui)* > *src* > *org.vadere.gui.projectview* > `VadereApplication`
- click the *run*-icon next to the `main` method
- edit the run configuration for `VadereApplication` to build the project using Maven instead of IntelliJ's internal builder to avoid compilation errors:
* click *Edit Configurations* (in dropdown menu next to the play/debug button)
* under *Before launch*, add *Run Maven Goal* and use the Maven goal `compile`
Alternatively, run `mvn eclipse:eclipse` using the [Maven Eclipse Plugin](http://maven.apache.org/plugins/maven-eclipse-plugin/usage.html) or `mvn idea:idea` using the [Maven IntelliJ Plugin](http://maven.apache.org/plugins/maven-idea-plugin/).
......
......@@ -34,7 +34,7 @@ def find_scenario_files(path="VadereModelTests", scenario_search_pattern = "*.sc
return sorted(scenario_files)
def run_scenario_files_with_vadere_console(scenario_files, vadere_console="VadereGui/target/vadere-console.jar", scenario_timeout_in_sec=60):
def run_scenario_files_with_vadere_console(scenario_files, vadere_console="VadereSimulator/target/vadere-console.jar", scenario_timeout_in_sec=60):
output_dir = "output"
if not os.path.exists(output_dir):
......
......@@ -594,7 +594,7 @@ public class UniformRefinementTriangulatorSFC<P extends IPoint, V extends IVerte
F twin = getMesh().getTwinFace(edge);
VTriangle triangle = getMesh().toTriangle(face);
return (!triangle.intersect(bbox) && (getMesh().isBoundary(twin) || !getMesh().toTriangle(twin).intersect(bbox)));
return (!triangle.intersects(bbox) && (getMesh().isBoundary(twin) || !getMesh().toTriangle(twin).intersects(bbox)));
}
/**
......
......@@ -208,7 +208,7 @@ public class UniformSFCTriangulator<P extends IPoint, V extends IVertex<P>, E ex
VLine line = mesh.toLine(edge);
return (line.length() <= lenFunc.apply(line.midPoint()) && random.nextDouble() < 0.96)
|| (!triangle.intersect(bbox) && (mesh.isBoundary(twin) || !mesh.toTriangle(twin).intersect(bbox)))
|| (!triangle.intersects(bbox) && (mesh.isBoundary(twin) || !mesh.toTriangle(twin).intersects(bbox)))
|| boundary.stream().anyMatch(shape -> shape.contains(triangle.getBounds2D()) || (!mesh.isBoundary(twin) && shape.contains(mesh.toTriangle(twin).getBounds2D())));
}
......
......@@ -262,11 +262,6 @@ public class VCircle implements VShape, ICircleSector {
return ShapeType.CIRCLE;
}
@Override
public boolean intersect(final VShape shape) {
throw new UnsupportedOperationException("not yet implemented");
}
@Override
public List<VPoint> getPath() {
// approximate the circle!
......@@ -280,4 +275,15 @@ public class VCircle implements VShape, ICircleSector {
}
return points;
}
@Override
public boolean intersects(VShape shape) {
if(shape instanceof VCircle) {
VCircle otherCircle = (VCircle)shape;
return otherCircle.getCenter().distance(this.getCenter()) < (otherCircle.getRadius() + this.getRadius());
}
else {
return VShape.super.intersects(shape);
}
}
}
......@@ -479,7 +479,7 @@ public class VPolygon extends Path2D.Double implements VShape {
}
@Override
public boolean intersect(final VShape shape) {
public boolean intersects(final VShape shape) {
if(shape instanceof VPolygon) {
return intersects((VPolygon) shape);
}
......@@ -487,7 +487,7 @@ public class VPolygon extends Path2D.Double implements VShape {
return intersects(((VRectangle)shape));
}
else {
throw new UnsupportedOperationException("not yet implemented");
return VShape.super.intersects(shape);
}
}
......
......@@ -95,18 +95,18 @@ public class VRectangle extends Rectangle2D.Double implements VShape {
}
@Override
public VShape translatePrecise(final IPoint vector) {
public VRectangle translatePrecise(final IPoint vector) {
VPoint dp = VPoint.addPrecise(vector, new VPoint(getX(), getY()));
return new VRectangle(dp.getX(), dp.getY(), getWidth(), getHeight());
}
@Override
public VShape translate(final IPoint vector) {
public VRectangle translate(final IPoint vector) {
return new VRectangle(getX() + vector.getX(), getY() + vector.getY(), getWidth(), getHeight());
}
@Override
public VShape scale(final double scalar) {
public VRectangle scale(final double scalar) {
return new VRectangle(getX() * scalar, getY() * scalar, getWidth() * scalar, getHeight() * scalar);
}
......@@ -134,12 +134,12 @@ public class VRectangle extends Rectangle2D.Double implements VShape {
}
@Override
public boolean intersect(final VShape shape) {
public boolean intersects(final VShape shape) {
if(shape instanceof VRectangle){
return super.intersects(((VRectangle)shape));
}
else if(shape instanceof VPolygon) {
return shape.intersect(this);
return ((VPolygon)shape).intersects(this);
}
else {
throw new UnsupportedOperationException("not yet implemented");
......
......@@ -221,7 +221,7 @@ public class VRing implements VShape {
}
@Override
public boolean intersect(VShape shape) {
public boolean intersects(VShape shape) {
throw new UnsupportedOperationException("not yet implemented.");
}
......
......@@ -31,7 +31,20 @@ public interface VShape extends Shape, Cloneable {
ShapeType getType();
boolean intersect(VShape shape);
default boolean sameArea(VShape shape){
Area thisShape = new Area(this);
Area otherShape = new Area(shape);
thisShape.subtract(otherShape);
return thisShape.isEmpty();
}
default boolean containsShape(VShape otherShape){
Area thisArea = new Area(this);
Area otherArea = new Area(otherShape);
thisArea.intersect(otherArea);
return thisArea.equals(otherArea);
}
/**
* Returns a list of points (p1, p2, ..., pn) such that the line (p1,p2) is part of the boundary
......
......@@ -73,25 +73,6 @@
<artifactId>maven-assembly-plugin</artifactId>
<version>2.4</version>
<executions>
<execution>
<id>build-vadere-console</id> <!-- this is used for inheritance merges -->
<phase>package</phase> <!-- bind to the packaging phase -->
<goals>
<goal>single</goal>
</goals>
<configuration>
<archive>
<manifest>
<mainClass>org.vadere.simulator.entrypoints.VadereConsole</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<finalName>vadere-console</finalName>
<appendAssemblyId>false</appendAssemblyId>
</configuration>
</execution>
<execution>
<id>build-vadere</id> <!-- this is used for inheritance merges -->
<phase>package</phase> <!-- bind to the packaging phase -->
......
#Eclipse messages class
#Tue Sep 17 13:33:04 CEST 2013
include=i18n_simulation
AttributeFileView.btnChangeAttributeFile.text=Change attribute file...
AttributesFileView.btnSaveToFile.text=Save to file...
AttributesFileView.txtrAttributefiletextarea.text=attributeFileTextArea
......@@ -62,9 +64,7 @@ ProjectView.btnAbout.tooltip=About
ProjectView.about.title=About
ProjectView.title=Vadere
ProjectView.version= Version {0}
ProjectView.cooperation=Vadere has been developed at the Munich University of Applied Sciences at the department for Computer Science and Mathematics
ProjectView.license.text=This software is licensed under the {0}
ProjectView.aboutDialog.text=Vadere GUI\nVersion: 2.0\nOrganisation: University of Applied Sciences Munich\nManagement-Tool for Vadere Pedestrian Crowd Simulations.
ProjectView.aboutDialog.label=About Vadere
ProjectView.startDialog.label=Vadere GUI
ProjectView.startDialog.text=Create a new Project or load an existing project
......@@ -123,6 +123,7 @@ ProjectView.mntmReapplyMigration.text=Remigrate project and open...
ProjectView.chooseMigrationBaseDialog.text=Choose the version of this project
ProjectView.chooseMigrationBaseDialog.title=Migration
ProjectView.chooseMigrationBaseDialog.defaultOption=automatic
ProjectView.chooseFile=Chose file
SaveBeforeClosing.text=Do you want to save the current project before closing?
SaveBeforeClosing.unsavedChanges.text=Unsaved changes:
......@@ -276,6 +277,8 @@ ProjectView.btnShowDensity.tooltip=Show Density
ProjectView.btnSettings.tooltip=Settings
ProjectView.btnOk=OK
ProjectView.btnCancel=Cancel
ProjectView.btnExpertCSV=Export as csv
ProjectView.label.simResults=Simulation Results
TopographyCreator.btnMergeObstacles.tooltip=Merge Obstacles
TopographyCreator.btnMinimizeTopography.tooltip=Select Viewport area
......@@ -290,6 +293,7 @@ TopographyCreator.btnRedo.tooltip=Redo
TopographyCreator.btnCutTopography.tooltip=Cut Scenario
TopographyCreator.btnInsertPedestrian.tooltip=Pedestrian
TopographyCreator.btnTopographyBound.tooltip=Topography Bound
TopographyCreator.btnTranslation.tooltip=Translate topography
TopographyCreator.btnInsertObstacle.tooltip=Obstacle
TopographyCreator.btnInsertTarget.tooltip=Target
TopographyCreator.btnInsertSource.tooltip=Source
......@@ -299,9 +303,12 @@ TopographyCreator.btnConvexHull.label=Convex Hull
TopographyCreator.btnSimplePolygon.label=Simple Polygon
TopographyCreator.btnCircle.label=Circle
TopographyCreator.btnRectangle.label=Rectangle
TopographyCreator.btnChecker.tooltip=Show Topography Checker Messages
TopographyCreator.btnMakro.tooltip=Generate not set IDs.
select_shape_tooltip=Select Shape
# tab titles Topography creator / postvis
Tab.Simulation.title=Simulation
Tab.Model.title=Model
......@@ -336,8 +343,12 @@ ActionSeeDiscardChanges.popup.title=Unsaved changes
SaveDespiteJsonErrors.title=JSON-Errors.
SaveDespiteJsonErrors.text=There are errors in the JSON of the currently open scenario. Do you want to correct those?
SaveDespiteTopographyCheckerErrors.title=Topography-Errors.
SaveDespiteTopographyCheckerErrors.text=There are errors in the Topography of the currently open scenario. Do you want to correct those?
RunScenarioJsonErrors.title=Resolve JSON errors
RunScenarioJsonErrors.text=The simulation can't be started with erroneous JSON.
RunScenarioTopographyCheckerErrors.title=Resolve TopographyChecker errors
RunScenarioTopographyCheckerErrors.text=The simulation can't be started with erroneous Topography setup.
RunScenarioNotReadyToRun.text=One or more of the selected scenarios isn't ready to run.
ActionEditScenarioDescription.menu.title=Edit description
#Eclipse messages class
#Tue Sep 17 13:49:11 CEST 2013
include=i18n_simulation
AttributeFileView.btnChangeAttributeFile.text=Attributsdatei \u00E4ndern...
AttributesFileView.btnSaveToFile.text=In Datei speichern...
AttributesFileView.txtrAttributefiletextarea.text=attributeFileTextArea
......@@ -63,8 +65,6 @@ ProjectView.about.title=\u00dcber
ProjectView.title=Vadere
ProjectView.version= Version {0}
ProjectView.license.text=Dieses Software ist unter der {0} lizenziert
ProjectView.cooperation=Vadere wurde an der Hochschule f\u00FCr angewandte Wissenschaften M\u00FCnchen an der Fakult\u00E4t f\u00FCr Informatik und Mathematik entwickelt
ProjectView.aboutDialog.text=Vadere GUI\nVersion: 2.0\nOrganisation: Hochschule M\u00FCnchen\nManagement-Tool f\u00FCr Vadere Pedestrian Crowd Simulationen.
ProjectView.aboutDialog.label=\u00DCber Vadere
ProjectView.startDialog.label=Vadere GUI
ProjectView.startDialog.text=Erstellen oder laden Sie ein existierendes Projekt
......@@ -122,6 +122,9 @@ ProjectView.mntmReapplyMigration.text=Projekt remigrieren und \u00F6ffnen...
ProjectView.chooseMigrationBaseDialog.text=W\u00c4hlen Sie die Version dieses Projekts
ProjectView.chooseMigrationBaseDialog.title=Migration
ProjectView.chooseMigrationBaseDialog.defaultOption=Automatisch
ProjectView.chooseFile=Datei ausw\u00E4hlen
ProjectView.btnExpertCSV=Als CSV exportieren
ProjectView.label.simResults=Simulationsergebniss
SaveBeforeClosing.text=Aktuelles Projekt vor dem Beenden speichern?
SaveBeforeClosing.unsavedChanges.text=Ungespeicherte \u00c4nderungen:
......@@ -205,11 +208,6 @@ PostVis.btnPlay.tooltip=Start
PostVis.btnPause.tooltip=Pause
PostVis.btnStop.tooltip=Stopp
PostVis.btnRecord.tooltip=Starte Aufnahme
PostVis.btnAbout.tooltip=\u00dcber
PostVis.about.title=\u00dcber
PostVis.title=Vadere Post-Visualization
PostVis.version= Version {0}
PostVis.license.text=Dieses Produkt ist unter der {0} lizenziert
PostVis.chbHidePedAtTarget.text=Fu\u00dfg\u00E4nger im Ziel nicht anzeigen
PostVis.chbHideTrajAtTarget.text=Trajektorien am Ziel nicht anzeigen
......@@ -290,6 +288,7 @@ TopographyCreator.btnInsertPedestrian.tooltip=Fu\u00dfg\u00e4nger
TopographyCreator.btnInsertObstacle.tooltip=Hindernis
TopographyCreator.btnInsertTarget.tooltip=Ziel
TopographyCreator.btnTopographyBound.tooltip=Topographie Grenze
TopographyCreator.btnTranslation.tooltip=Topographie verschieben
TopographyCreator.btnInsertSource.tooltip=Quelle
TopographyCreator.btnInsertStairs.tooltip=Treppen
TopographyCreator.btnErase.tooltip=Radierer
......@@ -298,6 +297,9 @@ TopographyCreator.btnConvexHull.label=Convexe H\u00fclle
TopographyCreator.btnSimplePolygon.label=Einfaches Polygon
TopographyCreator.btnCircle.label=Kreis
TopographyCreator.btnRectangle.label=Rechteck
TopographyCreator.btnChecker.tooltip=Topography Linter Nachrichten
TopographyCreator.btnMakro.tooltip=Erzeuge nicht gesetzte IDs.
# tab titles Topography creator / postvis
Tab.Simulation.title=Simulation
......@@ -333,8 +335,12 @@ ActionSeeDiscardChanges.popup.title=Ungespeicherte \u00c4nderungen
SaveDespiteJsonErrors.title=Fehlerhaftes JSON.
SaveDespiteJsonErrors.text=Im ge\u00f6ffneten Szenario bestehen Fehler im JSON. Wollen Sie diese korrigieren?
SaveDespiteTopographyCheckerErrors.title=Fehlerhafte Topography.
SaveDespiteTopographyCheckerErrors.text=Im ge\u00f6ffneten Szenario bestehen Fehler in der Topography. Wollen Sie diese korrigieren?
RunScenarioJsonErrors.title=JSON Fehler beheben
RunScenarioJsonErrors.text=Die Simulation kann nicht mit fehlerhaftem JSON gestartet werden.
RunScenarioTopographyCheckerErrors.title=TopographyChecker Fehler beheben
RunScenarioTopographyCheckerErrors.text=Die Simulation kann nicht mit einer fehlerhaften Topography gestartet werden.
RunScenarioNotReadyToRun.text=Eines oder mehrere der ausgew\u00e4hlten Szenario sind derzeit nicht lauff\u00e4hig.
ActionEditScenarioDescription.menu.title=Beschreibung bearbeiten
package org.vadere.gui.components.control;
import org.vadere.gui.projectview.view.ScenarioNamePanel;
import org.vadere.gui.projectview.view.ScenarioPanel;
import org.vadere.gui.projectview.view.VDialogManager;
import org.vadere.gui.topographycreator.model.IDrawPanelModel;
import org.vadere.simulator.projects.Scenario;
import org.vadere.simulator.utils.scenariochecker.ScenarioChecker;
import org.vadere.simulator.utils.scenariochecker.ScenarioCheckerMessage;
import java.awt.event.ActionEvent;
import java.util.Observable;
import java.util.Observer;
import java.util.PriorityQueue;
import javax.swing.*;
public class ActionScenarioChecker extends AbstractAction implements Observer {
private PriorityQueue<ScenarioCheckerMessage> messages;
private ScenarioCheckerMessageDocumentView msgDocument;
private IDrawPanelModel model;
private ScenarioNamePanel view;
public
ActionScenarioChecker(String name, ScenarioNamePanel view) {
super(name);
this.messages = new PriorityQueue<>();
this.view = view;
}
/**
* Handel click on traffic light icon and show all ScenarioChecker messages generated for the
* current state of the topography.
*/
@Override
public void actionPerformed(ActionEvent e) {
VDialogManager.showMessageDialogWithBodyAndTextEditorPane(
"Topography Checker",
"The following problems where found",
msgDocument,
JOptionPane.INFORMATION_MESSAGE
);
}
public void observerModel(IDrawPanelModel model){
model.addObserver(this);
this.model = model;
}
/**
* After each change of the Topography which yields a valid json representation check run the
* {@link ScenarioChecker} and change the icon respectively. This function also creates the
* message document presented in various dialog windows.
*/
@Override
public void update(Observable o, Object arg) {
if(model != null){
check(model.getScenario());
}
}
public void check(final Scenario scenario){
ScenarioChecker checker = new ScenarioChecker(scenario);
messages.clear();
ScenarioPanel.setActiveTopographyErrorMsg(null);
messages = checker.checkBuildingStep();
msgDocument = new ScenarioCheckerMessageDocumentView(model);
msgDocument.setMessages(messages);
view.setGreen();
if (messages.size() > 0){
if(messages.peek().getMsgType().isWarnMsg()) {
view.setYellow();
}
if (messages.peek().getMsgType().isErrorMsg()) {
view.setRed();
ScenarioPanel.setActiveTopographyErrorMsg(msgDocument);
}
}
}
}
......@@ -4,6 +4,8 @@ import javax.swing.*;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;
import org.vadere.gui.components.model.IDefaultModel;
import java.awt.*;
......@@ -15,6 +17,7 @@ import java.awt.geom.Rectangle2D;
*/
public class JViewportChangeListener implements ChangeListener {
private Logger logger = LogManager.getLogger(JViewportChangeListener.class);
private final JScrollBar verticalScrollBar;
private final IDefaultModel defaultModel;
......@@ -26,14 +29,25 @@ public class JViewportChangeListener implements ChangeListener {
@Override
public void stateChanged(final ChangeEvent e) {
Rectangle2D.Double topographyBound = defaultModel.getTopographyBound();
Rectangle2D.Double viewp = defaultModel.getViewportBound();
JViewport viewPort = (JViewport) e.getSource();
if (topographyBound != null) {
Rectangle rect = viewPort.getViewRect();
double x = Math.max(0.0, rect.getX() / defaultModel.getScaleFactor());
double y = Math.max(0.0, topographyBound.getHeight()
- ((rect.getY() + verticalScrollBar.getHeight()) / defaultModel.getScaleFactor()));
double x = Math.max(topographyBound.getMinX(), topographyBound.getMinX() + rect.getX() / defaultModel.getScaleFactor());
double barHeight;
if(verticalScrollBar.getHeight() > 0) {