Package eas.plugins.standard.visualization

Source Code of eas.plugins.standard.visualization.AllroundTrajectoryPlugin

/*
* File name:    TrajectoryPlugin.java
* Java version: 6.0
* Author(s):    Lukas König
* File created: 01.10.2010 (in Budapest, airport)
*
* (c) This file and the EAS (Easy Agent Simulation) framework containing it
* is protected by Creative Commons by-nc-sa license. Any altered or
* further developed versions of this file have to meet the agreements
* stated by the license conditions.
*
* In a nutshell
* -------------
* You are free:
* - to Share -- to copy, distribute and transmit the work
* - to Remix -- to adapt the work
*
* Under the following conditions:
* - Attribution -- You must attribute the work in the manner specified by the
*   author or licensor (but not in any way that suggests that they endorse
*   you or your use of the work).
* - Noncommercial -- You may not use this work for commercial purposes.
* - Share Alike -- If you alter, transform, or build upon this work, you may
*   distribute the resulting work only under the same or a similar license to
*   this one.
*
* + Detailed license conditions (Germany):
*   http://creativecommons.org/licenses/by-nc-sa/3.0/de/
* + Detailed license conditions (unported):
*   http://creativecommons.org/licenses/by-nc-sa/3.0/deed.en
*
* This header must be placed in the beginning of any version of this file.
*/

package eas.plugins.standard.visualization;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.TreeMap;

import javax.imageio.ImageIO;

import eas.math.geometry.Rectangle2D;
import eas.math.geometry.Vector2D;
import eas.miscellaneous.StaticMethods;
import eas.plugins.AbstractDefaultPlugin;
import eas.simulation.Wink;
import eas.simulation.agent.AbstractAgent;
import eas.simulation.event.EASEvent;
import eas.simulation.spatial.sim2D.standardAgents.AbstractAgent2D;
import eas.simulation.spatial.sim2D.standardEnvironments.AbstractEnvironment2D;
import eas.startSetup.GlobalVariables;
import eas.startSetup.ParCollection;
import eas.startSetup.SingleParameter;
import eas.startSetup.parameterDatatypes.ArrayListVec2D;
import eas.startSetup.parameterDatatypes.Datatypes;

/**
* @author Lukas König
*/
public class AllroundTrajectoryPlugin extends AbstractDefaultPlugin<AbstractEnvironment2D<AbstractAgent2D<?>>> {

    private static final long serialVersionUID = 9017869109522644959L;

    @Override
    public List<String> getRequiredPlugins() {
        return null;
    }

    @Override
    public List<SingleParameter> getParameters() {
        LinkedList<SingleParameter> list = new LinkedList<SingleParameter>();
        list.add(new SingleParameter(
                "liveTrajectories?",
                Datatypes.BOOLEAN,
                true,
                "Paints trajectories on screen during simulation if true.",
                this.id().toUpperCase()));
        list.add(new SingleParameter(
                "fileNameTrajectories",
                Datatypes.STRING,
                "trajectories.png",
                "Paints trajectories in png file with this filename ('.png' "
                + "is added automatically!). 'null' for no file creation.",
                this.id().toUpperCase()));
        ArrayListVec2D a = new ArrayListVec2D(1);
        a.add(new Vector2D(-1, 0));
        ArrayListVec2D b = new ArrayListVec2D(1);
        b.add(new Vector2D(-1, Double.MAX_VALUE));
        list.add(new SingleParameter(
                "startTrajectories",
                Datatypes.VECTOR2D_ARR,
                a,
                "If live painting is turned OFF: start trajectory painting "
                + "for any of the given tuples (x, y) by interpreting x as "
                + "agent id and y as time step. x = -1 means all agents.",
                this.id().toUpperCase()));
        list.add(new SingleParameter(
                "endTrajectories",
                Datatypes.VECTOR2D_ARR,
                b,
                "If live painting is turned OFF: stop trajectory painting "
                + "for any of the given tuples (x, y) by interpreting x as "
                + "agent id and y as time step. x = -1 means all agents.",
                this.id().toUpperCase()));
        list.add(new SingleParameter(
                "captureUpperLeftCoordinate",
                Datatypes.VECTOR2D,
                new Vector2D(0, 0),
                "The upper left corner of the simulation field that should"
                + "be captured.",
                this.id().toUpperCase()));
        list.add(new SingleParameter(
                "captureLowerRightCoordinate",
                Datatypes.VECTOR2D,
                new Vector2D(100, 100),
                "The lower right corner of the simulation field that should"
                + "be captured.",
                this.id().toUpperCase()));
        list.add(new SingleParameter(
                "autoScale?",
                Datatypes.BOOLEAN,
                true,
                "Scales automatically to field view size. Environment must "
                + "support this! (Can be useless "
                + "if environment zooms out etc. as agent trajectories may "
                + "disappear behind the borders of the image.)",
                this.id().toUpperCase()));
        list.add(new SingleParameter(
                "saveInterval",
                Datatypes.DOUBLE,
                1000d,
                "Interval stating how often the trajectory image is saved.",
                this.id().toUpperCase(),
                this.getClass()));
        return list;
    }

    private static double saveInterval = 0;
   
    public static void setSaveInterval(double saveInterval) {
        if (saveInterval != AllroundTrajectoryPlugin.saveInterval) {
            GlobalVariables.getPrematureParameters().logDebug(
                    "<" + new AllroundTrajectoryPlugin().id()
                            + "> Value of 'saveInterval' changed from "
                            + AllroundTrajectoryPlugin.saveInterval
                            + " to "
                            + saveInterval);
            AllroundTrajectoryPlugin.saveInterval = saveInterval;
        }
    }
   
    @Override
    public String id() {
        return AbstractDefaultPlugin.ALLROUND_PLUGIN_PREFIX + "-trajectoryPlugin2D";
    }

    private transient BufferedImage trajectoryImage;
    private transient Graphics2D trajectoryImageGraphics;
   
    private int fieldWidth;
    private int fieldHeight;
    private Vector2D upperLeft;
    private Vector2D lowerRight;
    private boolean autoscale;
   
    /**
     * Last position of currently active agents. Position <code>null</code>
     * means that there is no known last position available.
     */
    private HashMap<Integer, Vector2D> activeAgents;
   
    /**
     * (x, y): Start trajectories of agents y at time steps x.
     * Keys are sorted.
     */
    private TreeMap<Double, LinkedList<Integer>> beginAgents;

    /**
     * (x, y): End trajectories of agents y at time steps x.
     * Keys are sorted.
     */
    private TreeMap<Double, LinkedList<Integer>> endAgents;
   
    private LiveWindow liveWindow = null;
   
    /**
     * TODO: Unchecked conversion.
     */
    @Override
    public void runBeforeSimulation(AbstractEnvironment2D<AbstractAgent2D<?>> env, ParCollection params) {
        env.addVisualizer(this);
        this.createImage(env, params);
       
        boolean showLiveWindow = params.getParValueBoolean("liveTrajectories?");
       
        this.activeAgents = new HashMap<Integer, Vector2D>();
       
        // Create lists of time steps to activate or deactivate trajectories.
        ArrayListVec2D begin = params.getParValueArrayListVector2D(
                "startTrajectories");
        ArrayListVec2D end = params.getParValueArrayListVector2D(
                "endTrajectories");
        this.beginAgents = new TreeMap<Double, LinkedList<Integer>>();
        this.endAgents = new TreeMap<Double, LinkedList<Integer>>();
       
        for (Vector2D v : begin) {
            if (this.beginAgents.get(v.y) == null) {
                this.beginAgents.put(v.y, new LinkedList<Integer>());
            }
            this.beginAgents.get(v.y).add((int) v.x);
        }

        for (Vector2D v : end) {
            if (this.endAgents.get(v.y) == null) {
                this.endAgents.put(v.y, new LinkedList<Integer>());
            }
            this.endAgents.get(v.y).add((int) v.x);
        }
       
        if (showLiveWindow) {
            this.liveWindow = new LiveWindow(
                    "Live Trajectory View",
                    env,
                    params,
                    this.trajectoryImage.getWidth() + 25,
                    this.trajectoryImage.getHeight() + 25,
                    true);
            this.liveWindow.metaInfVis.img = this.trajectoryImage;
        }
    }

    private void createImage(AbstractEnvironment2D<AbstractAgent2D<?>> env, ParCollection params) {
        BufferedImage fieldView;
        this.autoscale = params.getParValueBoolean("autoScale?");
        boolean perfectFit = env.isPerfectFit();
       
        env.getSimTime().neglectTicks(this);
        env.getSimTime().requestAllNotifications(this);

//        Rectangle2D oldZoom = env.getZoomBox();
       
        if (this.autoscale) {
            if (env.getCurrentViewBox() != null) {
//                env.setZoomBox(null);
                this.upperLeft = new Vector2D(env.getCurrentViewBox().upperLeftCorner());
                this.lowerRight = new Vector2D(env.getCurrentViewBox().lowerRightCorner());
//                env.setZoomBox(new Rectangle2D(
//                        env.getCurrentViewBox().liObEcke(),
//                        env.getCurrentViewBox().rechtUntEcke()));
            } else {
                this.upperLeft = params
                        .getParValueVector2D("captureUpperLeftCoordinate");
                this.lowerRight = params
                        .getParValueVector2D("captureLowerRightCoordinate");
//                env.setZoomBox(new Rectangle2D(this.upperLeft, this.lowerRight));
                StaticMethods.logWarning(
                        this.id() + ": Automatic Scaling turned off.",
                        params);
            }
        } else {
            this.upperLeft = params
                    .getParValueVector2D("captureUpperLeftCoordinate");
            this.lowerRight = params
                    .getParValueVector2D("captureLowerRightCoordinate");
//            env.setZoomBox(new Rectangle2D(this.upperLeft, this.lowerRight));
        }

        boolean isShowIDs = env.isShowIDs();
        env.setShowIDs(false);
        fieldView = env.generateEnvironmentView(
                700,
                700,
                0,
                null,
                new Rectangle2D(this.upperLeft, this.lowerRight));
        env.setShowIDs(isShowIDs);
       
//        env.setZoomBox(oldZoom);
        env.setPerfectFit(perfectFit);
       
        this.fieldWidth = fieldView.getWidth();
        this.fieldHeight = fieldView.getHeight();

        this.trajectoryImage = new BufferedImage(
                this.fieldWidth,
                this.fieldHeight,
                BufferedImage.TYPE_INT_RGB);
        this.trajectoryImageGraphics = this.trajectoryImage.createGraphics();
        this.trajectoryImageGraphics.setBackground(Color.white);
        this.trajectoryImageGraphics.fillRect(0, 0, this.fieldWidth, this.fieldHeight);
        this.trajectoryImageGraphics.drawImage(fieldView, 0, 0, null);
       
        this.trajectoryImageGraphics.setStroke(
                new BasicStroke(3));
    }
   
    private void saveImage(AbstractEnvironment2D<AbstractAgent2D<?>> env, ParCollection params) {
        String filename =
            params.getStdDirectory()
                + File.separatorChar
                + params.getParValueString("fileName-Trajectories")
                + "-"
                + this.beginTrajectory
                + "-"
                + this.endTrajectory
                + ".png";
       
        if (!params.getParValueString("fileName-Trajectories").equals("null")) {
            try {
                ImageIO.write(this.trajectoryImage, "png", new File(filename));
                StaticMethods.logInfo(
                        "Trajectory image saved: " + filename,
                        params);
            } catch (IOException e) {
                StaticMethods.logError(
                        "Trajectory image not saved: " + filename,
                        params);
            }
        }
       
        for (int agent : this.activeAgents.keySet()) {
            this.activeAgents.put(agent, null);
        }
       
        this.createImage(env, params);
    }
   
    @Override
    public void runAfterSimulation(AbstractEnvironment2D<AbstractAgent2D<?>> env, ParCollection params) {
        this.endTrajectory = "end";
        this.saveImage(env, params);
    }

    private double sofar = 0;

    private String beginTrajectory = "0";
   
    private String endTrajectory = "end";
   
