⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 edgeanimation.java

📁 一个用于排队系统仿真的开源软件,有非常形象的图象仿真过程!
💻 JAVA
字号:
/**    
  * Copyright (C) 2006, Laboratorio di Valutazione delle Prestazioni - Politecnico di Milano

  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version.

  * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.

  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  */
  
package jmt.gui.common.animation;

import java.awt.*;
import java.awt.image.ImageObserver;
import java.util.Vector;

/**
 * Created by IntelliJ IDEA.
 * User: orsotronIII
 * Date: 17-gen-2005
 * Time: 13.55.01
 * This class implements an animation for an edge of the graph that represents the queue net.
 * Once the coords of the angles (which may only be straight angles)of that edge are set, the
 * methods provide support for the output of this edge animation. This means that once the
 * paint method is called, the bounding box for this animation is refreshed with the new frame.
 */
public class EdgeAnimation implements Animation, JobContainer{

    //points this edge passes through
    private Point[] anglePoints;

    /**vector containing all of the jobs that currently are running on this edge of the
    queue net*/
    protected Vector jobAnimations = new Vector();

    //bounding box for this animation.
    private Rectangle bounds;

    //background image for this animation, tipically the trace of the edge
    private Image bgImage;

    //icon toolkit to be used for renderization of the images.
    private IconsToolkit toolkit;


    /**Creates a new instance of Edgeanimation. This must be initialized with a set of points
     * which are coords of starting point of this edge, points where this edge turns with a
     * straight angle (which may be omitted in case this edge doesn't turn), and finally
     * ending point for this edge. All of the coords must be given in the real animation
     * resolution scale.
     * @param angles: coords of the angle points.
     * @param margin: width of border of this edge. Used to calculate boundingbox for this
     * animation from coords of the angle points
     */
    public EdgeAnimation(Point[] angles, int margin){
        this(angles, margin, new DefaultIconsToolkit());
    }

    /**Creates a new instance of Edgeanimation. This must be initialized with a set of points
     * which are coords of starting point of this edge, points where this edge turns with a
     * straight angle (which may be omitted in case this edge doesn't turn), and finally
     * ending point for this edge. All of the coords must be given in the real animation
     * resolution scale.
     * @param angles: coords of the angle points.
     * @param margin: width of border of this edge. Used to calculate boundingbox for this
     * animation from coords of the angle points
     * @param toolkit: toolkit for customized renderization of this edge.
     */
    public EdgeAnimation(Point[] angles, int margin, IconsToolkit toolkit){
        anglePoints = angles;
        calculateBounds(margin);
        this.toolkit = toolkit;
        bgImage = toolkit.getEdgeIcon(bounds, angles);
    }

    /**Creates a new instance of Edgeanimation from another edge animation.
     * @param edge: edge to be copied.
     */
    public EdgeAnimation(EdgeAnimation edge){
        this(edge.anglePoints, 10, edge.toolkit);
        Point[] angles = edge.anglePoints;
        int margin = (edge.bounds.width-Math.abs(angles[0].x-angles[angles.length-1].x))/2;
        calculateBounds(margin);
        bgImage = toolkit.getEdgeIcon(bounds,anglePoints);
    }

    //calculates bounding box position and size from angle points coordinates.
    private void calculateBounds(int margin){
        int maxX=-1, maxY=-1, minX=-1, minY=-1;
        for(int i=0; i<anglePoints.length; i++){
            if(maxX==-1) maxX=anglePoints[i].x;
            if(maxY==-1) maxY=anglePoints[i].y;
            if(minX==-1) minX=anglePoints[i].x;
            if(minY==-1) minY=anglePoints[i].y;
            if(anglePoints[i].x > maxX) maxX=anglePoints[i].x;
            if(anglePoints[i].y > maxY) maxY=anglePoints[i].y;
            if(anglePoints[i].x < minX) minX=anglePoints[i].x;
            if(anglePoints[i].y < minY) minY=anglePoints[i].y;
        }
        maxX+=margin;
        minX-=margin;
        maxY+=margin;
        minY-=margin;
        bounds = new Rectangle(minX, minY, maxX-minX, maxY-minY);
    }


    /*Converts current linear position to 2d coordinates for representing this job in the
    animation. This way provides a simple way to calculate final coordinates of the image from
    the speed value*/
    private Point convertPositionToCoord(double position){
        //find between which couple of angle points the job must be placed
        int firstPointIndex=0;
        double length = 0;
        for(firstPointIndex=0; firstPointIndex<anglePoints.length-1; firstPointIndex++){
            /*calculate distance between points and add result to the length formerly calculated
            for comparison with position parameter*/
            Point firstPoint = anglePoints[firstPointIndex], nextPoint = anglePoints[firstPointIndex+1];
            double intervalEnd=length+getEuclideanDistance(firstPoint, nextPoint);
            if(position<intervalEnd)return getPointOnSegment(firstPoint, nextPoint, position-length);
            else length = intervalEnd;
        }
        /*if execution gets here, job has exited this edge. Job must be routed to the
        next component*/
        return null;
    }

