|








|
|
 |
|
 |
/*
GoldenSquare.java
Any portion of this code may be used without permission from BrainyPage.
www.BrainyPage.com | Created by Raul Aguilar | Last Modified 200205152213
Enjoy!
*/
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
import java.awt.geom.*;
import java.math.*;
import java.applet.*;
import com.borland.jbcl.layout.*;
import java.util.*;
public class GoldenSquare extends JApplet{
private aJFrame f;
public static final int WIDTH = 400;
public static final int HEIGHT = 400;
public void init() {
// Set the arguments.
String[] args = { "11.0" };
f = new aJFrame(args, getContentPane());
}
public void paint(Graphics g) {
super.paint(g);
f.redraw();
}
public static void main(String[] args) {
aJFrame frame = new aJFrame(args);
frame.setTitle("GoldenSquare");
frame.setSize(WIDTH,HEIGHT);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.show();
}
}
class aJFrame extends JFrame {
public aJFrame(String[] args) {
buildPanels(args, getContentPane());
}
public aJFrame(String[] args, Container cp) {
buildPanels(args, cp);
}
public void buildPanels(String[] args, Container cp) {
panelSimulate = new Simulate(args);
Control panelControl = new Control(args, panelSimulate);
JPanel p = new JPanel();
p.setLayout(new XYLayout());
p.add(panelSimulate, new XYConstraints(5, 5, 380, 335));
p.add(panelControl, new XYConstraints(5, 345, 380, 90));
cp.add(p,BorderLayout.CENTER);
}
public void redraw() {
panelSimulate.repaint();
}
Simulate panelSimulate;
}
class Simulate extends JPanel {
private double base;
private String[] args;
int w;
int h;
double w2;
double h2;
double cx;
double cy;
double positiveUnitsX;
double positiveUnitsY;
double transMathToDeviceX;
double transMathToDeviceY;
Point2D[] v;
double Phi;
double phi;
public Simulate(String[] args) {
setParameters(args);
//Initialize drawing colors
setBackground(Color.white);
setForeground(Color.black);
v = new Point2D[2];
}
public void setParameters(String controlValues) {
StringTokenizer st = new StringTokenizer(controlValues);
ArrayList al = new ArrayList();
while (st.hasMoreTokens()) {
al.add((String) st.nextToken());
}
String[] s = (String[]) al.toArray(new String[0]);
setParameters(s);
}
public void setParameters(String[] args) {
base = Double.parseDouble(args[0]);
System.out.println("parameter values:");
System.out.println();
System.out.println("base = " + base);
}
public void fixDimensions() {
// Find the width and height of the JPanel.
Dimension d = getSize();
w = d.width;
h = d.height;
// Calculate the half height.
w2 = w / 2.0;
h2 = h / 2.0;
// Set the graph center at center of graph.
cx = w / 8.0;
cy = h / 8.0;
// Set size of positive x-axis.
positiveUnitsX = 12.0;
// Find size of positive y-axis.
positiveUnitsY = positiveUnitsX * h2 / w2;
// In this code version,
// transMathToDeviceX is same value as transMathToDeviceY.
transMathToDeviceX = w2 / positiveUnitsX;
transMathToDeviceY = h2 / positiveUnitsY;
Phi = (1.0 + Math.sqrt(5))/2;
phi = Phi - 1.0;
}
public void paint(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
fixDimensions();
drawGrid(g2);
// Set the pen width.
int penWidth = 2;
g2.setStroke(new BasicStroke(penWidth));
StartSquareOne();
drawSquare(g2, v);
for (int i=0; i<5; ++i) {
MakeSquare();
drawSquare(g2, v);
}
drawLogSpiral(g2);
}
private void StartSquareOne() {
// Make a unit square in quadrant IV.
v[0] = new Point2D.Double(0.0, 0.0);
v[1] = new Point2D.Double(base, -1.0 * base);
}
private void drawSquare(
Graphics2D g2,
Point2D[] p) {
g2.setPaint(new Color(255, 92, 0));
Rectangle2D rect = new Rectangle2D.Double();
rect.setFrameFromDiagonal(
userToDevice(p[0].getX(), p[0].getY()),
userToDevice(p[1].getX(), p[1].getY()));
g2.draw(rect);
}
private void MakeSquare() {
Point2D[] vNew = new Point2D[2];
// Let the new vector start at tail of previous square.
vNew[0] = new Point2D.Double();
vNew[0].setLocation(v[1]);
// For the previous vector:
// find the diagonal vector,
Point2D dv = sub(v[1], v[0]);
// find unit vector,
Point2D u = unit(dv);
// and find the length
double len = length(dv) / Math.sqrt(2.0);
// Find tail of new vector.
//
// Add start point of new vector
// to
// (little) phi times
// square root of 2 times
// the length times
// the unit vector rotated ninety degrees.
//
vNew[1] = new Point2D.Double(
vNew[0].getX() + phi * Math.sqrt(2) * len * (-1.0 * u.getY()),
vNew[0].getY() + phi * Math.sqrt(2) * len * ( 1.0 * u.getX()));
v = vNew;
}
private double length(Point2D p) {
double px = p.getX();
double py = p.getY();
return Math.sqrt(px * px + py * py);
}
private Point2D unit(Point2D p) {
double len = Math.sqrt(p.getX() * p.getX() + p.getY() * p.getY());
return new Point2D.Double(p.getX() / len, p.getY() / len);
}
private Point2D sub(Point2D a, Point2D b) {
return new Point2D.Double(a.getX() - b.getX(), a.getY() - b.getY());
}
private void drawGrid(Graphics2D g2) {
// Use physical xy points.
double px;
double py;
double nx;
double ny;
double unitsPerGridLine = 1.0;
double gridLines = positiveUnitsX/unitsPerGridLine;
for (int i=0; i < 2*gridLines ; ++i) {
px = cx + (i * unitsPerGridLine) * transMathToDeviceX;
py = cy - (i * unitsPerGridLine) * transMathToDeviceY;
// Find the minus x values for grid lines
// on the negative side of the graph.
nx = cx - (i * unitsPerGridLine) * transMathToDeviceX;
ny = cy + (i * unitsPerGridLine) * transMathToDeviceY;
if (i == 0) {
// Draw the xy axis.
g2.setPaint(new Color(255, 0, 255));
}
else {
g2.setPaint(new Color(0, 255, 255));
g2.draw(new Line2D.Double( nx, 0, nx, h));
g2.draw(new Line2D.Double( 0, ny, w, ny));
}
g2.draw(new Line2D.Double( px, 0, px, h));
g2.draw(new Line2D.Double( 0, py, w, py));
}
}
private void drawLogSpiral(Graphics2D g2) {
double cxLogSpiral = (5.0 + 3.0 * Math.sqrt(5.0)) / 10.0;
double cyLogSpiral = (Math.sqrt(5.0) - 5.0) / 10.0;
double a = Math.pow(4.0/5.0, 1.0/4.0) * Math.pow(Phi, Math.atan(2.0)/Math.PI);
double b = 2.0 * Math.log(Phi)/Math.PI;
// Set pen color.
g2.setPaint(new Color(0, 0, 255));
// Angular change in degree.
double delta = 1.0;
// Previous x and y device values.
int x_prev = 0;
int y_prev = 0;
// Use a start angle of -1080 degrees to begin the spiral
// near the Golden Square convergence point.
double degreeStart = -1080;
for (double degree = degreeStart; degree < 14.0; degree += delta) {
// Convert to radian.
double radian = Math.toRadians(degree);
// Find the cosine.
double radius = base * a * Math.exp(b * radian);
// Polar to cartesian transform of the positive square root.
double px = radius * Math.cos(radian);
double py = radius * Math.sin(radian);
// Quadrant 1.
// Switch the coordinates.
int x = userToDeviceX(-1.0 * px + base * cxLogSpiral);
int y = userToDeviceY(py + base * cyLogSpiral);
if ((degreeStart + delta / 2.0) < degree) {
// Render the normal distribution line.
Point2D startP = new Point2D.Double(x_prev, y_prev);
Point2D endP = new Point2D.Double(x, y);
g2.draw(new Line2D.Double(startP, endP));
}
x_prev = x;
y_prev = y;
}
}
private Point2D userToDevice(double x, double y) {
double px = cx + x * transMathToDeviceX;
double py = cy - y * transMathToDeviceY;
return new Point2D.Double(px, py);
}
private int userToDeviceX(double x) {
return (int) (cx + x * transMathToDeviceX);
}
private int userToDeviceY(double y) {
return (int) (cy - y * transMathToDeviceY);
}
}
class Control extends JPanel {
private String[] args;
private JTextField tf;
private Simulate s;
public Control(String[] args, Simulate sp) {
this.args = args;
this.setLayout(new XYLayout());
s = sp;
JButton b = new JButton("Go");
ActionListener bl = new ActionListener() {
public void actionPerformed(ActionEvent event) {
s.setParameters(tf.getText().trim());
s.repaint();
}
};
b.addActionListener(bl);
add(b, new XYConstraints(0, 3, 50, 20));
tf = new JTextField("11.0",5);
add(tf, new XYConstraints(60, 3, 50, 20));
}
}
|