    @Override
    public synchronized void runDuringSimulation(AbstractEnvironment2D<AbstractAgent2D<?>> env, Wink simZyk,
            ParCollection params) {
        // Live view.
        if (this.liveWindow != null) {
            this.liveWindow.metaInfVis.img = this.trajectoryImage;
            this.liveWindow.metaInfVis.repaint();
        }
       
        // Save image?
        if (simZyk.getCurrentTime() - this.sofar >= saveInterval) {
            this.endTrajectory = (simZyk.getCurrentTime() + "").replace('.', '_');
            this.sofar = simZyk.getCurrentTime();

            this.saveImage(env, params);
           
            this.beginTrajectory
                = (simZyk.getCurrentTime() + "").replace('.', '_');
        }
       
        // Aktiviere Agenten.
        HashSet<Double> removeTimeStepsBegin = new HashSet<Double>();
        HashSet<Double> removeTimeStepsEnd = new HashSet<Double>();
        for (double d : this.beginAgents.keySet()) {
            if (d > simZyk.getCurrentTime()) {
                break;
            }

            for (int agent : this.beginAgents.get(d)) {
                if (agent == -1) {
                    for (AbstractAgent<?> ag : env.getAgents()) {
                        this.activeAgents.put(ag.id(), null);
                    }
                } else {
                    this.activeAgents.put(agent, null);
                }
            }
           
            removeTimeStepsBegin.add(d);
        }

        for (double d : removeTimeStepsBegin) {
            this.beginAgents.remove(d);
        }
       
        // Zeichne Trajektorien.
//        Rectangle2D oldZoom = env.getZoomBox();
//        double width = env.getScreenWidth();
//        double height = env.getScreenHeight();
       
//        env.setZoomBox(new Rectangle2D(this.upperLeft, this.lowerRight));
//        env.setScreenWidth(700);
//        env.setScreenHeight(700);
       
        for (int i : this.activeAgents.keySet()) {
            Vector2D pos;
            try {
                pos = env.getPositionInVisualization(
                        i,
                        700,
                        700,
                        0,
                        null,
                        new Rectangle2D(this.upperLeft, this.lowerRight));
            } catch (Exception e) {
                pos = env.getPositionInVisualization(i);
            }
           
            if (pos != null) {
                Vector2D oldPos = this.activeAgents.get(i);
                if (oldPos != null) {
                    this.trajectoryImageGraphics.setColor(
                            new Color(
                                    (i * 13) % 199,
                                    (i * 137) % 199,
                                    (i * 227) % 199));
                    this.trajectoryImageGraphics.drawLine(
                            (int) oldPos.x,
                            (int) oldPos.y,
                            (int) pos.x,
                            (int) pos.y);
                }
                this.activeAgents.put(i, pos);
            }
        }
       
//        env.setZoomBox(oldZoom);
//        env.setScreenWidth(width);
//        env.setScreenHeight(height);
       
        // Deaktiviere Agenten.
        for (double d : this.endAgents.keySet()) {
            if (d > simZyk.getCurrentTime()) {
                break;
            }

            for (int agent : this.endAgents.get(d)) {
                if (agent == -1) {
                    for (AbstractAgent<?> ag : env.getAgents()) {
                        this.activeAgents.remove(ag.id());
                    }
                } else {
                    this.activeAgents.remove(agent);
                }
            }
           
            removeTimeStepsEnd.add(d);
        }

        for (double d : removeTimeStepsEnd) {
            this.endAgents.remove(d);
        }
    }

    @Override
    public void handleEvent(EASEvent e, AbstractEnvironment2D<AbstractAgent2D<?>> env,
            Wink lastTimeStep, ParCollection params) {
//        this.runDuringSim(env, lastTimeStep, params);
    }

    @Override
    public List<String> getSupportedPlugins() {
        return null;
    }

    @Override
    public void onSimulationResumed(AbstractEnvironment2D<AbstractAgent2D<?>> env, Wink resumeTime,
            ParCollection params) {
//        env.requestRedraw();
        super.onSimulationResumed(env, resumeTime, params);
        this.createImage(env, params);
        if (params.getParValueBoolean("liveTrajectories?")) {
            this.liveWindow.setVisible(true);
        }
    }
}
TOP

Related Classes of eas.plugins.standard.visualization.AllroundTrajectoryPlugin

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.