📄 plotter.java
字号:
/*
* YALE - Yet Another Learning Environment
* Copyright (C) 2001-2004
* Simon Fischer, Ralf Klinkenberg, Ingo Mierswa,
* Katharina Morik, Oliver Ritthoff
* Artificial Intelligence Unit
* Computer Science Department
* University of Dortmund
* 44221 Dortmund, Germany
* email: yale-team@lists.sourceforge.net
* web: http://yale.cs.uni-dortmund.de/
*
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA.
*/
package edu.udo.cs.yale.gui;
import edu.udo.cs.yale.Statistics;
import edu.udo.cs.yale.StatisticsRow;
import edu.udo.cs.yale.StatisticsListener;
import javax.swing.filechooser.FileFilter;
import javax.swing.*;
import java.awt.geom.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.font.FontRenderContext;
import java.util.SortedSet;
import java.util.TreeSet;
import java.util.List;
import java.util.LinkedList;
import java.util.Iterator;
import java.util.Comparator;
import java.text.DecimalFormat;
import java.io.File;
import java.io.FileWriter;
import java.io.FileOutputStream;
import java.io.PrintStream;
import java.io.PrintWriter;
import java.io.IOException;
public class Plotter extends JPanel implements StatisticsListener {
public final Action SAVE_ACTION = new AbstractAction("Save...") {
{
putValue(SHORT_DESCRIPTION, "Save the statistics to disk.");
}
public void actionPerformed(ActionEvent e) {
JFileChooser chooser = SwingTools.createFileChooser(null, false,
new FileFilter[] {
new SimpleFileFilter("Raw statistics", ".dat", 1),
new SimpleFileFilter("GNUPlot file", ".gnu", 2)
});
if (chooser.showSaveDialog(Plotter.this) == JFileChooser.APPROVE_OPTION) {
File file = chooser.getSelectedFile();
try {
int id = ((SimpleFileFilter)chooser.getFileFilter()).getId();
switch (id) {
case 1:
PrintWriter out1 = new PrintWriter(new FileWriter(file));
statistics.write(out1);
out1.close();
break;
case 2:
PrintStream out2 = new PrintStream(new FileOutputStream(file));
statistics.writeGNUPlot(out2,
xAxis, yAxis, getZ(),
gnuPlotDialog.getLineType(),
gnuPlotDialog.getGNUPlotCommands()+"\n"+
"set view "+rotX+","+rotZ+"", (String)null);
out2.close();
break;
default: throw new RuntimeException("Unknown FileFilter id: "+id + " (this cannot happen)!");
}
} catch (Exception ex) {
SwingTools.showErrorMessage("Cannot write to file '"+file+"'", ex);
}
}
}
};
private static final Color[] LINE_COLORS =
{ Color.black, Color.red, Color.blue, Color.gray, Color.orange, new Color(0,200,0), Color.pink, Color.yellow };
private static final Stroke[] LINE_STROKES =
{ new BasicStroke()
};
// private static final Stroke[] LINE_STROKES =
// { new BasicStroke(),
// new BasicStroke(1f, BasicStroke.CAP_SQUARE, BasicStroke.JOIN_MITER, 10f, new float[] {6f,4f}, 0f ),
// new BasicStroke(1f, BasicStroke.CAP_SQUARE, BasicStroke.JOIN_MITER, 10f, new float[] {6f,4f,2f,4f}, 0f ),
// new BasicStroke(1f, BasicStroke.CAP_SQUARE, BasicStroke.JOIN_MITER, 10f, new float[] {3f,3f}, 0f ),
// };
public static final LineStyle[] LINE_STYLES = new LineStyle[LINE_COLORS.length*LINE_STROKES.length];
static {
for (int i = 0; i < LINE_STROKES.length; i++) {
for (int j = 0; j < LINE_COLORS.length; j++) {
LINE_STYLES[i*LINE_COLORS.length + j] = new LineStyle(LINE_COLORS[j],
LINE_STROKES[i]);
}
}
}
public static class LineStyle {
private Color color;
private Stroke stroke;
private LineStyle(Color color, Stroke stroke) {
this.color = color;
this.stroke = stroke;
}
public void set(Graphics2D g) {
g.setColor(color);
g.setStroke(stroke);
}
}
private class Plot extends TreeSet {
private int styleIndex;
private Plot(int styleIndex) {
super(new Comparator() {
public int compare(Object o1, Object o2) {
PlotterPoint p1 = (PlotterPoint)o1;
PlotterPoint p2 = (PlotterPoint)o2;
double diffX = p1.getX() - p2.getX();
double diffY = p1.getY() - p2.getY();
double diff = Math.sqrt(diffX * diffX + diffY * diffY);
if (diff == 0.0d) return 0;
else return (diff < 0) ? -1 : 1;
//if ((diffX == 0.0d) && (diffY == 0.0d)) return 0;
//else return (dif < 0) ? -1 : 1;
}
});
this.styleIndex = styleIndex;
}
private LineStyle getLineStyle() {
return LINE_STYLES[styleIndex%LINE_STYLES.length];
}
}
public class PlotterPoint {
private String id = null;
private double x,y;
private double color;
public PlotterPoint(String id, double x, double y, double color) {
this.id = id;
this.x = x;
this.y = y;
this.color = color;
}
public String getId() { return id; }
public double getX() { return x; }
public double getY() { return y; }
public double getColor() { return color; }
public boolean contains(int x, int y) {
Point2D point = transform.transform(new Point2D.Double(this.x, this.y), null);
if ((Math.abs(point.getX() - x) < 2) && (Math.abs(point.getY() - y) < 2)) return true;
else return false;
}
public boolean isIn(double minX, double maxX, double minY, double maxY) {
return (x >= minX) && (x <= maxX) && (y >= minY) && (y <= maxY);
}
}
private class RotationListener extends MouseAdapter implements MouseMotionListener {
private Point dragStart;
private int rotXStart;
private int rotZStart;
public void mousePressed(MouseEvent e) {
dragStart = e.getPoint();
rotXStart = rotX;
rotZStart = rotZ;
}
public void mouseMoved(MouseEvent e) { }
public void mouseDragged(MouseEvent e) {
rotX = (rotXStart + (int)(dragStart.getY() - e.getY())) % 180;
if (rotX < 0) rotX += 180;
rotZ = (rotZStart + (int)(dragStart.getX()- e.getX())) % 360;
if (rotZ < 0) rotZ += 360;
statisticsUpdated(null);
}
}
private int rotX = 60, rotZ = 30;
private static final int[] TICS = {1,2,5};
private static final Font LABEL_FONT = new Font("Lucida Sans", Font.PLAIN, 11).deriveFont(AffineTransform.getScaleInstance(1, -1));
private static final Color GRID_COLOR = Color.lightGray;
private static final int MARGIN = 20;
private static final int LABEL_MARGIN_X = 15;
private static final int LABEL_MARGIN_Y = 50;
private Statistics statistics;
private List plots = new LinkedList();
private double minX, maxX, minY, maxY, minColor, maxColor, xTicSize, yTicSize;
private double drawMinX = Double.NEGATIVE_INFINITY;
private double drawMaxX = Double.POSITIVE_INFINITY;
private double drawMinY = Double.NEGATIVE_INFINITY;
private double drawMaxY = Double.POSITIVE_INFINITY;
private int xAxis = 0;
private int yAxis = -1;
private boolean[] columns;
private boolean hasChanged = false;
private java.awt.Image cachedImage = null;
private int drawAmount = 100;
private boolean plot3D = true;
private String currentToolTip = null;
private double toolTipX = 0.0d;
private double toolTipY = 0.0d;
private int dragX, dragY, dragWidth, dragHeight;
/** The transformation from pixel space into data space. */
private AffineTransform transform;
private GNUPlotDialog gnuPlotDialog = new GNUPlotDialog(this);
public Plotter(Statistics statistics) {
this.statistics = statistics;
statistics.addStatisticsListener(this);
columns = new boolean[statistics.getNumberOfColumns()];
prepareData();
setBackground(Color.white);
RotationListener listener = new RotationListener();
addMouseMotionListener(listener);
addMouseListener(listener);
}
public Statistics getStatistics() {
return statistics;
}
public void showGNUPlotDialog() {
gnuPlotDialog.show();
}
/** Sets the draw range in plotter (mouse) space. */
public void setDrawRange(double drawMinX, double drawMaxX, double drawMinY, double drawMaxY) {
if ((drawMinX == -1) || (drawMaxX == -1) || (drawMinY == -1) || (drawMaxY == -1)) {
this.drawMinX = Double.NEGATIVE_INFINITY;
this.drawMaxX = Double.POSITIVE_INFINITY;
this.drawMinY = Double.NEGATIVE_INFINITY;
this.drawMaxY = Double.POSITIVE_INFINITY;
} else {
try {
Point2D minPoint = transform.inverseTransform(new Point2D.Double(drawMinX, drawMinY), null);
Point2D maxPoint = transform.inverseTransform(new Point2D.Double(drawMaxX, drawMaxY), null);
this.drawMinX = minPoint.getX();
this.drawMaxX = maxPoint.getX();
this.drawMaxY = minPoint.getY();
this.drawMinY = maxPoint.getY();
} catch (java.awt.geom.NoninvertibleTransformException e) {
e.printStackTrace();
}
}
}
/** Sets the draw range in data space. */
public void setDrawRangeInDataSpace(double drawMinX, double drawMaxX, double drawMinY, double drawMaxY) {
if ((drawMinX == -1) || (drawMaxX == -1) || (drawMinY == -1) || (drawMaxY == -1)) {
this.drawMinX = Double.NEGATIVE_INFINITY;
this.drawMaxX = Double.POSITIVE_INFINITY;
this.drawMinY = Double.NEGATIVE_INFINITY;
this.drawMaxY = Double.POSITIVE_INFINITY;
} else {
this.drawMinX = drawMinX;
this.drawMaxX = drawMaxX;
this.drawMinY = drawMinY;
this.drawMaxY = drawMaxY;
}
}
public boolean is3DMode() {
return plot3D && (yAxis != -1);
}
private void prepareData() {
plots.clear();
maxX = maxY = maxColor = Double.NEGATIVE_INFINITY;
minX = minY = minColor = Double.POSITIVE_INFINITY;
for (int column = 0; column < columns.length; column++) {
if (columns[column]) {
SortedSet points = new Plot(column);
int drawEachPoint = 101 - drawAmount;
synchronized (statistics) {
Iterator i = statistics.iterator();
int pointNumber = 0;
while (i.hasNext()) {
StatisticsRow statRow = (StatisticsRow)i.next();
Object[] row = statRow.getRow();
if ((pointNumber++ % drawEachPoint) == 0) {
double x = Double.NaN;
double y = Double.NaN;
try {
if ((row[column] != null) && (row[xAxis] != null)) {
x = Double.parseDouble(row[xAxis].toString());
double color = Double.NaN;
if (yAxis != -1) {
y = Double.parseDouble(row[yAxis].toString());
} else {
y = Double.parseDouble(row[column].toString());
}
if ((!plot3D) && (column != -1)) {
color = Double.parseDouble(row[column].toString());
minColor = Math.min(minColor, color);
maxColor = Math.max(maxColor, color);
}
// if (!plot3D) {
// if (yAxis != -1)
// y = Double.parseDouble(row[yAxis].toString());
// if (column != -1) {
// color = Double.parseDouble(row[column].toString());
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -