Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
JSci.awt.Graph2D.vm Maven / Gradle / Ivy
package ${package};
import java.awt.*;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.text.ParseException;
#if(!($api == "AWT"))import JSci.awt.*;#end
import JSci.maths.ExtraMath;
/**
* The ${className} superclass provides an abstract encapsulation of 2D graphs.
* There is some support for the handling of NaN values.
* @version 1.8
* @author Mark Hale
*/
public abstract class ${className} extends ${extendsClassName} implements GraphDataListener {
public final static int LINEAR_SCALE = 0;
public final static int LOG_SCALE = 1;
/**
* Data model.
*/
protected Graph2DModel model;
/**
* Origin.
*/
protected Point origin = new Point();
protected Graph2D.DataMarker dataMarker = Graph2D.DataMarker.NONE;
/**
* Series colors.
*/
protected Color seriesColor[]={Color.black,Color.blue,Color.green,Color.red,Color.yellow,Color.cyan,Color.lightGray,Color.magenta,Color.orange,Color.pink};
/**
* Axis numbering.
*/
protected boolean xNumbering = true, yNumbering = true;
protected NumberFormat xNumberFormat = new DecimalFormat("${numberFormat}");
protected NumberFormat yNumberFormat = new DecimalFormat("${numberFormat}");
protected boolean xAxisLine = true, yAxisLine = true;
protected boolean gridLines = false;
private final Color gridLineColor = Color.lightGray;
/**
* Axis scaling.
*/
private float xScale,yScale;
/**
* Axis scaling type.
*/
private int xScaleType, yScaleType;
/**
* Axis extrema.
*/
private float minX, minY, maxX, maxY;
private float scaledMinX, scaledMinY, scaledMaxX, scaledMaxY;
private boolean autoXExtrema=true, autoYExtrema=true;
private float xGrowth, yGrowth;
/**
* Axis numbering increment.
*/
private final float xIncPixels = 40.0f;
private final float yIncPixels = 40.0f;
private float xInc,yInc;
private boolean autoXInc=true,autoYInc=true;
/**
* Padding.
*/
protected final int scalePad=5;
protected final int axisPad=25;
protected int leftAxisPad;
/**
* Constructs a 2D graph.
*/
public ${className}(Graph2DModel gm) {
model=gm;
model.addGraphDataListener(this);
dataChanged(new GraphDataEvent(model));
}
/**
* Sets the data plotted by this graph to the specified data.
*/
public final void setModel(Graph2DModel gm) {
model.removeGraphDataListener(this);
model=gm;
model.addGraphDataListener(this);
dataChanged(new GraphDataEvent(model));
}
/**
* Returns the model used by this graph.
*/
public final Graph2DModel getModel() {
return model;
}
/**
* Implementation of GraphDataListener.
* Supports {@link JSci.awt.GraphDataEvent#isIncremental() incremental} updates.
* Application code will not use this method explicitly, it is used internally.
*/
public void dataChanged(GraphDataEvent e) {
if(e.isIncremental()) {
Graphics g = getOffscreenGraphics();
if(g == null)
return;
final int series = e.getSeries();
if(series == GraphDataEvent.ALL_SERIES) {
model.firstSeries();
int n = 0;
do {
final int i = model.seriesLength() - 1;
incrementalRescale(model.getXCoord(i), model.getYCoord(i));
g.setColor(seriesColor[n]);
drawDataPoint(g, i);
n++;
} while(model.nextSeries());
} else {
model.firstSeries();
int n=0;
for(; nseriesColor.length) {
Color tmp[]=seriesColor;
seriesColor=new Color[n];
System.arraycopy(tmp,0,seriesColor,0,tmp.length);
for(int i=tmp.length; i maxX)
max = autoXExtrema ? Math.max(x, maxX+xGrowth) : maxX+xGrowth;
else
max = maxX;
rescaleX(min, max);
if(y < minY)
min = autoYExtrema ? Math.min(y, minY-yGrowth) : minY-yGrowth;
else
min = minY;
if(y > maxY)
max = autoYExtrema ? Math.max(y, maxY+yGrowth) : maxY+yGrowth;
else
max = maxY;
rescaleY(min, max);
}
/**
* Turns axis numbering on/off.
* Default is on.
*/
public final void setNumbering(boolean flag) {
setNumbering(flag, flag);
}
public final void setNumbering(boolean xFlag, boolean yFlag) {
xNumbering = xFlag;
yNumbering = yFlag;
leftAxisPad = axisPad;
if(yNumbering && getFont() != null) {
// adjust leftAxisPad to accomodate y-axis numbering
final FontMetrics metrics = getFontMetrics(getFont());
final int maxYNumLen = metrics.stringWidth(yNumberFormat.format(maxY));
final int minYNumLen = metrics.stringWidth(yNumberFormat.format(minY));
int yNumPad = Math.max(minYNumLen, maxYNumLen);
if(scaledMinX<0.0f) {
final int negXLen = (int)((Math.max(getSize().width,getMinimumSize().width)-2*(axisPad+scalePad))*scaledMinX/(scaledMinX-scaledMaxX));
yNumPad = Math.max(yNumPad-negXLen, 0);
}
leftAxisPad += yNumPad;
}
rescale();
}
public void addNotify() {
super.addNotify();
// getFont() is now not null
// recalculate padding
setNumbering(xNumbering, yNumbering);
}
/**
* Sets the display format used for axis numbering.
* Convenience method.
* @see #setXNumberFormat(NumberFormat)
* @see #setYNumberFormat(NumberFormat)
*/
public final void setNumberFormat(NumberFormat format) {
xNumberFormat = format;
yNumberFormat = format;
setNumbering(xNumbering, yNumbering);
}
/**
* Sets the display format used for x-axis numbering.
*/
public final void setXNumberFormat(NumberFormat format) {
xNumberFormat = format;
setNumbering(xNumbering, yNumbering);
}
/**
* Sets the display format used for y-axis numbering.
*/
public final void setYNumberFormat(NumberFormat format) {
yNumberFormat = format;
setNumbering(xNumbering, yNumbering);
}
/**
* Turns the axis lines on/off.
*/
public final void setAxisLines(boolean xFlag, boolean yFlag) {
xAxisLine = xFlag;
yAxisLine = yFlag;
redraw();
}
/**
* Turns grid lines on/off.
* Default is off.
*/
public final void setGridLines(boolean flag) {
gridLines = flag;
redraw();
}
/**
* Sets the x-axis scale type.
* @param t a _SCALE constant.
*/
public final void setXScale(int t) {
if(xScaleType != t) {
xScaleType = t;
dataChanged(new GraphDataEvent(model));
}
}
/**
* Sets the y-axis scale type.
* @param t a _SCALE constant.
*/
public final void setYScale(int t) {
if(yScaleType != t) {
yScaleType = t;
dataChanged(new GraphDataEvent(model));
}
}
/**
* Sets the x-axis numbering increment.
* @param dx use 0.0f for auto-adjusting (default).
*/
public final void setXIncrement(float dx) {
if(dx < 0.0f) {
throw new IllegalArgumentException("Increment should be positive.");
} else if(dx == 0.0f) {
if(!autoXInc) {
autoXInc = true;
rescale();
}
} else {
autoXInc = false;
if(dx != xInc) {
xInc = dx;
rescale();
}
}
}
/**
* Returns the x-axis numbering increment.
*/
public final float getXIncrement() {
return xInc;
}
/**
* Sets the y-axis numbering increment.
* @param dy use 0.0f for auto-adjusting (default).
*/
public final void setYIncrement(float dy) {
if(dy < 0.0f) {
throw new IllegalArgumentException("Increment should be positive.");
} else if(dy == 0.0f) {
if(!autoYInc) {
autoYInc = true;
rescale();
}
} else {
autoYInc = false;
if(dy != yInc) {
yInc = dy;
rescale();
}
}
}
/**
* Returns the y-axis numbering increment.
*/
public final float getYIncrement() {
return yInc;
}
/**
* Sets the minimum/maximum values on the x-axis.
* Set both min and max to 0.0f for auto-adjusting (default).
*/
public final void setXExtrema(float min, float max) {
if(min==0.0f && max==0.0f) {
autoXExtrema=true;
// determine min and max from model
min=Float.POSITIVE_INFINITY;
max=Float.NEGATIVE_INFINITY;
float tmp;
model.firstSeries();
do {
for(int i=0;i 0.0f;
if(autoYInc) {
yInc = (float) ExtraMath.round((double)yIncPixels/(double)yScale, 1);
if(yInc == 0.0f)
yInc = Float.MIN_VALUE;
}
//assert yInc > 0.0f;
origin.x=leftAxisPad-Math.round(scaledMinX*xScale);
origin.y=thisHeight-axisPad+Math.round(scaledMinY*yScale);
redraw();
}
/**
* Converts a data point to screen coordinates.
*/
protected final Point dataToScreen(float x,float y) {
if(xScaleType == LOG_SCALE)
x = (float) Math.log(x);
if(yScaleType == LOG_SCALE)
y = (float) Math.log(y);
return scaledDataToScreen(x, y);
}
/**
* Converts a scaled data point to screen coordinates.
*/
protected final Point scaledDataToScreen(float x, float y) {
return new Point(origin.x+Math.round(xScale*x), origin.y-Math.round(yScale*y));
}
/**
* Converts a screen point to data coordinates.
*/
protected final Point2D.Float screenToData(Point p) {
double x = (double)(p.x-origin.x) / (double)xScale;
double y = (double)(origin.y-p.y) / (double)yScale;
if(xScaleType == LOG_SCALE)
x = Math.exp(x);
if(yScaleType == LOG_SCALE)
y = Math.exp(y);
return new Point2D.Float((float)x, (float)y);
}
/**
* Draws the graph axes.
*/
protected final void drawAxes(Graphics g) {
#if($api == "Swing")
// Swing optimised
final int width = getWidth();
final int height = getHeight();
#else
final Dimension size = getSize();
final int width = size.width;
final int height = size.height;
#end
g.setColor(getForeground());
// grid lines and numbering
if(gridLines || xNumbering) {
// x-axis numbering and vertical grid lines
float xAxisY;
if(scaledMinY > 0.0f)
xAxisY = scaledMinY;
else if(scaledMaxY < 0.0f)
xAxisY = scaledMaxY;
else
xAxisY = 0.0f;
for(double x=(scaledMinX>0.0f)?scaledMinX:xInc; x<=scaledMaxX; x+=xInc) {
Point p=scaledDataToScreen((float)x, xAxisY);
if(gridLines) {
g.setColor(gridLineColor);
g.drawLine(p.x, axisPad-scalePad, p.x, height-(axisPad-scalePad));
g.setColor(getForeground());
}
if(xNumbering) {
drawXLabel(g, x, p);
}
}
for(double x=-xInc; x>=scaledMinX; x-=xInc) {
Point p=scaledDataToScreen((float)x, xAxisY);
if(gridLines) {
g.setColor(gridLineColor);
g.drawLine(p.x, axisPad-scalePad, p.x, height-(axisPad-scalePad));
g.setColor(getForeground());
}
if(xNumbering) {
drawXLabel(g, x, p);
}
}
}
if(gridLines || yNumbering) {
// y-axis numbering and horizontal grid lines
float yAxisX;
if(scaledMinX > 0.0f)
yAxisX = scaledMinX;
else if(scaledMaxX < 0.0f)
yAxisX = scaledMaxX;
else
yAxisX = 0.0f;
for(double y=(scaledMinY>0.0f)?scaledMinY:yInc; y<=scaledMaxY; y+=yInc) {
Point p=scaledDataToScreen(yAxisX, (float)y);
if(gridLines) {
g.setColor(gridLineColor);
g.drawLine(leftAxisPad-scalePad, p.y, width-(axisPad-scalePad), p.y);
g.setColor(getForeground());
}
if(yNumbering) {
drawYLabel(g, y, p);
}
}
for(double y=-yInc; y>=scaledMinY; y-=yInc) {
Point p=scaledDataToScreen(yAxisX, (float)y);
if(gridLines) {
g.setColor(gridLineColor);
g.drawLine(leftAxisPad-scalePad, p.y, width-(axisPad-scalePad), p.y);
g.setColor(getForeground());
}
if(yNumbering) {
drawYLabel(g, y, p);
}
}
}
// axis lines
if(xAxisLine) {
// horizontal axis
if(scaledMinY > 0.0f) {
// draw at bottom
g.drawLine(leftAxisPad-scalePad, height-axisPad, width-(axisPad-scalePad), height-axisPad);
} else if(scaledMaxY < 0.0f) {
// draw at top
g.drawLine(leftAxisPad-scalePad, axisPad, width-(axisPad-scalePad), axisPad);
} else {
// draw through y origin
g.drawLine(leftAxisPad-scalePad, origin.y, width-(axisPad-scalePad), origin.y);
}
}
if(yAxisLine) {
// vertical axis
if(scaledMinX > 0.0f) {
// draw at left
g.drawLine(leftAxisPad, axisPad-scalePad, leftAxisPad, height-(axisPad-scalePad));
} else if(scaledMaxX < 0.0f) {
// draw at right
g.drawLine(width-axisPad, axisPad-scalePad, width-axisPad, height-(axisPad-scalePad));
} else {
// draw through x origin
g.drawLine(origin.x, axisPad-scalePad, origin.x, height-(axisPad-scalePad));
}
}
}
protected void drawXLabel(Graphics g, double x, Point p) {
double scaledX;
if(xScaleType == LOG_SCALE)
scaledX = Math.exp(x);
else
scaledX = x;
String str = xNumberFormat.format(scaledX);
FontMetrics metrics=g.getFontMetrics();
int strWidth=metrics.stringWidth(str);
int strHeight=metrics.getHeight();
g.drawLine(p.x,p.y,p.x,p.y+5);
g.drawString(str,p.x-strWidth/2,p.y+5+strHeight);
}
protected void drawYLabel(Graphics g, double y, Point p) {
double scaledY;
if(yScaleType == LOG_SCALE)
scaledY = Math.exp(y);
else
scaledY = y;
String str = yNumberFormat.format(scaledY);
FontMetrics metrics=g.getFontMetrics();
int strWidth=metrics.stringWidth(str);
int strHeight=metrics.getHeight();
g.drawLine(p.x,p.y,p.x-5,p.y);
g.drawString(str,p.x-8-strWidth,p.y+strHeight/3);
}
/**
* Draws the graph data.
* Override this method to change how the graph data is plotted.
*/
protected void drawData(Graphics g) {
// points
model.firstSeries();
g.setColor(seriesColor[0]);
int i;
for(i=0; i