package graph;
import java.awt.*;
import java.applet.*;
import java.util.*;
import java.lang.*;
import java.io.StreamTokenizer;
import java.io.InputStream;
import java.io.IOException;
import java.net.URL;
/*
**************************************************************************
**
** Class graph.Graph2D
**
**************************************************************************
** Modified from Leigh Brookshaw's graph classes by Michael Cross
** Copyright (C) 1995, 1996 Leigh Brookshaw
**
** 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., 675 Mass Ave, Cambridge, MA 02139, USA.
**************************************************************************
**
** class Graph2D extends Canvas
**
** The main entry point and interface for the 2D graphing package.
** This class keeps track of the DataSets and the Axes.
** It has the main drawing engine that positions axis etc.
**
*************************************************************************/
/**
* This is the main plotting class. It partitions the canvas to contain the
* specified axes with the remaining space taken with the plotting region.
* Axes are packed against the walls of the canvas. The paint and
* update methods of this class handle all the drawing operations of the
* graph. This means that independent components like Axis and DataSets must be
* registered with this class to be incorporated into the plot.
*
* @version LB1.12 MCC 3/19/97
* @author Leigh Brookshaw modified by Michael Cross
*/
public class Graph2D extends Canvas {
/*
** Default Background Color
*/
private Color DefaultBackground = null;
/*
*********************
**
** Protected Variables
**
*********************/
/**
* A vector list of All the axes attached
* @see Graph2d#attachAxis()
*/
protected Vector axis = new Vector(4);
/**
* A vector list of All the DataSets attached
* @see Graph2d#attachDataSet()
* @see DataSet
*/
protected Vector dataset = new Vector(10);
/**
* The markers that may have been loaded
* @see Graph2D#setMarkers()
*/
protected Markers markers = null;
/**
* The blinking "data loading" thread
* @see Graph2D#startedloading()
*/
protected LoadMessage load_thread = null;
/**
* The background color for the data window
*/
protected Color DataBackground = null;
/**************************************
**
** Protected Variables added by MCC
**
**************************************/
/*
** The offscreen graphics
*/
protected Graphics lg = null;
protected Image offScreenImage;
protected Graphics offScreenGraphics=null;
/*
** Size of graphics region
*/
protected Rectangle r_save=null;
/*
** Size of graphics region clipped by axes etc
*/
protected Rectangle r_g=null;
/*
** True if new graphics region
*/
protected boolean newRectangle = false;
/*
**********************
**
** Public Variables
**
*********************/
/**
* If this is greater than zero it means that
* data loading threads are active so the message "loading data"
* is flashed on the plot canvas. When it is back to zero the plot
* progresses normally
*/
public int loadingData = 0;
/**
* The width of the border at the top of the canvas. This allows
* slopover from axis labels, legends etc.
*/
public int borderTop = 20;
/**
* The width of the border at the bottom of the canvas. This allows
* slopover from axis labels, legends etc.
*/
public int borderBottom = 20;
/**
* The width of the border at the left of the canvas. This allows
* slopover from axis labels, legends etc.
*/
public int borderLeft = 20;
/**
* The width of the border at the right of the canvas. This allows
* slopover from axis labels, legends etc.
*/
public int borderRight = 20;
/**
* If set true a frame will be drawn around the data window.
* Any axes will overlay this frame.
*/
public boolean frame = true;
/**
* The color of the frame to be drawn
*/
public Color framecolor;
/**
* If set true (the default) a grid will be drawn over the data window.
* The grid will align with the major tic marks of the Innermost axes.
*/
public boolean drawgrid = true;
/**
* The color of the grid to be drawn
*/
public Color gridcolor = Color.pink;
/**
* If set true (the default) a grid line will be drawn
* across the data window
* at the zeros of the innermost axes.
*/
public boolean drawzero = true;
/**
* The color of the zero grid lines.
*/
public Color zerocolor = Color.orange;
/**
* The rectangle that the data will be plotted within. This is an output
* variable only.
*/
public Rectangle datarect = new Rectangle();
/**
* If set true (the default) the canvas will be set to the background
* color (erasing the plot) when the update method is called.
* This would only be changed for special effects.
*/
public boolean clearAll = true;
/**
* If set true (the default) everything associated with the plot
* will be drawn when the update method or paint method are called.
* Normally
* only modified for special effects
*/
public boolean paintAll = true;
/**
* Modify the position of the axis and the range of the axis so that
* the aspect ratio of the major tick marks are 1 and the plot is square
* on the screen
*/
public boolean square = false;
/**
* Text to be painted Last onto the Graph Canvas.
*/
public TextLine lastText = null;
/*
*******************
**
** Public Methods
**
*******************/
/**
* Load and Attach a DataSet from a File.
* The method loads the data into a DataSet class
* and attaches the class to the graph for plotting.
*
* The data is assumed to consist
* (at this stage) 2 ASCII columns of numbers x, y. As always blank lines
* are ignored and everything following # is ignored as a comment.
*
* @param file The URL of the data file to read.
* @return The DataSet constructed containing the data read.
*/
public DataSet loadFile( URL file) {
byte b[] = new byte[50];
int nbytes = 0;
int max = 100;
int inc = 100;
int n = 0;
double data[] = new double[max];
InputStream is = null;
boolean comment = false;
int c;
try {
is = file.openStream();
while( (c=is.read()) > -1 ) {
switch (c) {
case '#':
comment = true;
break;
case '\r': case '\n':
comment = false;
case ' ': case '\t':
if( nbytes > 0 ) {
String s = new String(b,0,0,nbytes);
data[n] = Double.valueOf(s).doubleValue();
n++;
if( n >= max ) {
max += inc;
double d[] = new double[max];
System.arraycopy(data, 0, d, 0, n);
data = d;
}
nbytes = 0;
}
break;
default:
if( !comment ) {
b[nbytes] = (byte)c;
nbytes++;
}
break;
}
}
if (is != null) is.close();
} catch(Exception e) {
System.out.println("Failed to load Data set from file ");
e.printStackTrace();
if (is != null) try { is.close(); } catch (Exception ev) { }
return null;
}
return loadDataSet(data,n/2);
}
/**
* Load and Attach a DataSet from an array.
* The method loads the data into a DataSet class
* and attaches the class to the graph for plotting.
*
* The data is assumed to be stored
* in the form x,y,x,y,x,y.... A local copy of the data is made.
*
* @param data The data to be loaded in the form x,y,x,y,...
* @param n The number of (x,y) data points. This means that the
* minimum length of the data array is 2*n.
* @return The DataSet constructed containing the data read.
*/
public DataSet loadDataSet( double data[], int n ) {
DataSet d;
try {
d = new DataSet(data, n);
dataset.addElement( d );
d.g2d = this;
}
catch (Exception e) {
System.out.println("Failed to load Data set ");
e.printStackTrace();
return null;
}
return d;
}
/**
* Attach a DataSet to the graph. By attaching the data set the class
* can draw the data through its paint method.
*/
public void attachDataSet( DataSet d ) {
if( d != null) {
dataset.addElement( d );
d.g2d = this;
}
}
/**
* Detach the DataSet from the class. Data associated with the DataSet
* will nolonger be plotted.
*
* @param d The DataSet to detach.
*/
public void detachDataSet( DataSet d ) {
if(d != null) {
if(d.xaxis != null) d.xaxis.detachDataSet(d);
if(d.yaxis != null) d.yaxis.detachDataSet(d);
dataset.removeElement(d);
}
}
/**
* Detach All the DataSets from the class.
*/
public void detachDataSets() {
DataSet d;
int i;
if(dataset == null | dataset.isEmpty() ) return;
for (i=0; i datarect (MCC 6/2/97)
if( !dataset.isEmpty() ) {
for (i=0; i 0) return;
if(load_thread != null) load_thread.end();
load_thread = null;
}
/**
* Change the message to be flashed on the canvas
* @param s String contining the new message.
* @see Graph2D#startedloading()
* @see Graph2D#finishedloading()
* @see LoadMessage
*/
public void loadmessage(String s) {
if(load_thread == null) load_thread = new LoadMessage(this);
load_thread.setMessage(s);
}
/*
*******************
**
** Protected Methods
**
*******************/
/**
* Check to see if any of axes range has changed. (MCC 3/19/97)
*/
protected boolean axesChanged() {
boolean changed = false;
Axis a;
for (int i=0; i yrange ) range = xrange;
else range = yrange;
for (int i=0; i dr.height) {
x += (dr.width-dr.height)/2.0;
width -= dr.width-dr.height;
} else {
y += (dr.height-dr.width)/2.0;
height -= dr.height-dr.width;
}
return new Rectangle(x,y,width,height);
}
/**
* Calculate the rectangle occupied by the data
*/
protected Rectangle getDataRectangle(Graphics g, Rectangle r) {
Axis a;
int waxis;
int x = r.x;
int y = r.y;
int width = r.width;
int height = r.height;
for (int i=0; i