/*
* DrawingRegion.java
*
* Created on 4. juli 2002, 15:24
*/
package org.joone.edit;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.util.*;
import org.joone.log.*;
/**
* @author Jan Erik Garshol, jangar@idi.ntnu.no
* @version 0.1 beta
*
* This object plot what it's told to plott by the assigned SharedBuffer object.
* (Adapted to Joone by P. Marrone pmarrone@users.sourceforge.net)
*/
public class DrawingRegion extends java.awt.Canvas implements java.lang.Runnable{
/**
* Logger
* */
private static final ILogger log = LoggerFactory.getLogger(DrawingRegion.class);
private static final int ERROR = 0; // error[i][ERROR] --> returns the error value, Y axis value
private static final int CYCLE = 1; // error[i][CYCLE] --> returns the cycle value, X axis value
private int X_ENHETER = 0; // Number of labels on the x-axis
private double X_INTERVALL = 0; // Interval between each label on the x-axis
private int Y_ENHETER = 10; // Number of labels on the y-axis
private int MAX_X; // Calculated due to myDim max absolute value on x-axis
private int MAX_Y; // Calculated due to myDim max absolute value p� y-axis
// Data buffers
private double[] grafData; // a local copy of the sharedBuffer
private Hashtable grafDataMul; // a local copy of the sheardBuffers for the multiple plotting
private SharedBuffer grafBuffer;
private Hashtable buffers;
private Thread myThread;
private java.awt.Dimension myDim;
private int currentCycle = 0;
private boolean keepPlotting = true;
private java.awt.Color original;
private java.awt.Color background;
private java.awt.Color gray;
private int max_x_value;
private double max_y_value;
private double stepY;
private double stepX;
private int X = 45; // Space between the frame border and the y-axis of the graph
private int Y = 25; // Space between the frame border and the x-axis of the graph
private BufferedImage bi;
private Graphics big;
private static final long serialVersionUID = -1681735154132358889L;
/**
* Creates a drawing area, with a interval between each label on
* the x-axis calculated by the int xSpredning. Use number of trainig cycles
* as a roule of thumb.
*/
public DrawingRegion(java.awt.Dimension dimension, double ySpredning, int xSpredning) {
if ( dimension.width < X && dimension.height < Y)
log.warn( "Drawing area too small, use min " + X + " * " + Y + " pixels.");
else if (xSpredning < 2)
log.warn("X Spredning must be > 1");
else if (ySpredning <= 0.0)
log.warn("Y Spredning must be > 0.0");
else {
myDim = dimension;
max_x_value = xSpredning;
max_y_value = ySpredning;
setSize(myDim);
getXEnhet(xSpredning);
constructorInit();
}
}
public DrawingRegion(java.awt.Dimension dimension, int xSpredning) {
this(dimension, 1.0, xSpredning);
}
/**
* Creates a drowing area of 550x350, with a interval between each label on
* the x-axis calculated by the int xSpredning. Use number of trainig cycles
* as a roule of thumb.
*/
public DrawingRegion(int xSpredning) {
this(new java.awt.Dimension(550,350),xSpredning);
}
/**
* Initialize the different values describe above and starts the shared
* buffer.
*/
private void constructorInit() {
buffers = new Hashtable();
// grafBuffer = new SharedBuffer();
grafData = new double[max_x_value + 1];
grafDataMul = new Hashtable();
original = new java.awt.Color(0,0,0);
background = new java.awt.Color(200,200,200);
gray = new java.awt.Color(160,160,160);
setBackground(background);
setDimensions(myDim);
start();
}
private void setDimensions(java.awt.Dimension dimension) {
double tempX, tempY;
myDim = dimension;
tempX = (myDim.width - (2 * X));
tempY = (myDim.height - (2 * Y));
MAX_X = new Double(tempX).intValue();
MAX_Y = new Double(tempY).intValue();
stepX = MAX_X / (double)max_x_value;
stepY = MAX_Y / max_y_value;
}
/**
* Calculate a sensible interval between each label on the x-axis based on
* a drowing area of 650x650, with a given int xSpredning.
*/
private void getXEnhet(int xSpredning) {
X_INTERVALL = xSpredning / 5;
X_ENHETER = new Double(xSpredning/X_INTERVALL).intValue();
}
/**
* This will stop the object and end the thread.
*/
public void stopPloting() {
keepPlotting = false;
}
/**
* Return the sharedBuffer object for a mono-serie plotting, have to be called by the Producer object.
* @return a SharedBuffer not linked to a particular ChartingHandle
*/
public SharedBuffer getBuffer() {
if (grafBuffer == null)
grafBuffer = new SharedBuffer();
return grafBuffer;
}
/**
* Return the sharedBuffer object for a multi-serie plotting, have to be called by the Producer object.
* @return a SharedBuffer linked to the passed ChartingHandle
*/
public SharedBuffer getBuffer(ChartingHandle handle) {
SharedBuffer sb = (SharedBuffer)buffers.get(handle);
if (sb == null) {
sb = new SharedBuffer();
sb.setHandle(handle);
buffers.put(handle, sb);
}
return sb;
}
/**
* Is called by the System, to paint the drawing area. Do not use this!
*/
public void paint(Graphics g) {
update(g);
}
public void update(Graphics g) {
java.awt.Dimension dim = getSize();
if ((bi == null) || (bi.getWidth() != dim.width) || (bi.getHeight() != dim.height)) {
bi = new BufferedImage(dim.width, dim.height, BufferedImage.TYPE_INT_RGB);
big = bi.getGraphics();
}
big.setColor(background);
big.fillRect(0,0, dim.width, dim.height);
if ((myDim.height != dim.height)
|| (myDim.width != dim.width)) {
setDimensions(dim);
}
initDrawingRegion(big);
if (grafBuffer != null)
plot(big, grafData, new Color(0,0,200));
for (Enumeration k=buffers.keys(); k.hasMoreElements();) {
ChartingHandle handle = (ChartingHandle)k.nextElement();
double[] data = (double[])grafDataMul.get(handle);
Color col = new Color(handle.getRedColor(), handle.getGreenColor(), handle.getBlueColor());
if (data != null)
plot(big, data, col);
}
big.setColor(original);
// Plots last cycle value
int plassering = new Double(myDim.width*0.5).intValue();
big.drawString("Current cycle is "+currentCycle, plassering, 70);
g.drawImage(bi,0,0,this);
}
/**
* Plots the x and Y axis, the labels and the grid.
*/
private void initDrawingRegion(Graphics g) {
g.setColor(original);
g.drawRect(0, 0, myDim.width-1, myDim.height-1); // Paints a border
g.drawString("Y", 20, 12); // Paints the y-axis
plotLine(g,0,0,0,max_y_value);
g.drawString("X", myDim.width-20, myDim.height-20); // Paints tha x-axis
plotLine(g,0,0,max_x_value,0);
g.drawString("0,0", 10, myDim.height-10); // Paints origo
// Paints numbers and intervals on x-axis (cycle)
int xx = new Float(max_x_value/X_ENHETER).intValue();
int x = 0;
String text = new Integer(new Double(X_INTERVALL).intValue()).toString();
for (int i = 1; i < X_ENHETER+1;) {
x = x + xx;
g.drawString(text, getAbsX(x)-15, myDim.height-2);
plotLine(g, x, 5/stepY, x, -5/stepY);
plotXGridLine(g, x);
text = new Integer(new Double(X_INTERVALL * ++i).intValue()).toString();
}
// Paints numbers and intervals on y-axis (error)
Y_ENHETER = 10; // Splits the y-axis in 10 egual parts
double yy = max_y_value/Y_ENHETER;
double y = 0;
// The numbers are rounded to the min needed decimals
int prc = getPrecision(max_y_value);
int exp = (int) Math.pow(10.0, prc);
//int exp = new Double(Math.pow(10.0, (double)prc)).intValue();
for (int i = 1; i < Y_ENHETER+1; i++) {
y = y + yy;
double valY = (max_y_value/Y_ENHETER) * (Y_ENHETER+1 - i);
int truncY = new Double(valY * exp).intValue();
valY = new Double(truncY).doubleValue() / exp;
text = new Double(valY).toString();
plotLine(g, new Double(-5/stepX).intValue(), y, new Double(5/stepX).intValue(), y);
plotYGridLine(g, y);
g.drawString(text, 2, getAbsY(max_y_value - y + yy)+2);
}
}
private int getPrecision(double xMax) {
int div = new Double(10.0/xMax).intValue();
if (div == 0) div = 1;
double log10 = Math.log(div) / Math.log(10);
int dec = new Double(log10).intValue()+2;
return dec;
}
/**
* Plots a line from (start_x,start_y) to (slutt_x,slutt_y)
*/
private void plotLine(Graphics g, int start_x, double start_y, int slutt_x, double slutt_y) {
int x1 = getAbsX(start_x);
int y1 = getAbsY(start_y);
int x2 = getAbsX(slutt_x);
int y2 = getAbsY(slutt_y);
g.drawLine(x1, y1, x2, y2);
}
private int getAbsX(int x) {
int x1 = new Double(x * stepX).intValue();
return x1+X;
}
private int getAbsY(double y) {
int y1 = new Double(y * stepY).intValue();
return myDim.height-Y-y1;
}
/**
* Plots the y-axis grid lines
*/
private void plotYGridLine(Graphics g, double y) {
g.setColor(gray);
plotLine(g,0,y,max_x_value,y);
g.setColor(original);
}
/**
* Plots the x-axis grid lines
*/
private void plotXGridLine(Graphics g, int x) {
g.setColor(gray);
plotLine(g,x,0,x,max_y_value);
g.setColor(original);
}
/**
* Plots the graph from the local absolut grafData[]
*/
private void plot(Graphics g, double[] grafData, Color col) {
boolean firstPoint = false;
g.setColor(col);
for (int i = 2; i <= currentCycle; i++) {
if ((grafData[i-1] != 0) || (firstPoint)) { // Does not plot the initial zero values
plotLine(g, i - 1, grafData[i-1], i, grafData[i]);
firstPoint = true;
}
}
}
/**
* Starts the thread
*/
public void start() { //implements java.lang.Runnable
if (myThread == null) {
myThread = new Thread(this, "DrawingRegion");
try { myThread.start(); }
catch (Exception e) {
String msg = "DrawingRegion:start() : " + e.getMessage();
log.fatal(msg, e);
System.exit(1);
}
}
}
/**
* Gets the new data from the producer and store them to grafData[].
*/
public void run() { //implements java.lang.Runnable
int i;
int imax;
i = 0;
while (keepPlotting) {
if (grafBuffer != null)
i = getData(null);
imax = i;
for (Enumeration k=buffers.keys(); k.hasMoreElements();) {
ChartingHandle handle = (ChartingHandle)k.nextElement();
i = getData(handle);
if (i > imax)
imax = i;
}
if ( imax > 0 ) {
// There have been updates on the screen, calls repaint()
currentCycle = imax;
repaint();
}
try {
Thread.sleep(500);
} catch (InterruptedException ie) { }
}
myThread = null; // Stop running
}
private int getData(ChartingHandle handle) {
double[][] error;
double[] data;
if (handle == null) {
error = grafBuffer.get(); // get the new data
data = grafData;
}
else {
SharedBuffer buff = (SharedBuffer)buffers.get(handle);
error = buff.getNoWait();
data = (double[])grafDataMul.get(handle);
if (data == null) {
data = new double[max_x_value+1];
grafDataMul.put(handle, data);
}
}
int cycle = 0;
if (error != null)
for (int i = 0; i < error.length; i++) {
int x = new Double(error[i][CYCLE]).intValue();
if ((x == -1) || (x >= data.length)) { // reached the end
break;
}
data[x] = error[i][ERROR];
cycle = x;
}
return cycle;
}
/** Getter for property max_x_value.
* @return Value of property max_x_value.
*/
public int getMaxXvalue() {
return max_x_value;
}
/** Setter for property max_x_value.
* @param max_x_value New value of property max_x_value.
*/
public void setMaxXvalue(int max_x_value) {
this.max_x_value = max_x_value;
copyBuffer(max_x_value);
getXEnhet(max_x_value);
setDimensions(myDim);
repaint();
}
/** Getter for property max_y_value.
* @return Value of property max_y_value.
*/
public double getMaxYvalue() {
return max_y_value;
}
/** Setter for property max_y_value.
* @param max_y_value New value of property max_y_value.
*/
public void setMaxYvalue(double max_y_value) {
this.max_y_value = max_y_value;
setDimensions(myDim);
repaint();
}
private void copyBuffer(int newSize) {
double[] newBuff = new double[newSize+1];
int xMax = newSize;
if (xMax > grafData.length)
xMax = grafData.length;
for (int i=0; i < xMax; ++i) {
newBuff[i] = grafData[i];
}
if (currentCycle >= xMax)
currentCycle = xMax - 1;
grafData = newBuff;
}
protected void removeHandle(ChartingHandle handle) {
if (buffers != null)
buffers.remove(handle);
if (grafDataMul != null)
grafDataMul.remove(handle);
}
}
Ads help maintain this website.