Commit 55abea16 authored by Stefan Schuhbaeck's avatar Stefan Schuhbaeck
Browse files

refactor group rendering and move to gui package.

Add new online and offline visualization button to toggle
group view for pedestrians.
parent 0add8d64
......@@ -234,6 +234,7 @@ SettingsDialog.menuOpenFloorFieldFile.title=Add Floor Field File...
View.btnDrawVoronoiDiagram.tooltip=Draw and display a Voronoi Diagram
View.chbLogo.text=Show the Vadere logo
View.btnShowWalkingDirection.tooltip=Show the walking direction of all pedestrians
View.btnShowGroupInformation.tooltip=Draw pedestrians within one group with same shape and color
View.btnShowPedestrian.tooltip=Show Pedestrians
View.btnShowPotentialfield.tooltip=Show Potential Field (only possible after adding potential field file)
View.btnShowTrajectories.tooltip=Show Trajectories
......
......@@ -233,6 +233,7 @@ SettingsDialog.menuOpenFloorFieldFile.title=Floor Field-Datei hinzuf\u00fcgen...
View.btnDrawVoronoiDiagram.tooltip=Voronoi-Diagramm zeichnen und anzeigen
View.chbLogo.text=VADERE-Logo anzeigen
View.btnShowWalkingDirection.tooltip=Gehrichtung aller Fu\u00dfg\u00e4nger anzeigen
View.btnShowGroupInformation.tooltip=Zeichne Fu\u00dfg\u00e4nger einer Gruppe mit denn selben Formen und Farben
View.btnShowPedestrian.tooltip=Fu\u00dfg\u00e4nger anzeigen
View.btnShowPotentialfield.tooltip=Potenzialfeld anzeigen (nur m\u00f6glich, nachdem eine Datei f\u00fcr das Potenzialfeld hinzugef\u00fcgt wurde)
View.btnShowTrajectories.tooltip=Trajektorien anzeigen
......
......@@ -22,6 +22,7 @@ public class DefaultSimulationConfig extends DefaultConfig {
private boolean showTrajectories = false;
private boolean showGrid = false;
private boolean showDensity = false;
private boolean showGroups = false;
protected final Color pedestrianDefaultColor = Color.BLUE;
public DefaultSimulationConfig() {
......@@ -37,6 +38,15 @@ public class DefaultSimulationConfig extends DefaultConfig {
this.showPedestrians = config.showPedestrians;
this.showLogo = config.showLogo;
this.showStairs = config.showStairs;
this.showGroups = config.showGroups;
}
public boolean isShowGroups() {
return showGroups;
}
public void setShowGroups(boolean showGroups) {
this.showGroups = showGroups;
}
public boolean isShowLogo() {
......
......@@ -16,6 +16,7 @@ import org.vadere.gui.components.model.SimulationModel;
import org.vadere.gui.components.utils.CLGaussianCalculator;
import org.vadere.gui.components.utils.ColorHelper;
import org.vadere.gui.components.utils.Resources;
import org.vadere.gui.renderer.agent.AgentRender;
import org.vadere.state.scenario.Agent;
import org.vadere.util.geometry.shapes.VPoint;
import org.vadere.util.geometry.shapes.VTriangle;
......@@ -35,12 +36,14 @@ public abstract class SimulationRenderer extends DefaultRenderer {
private ColorHelper colorHelper;
private Color lastDensityColor = null;
private int topographyId;
private AgentRender agentRender;
public SimulationRenderer(final SimulationModel model) {
super(model);
this.model = model;
this.topographyId = -1;
this.colorHelper = new ColorHelper(40);
this.agentRender = new AgentRender(model);
}
@Override
......@@ -205,4 +208,12 @@ public abstract class SimulationRenderer extends DefaultRenderer {
private float getGridLineWidth() {
return (float) (0.5 / model.getScaleFactor());
}
public AgentRender getAgentRender() {
return agentRender;
}
public void setAgentRender(AgentRender agentRender) {
this.agentRender = agentRender;
}
}
\ No newline at end of file
......@@ -101,6 +101,15 @@ public class OnlineVisualisationWindow extends JPanel implements Observer {
}
};
AbstractAction showGroupInformationAction = new AbstractAction("showGroupInformationAction",
resources.getIcon("group.png", iconWidth, iconHeight)) {
@Override
public void actionPerformed(ActionEvent e) {
model.config.setShowGroups(!model.config.isShowGroups());
model.notifyObservers();
}
};
AbstractAction paintGridAction = new AbstractAction("paintGridAction",
resources.getIcon("grid.png", iconWidth, iconHeight)) {
......@@ -166,6 +175,8 @@ public class OnlineVisualisationWindow extends JPanel implements Observer {
Messages.getString("View.btnShowTrajectories.tooltip"));
SwingUtils.addActionToToolbar(toolbar, paintArrowAction,
Messages.getString("View.btnShowWalkingDirection.tooltip"));
SwingUtils.addActionToToolbar(toolbar, showGroupInformationAction,
Messages.getString("View.btnShowGroupInformation.tooltip"));
toolbar.addSeparator();
......
......@@ -8,6 +8,7 @@ import java.util.Map;
import org.vadere.gui.components.view.DefaultRenderer;
import org.vadere.gui.components.view.SimulationRenderer;
import org.vadere.gui.onlinevisualization.model.OnlineVisualizationModel;
import org.vadere.gui.renderer.agent.AgentRender;
import org.vadere.state.scenario.Agent;
import org.vadere.util.geometry.shapes.VPoint;
......@@ -55,11 +56,11 @@ public class OnlinevisualizationRenderer extends SimulationRenderer {
}
private void renderPedestrians(final Graphics2D g) {
AgentRender agentRender = getAgentRender();
g.setColor(model.config.getPedestrianDefaultColor());
for (Agent ped : model.getAgents()) {
VPoint position = ped.getPosition();
// g.fill(ped.getShape());
ped.render(g);
agentRender.render(ped, g);
if (!pedestrianPositions.containsKey(ped.getId())) {
pedestrianPositions.put(ped.getId(), new LinkedList());
......
......@@ -13,6 +13,7 @@ import org.vadere.gui.components.utils.ColorHelper;
import org.vadere.gui.components.view.DefaultRenderer;
import org.vadere.gui.components.view.SimulationRenderer;
import org.vadere.gui.postvisualization.model.PostvisualizationModel;
import org.vadere.gui.renderer.agent.AgentRender;
import org.vadere.state.scenario.Agent;
import org.vadere.state.simulation.Step;
import org.vadere.state.simulation.Trajectory;
......@@ -70,6 +71,7 @@ public class PostvisualizationRenderer extends SimulationRenderer {
private void renderTrajectory(final Graphics2D g, final Color color, final Trajectory trajectory, final Step step) {
Optional<Agent> optionalPedestrian = trajectory.getAgent(step);
AgentRender agentRender = getAgentRender();
if (optionalPedestrian.isPresent()) {
Agent pedestrian = optionalPedestrian.get();
......@@ -88,7 +90,7 @@ public class PostvisualizationRenderer extends SimulationRenderer {
// renderImage the pedestrian
if (model.config.isShowPedestrians()) {
if (model.config.isShowFaydedPedestrians() || !trajectory.isPedestrianDisappeared(step)) {
g.fill(pedestrian.getShape());
agentRender.render(pedestrian, g);
if (model.config.isShowPedestrianIds()) {
DefaultRenderer.paintAgentId(g, pedestrian);
}
......
......@@ -203,6 +203,17 @@ public class PostvisualizationWindow extends JPanel implements Observer {
}, "View.btnShowWalkingDirection.tooltip");
addActionToToolbar(toolbar,
new ActionVisualization("show_groups",
resources.getIcon("group.png", iconWidth, iconHeight), model) {
@Override
public void actionPerformed(ActionEvent e) {
model.config.setShowGroups(!model.config.isShowGroups());
model.notifyObservers();
}
}, "View.btnShowGroupInformation.tooltip");
addActionToToolbar(toolbar,
new ActionSwapSelectionMode("draw_voronoi_diagram",
resources.getIcon("voronoi.png", iconWidth, iconHeight), model),
......@@ -332,6 +343,7 @@ public class PostvisualizationWindow extends JPanel implements Observer {
public void loadOutputFile(final File trajectoryFile, final Scenario scenario) throws IOException {
Player.getInstance(model).stop();
//todo
model.init(IOOutput.readTrajectories(trajectoryFile.toPath(), scenario), scenario, trajectoryFile.getParent());
model.notifyObservers();
}
......
package org.vadere.gui.renderer.agent;
import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;
import org.vadere.gui.components.model.SimulationModel;
import org.vadere.state.scenario.Agent;
import org.vadere.state.scenario.Pedestrian;
import org.vadere.util.geometry.shapes.VShape;
import java.awt.*;
import java.util.concurrent.ConcurrentHashMap;
public class AgentRender implements Renderer {
private static Logger logger = LogManager.getLogger(AgentRender.class);
private static final Integer COLOR_NUM = 9;
private final SimulationModel model;
private final Color defaultColor;
private ConcurrentHashMap<Integer, Color> colorMap;
public AgentRender(SimulationModel model) {
this.model = model;
this.defaultColor = model.config.getPedestrianDefaultColor();
this.colorMap = new ConcurrentHashMap<>();
}
@Override
public void render(Agent a, Graphics2D g) {
if (model.config.isShowGroups()) {
try {
Pedestrian ped = (Pedestrian) a;
renderGroup(ped, g);
} catch (ClassCastException cce) {
logger.error("Error casting to Pedestrian");
cce.printStackTrace();
model.config.setShowGroups(false);
renderDefault(a, g, defaultColor);
}
} else {
renderDefault(a, g, defaultColor);
}
}
private void renderGroup(Pedestrian ped, Graphics2D g) {
g.setColor(getColor(ped));
g.fill(getShape(ped));
}
private void renderDefault(Agent a, Graphics2D g, Color c) {
g.setColor(c);
g.fill(a.getShape());
}
private Color getHSBColor(int groupId) {
float hue = ((float) (groupId) / COLOR_NUM);
// System.out.printf("groupId: %d | hue: %f%n",groupId, hue);
return new Color(Color.HSBtoRGB(hue, 1f, 0.75f));
}
private Color getColor(Pedestrian ped) {
if (ped.getGroupIds().isEmpty()) {
return defaultColor;
}
int groupId = ped.getGroupIds().getFirst();
Color c = colorMap.get(groupId);
if (c == null) {
c = getHSBColor(groupId);
colorMap.put(groupId, c);
}
return c;
}
private VShape getShape(Pedestrian ped) {
if (ped.getGroupIds().isEmpty()) {
return ped.getShape();
} else {
return FormHelper.getShape(ped.getGroupIds().getFirst(), ped.getPosition(), ped.getRadius());
}
}
}
package org.vadere.state.scenario.renderer;
package org.vadere.gui.renderer.agent;
import org.vadere.util.geometry.shapes.VPoint;
import org.vadere.util.geometry.shapes.VPolygon;
......@@ -8,79 +8,70 @@ import java.awt.geom.Path2D;
public class FormHelper {
enum FORM {
PENTAGON,
DIAMOND,
TRIANGLE,
STAR,
STAR_X;
}
public static VPolygon getShape(int id, VPoint p, double r){
public static VPolygon getShape(int id, VPoint p, double r) {
int form = id % 6;
if (form == 0){
if (form == 0) {
return getPentagon(p, r);
} else if(form == 1){
} else if (form == 1) {
return getDiamond(p, r);
} else if(form == 2) {
} else if (form == 2) {
return getTriangle(p, r);
} else if(form == 4){
} else if (form == 4) {
return getStar5(p, r);
} else if(form == 5){
} else if (form == 5) {
return getStarX(p, r);
} else {
return getStar7(p, r);
}
}
public static VPolygon getPentagon(VPoint center, double r){
private static VPolygon getPentagon(VPoint center, double r) {
return polygon(center, r, 5);
}
public static VPolygon getDiamond (VPoint center, double r){
private static VPolygon getDiamond(VPoint center, double r) {
return polygon(center, r, 4);
}
public static VPolygon getTriangle(VPoint center, double r){
private static VPolygon getTriangle(VPoint center, double r) {
return polygon(center, r, 3);
}
public static VPolygon getStar7(VPoint center, double r){
private static VPolygon getStar7(VPoint center, double r) {
return star(center, r, 7);
}
public static VPolygon polygon(VPoint center, double r, int corners){
VPoint p = new VPoint(0,r);
private static VPolygon polygon(VPoint center, double r, int corners) {
VPoint p = new VPoint(0, r);
Path2D.Double path = new Path2D.Double();
path.moveTo(center.x + p.x, center.y + p.y);
for (int i = 0 ; i < corners ; i++) {
for (int i = 0; i < corners; i++) {
p = p.rotate(2 * Math.PI / corners);
path.lineTo(center.x + p.x, center.y + p.y);
}
return new VPolygon(path);
}
public static VPolygon getStar5(VPoint center, double r) {
private static VPolygon getStar5(VPoint center, double r) {
return star(center, r, 5);
}
public static VPolygon getStarX(VPoint center, double r) {
private static VPolygon getStarX(VPoint center, double r) {
return star(center, r, 4).rotate(center, Math.PI/4);
return star(center, r, 4).rotate(center, Math.PI / 4);
}
public static VPolygon star(VPoint center, double r, int corners){
VPoint p = new VPoint(0,r);
private static VPolygon star(VPoint center, double r, int corners) {
VPoint p = new VPoint(0, r);
Path2D.Double path = new Path2D.Double();
path.moveTo(center.x + p.x, center.y + p.y);
double alpha = Math.PI / corners;
for (int i = 0 ; i < corners ; i++) {
for (int i = 0; i < corners; i++) {
p = p.rotate(alpha);
path.lineTo(center.x + p.x, center.y + p.y);
p = p.scalarMultiply(0.5);
......@@ -93,9 +84,6 @@ public class FormHelper {
VPolygon polygon = new VPolygon(path);
return polygon.rotate(center, -0.5*alpha);
return polygon.rotate(center, -0.5 * alpha);
}
}
package org.vadere.state.scenario.renderer;
package org.vadere.gui.renderer.agent;
import org.vadere.state.scenario.Agent;
import java.awt.*;
public interface Renderer{
public interface Renderer {
void render(final Agent a, final Graphics2D g, Color c);
void render(final Agent a, final Graphics2D g);
default void setColor(final Graphics2D g, Color c){
g.setColor(c);
}
}
package org.vadere.state.scenario;
import java.awt.*;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
......@@ -9,8 +8,6 @@ import java.util.Random;
import org.apache.commons.math3.random.JDKRandomGenerator;
import org.apache.commons.math3.random.RandomGenerator;
import org.vadere.state.attributes.scenario.AttributesAgent;
import org.vadere.state.scenario.renderer.AgentDefaultRenderer;
import org.vadere.state.scenario.renderer.Renderer;
import org.vadere.util.geometry.Vector2D;
import org.vadere.util.geometry.shapes.VCircle;
import org.vadere.util.geometry.shapes.VPoint;
......@@ -20,7 +17,7 @@ import org.vadere.util.math.TruncatedNormalDistribution;
public abstract class Agent extends DynamicElement {
/**
* Source where the agent was spawned. The {@link SourceController} should
* Source where the agent was spawned. The SourceController should
* set this field. It may be <code>null</code> when the agent is created
* in different way.
*/
......@@ -35,7 +32,7 @@ public abstract class Agent extends DynamicElement {
private double freeFlowSpeed;
private final AttributesAgent attributes;
private Renderer renderer;
public Agent(AttributesAgent attributesAgent) {
position = new VPoint(0, 0);
......@@ -44,19 +41,6 @@ public abstract class Agent extends DynamicElement {
nextTargetListIndex = 0;
attributes = attributesAgent;
setRenderer(new AgentDefaultRenderer());
}
public void setRenderer(Renderer render){
this.renderer = render;
}
public void render(Graphics2D g){
renderer.render(this, g);
}
public void render(Graphics2D g, Color c){
renderer.render(this, g, c);
}
......
package org.vadere.state.scenario;
import org.vadere.state.attributes.scenario.AttributesAgent;
import org.vadere.state.scenario.renderer.AgentGlyphRenderer;
import org.vadere.state.scenario.renderer.PedestrianGroupRenderer;
import org.vadere.state.scenario.renderer.PedestrianTriangleRenderer;
import org.vadere.state.types.ScenarioElementType;
import org.vadere.util.geometry.shapes.VShape;
......@@ -46,7 +43,6 @@ public class Pedestrian extends Agent {
isChild = false;
isLikelyInjured = false;
groupIds = new LinkedList<>();
setRenderer(new PedestrianGroupRenderer());
}
/**
......
package org.vadere.state.scenario.renderer;
import org.vadere.state.scenario.Agent;
import org.vadere.util.geometry.shapes.VCircle;
import org.vadere.util.geometry.shapes.VShape;
import java.awt.*;
public class AgentDefaultRenderer implements ShapeRenderer{
public AgentDefaultRenderer(){
}
public void setColor(Agent a, Graphics2D g) {
g.setColor(Color.GREEN);
}
@Override
public VShape drawShape(Agent a) {
return new VCircle(a.getPosition(), a.getAttributes().getRadius());
}
@Override
public void setColor(Graphics2D g, Color c) {
g.setColor(c);
}
}
package org.vadere.state.scenario.renderer;
import org.vadere.state.scenario.Agent;
import java.awt.*;
import java.awt.font.FontRenderContext;
import java.awt.font.GlyphVector;
public class AgentGlyphRenderer implements GlyphRenderer{
@Override
public void render(Agent a, Graphics2D g, Color c) {
}
@Override
public void render(Agent a, Graphics2D g) {
String s = "\u20df";
Font font = new Font("Serif", Font.PLAIN, 12);
FontRenderContext frc = g.getFontRenderContext();
GlyphVector gv = font.createGlyphVector(frc, s);
g.drawGlyphVector(gv, (float)a.getPosition().x, (float)a.getPosition().y);
}
}
package org.vadere.state.scenario.renderer;
public interface GlyphRenderer extends Renderer {
}
package org.vadere.state.scenario.renderer;
import org.vadere.state.scenario.Agent;
import org.vadere.state.scenario.Pedestrian;
import org.vadere.util.geometry.shapes.VShape;
import java.awt.*;
import java.util.concurrent.ConcurrentHashMap;
public class PedestrianGroupRenderer implements ShapeRenderer{
private static ConcurrentHashMap<Integer, Color> color = new ConcurrentHashMap<>();
private static final Integer COLOR_NUM = 9;
@Override
public void render(Agent a, final Graphics2D g){
g.setColor(getColor(a));
g.fill(drawShape(a));
}
@Override
public VShape drawShape(Agent a) {
// return FormHelper.getStarX(a.getPosition(), a.getRadius());
Pedestrian ped = (Pedestrian)a;
return FormHelper.getShape(ped.getGroupIds().getFirst(), ped.getPosition(), ped.getRadius());
}
private Color getHSBColor(int groupId){
float hue = ((float)(groupId) / COLOR_NUM);
// System.out.printf("groupId: %d | hue: %f%n",groupId, hue);
return new Color(Color.HSBtoRGB(hue, 1f, 0.75f));
}
private Color getColor(Agent a){
Pedestrian ped = (Pedestrian)a;
int groupId = ped.getGroupIds().getFirst();
Color c = color.get(groupId);
if (c == null){
c = getHSBColor(groupId);
color.put(groupId, c);
}
return c;
}