import java.util.*;
import java.awt.*;
import java.applet.Applet;
class GraphSysGraphics
{
boolean is_offscreen;
Panel ownerpanel;
Dimension offscreensize;
Graphics offgraphics;
Image offscreen;
int ixmin;
int ixmax;
int iymin;
int iymax;
int ixpos;
int iypos;
double xmin;
double xmax;
double ymin;
double ymax;
double xpos;
double ypos;
final Color nodeColor = new Color(250, 220, 100);
final Color backColor = Color.white;
final Color errColor = Color.gray;
final Color functionColor = Color.blue;
final Color axesColor = Color.black;
final Color pathColor = Color.red;
final Color lastColor = new Color(0, 128, 0);
final Color llastColor = new Color(0, 0, 250);
final Color llineColor = new Color(0, 250, 250);
final Color lbackColor = new Color(40, 40, 40);
GraphSysGraphics(Panel ownerpanel_)
{
this.is_offscreen = false;
this.ownerpanel = ownerpanel_;
}
public void setScale(double xmin_,double ymin_,double xmax_,double ymax_)
{
xmin = xmin_;
xmax = xmax_;
ymin = ymin_;
ymax = ymax_;
}
public void setColor(int paletteIndex_)
{
if (paletteIndex_ == -1)
offgraphics.setColor(ownerpanel.getBackground());
else
if (paletteIndex_ == 0)
offgraphics.setColor(backColor);
else
if (paletteIndex_ == 1)
offgraphics.setColor(functionColor);
else
if (paletteIndex_ == 2)
offgraphics.setColor(axesColor);
else
if (paletteIndex_ == 3)
offgraphics.setColor(pathColor);
else
if (paletteIndex_ == 4)
offgraphics.setColor(lastColor);
else
if (paletteIndex_ == 11)
offgraphics.setColor(lbackColor);
else
if (paletteIndex_ == 12)
offgraphics.setColor(llastColor);
else
if (paletteIndex_ == 13)
offgraphics.setColor(llineColor);
else
offgraphics.setColor(errColor);
}
public int X2IX(double x_)
{
double xx = (x_ - xmin) / ( xmax - xmin ) * ( ixmax - ixmin ) + ixmin;
return (int) xx;
}
public int Y2IY(double y_)
{
double yy = (y_ - ymin) / ( ymax - ymin ) * ( iymax - iymin ) + iymin;
return (int) yy;
}
public double IX2X(int ix_)
{
double xx = ((double)(ix_ - ixmin)) / ((double)( ixmax - ixmin )) * ( xmax - xmin ) + xmin;
return xx;
}
public double IY2Y(int iy_)
{
double yy = ((double)(iy_ - iymin)) / ((double)( iymax - iymin )) * ( ymax - ymin ) + ymin;
return yy;
}
public void moveTo(double x_,double y_)
{
xpos = x_;
ypos = y_;
ixpos = X2IX( x_ );
iypos = Y2IY( y_ );
}
public void lineTo(double x_,double y_)
{
int new_ixpos = X2IX( x_ );
int new_iypos = Y2IY( y_ );
offgraphics.drawLine(ixpos,iypos,new_ixpos,new_iypos);
ixpos = new_ixpos;
iypos = new_iypos;
xpos = x_;
ypos = y_;
}
public void createDraw(Graphics g,int pal)
{
is_offscreen = true;
Dimension d = ownerpanel.size();
offscreen = ownerpanel.createImage(d.width, d.height);
offscreensize = d;
offgraphics = offscreen.getGraphics();
ixmin = 0;
iymin = d.height;
ixmax = d.width;
iymax = 0;
ixpos = 0;
iypos = 0;
xpos = 0;
ypos = 0;
xmin = 0;
xmax = 1;
ymin = 0;
ymax = 1;
clearDraw(g,pal);
}
public void clearDraw(Graphics g,int pal)
{
xpos = 0;
ypos = 0;
ixpos = 0;
iypos = 0;
setColor(pal);
Dimension d = ownerpanel.size();
offgraphics.fillRect(0, 0, d.width, d.height);
}
public void resetDraw(Graphics g,int pal)
{
clearDraw(g,pal);
}
public void openDraw(Graphics g,int pal)
{
if (!is_offscreen)
{
createDraw(g,pal);
}
}
public void closeDraw(Graphics g)
{
g.drawImage(offscreen, 0, 0, null);
}
}
class GraphLinePanel extends Panel {
GraphSys graph;
GraphSysGraphics gr;
GraphSysPanel panel;
int ix_last;
int ix_curr;
int iy_last;
int iy_curr;
boolean is_startpoint;
boolean is_lastpoint;
boolean is_reset;
GraphLinePanel(GraphSys graph, GraphSysPanel panel)
{
this.graph = graph;
this.panel = panel;
this.gr = new GraphSysGraphics(this);
this.is_reset = true;
this.is_startpoint = false;
this.is_lastpoint = false;
}
// public Dimension PreferredLayoutSize(Container parent)
// {
// return new Dimension(640,200);
// };
// public Dimension MinimumLayoutSize(Container parent)
// {
// return new Dimension(100,200);
// };
public void start()
{
// relaxer = new Thread(this);
// relaxer.start();
}
public void stop()
{
// relaxer.stop();
}
public synchronized void resetAction()
{
this.is_reset = true;
this.is_startpoint = false;
this.is_lastpoint = false;
}
public synchronized void update(Graphics g)
{
gr.openDraw(g,11);
drawLineGraph(g);
gr.closeDraw(g);
}
public synchronized void setPoint(double x_)
{
if (panel.is_drawnfunction)
{
is_startpoint = true;
ix_curr = gr.Y2IY(x_);
}
}
public synchronized boolean mouseDown(Event evt, int ix_, int iy_)
{
if (panel.is_drawnfunction)
{
resetScaleGraph();
setPoint(gr.IY2Y(iy_));
repaint();
}
return true;
}
public synchronized void drawLineSingleGraph(Graphics g,int ix, int pal)
{
double x = gr.IY2Y(ix);
double y = x;
gr.setColor(pal);
gr.moveTo( 0., x );
for (int i = 0; i < panel.n_iters; i++ )
{
y = panel.f(x,y,i);
gr.lineTo((double)i,x);
x = y;
}
}
public synchronized void resetScaleGraph()
{
if (panel.is_use_yscale)
{
gr.setScale( 0., panel.y_min, (double)panel.n_iters, panel.y_max );
}
else
{
gr.setScale( 0., panel.x_min, (double)panel.n_iters, panel.x_max );
};
}
public synchronized void drawLineGraph(Graphics g)
{
if (is_reset)
{
is_reset = false;
gr.resetDraw(g,11);
resetScaleGraph();
}
if (is_startpoint)
{
is_startpoint = false;
if (is_lastpoint)
{
drawLineSingleGraph(g,ix_last,12);
}
drawLineSingleGraph(g,ix_curr,13);
ix_last = ix_curr;
is_lastpoint = true;
}
}
synchronized void relax()
{
repaint();
}
public void run()
{
// relax();
// while (true)
// {
// try
// {
// Thread.sleep(100);
// }
// catch (InterruptedException e)
// {
// break;
// }
// }
}
}
class GraphSysPanel extends Panel implements Runnable {
GraphSys graph;
GraphSysGraphics gr;
GraphLinePanel lpanel;
Thread relaxer;
int n_pts;
int n_iters;
int n_comp;
int ix0_zoom;
int iy0_zoom;
int ix1_zoom;
int iy1_zoom;
int ix2_zoom;
int iy2_zoom;
int ix_last;
int ix_curr;
int iy_last;
int iy_curr;
int f_type;
boolean is_autoscale;
boolean is_use_yscale;
boolean was_startpoint;
boolean is_startpoint;
boolean is_lastpoint;
boolean is_reset;
boolean is_drawnfunction;
boolean is_singlemode;
boolean is_zooming;
boolean is_zoom_scale;
boolean is_dragging;
double x_min;
double x_max;
double y_min;
double y_max;
double x_corr;
double y_corr;
double x_add;
double y_add;
double y_alpha;
GraphSysPanel(GraphSys graph)
{
this.graph = graph;
this.gr = new GraphSysGraphics(this);
this.n_pts = 50;
this.n_iters = 20;
this.n_comp = 1;
this.is_reset = false;
this.was_startpoint = false;
this.is_startpoint = false;
this.is_drawnfunction = false;
this.is_use_yscale = false;
this.is_autoscale = true;
this.is_lastpoint = false;
this.is_singlemode = true;
this.is_zooming = false;
this.is_zoom_scale = false;
this.is_dragging = false;
this.x_min = 0;
this.x_max = 1;
this.y_min = 0;
this.y_max = 1;
this.y_alpha = 1;
this.x_corr = 1;
this.y_corr = 1;
this.x_add = 0;
this.y_add = 0;
this.f_type = 1;
}
public void run()
{
while (true)
{
relax();
try
{
Thread.sleep(100);
}
catch (InterruptedException e)
{
break;
}
}
}
synchronized void relax()
{
repaint();
}
public synchronized void resetAction()
{
this.is_reset = true;
this.was_startpoint = false;
this.is_startpoint = false;
this.is_lastpoint = false;
this.is_drawnfunction = false;
this.is_singlemode = true;
this.is_zooming = false;
this.is_dragging = false;
lpanel.resetAction();
}
public synchronized void drawFunction(Graphics g)
{
if (!is_drawnfunction && is_reset)
{
is_reset = false;
is_drawnfunction = true;
setFunctionRange();
gr.resetDraw(g,0);
double dx = ( x_max - x_min ) / n_pts;
gr.setScale( x_min, y_min, x_max, y_max );
gr.setColor(2);
gr.moveTo( x_min, x_min );
gr.lineTo( x_max, x_max );
gr.setColor(1);
gr.moveTo( x_min, f(x_min,x_min,0) );
double y = x_min;
for (double x = x_min; x <= x_max + dx ; x = x + dx )
{
y = f(x,y,0);
gr.lineTo( x, y );
}
}
}
public synchronized void setFunctionRange()
{
if (is_zoom_scale)
{
is_zoom_scale = false;
}
else
if (is_autoscale)
{
double dx = ( x_max - x_min ) / n_pts;
y_min = Math.min( x_min, x_max);
y_max = Math.max( x_min, x_max);
double y = x_min;
for (double x = x_min; x <= x_max + dx; x = x + dx )
{
y = f( x, y, 0);
if (y < y_min) y_min = y;
if (y > y_max) y_max = y;
}
graph.setDialogParms();
}
}
public synchronized void drawSinglePath(Graphics g,int ix, int pal)
{
double x = gr.IX2X(ix);
double y = x;
gr.setColor(pal);
gr.moveTo( x, y_min );
for (int i = 0; i < n_iters; i++ )
{
y = f(x,y,i);
gr.lineTo(x,y);
gr.lineTo(y,y);
x = y;
}
}
public synchronized void drawPointPath(Graphics g)
{
if (is_startpoint)
{
is_startpoint = false;
if (is_lastpoint)
{
drawSinglePath(g,ix_last,4);
}
is_lastpoint = true;
drawSinglePath(g,ix_curr,3);
ix_last = ix_curr;
}
}
public synchronized void update(Graphics g)
{
if (!is_dragging)
{
gr.openDraw(g,0);
drawFunction(g);
drawPointPath(g);
if (is_singlemode)
{
lpanel.repaint();
}
gr.closeDraw(g);
}
else
{
gr.openDraw(g,0);
gr.closeDraw(g);
{
gr.setColor(2);
int ix0 = Math.min(ix0_zoom,ix1_zoom);
int iy0 = Math.min(iy0_zoom,iy1_zoom);
int iw0 = Math.max(ix0_zoom,ix1_zoom) - ix0;
int ih0 = Math.max(iy0_zoom,iy1_zoom) - iy0;
g.drawRect(ix0,iy0,iw0,ih0);
}
}
}
public synchronized boolean mouseDown(Event evt, int ix_, int iy_)
{
if (is_zooming)
{
is_dragging = true;
ix0_zoom = ix_;
iy0_zoom = iy_;
ix1_zoom = ix_;
iy1_zoom = iy_;
ix2_zoom = ix_;
iy2_zoom = iy_;
}
else
if (is_drawnfunction)
{
was_startpoint = true;
is_startpoint = true;
ix_curr = ix_;
iy_curr = iy_;
lpanel.setPoint(gr.IX2X(ix_));
repaint();
}
return true;
}
public synchronized boolean mouseUp(Event evt, int ix_, int iy_)
{
if (is_zooming)
{
is_dragging = false;
is_zooming = false;
if (ix0_zoom > ix_)
{ ix1_zoom = ix0_zoom; ix0_zoom = ix_; }
else
{ ix1_zoom = ix_; }
if (iy0_zoom < iy_)
{ iy1_zoom = iy0_zoom; iy0_zoom = iy_; }
else
{ iy1_zoom = iy_; }
if ((ix1_zoom != ix0_zoom)
&& (iy1_zoom != iy0_zoom))
{
x_min = gr.IX2X(ix0_zoom);
x_max = gr.IX2X(ix1_zoom);
y_min = gr.IY2Y(iy0_zoom);
y_max = gr.IY2Y(iy1_zoom);
is_zoom_scale = true;
}
else
{
is_zoom_scale = false;
}
graph.setDialogParms();
resetAction();
lpanel.repaint();
}
return true;
}
public synchronized boolean mouseDrag(Event evt, int ix_, int iy_)
{
if (is_dragging)
{
ix2_zoom = ix1_zoom;
iy2_zoom = iy1_zoom;
ix1_zoom = ix_;
iy1_zoom = iy_;
repaint();
}
return true;
}
public void start()
{
relaxer = new Thread(this);
relaxer.start();
}
public void stop()
{
relaxer.stop();
}
public Choice getFunctionChoice()
{
Choice c = new Choice();
c.addItem("x(1-x)");
c.addItem("(1-x)");
c.addItem("16x^3-24x^2+9x");
c.addItem("-2x^3+3x^2-1/2x+1/4");
c.addItem("-2(x-1/2)^2+x");
c.addItem("1/(x+1)");
c.addItem("exp(-x)");
c.addItem("exp(-(5(x-1/2))^2)");
c.addItem("sin(pi x)");
c.addItem("x sin(4 pi x) + x");
return c;
}
public void setFunctionChoice(String s)
{
if ( "x(1-x)" == s)
f_type = 1;
else
if ( "(1-x)" == s)
f_type = 2;
else
if ( "16x^3-24x^2+9x" == s)
f_type = 3;
else
if ( "-2x^3+3x^2-1/2x+1/4" == s)
f_type = 4;
else
if ( "-2(x-1/2)^2+x" == s)
f_type = 5;
else
if ( "1/(x+1)" == s)
f_type = 10;
else
if ( "exp(-x)" == s)
f_type = 11;
else
if ( "exp(-(5(x-1/2))^2)" == s)
f_type = 12;
else
if ( "sin(pi x)" == s)
f_type = 15;
else
if ( "x sin(4 pi x) + x" == s)
f_type = 16;
else
f_type = 0;
}
public double g(double x_,double y_,int n_)
{
double x = x_corr * x_ + x_add;
if (f_type == 1)
return y_add + y_corr * ( x + y_alpha * ( - x +
( (1. - x) * x )));
else
if (f_type == 2)
return y_add + y_corr * ( x + y_alpha * ( - x +
( 1. - x )));
else
if (f_type == 3)
return y_add + y_corr * ( x + y_alpha * ( - x +
( 16 * x * x * x - 24 * x * x + 9 * x )));
else
if (f_type == 4)
return y_add + y_corr * ( x + y_alpha * ( - x +
( -2 * x * x * x + 3 * x * x - .5 * x + .25 )));
else
if (f_type == 5)
return y_add + y_corr * ( x + y_alpha * ( - x +
( x - (x - .5) * (x - .5) )));
else
if (f_type == 10)
return y_add + y_corr * ( x + y_alpha * ( - x +
( 1./(x + 1.) )));
else
if (f_type == 11)
return y_add + y_corr * ( x + y_alpha * ( - x +
( Math.exp(-x) )));
else
if (f_type == 12)
return y_add + y_corr * ( x + y_alpha * ( - x +
( Math.exp(-25*((x-.5)*(x-.5))) )));
else
if (f_type == 15)
return y_add + y_corr * ( x + y_alpha * ( - x +
( Math.sin(Math.PI * x) )));
else
if (f_type == 16)
return y_add + y_corr * ( x + y_alpha * ( - x +
( Math.sin(4 * Math.PI * x) * x + x )));
else
return 0.;
}
public double f(double x_,double y_,int n_)
{
double x = x_;
double y = y_;
for ( int j = 0; j < n_comp; j++ )
{
y = g( x, y, n_ ); x = y;
}
return y;
}
}
public class GraphSys extends Applet {
GraphSysPanel panel;
GraphLinePanel lpanel;
TextField s_x_min;
TextField s_x_max;
TextField s_y_min;
TextField s_y_max;
TextField s_y_corr;
TextField s_x_corr;
TextField s_y_add;
TextField s_x_add;
TextField s_y_alpha;
TextField s_n_comp;
TextField s_n_iters;
TextField s_n_pts;
static LayoutManager dcLayout = new FlowLayout(FlowLayout.CENTER, 10, 5);
public void init()
{
setLayout(new BorderLayout());
panel = new GraphSysPanel(this);
lpanel = new GraphLinePanel(this,panel);
panel.lpanel = lpanel;
Panel p3 = new Panel();
p3.add(new Checkbox("Scale"));
p3.add(new Checkbox("Y Vert."));
p3.add(new Label("xmin:"));
p3.add(s_x_min = new TextField(Double.toString(panel.x_min), 6));
p3.add(new Label("xmax:"));
p3.add(s_x_max = new TextField(Double.toString(panel.x_max), 6));
p3.add(new Label("ymin:"));
p3.add(s_y_min = new TextField(Double.toString(panel.y_min), 6));
p3.add(new Label("ymax:"));
p3.add(s_y_max = new TextField(Double.toString(panel.y_max), 6));
Panel p1 = new Panel();
p1.add(new Label("x,y corr:"));
p1.add(s_y_alpha = new TextField(Double.toString(panel.y_alpha), 6));
p1.add(new Label("xadd:"));
p1.add(s_x_add = new TextField(Double.toString(panel.x_add), 6));
p1.add(new Label("xmult:"));
p1.add(s_x_corr = new TextField(Double.toString(panel.x_corr), 6));
p1.add(new Label("yadd:"));
p1.add(s_y_add = new TextField(Double.toString(panel.y_add), 6));
p1.add(new Label("ymult:"));
p1.add(s_y_corr = new TextField(Double.toString(panel.y_corr), 6));
Panel p2 = new Panel();
p2.add(panel.getFunctionChoice());
p2.add(new Label("comp:"));
p2.add(s_n_comp = new TextField(Integer.toString(panel.n_comp), 4));
p2.add(new Label("iters:"));
p2.add(s_n_iters = new TextField(Integer.toString(panel.n_iters), 4));
p2.add(new Label("points:"));
p2.add(s_n_pts = new TextField(Integer.toString(panel.n_pts), 4));
p2.add(new Button("Zoom"));
p2.add(new Button("Full"));
p2.add(new Button("Reset"));
Panel p = new Panel();
p.setLayout(new BorderLayout());
p.add("South", p2);
p.add("East", p1);
p.add("North", p3);
add("North", p);
lpanel.setLayout(new FlowLayout(FlowLayout.CENTER, 100, 350));
add("East", lpanel);
add("Center", panel);
}
public void setDialogParms()
{
s_x_min.setText(Double.toString(panel.x_min));
s_x_max.setText(Double.toString(panel.x_max));
s_y_min.setText(Double.toString(panel.y_min));
s_y_max.setText(Double.toString(panel.y_max));
s_y_alpha.setText(Double.toString(panel.y_alpha));
s_x_corr.setText(Double.toString(panel.x_corr));
s_y_corr.setText(Double.toString(panel.y_corr));
s_x_add.setText( Double.toString(panel.x_add));
s_y_add.setText( Double.toString(panel.y_add));
s_n_comp.setText( Integer.toString(panel.n_comp));
s_n_iters.setText(Integer.toString(panel.n_iters));
s_n_pts.setText( Integer.toString(panel.n_pts));
}
public void getDialogParms()
{
panel.x_min = Double.valueOf(s_x_min.getText()).doubleValue();
panel.x_max = Double.valueOf(s_x_max.getText()).doubleValue();
panel.y_min = Double.valueOf(s_y_min.getText()).doubleValue();
panel.y_max = Double.valueOf(s_y_max.getText()).doubleValue();
panel.y_alpha = Double.valueOf(s_y_alpha.getText()).doubleValue();
panel.x_corr = Double.valueOf(s_x_corr.getText()).doubleValue();
panel.y_corr = Double.valueOf(s_y_corr.getText()).doubleValue();
panel.x_add = Double.valueOf(s_x_add.getText()).doubleValue();
panel.y_add = Double.valueOf(s_y_add.getText()).doubleValue();
panel.n_comp = Integer.parseInt(s_n_comp.getText());
panel.n_iters = Integer.parseInt(s_n_iters.getText());
panel.n_pts = Integer.parseInt(s_n_pts.getText());
}
public void start()
{
panel.start();
lpanel.start();
}
public void stop()
{
lpanel.stop();
panel.stop();
}
public boolean action(Event evt, Object arg) {
if (evt.target instanceof Choice)
{
panel.setFunctionChoice((String)arg);
}
else
if (arg instanceof Boolean)
{
if (((Checkbox)evt.target).getLabel().equals("Scale"))
{
panel.is_autoscale = ! ((Boolean)arg).booleanValue();
}
else
if (((Checkbox)evt.target).getLabel().equals("Y Vert."))
{
panel.is_use_yscale = ! ((Boolean)arg).booleanValue();
}
return true;
}
if ("Reset".equals(arg))
{
panel.is_zoom_scale = false;
getDialogParms();
panel.resetAction();
lpanel.repaint();
return true;
}
else
if ("Full".equals(arg))
{
panel.is_zoom_scale = false;
getDialogParms();
panel.x_min = 0;
panel.x_max = 1;
setDialogParms();
panel.resetAction();
lpanel.repaint();
return true;
}
else
if ("Zoom".equals(arg))
{
panel.is_zooming = true;
return true;
}
return false;
}
}