    //calculates euclidean distance between two 2d coordinates
    private double getEuclideanDistance(Point p0, Point p1){
        //if x or y are equal in both the given points, calculate distance more rapidly
        if(p0.getX()==p1.getX())return Math.abs(p0.getY()-p1.getY());
        if(p0.getY()==p1.getY())return Math.abs(p0.getX()-p1.getX());
        //if points are on different x and y coords
        return Math.sqrt(Math.pow(p0.getX()-p1.getX(),2)+ Math.pow(p0.getY()-p1.getY(),2));
    }

    //calculates coordinates of a point given distance from p0 on the segment p0-p1
    private Point getPointOnSegment(Point p0, Point p1, double distanceFromP0){
        /*if the given points are on the same x or y coord, calculate resulting point in a more
        efficient way*/
        if(p0.getX()==p1.getX()){
            if(p0.y<=p1.y) return new Point((int)p0.getX(), (int)(p0.getY()+ distanceFromP0));
            else return new Point((int)p0.getX(), (int)(p0.getY()- distanceFromP0));
        }
        if(p0.getY()==p1.getY()){
            if(p0.x<=p1.x)return new Point((int)(p0.getX()+ distanceFromP0), (int)p0.getY());
            else return new Point((int)(p0.getX()- distanceFromP0), (int)p0.getY());
        }
        //else calculate a more accurate position
        double euclDist = getEuclideanDistance(p0,p1);
        int xDist = (int)(((p1.getX()-p0.getX())*distanceFromP0)/euclDist);
        int yDist = (int)(((p1.getY()-p0.getY())*distanceFromP0)/euclDist);
        return new Point(xDist+(int)p0.getX(), yDist+(int)p0.getY());
    }

    /**Puts another Job on this edge. The initial position is set to 0(e.g. the starting point
     * of this edge)
     * @param newJob: job to be added.
     */
    public void addJob(JobAnimation newJob){
        jobAnimations.add(newJob);
        newJob.setPosition(0);
        newJob.setRepaint(true);
        //centers job to starting point of this edge
        Rectangle jobSize = newJob.getBounds();
        Point p=new Point(anglePoints[0].x-jobSize.width/2, anglePoints[0].y-jobSize.height/2);
        newJob.getBounds().setLocation(p);
        newJob.resetTimeOfEntrance();
    }

    /**Refreshes appearence of the image to be rendered. In facts, recalculates all of the jobs'
     * new positions.*/
    public void refresh() {
        for(int i=0; i<jobAnimations.size(); i++){
            JobAnimation ja = (JobAnimation)jobAnimations.get(i);
            //update position as time*speed
            ja.setPosition((System.currentTimeMillis()-ja.getTimeOfEntrance())*ja.getSpeed());
            Point p = convertPositionToCoord(ja.getPosition());
            //tests if this job should be painted outside bounding box of this edge
            if(p!=null){
                boolean exceedsWidth = (p.getX()>=bounds.x+bounds.width),
                        exceedsHeight = (p.getY()>=bounds.y+bounds.height);
                if(exceedsWidth||exceedsHeight) routeJob(ja);
                //set bounds of the job in order to be centered to the coords.
                Rectangle r = ja.getBounds();
                p.setLocation(p.getX()-r.getWidth()/2,p.getY()-r.getHeight()/2);
                r.setLocation(p);
            }else{
                routeJob(ja);
            }
        }
    }

    //deletes job from local list of jobs to be rendered and routes it to the next element
    //of the queue net.
    private void routeJob(JobAnimation toDelete){
        int index = jobAnimations.indexOf(toDelete);
        jobAnimations.remove(index);
        toDelete.getNextElement().addJob(toDelete);
    }

    public void init() {
    }

    public void paint(Graphics g, ImageObserver io) {
        g.drawImage(bgImage, bounds.x, bounds.y, io);
    }

    public Image getBGImage() {
        return bgImage;
    }

    public void setBGImage(Image img) {
        bgImage = img;
    }

    public void setBounds(Rectangle r) {
        bounds=r;
        bgImage = toolkit.getEdgeIcon(bounds, anglePoints);
    }

    public Rectangle getBounds() {
        return bounds;
    }
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -