The demonstration program FractalsApplet,
shown below, displays a fractal pattern generated by an algorithm
selected from a JList.
The user can drag the cursor across a given area to obtain a rectangle
that will be expanded over the full display panel area. This lets
the user see the repetition of the patterns at finer and finer scaling,
thus illustrating a leading attribute of fractal behavior.
The routines involved in the applet are listed below. The MousePlotPanel
subclass of PlotPanel
adds the zoom in capability with the mouse. The fractal algorithms
are implemented in DrawFunction
subclasses and their code is given on the next
page. A graphics context is passed to their draw()
method and the drawLine()
method in the Graphics class is used to draw each point in the fractal
pattern.
In a later page, we discuss a
technique in which pixels of an image are modified to create the
pattern and then the image is drawn. This provides faster performance.
Demonstration:
Fractal Generation Display using Drawing Methods.
FractalsApplet.java
- Display a fractal algorithm selected from a list. The
X,Y text fields display the dimensions of the area in
which the fractal generation occurs. The user can drag
the cursor to create a rectangle whose position and dimensions
are used to generate a new fractal pattern. The new dimensions
are displayed in the X,Y text fields.
The P0, P1 text fields are the parameter settings for
the particular algorithm. One or more of these are inactive
depending on the algorithm.
The
Reset button returns the dimenstions to the default settings
and redraws the pattern using the current algorithm.
+ New classes:
FractalController.java
- interface with three methods used to pass information
between the parent class and FractalPanel: setFractalParameters(),
getFractalParameters() and public void setBusy().
FractalsApplet implements this interface.
MousePlotPanel.java
- This abstract subclass of PlotPanel adds the capability
for the user to drag open a rectangle on the plot. It
implements the MouseHandler interface. The subclass must
override the method handleMouseInfo(), which is invoked
after the cursor is dragged and the button released.
MouseHandler.java
- interface with five methods to provide responses to
mouse events on a plot. It is implemented by the MousePlotPanel
FractalPanel.java
- This class overrides the abstract method handleMouseInfo()
in MousePlotPanel. The method obtains the new dimenstions
from the rectangle created by dragging the cursor. It
invokes getScaling() to reset the scaling along the axes,
it calls back to the parent class (which implements the
FractalController interface) to send the new dimensions,
tells the parent that it is busy with the fractal generation,
and invokes repaint().
In
paintContents() it uses the DrawFunction object corresponding
to the selected algorithm to draw the fractal pattern.
After the drawing is finished, it calls back the parent
class, using the FractalContrller setBusy() method, to
announce that it is no longer busy.
A
reference to the parent FractalController is passed in
the constructor, along with the default dimensions and
the DrawFunction object.
The
setAlgorithm (DrawFunction drawFractal) method is used
to change the current algorithm.
The
setRange() method allows the parent to change the dimensions
of the plot.
DrawBifurcation.java
-
DrawFunction subclass that draws fractal pattern with
the Bifurcation algorithm.
DrawJuliaSet.java
-
DrawFunction subclass that draws fractal pattern with
the Julia Set algorithm.
DrawJuliaSetNewton.java
-
DrawFunction subclass that draws fractal pattern with
the Julia Set via Newton's method algorithm.
DrawMandlebrot.java
-
DrawFunction subclass that draws fractal pattern with
the Mandlebrot algorithm.
+ Previous classes:
Chapter
4:Tech: Complex.java
Chapter
6:Tech: PlotPanel.java,
PlotFormat.java
Chapter
6:Tech:
DrawFunction.java
|
// Begin from StarterJApplet11
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.event.*;
/**
* Demonstrate various fractal algorithms.
User selects
* from a list of algorithms. Graphical
output of the
* algorithm is displayed within a plot
frame using a
* subclass of MousePlotPanel, which
in turn is a subclass
* of PlotPanel.
*
* The fractal algorithms are included
in DrawFunction
* subclasses. They create the fractal
patterns by drawing
* the patters via the draw methods
for the graphics context
* object passed to it.
*
* The user can drag the cursor to outline
a rectangle
* whose dimensions are used for a rescaled
graph. The
* MousePlotPanel provides the mouse
event information.
*
* The class mplements the FractalController
interface so that the
* FractalPanel object can call back
to send new dimensions
* for the graph area. It also calls
back to indicate when
* fractal generation is happening so
that the controls
* can be put into a busy state and
not interfere with the
* operation.
**/
public class FractalsApplet extends JApplet
implements ActionListener,
ListSelectionListener,
FractalController
{
// Flag to indicate if the applet is in a browser
// or running as an application via the main ()
method.
boolean fInBrowser = true;
// Fractal panel can display different algorithms
by
// passing to it a new DrawFractal object.
FractalPanel fOutputPanel;
// A text field for input strings
JTextField fFieldXLeft, fFieldXRite, fFieldYTop,
fFieldYBot;
// Parameters for the algorithms.
double fParam0 = 0.0;
double fParam1 = 0.0;
// Text fields to input the algorithm parameters
JTextField fFieldParam0;
JTextField fFieldParam1;
// Labels for the parameters
JLabel fLabelParam0, fLabelParam1;
// A number to indicate the selected algorithm.
int fAlgorithm = ALG_BIFURCATION;
// Define a set of constants to specify a given
algorithm
final static int ALG_BIFURCATION =
0;
final static int ALG_JULIASET =
1;
final static int ALG_JULIASET_NEWT = 2;
final static int ALG_MANDLEBROT =
3;
// Default dimensions according to the algorithm
double [][] fXYDef =
{
{-2.0, 2.0,
-2.0, 2.0}, // Bifurcation
{-2.0, 2.0,
-2.0, 2.0}, // Julia set
{-3.0, 3.0,
-3.0, 3.0}, // Julia set from Newton's method
{-2.5, 2.5,
-2.5, 2.5} // Mandlebrot
};
// Hold the default algorithm parameters in this
2-d array.
double [][] fAlgorithmParams = {
{0.0, 0.0},
// Bifurcation
{0.36,
0.25},// Julia set
{0.0, 0.0},
// Julia set from Newton's method
{0.0, 0.0} //
Mandlebrot
};
// List component for the algorithms.
JList fAlgorithmJList;
String [] fAlgorithmList = {"Bifurcation",
"Julia
Set",
"Julia
Set- Newton's",
"Mandlebrot"
};
// Keep an array of the fractal generators
DrawFunction [] drawFractals = new DrawFunction[4];
// Need a button to return to the default dimensions.
JButton fResetButton;
/**
* Create a User Interface with four
fields that show the
* current dimensions of the fractal
graphing area.
* The interface also includes a JList
with the
* list of algorithms. Selecting one
will initiate the
* algorithm. A "Reset" button will
return the dimensions to
* the default values and redraw the
graph.
**/
public void init () {
JPanel panel = new JPanel (new BorderLayout
());
// When user hits reset button, the
graph will be
// redrawn with default dimensions.
fResetButton = new JButton ("Reset");
fResetButton.addActionListener (this);
// Use a textfield for an input parameter.
fFieldXLeft = new JTextField (Double.toString
(fXYDef[0][0]), 6);
fFieldXRite = new JTextField (Double.toString
(fXYDef[0][1]), 6);
fFieldYBot = new JTextField
(Double.toString (fXYDef[0][2]), 6);
fFieldYTop = new JTextField
(Double.toString (fXYDef[0][3]), 6);
// Use a GridLayout to show the dimensions
JPanel dim_labels_panel = new JPanel
(new GridLayout (2,1));
dim_labels_panel.add (new JLabel ("X
= ", SwingConstants.RIGHT));
dim_labels_panel.add (new JLabel ("Y
= ", SwingConstants.RIGHT));
JPanel dimensions_panel = new JPanel
(new GridLayout (2,2));
dimensions_panel.add (fFieldXLeft);
dimensions_panel.add (fFieldXRite);
dimensions_panel.add (fFieldYBot);
dimensions_panel.add (fFieldYTop);
// Parameters fields
fFieldParam0 = new JTextField (Double.toString
(fParam0),6);
fFieldParam1 = new JTextField (Double.toString
(fParam1),6);
JPanel parameters_panel = new JPanel
(new GridLayout (2,2));
fLabelParam0 = new JLabel ("P0 = ",
SwingConstants.RIGHT);
parameters_panel.add (fLabelParam0);
parameters_panel.add (fFieldParam0);
fLabelParam1 = new JLabel ("P1 = ",
SwingConstants.RIGHT);
parameters_panel.add (fLabelParam1);
parameters_panel.add (fFieldParam1);
// Combine the panels for the dimensions,
their labels
// and parameters onto
one panel.
JPanel dim_param_panel = new JPanel
();
dim_param_panel.add (dim_labels_panel);
dim_param_panel.add (dimensions_panel);
dim_param_panel.add (parameters_panel);
// Create a JList for the algorithms.
fAlgorithmJList = new JList (fAlgorithmList);
// Show only the current algorithm
fAlgorithmJList.setVisibleRowCount
(2);
// Allow only one of the items to
be selected.
fAlgorithmJList.setSelectionMode (
ListSelectionModel.SINGLE_SELECTION);
// Select initially the top item.
fAlgorithmJList.setSelectedIndex (ALG_BIFURCATION);
// Send selection events to this object.
fAlgorithmJList.addListSelectionListener
(this);
// Add the list to a JScrollPane so
that we can
// scroll to view other items.
JScrollPane list_scroll_pane = new
JScrollPane (fAlgorithmJList);
// Create a panel to hold the controls.
JPanel control_panel = new JPanel
();
control_panel.add (dim_param_panel);
control_panel.add (list_scroll_pane);
control_panel.add (fResetButton);
// And combine it with the FractalPanel.
panel.add (control_panel,"South");
// Create the bifurcation algorithm
as the first choice.
drawFractals[ALG_BIFURCATION] = new
DrawBifurcation ();
// Only need one parameter for the
bifurcation algorithm
fLabelParam1.setEnabled (false);
fFieldParam1.setEnabled (false);
// Add the algorithm panel here.
fOutputPanel = new FractalPanel (this,
drawFractals[0],
fXYDef[fAlgorithm][0],
fXYDef[fAlgorithm][1],
fXYDef[fAlgorithm][2],
fXYDef[fAlgorithm][3]);
panel.add (fOutputPanel,"Center");
// Then add this panel to the applet.
add (panel);
} // init
/** Callback from the FractalPanel with the new
dimensions.**/
public void setFractalParameters (double x_min,
double x_max,
double
y_min, double y_max) {
// Reset dimensions to defaults.
fFieldXLeft.setText (PlotFormat.getFormatted
(x_min, 100.0, 1000.0, 3));
fFieldXRite.setText (PlotFormat.getFormatted
(x_max, 100.0, 1000.0, 3));
fFieldYBot.setText (PlotFormat.getFormatted
(y_min, 100.0, 1000.0, 3));
fFieldYTop.setText (PlotFormat.getFormatted
(y_max, 100.0, 1000.0, 3));
} // setFractalParameters
/**
* Implementation of FractalController
interface: This method
* provides the values in the text
fields for the parameters
* needed by a given algorithm.
**/
public void getFractalParameters (double [] parameters)
{
if (fAlgorithm == ALG_BIFURCATION)
{
try {
fParam0 =
Double.valueOf (fFieldParam0.getText ());
} catch (NumberFormatException
nfe) {
fParam0 =
fAlgorithmParams[ALG_BIFURCATION][0];
fFieldParam0.setText
("0.0");
}
parameters[2] = fParam0;
} else
if (fAlgorithm == ALG_JULIASET) {
// Julia Set
try {
fParam0 =
Double.valueOf (fFieldParam0.getText ());
fParam0 =
Double.valueOf (fFieldParam0.getText ());
} catch (NumberFormatException
nfe) {
fParam0 =
fAlgorithmParams[ALG_JULIASET][0];
fParam1 =
fAlgorithmParams[ALG_JULIASET][1];
fFieldParam0.setText
(Double.toString (fParam0));
}
parameters[2] = fParam0;
parameters[3] = fParam1;
} else
if (fAlgorithm == ALG_JULIASET_NEWT
||
fAlgorithm
== ALG_MANDLEBROT ) { // Julia Set - Newton's method
// or Mandlebrot
}
} // getFractalParameters
/**
* Implementation of FractalController
interface: This method
* turns off controls while fractal
generation runs. It turns
* them back on when the generation
is done.
**/
public void setBusy (boolean flag) {
if (flag) {
fResetButton.setEnabled
(false);
fAlgorithmJList.setEnabled
(false);
if (fAlgorithm
== ALG_BIFURCATION ||
fAlgorithm
== ALG_JULIASET) {
fFieldParam0.setEnabled (false);
fLabelParam0.setEnabled (false);
}
if (fAlgorithm
== ALG_JULIASET) {
fFieldParam1.setEnabled
(false);
fLabelParam1.setEnabled
(false);
}
fResetButton.setText
("BUSY");
} else {
fResetButton.setEnabled
(true);
fAlgorithmJList.setEnabled
(true);
if (fAlgorithm
== ALG_BIFURCATION ||
fAlgorithm
== ALG_JULIASET) {
fFieldParam0.setEnabled (true);
fLabelParam0.setEnabled (true);
}
if (fAlgorithm
== ALG_JULIASET) {
fFieldParam1.setEnabled
(true);
fLabelParam1.setEnabled
(true);
}
fResetButton.setText
("Reset");
}
} // setBusy
/**
* Reset button will reset the drawing
area back to
* the default dimensions.
**/
public void actionPerformed (ActionEvent e)
{
Object source = e.getSource ();
if (source == fResetButton) {
// Reset dimensions
to defaults
resetDefaultFrame
();
fOutputPanel.setRange
(fXYDef[fAlgorithm][0],
fXYDef[fAlgorithm][1],
fXYDef[fAlgorithm][2],
fXYDef[fAlgorithm][3]);
}
} // actionPerformed
/** Reset the frame to the default dimensions.
**/
public void resetDefaultFrame ()
{
// Reset dimensions to defaults
fFieldXLeft.setText (Double.toString
(fXYDef[fAlgorithm][0]));
fFieldXRite.setText (Double.toString
(fXYDef[fAlgorithm][1]));
fFieldYBot.setText (Double.toString
(fXYDef[fAlgorithm][2]));
fFieldYTop.setText (Double.toString
(fXYDef[fAlgorithm][3]));
} // resetDefaultFrame
/**
* User selects the algorithm from
the JList.
**/
public void valueChanged (ListSelectionEvent evt) {
// Get the reference to the JList
object
JList source = (JList)evt.getSource
();
// and get an array of the selected
items.
Object [] values = source.getSelectedValues
();
// In this case only one value can
be selected
// so just look at first item in array.
String algorithm_selected = (String)values[0];
// Set the title accordingly
fOutputPanel.setTitle (algorithm_selected);
// For the selected algorithm, pass
it to the FractalPanel
// and also set up the parameter elements
on the user interface.
if (algorithm_selected.equals (fAlgorithmList[0]))
{
// Only need
one parameter for the bifurcation algorithm
fLabelParam1.setEnabled
(false);
fFieldParam1.setEnabled
(false);
fAlgorithm
= ALG_BIFURCATION;
fParam0 =
fAlgorithmParams[fAlgorithm][0];
fFieldParam0.setText
(Double.toString (fParam0));
fFieldParam1.setText
(" ");
} else
if (algorithm_selected.equals (fAlgorithmList[1]))
{
// Need two
parameters for the Julia set algorithm
fLabelParam1.setEnabled
(true);
fFieldParam1.setEnabled
(true);
fAlgorithm
= ALG_JULIASET;
fParam0 =
fAlgorithmParams[fAlgorithm][0];
fParam1 =
fAlgorithmParams[fAlgorithm][1];
fFieldParam0.setText
(Double.toString (fParam0));
fFieldParam1.setText
(Double.toString (fParam1));
// Get the
algorithm
if (drawFractals[fAlgorithm]
== null)
drawFractals[fAlgorithm] = new DrawJuliaSet ();
// Pass the
new algorithm to the panel
fOutputPanel.setAlgorithm
(drawFractals[fAlgorithm]);
// Reseting
the range will cause the panel to redraw
// itself
with the new algorithm.
fOutputPanel.setRange
(fXYDef[fAlgorithm][0],
fXYDef[fAlgorithm][1],
fXYDef[fAlgorithm][2],
fXYDef[fAlgorithm][3]);
} else
if (algorithm_selected.equals (fAlgorithmList[2]))
{
// No parameters
used for the Julia set from Newton's method
fLabelParam0.setEnabled
(false);
fFieldParam0.setEnabled
(false);
fLabelParam1.setEnabled
(false);
fFieldParam1.setEnabled
(false);
fAlgorithm
= ALG_JULIASET_NEWT;
fFieldParam0.setText
(" ");
fFieldParam1.setText
(" ");
// Get the
algorithm
if (drawFractals[fAlgorithm]
== null)
drawFractals[fAlgorithm] = new DrawJuliaSetNewton ();
} else
if (algorithm_selected.equals (fAlgorithmList[3]))
{
// No parameters
used for the Mandlebrot algorithm
fLabelParam0.setEnabled
(false);
fFieldParam0.setEnabled
(false);
fLabelParam1.setEnabled
(false);
fFieldParam1.setEnabled
(false);
fAlgorithm
= ALG_MANDLEBROT;
fFieldParam0.setText
(" ");
fFieldParam1.setText
(" ");
// Get the
algorithm
if (drawFractals[fAlgorithm]
== null)
drawFractals[fAlgorithm] = new DrawMandlebrot ();
}
// Reset back to the default frame
scale
resetDefaultFrame ();
// Pass the new algorithm to the panel
fOutputPanel.setAlgorithm (drawFractals[fAlgorithm]);
// Reseting the range will cause the
panel to redraw
// itself with the new algorithm.
fOutputPanel.setRange (fXYDef[fAlgorithm][0],
fXYDef[fAlgorithm][1],
fXYDef[fAlgorithm][2],
fXYDef[fAlgorithm][3]);
} // valueChanged
/** Optional application mode. **/
public static void main (String[] args) {
// Frame size.
int frame_width = 550;
int frame_height = 300;
// Add an instance of this applet
to the frame
FractalsApplet applet = new FractalsApplet
();
applet.fInBrowser = false;
applet.init ();
// Following anonymous class used
to close window & exit program
JFrame f = new JFrame ("Draw Fractals");
f.setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);
// Add applet to the frame
f.add (applet);
f.setSize (new Dimension (frame_width,frame_height));
f.setVisible (true);
} // main
} // class FractalsApplet
|
/**
* Interface to allow callbacks from the fractal
panel
* to the controller.
**/
public interface FractalController {
// Pass display area dimensions.
public void setFractalParameters (double x_min,
double x_max,
double
y_min, double y_max);
public void getFractalParameters (double [] parameters);
public void setBusy (boolean flag);
} // FractalController
|
import
java.awt.*;
import java.awt.event.*;
/**
* This subclass of PlotPanel adds the capability
for the user to drag
* open a rectangle on the plot. The subclass must
override the method
* handleMouseInfo().
**/
public abstract class MousePlotPanel extends PlotPanel
implements
MouseHandler
{
// Flag if rectangle is within the frame bounds.
boolean fRectValid = false;
// The coords for the corners of the dragged rectangle
int fXMouseStart, fYMouseStart;
int fXMouseEnd, fYMouseEnd;
// Position of cursor when mouse clicked.
int fXMouseClicked, fYMouseClicked;
// Rectangle color
Color fRectColor = Color.BLACK;
// Color for XOR mode.
Color fXORColor = Color.WHITE;
// Flags to indicate what mouse information to
post.
public final static int RECT_DRAGGING = 1;
public final static int RECT_DONE
= 2;
/**
* The constructor creates mouse listeners
to
* send the mouse events to this object.
**/
public MousePlotPanel () {
// Send mouse events to this panel
addMouseListener (
new MouseAdapter ()
{
public void
mousePressed (MouseEvent evt) {
pressedOnPlot
(evt);
}
public void
mouseClicked (MouseEvent evt) {
clickedOnPlot
(evt);
}
public void
mouseReleased (MouseEvent evt) {
releasedOnPlot
(evt);
}
}
);
addMouseMotionListener(
new MouseMotionAdapter()
{
public void
mouseDragged (MouseEvent evt) {
draggedOnPlot(evt);
}
}
);
} // ctor
/**
* Get the starting point for the rectangle
* when the mouse button is pressed.
**/
public void pressedOnPlot (MouseEvent evt) {
// Get start coords of cursor
fXMouseStart = evt.getX ();
fYMouseStart = evt.getY ();
// Just started so put neg values
in stop coords
fXMouseEnd = -1;
fYMouseEnd = -1;
} // pressedOnPlot
public void clickedOnPlot (MouseEvent evt) {
// Get coords of cursor
fXMouseClicked = evt.getX ();
fYMouseClicked = evt.getY ();
} // clickedOnPlot
/** The rectangle opening is finished. Now
* execute the desired operation with
it.
**/
public void releasedOnPlot (MouseEvent evt) {
if (fRectValid) handleMouseInfo (RECT_DONE);
} // releasedOnPlot
public void draggedOnPlot (MouseEvent evt) {
fRectValid = false;
// Don't start rectangle outside of
the frame box
if (fXMouseStart < fFrameX ||
fXMouseStart
>= (fFrameX + fFrameWidth)) return;
if (fYMouseStart < fFrameY ||
fYMouseStart
>= (fFrameY + fFrameHeight)) return;
fRectValid = true;
// Need a graphics context to draw
on the panel.
Graphics g = getGraphics ();
// Set the pen color
g.setColor (fRectColor);
g.setXORMode (fXORColor);
// First erase the old rectangle before
drawing the new one
if ((fXMouseEnd != -1) && (fYMouseEnd
!= -1))
g.drawRect (Math.min
(fXMouseStart, fXMouseEnd),
Math.min (fYMouseStart, fYMouseEnd),
Math.abs (fXMouseStart - fXMouseEnd),
Math.abs (fYMouseStart - fYMouseEnd)
);
// Get current coords of cursor
fXMouseEnd = evt.getX();
fYMouseEnd = evt.getY();
// Don't allow rectangle to extend
outside of the frame box
if (fXMouseEnd < fFrameX) fXMouseEnd
= fFrameX;
if (fXMouseEnd > (fFrameX + fFrameWidth))
fXMouseEnd = fFrameX + fFrameWidth;
if (fYMouseEnd < fFrameY) fYMouseEnd
= fFrameY;
if (fYMouseEnd > (fFrameY + fFrameHeight))
fYMouseEnd = fFrameY + fFrameHeight;
// Post the new rectangle info
handleMouseInfo (RECT_DRAGGING);
// Draw the new rectangle
g.drawRect (Math.min (fXMouseStart,
fXMouseEnd),
Math.min
(fYMouseStart, fYMouseEnd),
Math.abs
(fXMouseStart - fXMouseEnd),
Math.abs
(fYMouseStart - fYMouseEnd)
);
// Release the graphics resources.
g.dispose ();
} // draggedOnPlot
/**
* Receive the status info on the mouse
and
* do something with it.
**/
public abstract void handleMouseInfo (int flag);
} // MousePlotPanel
|
import
java.awt.*;
import java.awt.event.*;
/**
* Interface for a plot that needs to obtain
* mouse events occuring on it.
**/
public interface MouseHandler
{
public void pressedOnPlot (MouseEvent evt);
public void clickedOnPlot (MouseEvent evt);
public void releasedOnPlot (MouseEvent evt);
public void draggedOnPlot (MouseEvent evt);
public void handleMouseInfo (int flag);
} // MouseHandler
|
import
javax.swing.*;
import java.awt.*;
import java.awt.image.*;
/**
* This panel executes a given fractal
algorithm to generate a
* fractal display. It is a subclass
of MousePlotPanel and PlotPanel.
* PlotPanel provides a framed area
with text scale values along the
* axes.
*
* MousePlotPanel adds mouse event handling
methods that
* allow the user to drag a rectangle
open. The frame will be
* rescaled to the dimensions of this
rectangle and the algorithm
* re-run within that area.
*
* A reset button allows the user to
return to the initial dimensions.
**/
public class FractalPanel extends MousePlotPanel
{
// Call back to the controller with new dimensions
when
// user rescales with a new rectangular area.
FractalController fController;
// Limit values to x and y axes in data units.
double fXDataMin, fXDataMax;
double fYDataMin, fYDataMax;
// Parameters for x and y scales.
int fNumXScaleValues = 2;
int fNumYScaleValues = 2;
double [] fYScaleValue = new double [2];
double [] fXScaleValue = new double [2];
String fTitle = "Fractal Display";
// Need the fractal drawing function and
// a parameters array to pass to it.
DrawFunction fDrawFractal;
double [] fParameters = new double [4];
// Constants for message passing.
public static final int GET_START_VALUE = 1;
/**
* Create the panel for displaying
the fractal plot.
* Pass the x and y plot limits.
**/
public FractalPanel (FractalController controller,
DrawFunction drawFractal,
double x_data_min, double x_data_max,
double y_data_min, double y_data_max) {
fController = controller;
setRange (x_data_min, x_data_max,
y_data_min, y_data_max);
fDrawFractal = drawFractal;
} // ctor
/** Set the x and y data range values. Rescale
accordingly. **/
public void setRange (double x_data_min, double
x_data_max,
double
y_data_min, double y_data_max) {
fXDataMin = x_data_min;
fXDataMax = x_data_max;
fYDataMin = y_data_min;
fYDataMax = y_data_max;
getScaling ();
// Turn off controller during fractal
generation
fController.setBusy (true);
// Repaint the plot with the new dimensions.
repaint ();
} // setRange
/** Pass a new alogorthim to plot. **/
public void setAlgorithm (DrawFunction drawFractal)
{
fDrawFractal= drawFractal;
} // setAlgorithm
/**
* Get the status info on the mouse
and
* send the info to the controller.
**/
public void handleMouseInfo (int flag) {
if (flag == RECT_DRAGGING) {
//fController.sendInfo
(flag);
} else
if (flag == RECT_DONE) {
// Get the rectangle coords
in pixel dimensions
int rect_x_pix_beg = Math.min
(fXMouseStart, fXMouseEnd)
- fFrameX;
int rect_x_pix_end = Math.max
(fXMouseStart, fXMouseEnd)
- fFrameX;
int rect_y_pix_beg = Math.min
(fYMouseStart, fYMouseEnd)
- fFrameY;
int rect_y_pix_end = Math.max
(fYMouseStart, fYMouseEnd)
- fFrameY;
// Check limits in horizontal
if (rect_x_pix_beg < 0)
rect_x_pix_beg = 0;
if (rect_x_pix_end > fFrameWidth)
rect_x_pix_end
= fFrameWidth;
// and in vertical.
if (rect_y_pix_beg < 0)
rect_y_pix_beg = 0;
if (rect_y_pix_end > fFrameHeight)
rect_y_pix_end
= fFrameHeight;
// Now convert from pixel
scale to data scale
// First calculate conversion
factor from pixels
// to data for the x axis.
double range = fXDataMax
- fXDataMin;
double del = range/fFrameWidth;
// Then apply it to the
horizontal poitns.
fXDataMin = rect_x_pix_beg
* del + fXScaleValue[0];
fXDataMax = rect_x_pix_end
* del + fXScaleValue[0];
// Calculate conversion
factor for vertical axis.
range = fYDataMax - fYDataMin;
del = range/fFrameHeight;
// and then apply to vertical
points.
fYDataMin = fYScaleValue[0]
+ (range - rect_y_pix_end * del);
fYDataMax = fYScaleValue[0]
+ (range - rect_y_pix_beg * del);
// Re-set the axes settings
according to the new rectangle.
getScaling ();
// Tell the controller
about the new settings
fController.setFractalParameters
(fXDataMin, fXDataMax,
fYDataMin,
fYDataMax);
// Turn off controller
during fractal generation
fController.setBusy (true);
repaint ();
};
} // handleMouseInfo
/**
* Get the values for the scaling numbers
on
* the plot axes.
**/
void getScaling () {
fYScaleValue = new double[fNumYScaleValues];
// Use lowest value of 0;
fYScaleValue[0] = fYDataMin;
fYScaleValue[fNumYScaleValues-1] =
fYDataMax;
// Then calculate the difference between
the values
double range = fYDataMax - fYDataMin;
double del = range/(fNumYScaleValues-1);
// Now set the intermediate scale
values.
for (int i=1; i < (fNumYScaleValues-1);
i++) {
fYScaleValue[i]
= i * del + fYScaleValue[0];
}
fXScaleValue = new double[fNumXScaleValues];
// First get the low and high values;
fXScaleValue[0] = fXDataMin;
fXScaleValue[fNumXScaleValues-1] =
fXDataMax;
// Then calculate the difference between
the values
range = fXDataMax - fXDataMin;
del = range/(fNumXScaleValues-1);
// Now set the intermediate scale
values.
for (int i=1; i < (fNumXScaleValues-1);
i++) {
fXScaleValue[i]
= i * del + fXScaleValue[0];
}
} // getScaling
/**
* Override paintContents() to draw
the plot inside the frame.
* From the data arrays draw a different
symbol for each data
* data point and also draw x, y error
bars.
**/
void paintContents (Graphics g) {
g.setColor (Color.BLUE);
// Draw the numbers along the axes
drawAxesNumbers ( g, fXScaleValue,
fYScaleValue);
// Pass the x and y data ranges to
the algorithm.
fParameters[0] = fXDataMax - fXDataMin;
fParameters[1] = fYDataMax - fYDataMin;
fController.getFractalParameters (fParameters);
fDrawFractal.setParameters (fParameters,
null);
fDrawFractal.setColor (Color.LIGHT_GRAY);
// Draw the bifurcation plot
fDrawFractal.draw (g,
fFrameX, fFrameY,
fFrameWidth, fFrameHeight,
fXScaleValue,fYScaleValue);
fController.setBusy (false);
} // paintContents
/**
* Set the title of the plot.
**/
void setTitle (String title)
{ fTitle = title;}
/**
* Return the title at the top of the
plot.
* Overrides method in PlotPanel.
**/
String getTitle ()
{ return fTitle;}
/**
* Return the label on the horizontal
axis.
* Overrides method in PlotPanel.
**/
String getXLabel ()
{ return "Arbitrary units";}
} // class FractalPanel
|
Most recent update: June 25, 2005
|