package COM.furryandfrisky.fractal;
import java.applet.*;
import java.awt.*;
import java.awt.image.*;
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
class string_table
{
// do not make these 'final'
public static String title = "f(x) = rx(1 - x)";
public static String Ready = "Ready";
public static String Resolution = "Resolution:";
public static String Reset = "Reset";
public static String percent_sign = "%";
}
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
class chaos_application extends Frame
{
//------------------------------------------------------------------------
public chaos_application()
{
super( string_table.title );
the_applet.init();
add( "Center", the_applet );
pack();
show();
the_applet.start();
}
//------------------------------------------------------------------------
public boolean handleEvent( Event evt )
{
return the_applet.handleEvent( evt );
}
//------------------------------------------------------------------------
private ChaoticEquation the_applet = new ChaoticEquation();
}
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
public class ChaoticEquation extends Applet
{
//------------------------------------------------------------------------
public static void main( String[] args )
{
// if started from java, create frame for applet
new chaos_application();
}
//------------------------------------------------------------------------
public boolean handleEvent( Event evt )
{
if( evt.id == Event.WINDOW_DESTROY )
System.exit( 0 );
if( (evt.id == Event.ACTION_EVENT) && (evt.arg == string_table.Reset) )
{
the_graph.go( 1.0, 0.0, 3.01, 1.01 );
return true;
}
return super.handleEvent( evt );
}
//------------------------------------------------------------------------
private static boolean is102()
{
// is the java version 1.0.2?
return "1.02".equals( System.getProperty( "java.version" ))
|| "1.0.2".equals( System.getProperty( "java.version" ));
}
//------------------------------------------------------------------------
public void init()
{
Button reset = new Button( string_table.Reset );
Label status = is102()
? new Label( "___________________", Label.LEFT )
: new big_label();
TextField resolution = new TextField( 4 );
setLayout( new BorderLayout() );
Panel control_panel = new Panel();
control_panel.setLayout( new FlowLayout( FlowLayout.CENTER, 15, 15 ));
control_panel.add( status );
control_panel.add( new Label( string_table.Resolution ) );
control_panel.add( resolution );
control_panel.add( reset );
add( "South", control_panel );
the_graph = new screen_graph( status, resolution );
add( "Center", the_graph );
}
//------------------------------------------------------------------------
public void start()
{
the_graph.go( 1.0, 0.0, 3.01, 1.01 );
}
//------------------------------------------------------------------------
private screen_graph the_graph = null;
}
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
class big_label extends Label
{
//------------------------------------------------------------------------
public Dimension getPreferredSize()
{
// set width to half the width of the container
return new Dimension(
getParent().getSize().width / 2,
super.getPreferredSize().height );
}
}
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
class screen_graph extends Canvas implements Runnable
{
//------------------------------------------------------------------------
public screen_graph( Label status_label, TextField resolution_edit )
{
position = status_label;
resolution = resolution_edit;
resolution.setText( "100" );
}
//------------------------------------------------------------------------
public void go( double leftmost, double bottommost, double wide,
double high )
{
if( state == CALCULATING )
calculating_thread.stop();
left = leftmost;
bottom = bottommost;
width = wide;
height = high;
int res = 100;
try
{
res = Integer.parseInt( resolution.getText() );
if( res > 100 )
res = 100;
if( res < 1 )
res = 1;
}
catch( NumberFormatException e ) {}
resolution.setText( Integer.toString( res ) );
width_in_pixels = size().width * res / 100;
height_in_pixels = size().height * res / 100;
calculating_thread = new Thread( this );
calculating_thread.start();
}
//------------------------------------------------------------------------
public void run()
{
calculate_points();
position.setText( string_table.Ready );
repaint();
}
//------------------------------------------------------------------------
public Dimension preferredSize()
{
return new Dimension( 600, 400 );
}
//------------------------------------------------------------------------
public String toString()
{
String str = "screen_graph\n";
str += "left: " + left + "\n";
str += "bottom: " + bottom + "\n";
str += "width: " + width + "\n";
str += "height: " + height + "\n";
str += "width_in_pixels: " + width_in_pixels + "\n";
str += "height_in_pixels: " + height_in_pixels + "\n";
return str;
}
//------------------------------------------------------------------------
public void update( Graphics g )
{
paint( g );
}
//------------------------------------------------------------------------
public void paint( Graphics g )
{
if( state == READY )
g.drawImage( image, 0, 0, size().width, size().height, this );
}
//------------------------------------------------------------------------
public boolean mouseMove( Event evt, int x, int y )
{
if( state == READY )
draw_point_as_string( new Point( x, y ) );
return true;
}
//------------------------------------------------------------------------
public boolean mouseDown( Event evt, int x, int y )
{
if( state == READY )
{
selected_point = clip_point( x, y );
previous_point = selected_point;
dragging = true;
}
return true;
}
//------------------------------------------------------------------------
public boolean mouseUp( Event evt, int x, int y )
{
if( dragging )
{
dragging = false;
Point point = clip_point( x, y );
if( (point.x > selected_point.x) && (point.y > selected_point.y) )
set_new_bounds( selected_point, point );
}
return true;
}
//------------------------------------------------------------------------
public boolean mouseDrag( Event evt, int x, int y )
{
if( dragging )
{
Point point = clip_point( x, y );
draw_point_as_string( point );
Graphics g = getGraphics();
g.setXORMode( Color.white );
g.setColor( Color.black );
if( selected_point != previous_point )
g.drawRect( selected_point.x, selected_point.y,
previous_point.x - selected_point.x,
previous_point.y - selected_point.y );
if( (point.x > selected_point.x) && (point.y > selected_point.y) )
{
g.drawRect( selected_point.x, selected_point.y,
point.x - selected_point.x, point.y - selected_point.y );
previous_point = point;
}
else
previous_point = selected_point;
g.dispose();
}
return true;
}
//------------------------------------------------------------------------
protected Point clip_point( int x, int y )
{
if( x > size().width )
x = size().width;
if( y > size().height )
y = size().height;
return new Point( x, y );
}
//------------------------------------------------------------------------
protected void draw_point_as_string( Point point )
{
double delta_x = width / size().width;
double delta_y = height / size().height;
double leftmost = point.x * delta_x + left;
double bottommost = (size().height - point.y) * delta_y + bottom;
String str = "(" + leftmost + ", " + bottommost + ")";
position.setText( str );
}
//------------------------------------------------------------------------
protected synchronized void calculate_points()
{
state = CALCULATING;
int start_at_run = 1000;
int scatter_amount = height_in_pixels;
double init_y = 0.1;
int max_trys = 500;
double delta_x = width / width_in_pixels;
double delta_y = height / height_in_pixels;
int[] graph = new int[width_in_pixels * height_in_pixels];
for( int i = 0; i < graph.length; i++ )
graph[i] = 0xFFFFFFFF;
for( double x = left; x < left + width; x += delta_x )
{
int discrete_x = (int) ((x - left) / delta_x);
int percent_complete = (int) (discrete_x * 100 / width_in_pixels);
position.setText( percent_complete + string_table.percent_sign );
if( discrete_x < 0 )
discrete_x = 0;
if( discrete_x >= width_in_pixels )
discrete_x = width_in_pixels - 1;
double y = init_y;
int i;
for( i = 0; i < start_at_run; i++ )
y = function( x, y );
if( y < 0 )
continue;
scatter_chart:
for( i = 0; i < scatter_amount; i++ )
{
int trys = 0;
y = function( x, y );
while( true )
{
int discrete_y = (int) ((y - bottom) / delta_y);
discrete_y = height_in_pixels - 1 - discrete_y;
if( discrete_y < height_in_pixels && discrete_y >= 0 )
{
if( graph[discrete_x + discrete_y * width_in_pixels]
!= 0xFF000000 )
graph[discrete_x + discrete_y * width_in_pixels]
-= 0x00111111;
break;
}
y = function( x, y );
if( ++trys == max_trys )
break scatter_chart;
}
}
}
image = createImage( new MemoryImageSource(width_in_pixels,
height_in_pixels, graph, 0, width_in_pixels) );
state = READY;
}
//------------------------------------------------------------------------
protected void set_new_bounds( Point upper_left, Point lower_right )
{
double delta_x = width / size().width;
double delta_y = height / size().height;
double l = upper_left.x * delta_x + left;
double b = (size().height - lower_right.y) * delta_y + bottom;
double w = (lower_right.x - upper_left.x) * delta_x;
double h = (lower_right.y - upper_left.y) * delta_y;
go( l, b, w, h );
}
//------------------------------------------------------------------------
protected static final double function( double x, double y )
{
return ( x * y * (1 - y) );
}
//------------------------------------------------------------------------
private static final byte NEW = 1;
private static final byte CALCULATING = 2;
private static final byte READY = 3;
private byte state = NEW;
private Point selected_point = null;
private Point previous_point = null;
private boolean dragging = false;
private Image image = null;
private double left, bottom, width, height;
private int width_in_pixels;
private int height_in_pixels;
private Thread calculating_thread = null;
private Label position = null;
private TextField resolution = null;
}