Commit 6c6c883e authored by Benedikt Kleinmeier's avatar Benedikt Kleinmeier
Browse files

Refactored "ActionPlaceRandomPedestrians.java" and...

Refactored "ActionPlaceRandomPedestrians.java" and "ActionRandomPedestrianDialog.java" to make "Agent.setGroupMembership()" configurable
parent 2a1297e0
Pipeline #254805 passed with stages
in 134 minutes and 56 seconds
......@@ -349,14 +349,16 @@ TopographyCreator.btnInsertMeasurementArea.tooltip=Measurement Area
TopographyCreator.btnErase.tooltip=Eraser
TopographyCreator.btnConvexHull.label=Convex Hull
TopographyCreator.btnSimplePolygon.label=Simple Polygon
TopographyCreator.btnCircle.label=Circle
TopographyCreator.btnLine.label=Line
TopographyCreator.btnPedestrian.label=Pedestrian
TopographyCreator.btnRectangle.label=Rectangle
TopographyCreator.btnSubtractMeasurementArea.label=Subtract Obstacle from Area
TopographyCreator.PlaceRandomPedestrians.label=Place Random Pedestrians
TopographyCreator.PlaceRandomPedestrians.targetEmptyOption.label=Empty
TopographyCreator.PlaceRandomPedestrians.targetRandomOption.label=Random
TopographyCreator.PlaceRandomPedestrians.targetListOption.label=Use list
TopographyCreator.PlaceRandomPedestrians.couldNotPlaceAllPeds.title=Overlaps occured!
TopographyCreator.PlaceRandomPedestrians.couldNotPlaceAllPeds.requested.text=Requested pedestrians
TopographyCreator.PlaceRandomPedestrians.couldNotPlaceAllPeds.placed.text=Placed pedestrians
TopographyCreator.btnChecker.tooltip=Show Topography Checker Messages
TopographyCreator.btnGenerateIds.tooltip=Generate missing Ids for sources, targets, ...
......
......@@ -344,14 +344,16 @@ TopographyCreator.btnErase.tooltip=Radierer
select_shape_tooltip=Form ausw\u00e4hlen
TopographyCreator.btnConvexHull.label=Convexe H\u00fclle
TopographyCreator.btnSimplePolygon.label=Einfaches Polygon
TopographyCreator.btnCircle.label=Kreis
TopographyCreator.btnLine.label=Linie
TopographyCreator.btnPedestrian.label=Fu\u00dfg\u00e4nger
TopographyCreator.btnRectangle.label=Rechteck
TopographyCreator.btnSubtractMeasurementArea.label=Subtrahiere Hindernis von Messfl\u00e4che
TopographyCreator.PlaceRandomPedestrians.label=Plaziere Zuf\u00e4llige Fu\u00dfg\u00e4nger
TopographyCreator.PlaceRandomPedestrians.targetEmptyOption.label=Kein Ziel
TopographyCreator.PlaceRandomPedestrians.targetRandomOption.label=Zuf\u00e4llig
TopographyCreator.PlaceRandomPedestrians.targetListOption.label=Nutze Liste
TopographyCreator.PlaceRandomPedestrians.couldNotPlaceAllPeds.title=\u00dcberlappungem aufgetreten!
TopographyCreator.PlaceRandomPedestrians.couldNotPlaceAllPeds.requested.text=Angeforderte Fu\u00dfg\u00e4nger
TopographyCreator.PlaceRandomPedestrians.couldNotPlaceAllPeds.placed.text=Platzierte Fu\u00dfg\u00e4nger
TopographyCreator.btnChecker.tooltip=Topography Linter Nachrichten
TopographyCreator.btnGenerateIds.tooltip=Erzeuge fehlende Ids f\u00fcr Quellen, Ziele, ...
......
......@@ -138,4 +138,12 @@ public class VDialogManager {
return true;
}
public static void showWarning(String title, String message) {
JOptionPane.showMessageDialog(
ProjectView.getMainWindow(),
message,
title,
JOptionPane.WARNING_MESSAGE);
}
}
package org.vadere.gui.topographycreator.control;
import org.apache.commons.math3.distribution.BinomialDistribution;
import org.jetbrains.annotations.NotNull;
import org.vadere.gui.components.utils.Messages;
import org.vadere.gui.projectview.view.VDialogManager;
import org.vadere.gui.topographycreator.model.AgentWrapper;
import org.vadere.gui.topographycreator.model.IDrawPanelModel;
import org.vadere.gui.topographycreator.model.TopographyElementFactory;
import org.vadere.gui.topographycreator.view.ActionRandomPedestrianDialog;
import org.vadere.gui.topographycreator.view.ActionRandomPedestrianDialog.TARGET_OPTION;
import org.vadere.state.attributes.scenario.AttributesAgent;
import org.vadere.state.psychology.cognition.GroupMembership;
import org.vadere.state.scenario.Agent;
import org.vadere.state.scenario.Pedestrian;
import org.vadere.state.scenario.Target;
import org.vadere.state.types.ScenarioElementType;
import org.vadere.state.scenario.Topography;
import org.vadere.util.geometry.shapes.IPoint;
import org.vadere.util.geometry.shapes.VCircle;
import org.vadere.util.geometry.shapes.VPoint;
import org.vadere.util.geometry.shapes.VShape;
import org.vadere.util.logging.Logger;
import org.vadere.util.random.SimpleReachablePointProvider;
import javax.swing.*;
import javax.swing.undo.UndoableEdit;
import javax.swing.undo.UndoableEditSupport;
import java.awt.event.ActionEvent;
import java.awt.geom.Rectangle2D;
......@@ -28,15 +32,14 @@ import java.util.Random;
public class ActionPlaceRandomPedestrians extends TopographyAction {
private static Logger logger = Logger.getLogger(ActionPlaceRandomPedestrians.class);
private static final int BINOMIAL_DISTRIBUTION_SUCCESS_VALUE = 1;
private final UndoableEditSupport undoSupport;
private final double dotRadius;
private final double agentRadius;
public ActionPlaceRandomPedestrians(String name, ImageIcon icon, IDrawPanelModel panelModel,
UndoableEditSupport undoSupport) {
super(name, icon, panelModel);
this.undoSupport = undoSupport;
this.dotRadius = new AttributesAgent().getRadius();
this.agentRadius = new AttributesAgent().getRadius();
}
@Override
......@@ -44,44 +47,71 @@ public class ActionPlaceRandomPedestrians extends TopographyAction {
ActionRandomPedestrianDialog dialog = new ActionRandomPedestrianDialog();
if (dialog.showDialog() && dialog.isValid()) {
IDrawPanelModel model = getScenarioPanelModel();
int numOfPeds = dialog.getNumOfPeds();
Topography topography = getScenarioPanelModel().getTopography();
Random random = dialog.getRandom();
Rectangle2D.Double legalBound = dialog.getBoundaryRectangle();
SimpleReachablePointProvider provider = SimpleReachablePointProvider.uniform(random, legalBound, model.getTopography().getObstacleDistanceFunction());
SimpleReachablePointProvider pointProvider = SimpleReachablePointProvider.uniform(random, legalBound, topography.getObstacleDistanceFunction());
int placedPedestrians = 0;
while (placedPedestrians < numOfPeds) {
double groupMembershipRatio = dialog.getGroupMembershipRatio();
BinomialDistribution binomialDistribution = new BinomialDistribution(BINOMIAL_DISTRIBUTION_SUCCESS_VALUE, groupMembershipRatio);
IPoint p = provider.stream(dist -> dist > 0.25).findFirst().get();
getScenarioPanelModel().setSelectionShape(new VCircle(p.getX(), p.getY(), this.dotRadius));
if (!checkOverlap(model.getSelectionShape())){
// no overlap with existing pedestrians found. --> use this point
ScenarioElementType type = getScenarioPanelModel().getCurrentType();
UndoableEdit edit = new EditDrawShape(getScenarioPanelModel(), type);
undoSupport.postEdit(edit);
int numOfPeds = dialog.getNumOfPeds();
int createdPeds = 0;
model.getCurrentType();
model.hideSelection();
AgentWrapper element = (AgentWrapper)TopographyElementFactory.getInstance().createScenarioShape(model.getCurrentType(), model.getSelectionShape());
element.getAgentInitialStore().setTargets(getTargetList(dialog.getTargetOption(), dialog.getTargetList()));
model.addShape(element);
model.setSelectedElement(element);
for (int i = 0; i < numOfPeds; i++) {
IPoint point = pointProvider.stream(dist -> dist > 0.25).findFirst().get();
VCircle newPosition = new VCircle(point.getX(), point.getY(), this.agentRadius);
placedPedestrians++;
if (checkOverlap(newPosition) == false) {
Pedestrian pedestrian = createPedestrian(dialog, topography, random, binomialDistribution, point);
addPedestrianToTopography(pedestrian);
createdPeds++;
}
}
if (numOfPeds != createdPeds) {
showWarning(numOfPeds, createdPeds);
}
} else {
logger.warn("Dialog canceled or input invalid!");
}
new ActionSelectSelectShape("select shape mode", getScenarioPanelModel(), undoSupport).actionPerformed(null);
getScenarioPanelModel().notifyObservers();
}
private boolean checkOverlap(VShape newPedestrian){
boolean pedOverlap = getScenarioPanelModel().getTopography().getInitialElements(Pedestrian.class)
.stream()
.map(Agent::getShape)
.anyMatch(shape -> shape.intersects(newPedestrian));
boolean targetOverlap = getScenarioPanelModel().getTopography().getTargets()
.stream()
.map(Target::getShape)
.anyMatch(shape -> shape.intersects(newPedestrian));
return pedOverlap || targetOverlap;
}
@NotNull
private Pedestrian createPedestrian(ActionRandomPedestrianDialog dialog, Topography topography, Random random, BinomialDistribution binomialDistribution, IPoint point) {
AttributesAgent attributesAgent = new AttributesAgent(
topography.getAttributesPedestrian(),
topography.getNextDynamicElementId());
Pedestrian pedestrian = new Pedestrian(attributesAgent, random);
pedestrian.setPosition(new VPoint(point));
pedestrian.setTargets(getTargetList(dialog.getTargetOption(), dialog.getTargetList()));
if (binomialDistribution.sample() == BINOMIAL_DISTRIBUTION_SUCCESS_VALUE) {
pedestrian.setGroupMembership(GroupMembership.IN_GROUP);
} else {
pedestrian.setGroupMembership(GroupMembership.OUT_GROUP);
}
return pedestrian;
}
private LinkedList<Integer> getTargetList(TARGET_OPTION selectedOption, LinkedList<Integer> dialogList) {
LinkedList<Integer> targetList = new LinkedList<>();
......@@ -101,16 +131,22 @@ public class ActionPlaceRandomPedestrians extends TopographyAction {
return targetList;
}
private boolean checkOverlap(VShape newPedestrian){
boolean pedOverlap = getScenarioPanelModel().getTopography().getInitialElements(Pedestrian.class)
.stream()
.map(Agent::getShape)
.anyMatch(shape -> shape.intersects(newPedestrian));
boolean targetOverlap = getScenarioPanelModel().getTopography().getTargets()
.stream()
.map(Target::getShape)
.anyMatch(shape -> shape.intersects(newPedestrian));
private void addPedestrianToTopography(Pedestrian pedestrian) {
AgentWrapper agentWrapper = new AgentWrapper(pedestrian);
getScenarioPanelModel().addShape(agentWrapper);
getScenarioPanelModel().setElementHasChanged(agentWrapper);
}
return pedOverlap || targetOverlap;
private void showWarning(int numOfPeds, int createdPeds) {
String message = String.format("%s: %d\n%s: %d",
Messages.getString("TopographyCreator.PlaceRandomPedestrians.couldNotPlaceAllPeds.requested.text"), numOfPeds,
Messages.getString("TopographyCreator.PlaceRandomPedestrians.couldNotPlaceAllPeds.placed.text"), createdPeds);
VDialogManager.showWarning(
Messages.getString("TopographyCreator.PlaceRandomPedestrians.couldNotPlaceAllPeds.title"),
message
);
}
}
package org.vadere.gui.topographycreator.view;
import org.jetbrains.annotations.NotNull;
import org.vadere.gui.components.utils.Messages;
import org.vadere.gui.projectview.view.ProjectView;
......@@ -13,57 +11,77 @@ import java.awt.event.ItemListener;
import java.awt.geom.Rectangle2D;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.Locale;
import java.util.Random;
import java.util.stream.Collectors;
public class ActionRandomPedestrianDialog {
public enum TARGET_OPTION { EMPTY, RANDOM, USE_LIST };
public enum TARGET_OPTION { EMPTY, RANDOM, USE_LIST }
private JTextField numberOfPeds_field;
private JTextField boundaryRectangle_field;
private JTextField targets_field;
private JTextField seed_field;
// Member Variables
private JTextField numberOfPedsField;
private JTextField boundaryRectangleField;
private JTextField targetsField;
private JTextField seedField;
private JTextField groupMembershipRatioField;
private JRadioButton rbTargetEmpty;
private JRadioButton rbTargetRandom;
private JRadioButton rbTargetUseList;
private JPanel panel;
private JPanel panelWindow;
private JPanel panelRadioButtons;
private boolean valid;
private int numOfPeds;
private Rectangle2D.Double boundaryRectangle;
private LinkedList<Integer> targetList;
private int seed;
private double groupMembershipRatio;
private Random random;
// Constructors
public ActionRandomPedestrianDialog() {
numberOfPeds_field = new JTextField("10", 15);
numberOfPeds_field.setHorizontalAlignment(JTextField.RIGHT);
numberOfPeds_field.getDocument().addDocumentListener(new SimpleDocumentListener() {
valid = false;
numOfPeds = 10;
boundaryRectangle = new Rectangle2D.Double();
targetList = new LinkedList<>();
targetList.add(-1);
seed = -1;
groupMembershipRatio = 0.5;
createGuiElements();
groupGuiElements();
placeGuiElements();
}
private void createGuiElements() {
numberOfPedsField = new JTextField(String.format(Locale.US, "%d", numOfPeds), 15);
numberOfPedsField.setHorizontalAlignment(JTextField.RIGHT);
numberOfPedsField.getDocument().addDocumentListener(new SimpleDocumentListener() {
@Override
public void handle(DocumentEvent e) {
String text = numberOfPeds_field.getText();
try{
String text = numberOfPedsField.getText();
try {
numOfPeds = Integer.parseInt(text);
valid = true;
numberOfPeds_field.setForeground(Color.BLACK);
setValid(true, numberOfPedsField);
} catch (Exception ex){
valid = false;
numberOfPeds_field.setForeground(Color.RED);
setValid(false, numberOfPedsField);
}
}
});
boundaryRectangle_field = new JTextField("x, y, width, height", 15);
boundaryRectangle_field.setHorizontalAlignment(JTextField.RIGHT);
boundaryRectangle_field.getDocument().addDocumentListener(new SimpleDocumentListener() {
boundaryRectangleField = new JTextField("x, y, width, height", 15);
boundaryRectangleField.setHorizontalAlignment(JTextField.RIGHT);
boundaryRectangleField.getDocument().addDocumentListener(new SimpleDocumentListener() {
@Override
public void handle(DocumentEvent e) {
String text = boundaryRectangle_field.getText();
try{
String text = boundaryRectangleField.getText();
try {
String[] numbersAsString = text.split(",");
boundaryRectangle = new Rectangle2D.Double(
......@@ -73,83 +91,72 @@ public class ActionRandomPedestrianDialog {
Double.parseDouble(numbersAsString[3])
);
valid = true;
boundaryRectangle_field.setForeground(Color.BLACK);
setValid(true, boundaryRectangleField);
} catch (Exception ex){
valid = false;
boundaryRectangle_field.setForeground(Color.RED);
setValid(false, boundaryRectangleField);
}
}
});
targets_field = new JTextField("-1", 15);
targets_field.setHorizontalAlignment(JTextField.RIGHT);
targets_field.getDocument().addDocumentListener(new SimpleDocumentListener() {
targetsField = new JTextField("-1", 15);
targetsField.setHorizontalAlignment(JTextField.RIGHT);
targetsField.getDocument().addDocumentListener(new SimpleDocumentListener() {
@Override
public void handle(DocumentEvent e) {
String strippedText = targets_field.getText().replace(" ", "");
String strippedText = targetsField.getText().replace(" ", "");
String[] splittedText = strippedText.split(",");
try {
targetList = Arrays.stream(splittedText).mapToInt(Integer::parseInt).boxed().collect(Collectors.toCollection(LinkedList::new));
valid = true;
targets_field.setForeground(Color.BLACK);
setValid(true, targetsField);
}catch (Exception ex){
valid = false;
targets_field.setForeground(Color.RED);
setValid(false, targetsField);
}
}
});
JPanel panelRadioButtons = createTargetRadioButtonPanel();
createTargetRadioButtons();
seed_field = new JTextField("-1", 15);
seed_field.setHorizontalAlignment(JTextField.RIGHT);
seed_field.getDocument().addDocumentListener(new SimpleDocumentListener() {
seedField = new JTextField(String.format(Locale.US, "%d", seed), 15);
seedField.setHorizontalAlignment(JTextField.RIGHT);
seedField.getDocument().addDocumentListener(new SimpleDocumentListener() {
@Override
public void handle(DocumentEvent e) {
try{
seed = Integer.parseInt(seed_field.getText());
valid = true;
seed_field.setForeground(Color.BLACK);
seed = Integer.parseInt(seedField.getText());
setValid(true, seedField);
} catch (Exception ex){
valid = false;
seed_field.setForeground(Color.RED);
setValid(false, seedField);
}
}
});
GridBagLayout layout = new GridBagLayout();
panel = new JPanel();
panel.setLayout(layout);
panel.add(new JLabel("Set Number of Pedestrians"), c(GridBagConstraints.HORIZONTAL, 0, 0));
panel.add(numberOfPeds_field, c(GridBagConstraints.HORIZONTAL, 1, 0));
panel.add(new JLabel("In Boundary Rectangle"), c(GridBagConstraints.HORIZONTAL, 0, 1));
panel.add(boundaryRectangle_field, c(GridBagConstraints.HORIZONTAL, 1, 1));
panel.add(new JLabel("Set Targets"), c(GridBagConstraints.HORIZONTAL, 0, 2));
panel.add(panelRadioButtons, c(GridBagConstraints.HORIZONTAL, 1, 2));
panel.add(targets_field, c(GridBagConstraints.HORIZONTAL, 1, 3));
groupMembershipRatioField = new JTextField(String.format(Locale.US, "%.1f", groupMembershipRatio), 15);
groupMembershipRatioField.setHorizontalAlignment(JTextField.RIGHT);
groupMembershipRatioField.getDocument().addDocumentListener(new SimpleDocumentListener() {
@Override
public void handle(DocumentEvent e) {
try {
groupMembershipRatio = Double.parseDouble(groupMembershipRatioField.getText());
panel.add(new JLabel("Set Random Seed (-1 for random)"), c(GridBagConstraints.HORIZONTAL, 0, 4));
panel.add(seed_field, c(GridBagConstraints.HORIZONTAL, 1, 4));
panel.add(new JLabel("May take a while because intelligent distance function not available yet..."),
c(GridBagConstraints.HORIZONTAL, 0,5,2));
boolean isValid = (groupMembershipRatio >= 0.0 && groupMembershipRatio <= 1.0);
setValid(isValid, groupMembershipRatioField);
} catch (Exception ex) {
setValid(false, groupMembershipRatioField);
}
}
});
numOfPeds = 10;
targetList = new LinkedList<>();
targetList.add(-1);
seed = -1;
valid = false;
panelWindow = new JPanel();
panelRadioButtons = new JPanel();
}
@NotNull
private JPanel createTargetRadioButtonPanel() {
private void createTargetRadioButtons() {
rbTargetEmpty = new JRadioButton(Messages.getString("TopographyCreator.PlaceRandomPedestrians.targetEmptyOption.label"), true);
rbTargetRandom = new JRadioButton(Messages.getString("TopographyCreator.PlaceRandomPedestrians.targetRandomOption.label"), false);
rbTargetUseList = new JRadioButton(Messages.getString("TopographyCreator.PlaceRandomPedestrians.targetListOption.label"), false);
targets_field.setEditable(false);
targetsField.setEditable(false);
ButtonGroup buttonGroupTarget = new ButtonGroup();
buttonGroupTarget.add(rbTargetEmpty);
......@@ -160,30 +167,54 @@ public class ActionRandomPedestrianDialog {
@Override
public void itemStateChanged(ItemEvent e) {
boolean targetsFieldState = e.getStateChange() == ItemEvent.SELECTED;
targets_field.setEditable(targetsFieldState);
targetsField.setEditable(targetsFieldState);
}
});
JPanel panelRadioButtons = new JPanel();
}
private void groupGuiElements() {
panelRadioButtons.setLayout(new FlowLayout());
int x = 0;
int y = 0;
panelRadioButtons.add(rbTargetEmpty, c(GridBagConstraints.HORIZONTAL, x, y++));
panelRadioButtons.add(rbTargetRandom, c(GridBagConstraints.HORIZONTAL, x, y++));
panelRadioButtons.add(rbTargetUseList, c(GridBagConstraints.HORIZONTAL, x, y++));
return panelRadioButtons;
panelRadioButtons.add(rbTargetEmpty);
panelRadioButtons.add(rbTargetRandom);
panelRadioButtons.add(rbTargetUseList);
}
private void placeGuiElements() {
panelWindow.setLayout(new GridBagLayout());
int row = 0;
int col0 = 0;
int col1 = 1;
private GridBagConstraints c(int fill, int gridx, int gridy, int width){
panelWindow.add(new JLabel("Set Number of Pedestrians"), c(GridBagConstraints.HORIZONTAL, col0, row));
panelWindow.add(numberOfPedsField, c(GridBagConstraints.HORIZONTAL, col1, row++));
panelWindow.add(new JLabel("In Boundary Rectangle"), c(GridBagConstraints.HORIZONTAL, col0, row));
panelWindow.add(boundaryRectangleField, c(GridBagConstraints.HORIZONTAL, col1, row++));
panelWindow.add(new JLabel("Set Targets"), c(GridBagConstraints.HORIZONTAL, col0, row));
panelWindow.add(panelRadioButtons, c(GridBagConstraints.HORIZONTAL, col1, row++));
panelWindow.add(targetsField, c(GridBagConstraints.HORIZONTAL, col1, row++));
panelWindow.add(new JLabel("Set Random Seed (-1 for random)"), c(GridBagConstraints.HORIZONTAL, col0, row));
panelWindow.add(seedField, c(GridBagConstraints.HORIZONTAL, col1, row++));
panelWindow.add(new JLabel("Ingroup Membership Ratio"), c(GridBagConstraints.HORIZONTAL, col0, row));
panelWindow.add(groupMembershipRatioField, c(GridBagConstraints.HORIZONTAL, col1, row++));
panelWindow.add(new JLabel("May take a while because intelligent distance function not available yet..."),
c(GridBagConstraints.HORIZONTAL, col0,row,2));
}
private GridBagConstraints c(int fill, int gridx, int gridy, int width){
GridBagConstraints c = new GridBagConstraints();
c.fill = fill;
c.gridx = gridx;
c.gridy = gridy;
c.gridwidth = width;
c.insets = new Insets(2,2,2,2);
return c;
}
......@@ -193,9 +224,15 @@ public class ActionRandomPedestrianDialog {
c.gridx = gridx;
c.gridy = gridy;
c.insets = new Insets(2,2,2,2);
return c;
}
// Getter
public boolean isValid() {
return valid;
}
public int getNumOfPeds() {
return numOfPeds;
}
......@@ -218,6 +255,14 @@ public class ActionRandomPedestrianDialog {
return selectedOption;
}
public LinkedList<Integer> getTargetList() {
return targetList;
}
public double getGroupMembershipRatio() {
return groupMembershipRatio;
}
public Random getRandom(){
if (random == null){
if (seed == -1){
......@@ -229,20 +274,23 @@ public class ActionRandomPedestrianDialog {
return random;
}
public LinkedList<Integer> getTargetList() {
return targetList;
// Setter
private void setValid(boolean valid, JComponent causingElement) {
this.valid = valid;
Color color = (valid) ? Color.BLACK : Color.RED;
causingElement.setForeground(color);
}
public boolean showDialog(){
return JOptionPane