📄 sectors2dpanel.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.jaba.panels;
import jmt.engine.jaba.FinalSect2D;
import jmt.engine.jaba.Station2D;
import javax.swing.*;
import java.util.Vector;
import java.awt.*;
import java.awt.geom.Line2D;
import java.awt.geom.Rectangle2D;
import java.text.DecimalFormat;
/**
* <p>Title: Sectors 2D Panel</p>
* <p>Description: This panel is used to show saturation sectors on 2-class models.</p>
* <p>This was reimlemented by Bertoli Marco as original one had strong redraw
* problems, made strange things with rotations, didn't autoscale and overlapped labels
* too frequently.</p>
*
* @author Bertoli Marco, Zanzottera Andrea
* Date: 8-feb-2006
* Time: 11.33.48
*/
public class Sectors2DPanel extends JPanel {
private Vector s3d;
private String[] classNames;
// Margin used for labels and around graph
private static final int MARGIN = 10;
// Defines arrow length
private static final int AMARGIN = 12;
// Various colors
private static final Color SINGLE = new Color(125,255,0);
private static final Color DOUBLE = new Color(0,125,255);
private static final Color MORE = Color.RED;
private static final Color BLACK = Color.BLACK;
private static final Color GREY = Color.GRAY;
private static final Color BGCOLOR = Color.WHITE;
private static final BasicStroke DOTTED = new BasicStroke(1,1,1,1,new float[] {2f},1);
private static final BasicStroke SECTORS = new BasicStroke(3);
private static final BasicStroke LINES = new BasicStroke(1);
// Initial x and y values and measure unit
private int x0, y0, unit;
// Used to format numbers
private static final DecimalFormat formatter = new DecimalFormat("0.000");
/**
* Builds a new Sectors2DPanel
* @param s3d vector with output of Jaba engine
* @param classNames name of classes to be shown on axis
*/
public Sectors2DPanel(Vector s3d, String[] classNames){
super();
this.s3d = s3d;
this.classNames = classNames;
this.setBorder(BorderFactory.createEtchedBorder());
this.setBackground(BGCOLOR);
}
/**
* Overrides default paint method to draw the graph
* @param g graphic object. <b>Must</b> be an instance of Graphics2D
*/
public void paint(Graphics g)
{
super.paint(g);
Graphics2D g2;
// If g is not instance of Graphic2D, aborts method
if (g instanceof Graphics2D)
g2 = (Graphics2D) g;
else
return;
// Gets font metrics
Rectangle2D fontBounds = g2.getFontMetrics().getStringBounds("0.999", g2);
int maxStationNameWidth = (int)g2.getFontMetrics().getStringBounds("StationXXXXXX", g2).getWidth();
int maxDimension;
// Find if height or width is limiting size
int limitHeight, limitWidth;
limitHeight = getHeight() - 2 * MARGIN - 2*AMARGIN - (int)(fontBounds.getHeight()*2)- 5;
limitWidth = getWidth() - 3 * MARGIN - 2*AMARGIN - (int)fontBounds.getWidth() - 10 - maxStationNameWidth;
maxDimension = (limitHeight < limitWidth)? limitHeight: limitWidth;
// If space is too small or we have not any result yes, aborts draw.
if (maxDimension < 20 || s3d == null)
return;
Color sectorcolor;
// Initializes margins
x0 = (int)fontBounds.getWidth() + MARGIN + 5;
y0 = getHeight() - MARGIN - (int)(fontBounds.getHeight()*2)- 5;
unit = maxDimension;
// Position of station names labels
int xetich = (int)(getX(1) + (AMARGIN+MARGIN) * 2);
// Used to avoid station label overlapping
float previousFirstPos = Float.POSITIVE_INFINITY;
for (int i=0;i<s3d.size();i++) {
// Current sector
FinalSect2D sect = (FinalSect2D)s3d.get(i);
double pb11 = sect.getBeta11();
double pb12 = sect.getBeta1();
double pb21 = sect.getBeta22();
double pb22 = sect.getBeta2();
// Station's number
int numstat = sect.countStation();
if (numstat > 2)
sectorcolor = MORE;
else if (numstat == 2)
sectorcolor = DOUBLE;
else
sectorcolor = SINGLE;
g2.setStroke(SECTORS);
g2.setColor(sectorcolor);
g2.draw(new Line2D.Double(getX(pb11),getY(pb12),getX(pb21),getY(pb22)));
// Dotted line
g2.setStroke(DOTTED);
sectorcolor = GREY;
g2.setColor(sectorcolor);
g2.draw(new Line2D.Double(getX(pb21),getY(pb22),getX(0),getY(pb22)));
g2.draw(new Line2D.Double(getX(pb21),getY(pb22),getX(pb21),getY(0)));
// Values on X-axis
g2.setColor(BLACK);
String coordx = formatter.format(pb21);
if (i%2==1 || s3d.size() == 1) // alternate labels if this is odd
g2.drawString(coordx,(float)(getX(pb21)-fontBounds.getWidth()/2),(float)getY(0)+15);
else
{
g2.drawString(coordx,(float)(getX(pb21)-fontBounds.getWidth()/2),(float)(getY(0)+17+fontBounds.getHeight()));
g2.setStroke(DOTTED);
g2.setColor(GREY);
g2.draw(new Line2D.Double(getX(pb21),getY(0),getX(pb21),(float)(getY(0)+fontBounds.getHeight()+2)));
}
// Values on Y-axis
g2.setColor(BLACK);
String coordy = formatter.format(pb12);
g2.drawString(coordy,(float)(getX(0)-fontBounds.getWidth()-5),(float)(getY(pb12)+fontBounds.getHeight() / 2 - 2));
// Now draws station name labels. They are centered on the line of the caption (if possible)
g2.setColor(BLACK);
String etichetta = ((Station2D)(sect.getstation()).get(0)).getName();
// position of first label. Try to center with the middle of the sector but avoids overlapping with previous ones
boolean overlapping = false;
float firstpos = (float)(getY((pb12 + pb22)/2)- (numstat-1) * (fontBounds.getHeight()) / 2) + 3;
if (firstpos + (numstat+.5)*(float)fontBounds.getHeight() > previousFirstPos) {
// Labels are overlapping
firstpos = (float)(previousFirstPos - (numstat+.5)*fontBounds.getHeight());
overlapping = true;
}
// Updates previousFirstPos value
previousFirstPos = firstpos;
g2.drawString(etichetta,xetich, firstpos);
// Next labels
for (int j=1;j<numstat;j++)
{
String etich = ((Station2D)(sect.getstation()).get(j)).getName();
g2.drawString(etich,xetich,firstpos+j*(float)fontBounds.getHeight());
}
// Draws the line of the caption. Prefers horizontal line if possible
g2.setColor(BLACK);
g2.setStroke(LINES);
if (!overlapping)
g2.draw(new Line2D.Double(getX((pb11+pb21)/2)+MARGIN/2,getY((pb12+pb22)/2),xetich-MARGIN/2,getY((pb12+pb22)/2)));
else
g2.draw(new Line2D.Double(getX((pb11+pb21)/2)+MARGIN/2,getY((pb12+pb22)/2),xetich-MARGIN/2,(float)(firstpos+ (numstat-1) * (fontBounds.getHeight()) / 2)-3));
}
// Limit values
if (s3d.size() > 1) {
g2.setColor(BLACK);
String coordx = "1.000";
g2.drawString(coordx,(float)(getX(1)-fontBounds.getWidth()/2),(float)getY(0)+15);
g2.drawString(coordx,(float)(getX(0)-fontBounds.getWidth()-5),(float)(getY(1)+fontBounds.getHeight() / 2)-2);
}
// Eliminates graph area that overlaps axis
g2.setColor(BGCOLOR);
g2.fillRect((int)getX(0)-5,(int)getY(1)-5,5,10);
g2.fillRect((int)getX(1)-5,(int)getY(0),10,5);
// Paints Axis
g2.setStroke(LINES);
sectorcolor = BLACK;
g2.setColor(sectorcolor);
Line2D assex = new Line2D.Double(getX(0),getY(0),getX(1)+2*AMARGIN,getY(0));
Line2D assey = new Line2D.Double(getX(0),getY(0),getX(0), getY(1)-2*AMARGIN);
g2.draw(assex);
g2.draw(assey);
// Axis Label
g2.setColor(Color.GRAY);
g2.drawString(classNames[0] + " %", (float)(getX(1)+2*AMARGIN+5),(float)getY(0)+15);
g2.drawString(classNames[1] + " %",(float)getX(0)+AMARGIN,(float)(getY(1)-2*AMARGIN+5));
g2.setColor(BLACK);
// Arrows on axis
g2.draw(new Line2D.Double(getX(0)-AMARGIN/2,getY(1)-AMARGIN/3-AMARGIN,getX(0),getY(1)-2*AMARGIN));
g2.draw(new Line2D.Double(getX(0)+AMARGIN/2,getY(1)-AMARGIN/3-AMARGIN,getX(0),getY(1)-2*AMARGIN));
g2.draw(new Line2D.Double(getX(1)+AMARGIN/3+AMARGIN,getY(0)-AMARGIN/2,getX(1)+2*AMARGIN,getY(0)));
g2.draw(new Line2D.Double(getX(1)+AMARGIN/3+AMARGIN,getY(0)+AMARGIN/2,getX(1)+2*AMARGIN,getY(0)));
}
/**
* Transform double x coordinate into screen one
* @param x x coordinate
* @return screen x coordinate
*/
private double getX (double x) {
return x0 + x * unit;
}
/**
* Transform double y coordinate into screen one
* @param y y coordinate
* @return screen y coordinate
*/
private double getY (double y) {
return y0 - y * unit;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -