Commit 80ffce4b authored by Maxim Dudin's avatar Maxim Dudin
Browse files

#306 fixed implementation according to feedback. To change between connecting...

#306 fixed implementation according to feedback. To change between connecting lines and trajectories change a boolean constant in PostvisualizationRenderer.java
parent a766026a
......@@ -38,16 +38,7 @@
}
}, {
"type" : "org.vadere.simulator.projects.dataprocessing.processor.PedestriansNearbyProcessor",
"id" : 5,
"attributesType" : "org.vadere.state.attributes.processor.AttributesPedestrianNearbyProcessor",
"attributes" : {
"maxDistanceForANearbyPedestrian" : 1.5,
"sampleEveryNthStep" : 1,
"allowedAbsenceTimestepsIfContactReturns" : 0,
"minTimespanOfContactTimesteps" : 20,
"printContactTrajectories" : false,
"printForPostVis" : true
}
"id" : 5
} ],
"isTimestamped" : true,
"isWriteMetaData" : false
......
......@@ -81,12 +81,9 @@ public class ActionOpenFile extends ActionVisualization {
Optional<File> trajectoryFile = Optional.empty();
Optional<File> contactsTrajectoryFile = Optional.empty();
for (File f :trajFiles) {
logger.info("file read with filename "+ f.getName());
if (f.getName().contains("contacts")) {
logger.info("contactsTrajectoryFile is "+ f.getName());
contactsTrajectoryFile = Optional.of(f);
} else {
logger.info("trajectoryFile is "+ f.getName());
trajectoryFile = Optional.of(f);
}
}
......
package org.vadere.gui.postvisualization.model;
import org.jetbrains.annotations.NotNull;
import org.vadere.simulator.projects.io.ColumnNames;
import tech.tablesaw.api.*;
import java.util.ArrayList;
import java.util.List;
/**
* The {@link ContactData}
*/
public class ContactData {
private final Table contactsDataFrame;
private final List<Integer> rowsWithPedIds;
private static final double SIM_STEP_LENGTH = 0.4;
// columns, TODO: this is hard coded!
public final int startTimeStepCol;
public final int firstPedIdCol;
public final int secondPedIdCol;
public final int durationCol;
public final int xPathCol;
public final int yPathCol;
/**
* Default constructor.
*
* @param dataFrame the whole table containing all trajectories of all contacts for all times
*/
public ContactData(@NotNull final Table dataFrame) {
// get all ids of all columns
// 1. mandatory columns:
ColumnNames columnNames = ColumnNames.getInstance();
startTimeStepCol = columnNames.getStartTimeCol(dataFrame);
firstPedIdCol = columnNames.getPedestrianIdCol(dataFrame);
secondPedIdCol = columnNames.getSecondPedestrianIdCol(dataFrame);
durationCol = columnNames.getDurationCol(dataFrame);
xPathCol = columnNames.getStartXCol(dataFrame);
yPathCol = columnNames.getStartYCol(dataFrame);
this.contactsDataFrame = dataFrame;
StringColumn startTimes = getStartTimeStep(contactsDataFrame);
rowsWithPedIds = new ArrayList<>();
for (int i = 0; i < startTimes.size(); i++) {
if (!startTimes.get(i).equals("-")) {
rowsWithPedIds.add(i);
}
}
}
public List<Integer> getRowsWithPedIds() {
return rowsWithPedIds;
}
private StringColumn getStartTimeStep(@NotNull final Table table) {
return table.stringColumn(startTimeStepCol);
}
private StringColumn getFirstPedIdCol(@NotNull final Table table) {
return table.stringColumn(firstPedIdCol);
}
private StringColumn getSecondPedIdCol(@NotNull final Table table) {
return table.stringColumn(secondPedIdCol);
}
private StringColumn getDurationCol(@NotNull final Table table) {
return table.stringColumn(durationCol);
}
private DoubleColumn getXPathCol(@NotNull final Table table) {
return table.doubleColumn(xPathCol);
}
private DoubleColumn getYPathCol(@NotNull final Table table) {
return table.doubleColumn(yPathCol);
}
public List<Table> getTrajectoriesOfContactsUntil(double simTime) {
List<Table> result = new ArrayList<>();
for (Integer rowIndex: rowsWithPedIds) {
double contactStartTime = Double.parseDouble(getStartTimeStep(contactsDataFrame).get(rowIndex)) * SIM_STEP_LENGTH;
int durationTimeSteps = Integer.parseInt(getDurationCol(contactsDataFrame).get(rowIndex));
double contactDurationTime = durationTimeSteps * SIM_STEP_LENGTH;
boolean contactStartedBeforeSimTime = contactStartTime < simTime;
if (contactStartedBeforeSimTime) {
boolean contactHasNotEndedAtSimTime = simTime < contactStartTime + contactDurationTime;
int currentTimeStep = (int)Math.round(simTime);
int diffContactStartToCurrentTimestep = currentTimeStep - (int)contactStartTime;
if (diffContactStartToCurrentTimestep == 0) {
diffContactStartToCurrentTimestep = 1;
}
try {
DoubleColumn xCol = getXPathCol(contactsDataFrame).inRange(rowIndex, Math.min(rowIndex + durationTimeSteps, rowIndex + diffContactStartToCurrentTimestep));
DoubleColumn yCol = getYPathCol(contactsDataFrame).inRange(rowIndex, Math.min(rowIndex + durationTimeSteps, rowIndex + diffContactStartToCurrentTimestep));
Table trajectoryOfSingleContact = Table.create(xCol, yCol);
result.add(trajectoryOfSingleContact);
} catch (Exception e) {
System.out.println("yeet");
}
}
}
return result;
}
public Table getPairsOfPedestriansInContactAt(double simTime) {
IntColumn ped1IDs = IntColumn.create("ped1Ids");
IntColumn ped2IDs = IntColumn.create("ped2Ids");
for (Integer rowIndex: rowsWithPedIds) {
double contactStartTime = Double.parseDouble(getStartTimeStep(contactsDataFrame).get(rowIndex)) * SIM_STEP_LENGTH;
int durationTimeSteps = Integer.parseInt(getDurationCol(contactsDataFrame).get(rowIndex));
double contactDurationTime = durationTimeSteps * SIM_STEP_LENGTH;
boolean contactAtSimTime = contactStartTime < simTime && simTime < contactStartTime + contactDurationTime;
if (contactAtSimTime) {
int firstPedId = Integer.parseInt(getFirstPedIdCol(contactsDataFrame).get(rowIndex));
int secondPedId = Integer.parseInt(getSecondPedIdCol(contactsDataFrame).get(rowIndex));
ped1IDs.append(firstPedId);
ped2IDs.append(secondPedId);
}
}
return Table.create(ped1IDs, ped2IDs);
}
}
......@@ -63,7 +63,7 @@ public class PostvisualizationModel extends SimulationModel<PostvisualizationCon
private TableTrajectoryFootStep trajectories;
private TableTrajectoryFootStep contactTrajectories;
private ContactData contactData;
private String outputPath;
......@@ -74,7 +74,7 @@ public class PostvisualizationModel extends SimulationModel<PostvisualizationCon
public PostvisualizationModel() {
super(new PostvisualizationConfig());
this.trajectories = new TableTrajectoryFootStep(Table.create());
this.contactTrajectories = new TableTrajectoryFootStep(Table.create());
this.contactData = null;
this.scenario = new Scenario("");
this.topographyId = 0;
this.potentialContainer = null;
......@@ -104,9 +104,7 @@ public class PostvisualizationModel extends SimulationModel<PostvisualizationCon
this.simTimeStepLength = scenario.getAttributesSimulation().getSimTimeStepLength();
this.trajectories = new TableTrajectoryFootStep(trajectories);
if (contactTrajectories != null) {
this.contactTrajectories = new TableTrajectoryFootStep(contactTrajectories);
} else {
this.contactTrajectories = null;
this.contactData = new ContactData(contactTrajectories);
}
this.visTime = 0;
this.attributesAgent = attributesAgent;
......@@ -204,8 +202,8 @@ public class PostvisualizationModel extends SimulationModel<PostvisualizationCon
public synchronized TableTrajectoryFootStep getTrajectories() {
return trajectories;
}
public synchronized TableTrajectoryFootStep getContactTrajectories() {
return contactTrajectories;
public synchronized ContactData getContactData() {
return contactData;
}
public synchronized Table getAgentTable() {
......
......@@ -2,10 +2,10 @@ package org.vadere.gui.postvisualization.view;
import org.vadere.gui.components.view.DefaultRenderer;
import org.vadere.gui.components.view.SimulationRenderer;
import org.vadere.gui.postvisualization.model.ContactData;
import org.vadere.gui.postvisualization.model.PostvisualizationModel;
import org.vadere.gui.postvisualization.model.TableTrajectoryFootStep;
import org.vadere.gui.renderer.agent.AgentRender;
import org.vadere.state.scenario.Agent;
import org.vadere.state.scenario.Pedestrian;
import org.vadere.state.simulation.FootStep;
import org.vadere.util.geometry.shapes.VPoint;
......@@ -14,9 +14,8 @@ import org.vadere.util.visualization.ColorHelper;
import java.awt.*;
import java.awt.geom.Path2D;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.*;
import java.util.List;
import tech.tablesaw.api.Row;
import tech.tablesaw.api.Table;
......@@ -24,6 +23,9 @@ import tech.tablesaw.api.Table;
public class PostvisualizationRenderer extends SimulationRenderer {
private static final double MIN_ARROW_LENGTH = 0.1;
private static final boolean SHOW_CONTACTS = true;
private static final boolean CONTACT_LINES_INTEAD_OF_TRAJECTORIES = true;
Please register or sign in to reply
private static Logger logger = Logger.getLogger(PostvisualizationRenderer.class);
private PostvisualizationModel model;
......@@ -54,11 +56,68 @@ public class PostvisualizationRenderer extends SimulationRenderer {
private void renderPedestrians(final Graphics2D g, final Color color) {
if (!model.isEmpty()) {
renderTrajectories(g);
}
if (model.getContactTrajectories() != null) {
if (SHOW_CONTACTS && model.getContactData() != null) {
if (CONTACT_LINES_INTEAD_OF_TRAJECTORIES) {
renderConnectingLinesByContact(g);
} else {
renderContactTrajectories(g);
}
}
}
}
private void renderConnectingLinesByContact(Graphics2D g) {
if (!model.config.isShowAllTrajectories()) return;
Color color = g.getColor();
Stroke stroke = g.getStroke();
g.setStroke(new BasicStroke(getLineWidth() / 4.0f));
g.setColor(Color.red);
Collection<Pedestrian> agents = model.getPedestrians();
Map<Integer, VPoint> pedPositions = new HashMap<>();
agents.forEach(a -> pedPositions.put(a.getId(), a.getPosition()));
Table pairs = model.getContactData().getPairsOfPedestriansInContactAt(model.getSimTimeInSec());
for (Row row: pairs) {
VPoint ped1Pos = pedPositions.get(row.getInt(0));
VPoint ped2Pos = pedPositions.get(row.getInt(1));
Path2D.Double path = new Path2D.Double();
path.moveTo(ped1Pos.x, ped1Pos.y);
path.lineTo(ped2Pos.x, ped2Pos.y);
draw(path, g);
}
g.setStroke(stroke);
g.setColor(color);
}
private void renderContactTrajectories(Graphics2D g) {
if (!model.config.isShowAllTrajectories()) return;
Color color = g.getColor();
Stroke stroke = g.getStroke();
g.setStroke(new BasicStroke(getLineWidth() / 4.0f));
g.setColor(Color.red);
ContactData contactData = model.getContactData();
List<Table> trajectories = contactData.getTrajectoriesOfContactsUntil(model.getSimTimeInSec());
Random rand = new Random();
for (Table trajectory: trajectories) {
if (trajectory.column(0).size() != 1) {
for (int i = 1; i < trajectory.column(0).size(); i++) {
Path2D.Double path = new Path2D.Double();
double xPrev = Double.parseDouble(trajectory.getString(i - 1, 0));
double yPrev = Double.parseDouble(trajectory.getString(i - 1, 1));
double x = Double.parseDouble(trajectory.getString(i, 0));
double y = Double.parseDouble(trajectory.getString(i, 1));
// draws noisy lines to emphasize the spots of prolonged contact without peds moving
path.moveTo(xPrev + rand.nextDouble() * 0.3 - 0.15, yPrev + rand.nextDouble() * 0.3 - 0.15);
path.lineTo(x + rand.nextDouble() * 0.3 - 0.15, y + rand.nextDouble() * 0.3 - 0.15);
draw(path, g);
}
}
}
g.setStroke(stroke);
g.setColor(color);
}
private void renderTrajectories(final Graphics2D g) {
Color color = g.getColor();
......@@ -82,14 +141,14 @@ public class PostvisualizationRenderer extends SimulationRenderer {
Color c = g.getColor();
Stroke stroke = g.getStroke();
if (model.config.isShowTrajectories()) {
for(Row row : slice) {
for (Row row : slice) {
boolean isLastStep = row.getDouble(trajectories.endTimeCol) > model.getSimTimeInSec();
double startX = row.getDouble(trajectories.startXCol);
double startY = row.getDouble(trajectories.startYCol);
double endX = row.getDouble(trajectories.endXCol);
double endY = row.getDouble(trajectories.endYCol);
if(isLastStep && model.config.isInterpolatePositions()) {
if (isLastStep && model.config.isInterpolatePositions()) {
VPoint interpolatedPos = FootStep.interpolateFootStep(startX, startY, endX, endY, row.getDouble(trajectories.startTimeCol), row.getDouble(trajectories.endTimeCol), model.getSimTimeInSec());
endX = interpolatedPos.getX();
endY = interpolatedPos.getY();
......@@ -102,7 +161,7 @@ public class PostvisualizationRenderer extends SimulationRenderer {
g.setStroke(new BasicStroke(getLineWidth() / 2.0f));
} else {
Color cc = agentColors.get(pedId);
if(cc == null) {
if (cc == null) {
System.out.println("wtf");
}
g.setColor(agentColors.get(pedId));
......@@ -121,7 +180,7 @@ public class PostvisualizationRenderer extends SimulationRenderer {
// render agents i.e. circles
if (model.config.isShowPedestrians()) {
for(Pedestrian agent : agents) {
for (Pedestrian agent : agents) {
if (model.config.isShowFaydedPedestrians() || model.isAlive(agent.getId())) {
agentRender.render(agent, agentColors.get(agent.getId()), g);
if (model.config.isShowPedestrianIds()) {
......@@ -164,99 +223,6 @@ public class PostvisualizationRenderer extends SimulationRenderer {
}
g.setColor(color);
  • Do you already color agents having contact? My agents keep the default color. Can you fix that? It would be great change agent color from blue to red when they are in contact

Please register or sign in to reply
}
}
private void renderContactTrajectories(final Graphics2D g) {
Color color = g.getColor();
AgentRender agentRender = getAgentRender();
// sorted (by ped id) agent table
TableTrajectoryFootStep trajectories = model.getContactTrajectories();
trajectories.setSlice(0, model.getSimTimeInSec());
Table slice = trajectories.getCurrentSlice();
/*if (model.config.isShowAllTrajectories()) {
slice = model.getAppearedPedestrians();
} else {
slice = model.getAlivePedestrians();
}*/
//Collection<Pedestrian> agents = model.getPedestrians();
//Map<Integer, Color> agentColors = new HashMap<>();
//agents.forEach(agent -> agentColors.put(agent.getId(), Color.red));
Color c = g.getColor();
Stroke stroke = g.getStroke();
if (model.config.isShowTrajectories()) {
for(Row row : slice) {
boolean isLastStep = row.getDouble(trajectories.endTimeCol) > model.getSimTimeInSec();
double startX = row.getDouble(trajectories.startXCol);
double startY = row.getDouble(trajectories.startYCol);
double endX = row.getDouble(trajectories.endXCol);
double endY = row.getDouble(trajectories.endYCol);
if(isLastStep && model.config.isInterpolatePositions()) {
break;
/*VPoint interpolatedPos = FootStep.interpolateFootStep(startX, startY, endX, endY, row.getDouble(trajectories.startTimeCol), row.getDouble(trajectories.endTimeCol), model.getSimTimeInSec());
endX = interpolatedPos.getX();
endY = interpolatedPos.getY();*/
}
Path2D.Double path = new Path2D.Double();
path.moveTo(startX, startY);
path.lineTo(endX, endY);
g.setColor(Color.red);
g.setStroke(new BasicStroke(getLineWidth() / 4.0f));
draw(path, g);
}
}
g.setColor(c);
g.setStroke(stroke);
/*// render agents i.e. circles
if (model.config.isShowPedestrians()) {
for(Pedestrian agent : agents) {
if (model.config.isShowFaydedPedestrians() || model.isAlive(agent.getId())) {
agentRender.render(agent, agentColors.get(agent.getId()), g);
if (model.config.isShowPedestrianIds()) {
DefaultRenderer.paintAgentId(g, agent);
}
}
// renderImage the arrows indicating the walking direction
if (model.config.isShowWalkdirection() &&
(model.config.isShowFaydedPedestrians() || trajectories.getDeathTime(agent.getId()) > model.getSimTimeInSec())) {
int pedestrianId = agent.getId();
VPoint lastPosition = lastPedestrianPositions.get(pedestrianId);
VPoint position = agent.getPosition();
lastPedestrianPositions.put(pedestrianId, position);
if (lastPosition != null) {
VPoint direction;
if (lastPosition.distance(position) < MIN_ARROW_LENGTH) {
direction = pedestrianDirections.get(pedestrianId);
} else {
direction = new VPoint(lastPosition.getX() - position.getX(),
lastPosition.getY() - position.getY());
direction = direction.norm();
pedestrianDirections.put(pedestrianId, direction);
}
if (!pedestrianDirections.containsKey(pedestrianId)) {
pedestrianDirections.put(pedestrianId, direction);
}
if (direction != null) {
double theta = Math.atan2(-direction.getY(), -direction.getX());
DefaultRenderer.drawArrow(g, theta,
position.getX() - agent.getRadius() * 2 * direction.getX(),
position.getY() - agent.getRadius() * 2 * direction.getY());
}
}
}
}
}
g.setColor(color);*/
}
}
......@@ -386,7 +386,7 @@ public class PostvisualizationWindow extends JPanel implements Observer, DropTar
try {
if (contactsTrajectoryFile != null) {
model.init(IOOutput.readTrajectories(trajectoryFile.toPath()), IOOutput.readTrajectories(contactsTrajectoryFile.toPath()), scenario, contactsTrajectoryFile.getParent());
model.init(IOOutput.readTrajectories(trajectoryFile.toPath()), IOOutput.readContactData(contactsTrajectoryFile.toPath()), scenario, contactsTrajectoryFile.getParent());
} else {
model.init(IOOutput.readTrajectories(trajectoryFile.toPath()), scenario, trajectoryFile.getParent());
}
......
......@@ -645,16 +645,13 @@ public class ProjectView extends JFrame implements ProjectFinishedListener, Sing
private void loadScenarioIntoGui(OutputBundle bundle) throws IOException {
Scenario scenarioRM = bundle.getScenarioRM();
/*Optional<File> optionalTrajectoryFile = IOUtils
.getFirstFile(bundle.getDirectory(), IOUtils.TRAJECTORY_FILE_EXTENSION);*/
File[] trajFiles = IOUtils.getFileList(bundle.getDirectory(), IOUtils.TRAJECTORY_FILE_EXTENSION);
Optional<File> trajectoryFile = Optional.empty();
Optional<File> trajectoryFile = IOUtils
.getFirstFile(bundle.getDirectory(), IOUtils.TRAJECTORY_FILE_EXTENSION);
File[] txtFiles = IOUtils.getFileList(bundle.getDirectory(), ".txt");
Optional<File> contactsTrajectoryFile = Optional.empty();
for (File f :trajFiles) {
for (File f :txtFiles) {
if (f.getName().contains("contacts")) {
contactsTrajectoryFile = Optional.of(f);
} else {
trajectoryFile = Optional.of(f);
}
}
......
......@@ -14,8 +14,6 @@ public class PedestriansNearbyData {
private int durationTimesteps;
private int startTimestep;
private List<VPoint> trajectory;
private boolean printTrajectory;
private boolean printForPostVis; // is an ugly one time thing that shouldn't be merged
......@@ -32,14 +30,12 @@ public class PedestriansNearbyData {
return startTimestep;
}
public PedestriansNearbyData(int ped1, int ped2, final int durationTimesteps, int startTimestep, List<VPoint> contactTrajectory, boolean printTrajectory, boolean printForPostVis){
public PedestriansNearbyData(int ped1, int ped2, final int durationTimesteps, int startTimestep, List<VPoint> contactTrajectory){
this.pedId1 = Math.min(ped1, ped2);
this.pedId2 = Math.max(ped1, ped2);
this.durationTimesteps = durationTimesteps;
this.startTimestep = startTimestep;
this.trajectory = contactTrajectory;
this.printTrajectory = printTrajectory;
this.printForPostVis = printForPostVis;
}
public int getPedId1() {
......@@ -54,10 +50,6 @@ public class PedestriansNearbyData {
return durationTimesteps;
}
public boolean isPrintForPostVis() {
return printForPostVis;
}
public List<VPoint> getTrajectory() {
return trajectory;
}
......@@ -71,13 +63,13 @@ public class PedestriansNearbyData {
public PedestriansNearbyData getUpdatedData(PedestriansNearbyData newData, int sampleEveryNthStep) {
List<VPoint> traj = getTrajectory();
traj.addAll(newData.getTrajectory());
return new PedestriansNearbyData(getPedId1(), getPedId2(), getDurationTimesteps() + sampleEveryNthStep, getStartTimestep(),traj, printTrajectory, printForPostVis);
return new PedestriansNearbyData(getPedId1(), getPedId2(), getDurationTimesteps() + sampleEveryNthStep, getStartTimestep(),traj);
}
public String[] toStrings(){
// printForPostVis is an ugly one time thing that shouldn't be merged
if (printForPostVis) {
/*if (printForPostVis) {
StringBuilder ret = new StringBuilder();
List<VPoint> traj = getTrajectory();
for (int i = 0; i < traj.size(); i++) {
......@@ -99,17 +91,14 @@ public class PedestriansNearbyData {
}
}
return new String[]{ret.toString()};
}
if (!printTrajectory) {
return new String[]{Integer.toString(durationTimesteps)};
}
}*/
StringBuilder ret = new StringBuilder();
List<VPoint> traj = getTrajectory();
for (int i = 0; i < traj.size(); i++) {
VPoint p = traj.get(i);
ret.append(p.x).append(" ").append(p.y).append("\n");
ret.append(p.x).append(" ").append(p.y);
if (i != traj.size() -1) {
ret.append("- - - - ");
ret.append("\r\n").append("- - - - ");
}
}
return new String[]{Integer.toString(durationTimesteps), ret.toString()};
......
......@@ -13,22 +13,18 @@ public class TimestepPedestriansNearbyIdKey implements DataKey<TimestepPedestria
private final int timeStep;
private final int pedId1; //smaller id
private final int pedId2; //bigger id
private final boolean printForPostVis;
private static boolean staticPrintForPostVis;
public TimestepPedestriansNearbyIdKey(int timeStep, int pedA, int pedB, boolean printForPostVis) {
public TimestepPedestriansNearbyIdKey(int timeStep, int pedA, int pedB) {
this.timeStep = timeStep;
this.pedId1 = Math.min(pedA, pedB);
this.pedId2 = Math.max(pedA, pedB);
this.printForPostVis = printForPostVis; // is an ugly one time thing that shouldn't be merged
staticPrintForPostVis = printForPostVis;
}
public static String[] getHeaders(){