📄 edgeanimation.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 + -