-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 52dc55c
Showing
5 changed files
with
378 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
# Compiled class file | ||
|
||
*.class | ||
|
||
|
||
# Log file | ||
|
||
*.log | ||
|
||
|
||
# BlueJ files | ||
|
||
*.ctxt | ||
|
||
|
||
# Mobile Tools for Java (J2ME) | ||
|
||
.mtj.tmp/ | ||
|
||
|
||
# Package Files # | ||
|
||
*.jar | ||
*.war | ||
*.ear | ||
*.zip | ||
*.tar.gz | ||
*.rar | ||
|
||
|
||
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml | ||
|
||
hs_err_pid* | ||
|
||
|
||
# Eclipse files | ||
|
||
/bin/ | ||
/.settings/ | ||
.project | ||
.classpath |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,169 @@ | ||
package echau.gui.butterflycurve; | ||
|
||
/** | ||
* This class represents the actual butterfly curve. This class tells the Screen class where to | ||
* render the curve at a certain time. The main significant method in this class is {@link #update()}. | ||
* <br> | ||
* <br> | ||
* According to Wikipedia, the butterfly curve is a parametric function defined as: | ||
* <br> | ||
* <br> | ||
* {@code x(t) = [sin(t)][exp(cos(t)) - 2cos(4t) - (sin(t / 12))^5]} | ||
* <br> | ||
* {@code y(t) = [cos(t)][exp(cos(t)) - 2cos(4t) - (sin(t / 12))^5]} | ||
*/ | ||
public class ButterflyCurve { | ||
/* Current x- and y-coordinates of the curve */ | ||
private double xCoord; | ||
private double yCoord; | ||
|
||
/** t is the "time" variable in parametric equations. */ | ||
private double t; | ||
|
||
/* Lower and upper bounds of t */ | ||
private final double tLowerBound; | ||
private final double tUpperBound; | ||
|
||
// Used to compare the floating-point value of t to tLowerBound and tUpperBound. | ||
private static final double EPSILON = Gui.T_INCREMENT; | ||
|
||
// The array storing all coordinates of the function within the domain T_LOWER_BOUND <= t <= T_UPPER_BOUND | ||
private double[][] coordinateArray; | ||
|
||
// Current index of the coordinate array being accessed | ||
private int currentIndex; | ||
|
||
// Indicates whether the value of t is increasing | ||
private boolean tIncreasing; | ||
|
||
// Indicates whether the curve is about to change direction; i.e. whether t is at a lower or upper bound | ||
private boolean changingDirection; | ||
|
||
/** | ||
* Creates a ButterflyCurve with the specified lower and upper bound for t. | ||
*/ | ||
public ButterflyCurve(double tLowerBound, double tUpperBound) { | ||
this.tLowerBound = tLowerBound; | ||
this.tUpperBound = tUpperBound; | ||
|
||
if (tUpperBound - tLowerBound < Gui.T_INCREMENT) { | ||
// Guarantees that the initial value of currentIndex is within the array | ||
this.t = (tUpperBound + tLowerBound) / 2; | ||
} else { | ||
this.t = tLowerBound + 0.01; | ||
} | ||
|
||
currentIndex = (int) ((t - tLowerBound) / Gui.T_INCREMENT); | ||
|
||
this.generateCoordinateArray(); | ||
tIncreasing = true; | ||
} | ||
|
||
/** | ||
* Updates the state of the curve. First, the values of t and currentIndex are updated, then the | ||
* next x- and y-coordinates are fetched and assigned to the variables xCoord and yCoord. | ||
*/ | ||
public void update() { | ||
updateTAndCurrentIndex(); | ||
checkDirection(); | ||
xCoord = coordinateArray[currentIndex][0]; | ||
yCoord = coordinateArray[currentIndex][1]; | ||
} | ||
|
||
/** | ||
* Updates the values of t and currentIndex | ||
*/ | ||
private void updateTAndCurrentIndex() { | ||
if (tIncreasing) { | ||
currentIndex++; | ||
t += Gui.T_INCREMENT; | ||
} else { | ||
currentIndex--; | ||
t -= Gui.T_INCREMENT; | ||
} | ||
} | ||
|
||
/** | ||
* Checks whether the curve is about to change direction (i.e. whether {@code t} is at an upper or lower bound). | ||
* This method changes the values of goingClockwise and changingDirection accordingly. | ||
*/ | ||
private void checkDirection() { | ||
if (t <= tLowerBound + EPSILON || t >= tUpperBound - EPSILON) { | ||
tIncreasing = !tIncreasing; | ||
changingDirection = true; | ||
return; | ||
} | ||
changingDirection = false; | ||
} | ||
|
||
/** | ||
* This method is to be used for pre-generating the coordinate arrays for efficiency. | ||
*/ | ||
private void generateCoordinateArray() { | ||
// We add 10 extra spaces to the end of coordinateArray to prevent ArrayIndexOutOfBounds exceptions. | ||
// Floating-point arithmetic is dodgy | ||
coordinateArray = new double[10 + (int) ((tUpperBound - tLowerBound) / Gui.T_INCREMENT)][2]; | ||
for (double i = tLowerBound; i <= tUpperBound; i += Gui.T_INCREMENT) { | ||
// This is where the parametric equation goes | ||
// Casting to an int always rounds down, so we add 0.001 to prevent floating-point arithmetic from screwing things up | ||
coordinateArray[(int) ((i - tLowerBound + 0.001) / Gui.T_INCREMENT)][0] = Math.sin(i) * (Math.pow(Math.E, Math.cos(i)) - 2 * Math.cos(4 * i) - Math.pow(Math.sin(i / 12), 5)); | ||
coordinateArray[(int) ((i - tLowerBound + 0.001) / Gui.T_INCREMENT)][1] = Math.cos(i) * (Math.pow(Math.E, Math.cos(i)) - 2 * Math.cos(4 * i) - Math.pow(Math.sin(i / 12), 5)); | ||
} | ||
} | ||
|
||
/** | ||
* @return The current value of the t variable of the curve | ||
*/ | ||
public double getCurrentT() { | ||
return t; | ||
} | ||
|
||
/** | ||
* @return The current x-coordinate of the curve. | ||
*/ | ||
public double getCurrentXCoord() { | ||
return xCoord; | ||
} | ||
|
||
/** | ||
* @return The current y-coordinate of the curve. | ||
*/ | ||
public double getCurrentYCoord() { | ||
return yCoord; | ||
} | ||
|
||
/** | ||
* @return The current index of the coordinate array. | ||
*/ | ||
public int getCurrentIndex() { | ||
return currentIndex; | ||
} | ||
|
||
/** | ||
* @return The lower bound of the t variable. | ||
*/ | ||
public double getTLowerBound() { | ||
return tLowerBound; | ||
} | ||
|
||
/** | ||
* @return The upper bound of the t variable. | ||
*/ | ||
public double getTUpperBound() { | ||
return tUpperBound; | ||
} | ||
|
||
/** | ||
* @return A boolean indicating whether the value of t is increasing | ||
*/ | ||
public boolean isTIncreasing() { | ||
return tIncreasing; | ||
} | ||
|
||
/** | ||
* @return A boolean indicating whether the curve will reverse its direction on the next tick. | ||
*/ | ||
public boolean isChangingDirection() { | ||
return changingDirection; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
package echau.gui.butterflycurve; | ||
|
||
import javax.swing.JFrame; | ||
import javax.swing.Timer; | ||
|
||
import java.awt.Color; | ||
import java.awt.Container; | ||
|
||
@SuppressWarnings("serial") | ||
public class Gui extends JFrame { | ||
/* Constants */ | ||
private static final boolean IS_RESIZABLE = false; | ||
private static final Color BACKGROUND_COLOUR = Color.WHITE; | ||
|
||
private ButterflyCurve curve; | ||
private Screen screen; | ||
|
||
/** | ||
* The amount that {@link ButterflyCurve#getCurrentT()} will be incremented by every time the | ||
* Timer ticks (once per millisecond). | ||
* | ||
* <br> | ||
* <br> | ||
* | ||
* Setting the value of this constant to be greater than the difference between the upper and lower | ||
* bounds of the parametric curve's t value will cause problems. In other words do not make | ||
* the value of this constant greater than | ||
* {@code this.getCurve().getTUpperBound() - this.getCurve().getTLowerBound()} | ||
*/ | ||
public static final double T_INCREMENT = 0.003; | ||
|
||
public Gui() { | ||
// here, we subtract the preferred lower bound by T_LOWER_BOUND_EPSILON, and pass the | ||
// result into the ButterflyCurve constructor | ||
curve = new ButterflyCurve(0, 6.2835); | ||
screen = new Screen(curve); | ||
this.add(screen); | ||
} | ||
|
||
public void setUpGui() { | ||
Container c = this.getContentPane(); | ||
c.setBackground(BACKGROUND_COLOUR); | ||
this.setResizable(IS_RESIZABLE); | ||
this.pack(); | ||
this.setTitle("Butterfly Curve"); | ||
this.setLocationRelativeTo(null); | ||
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); | ||
this.setVisible(true); | ||
|
||
new Timer(1, screen.getPainter()).start(); | ||
} | ||
|
||
public ButterflyCurve getCurve() { | ||
return curve; | ||
} | ||
|
||
public Screen getScreen() { | ||
return screen; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
package echau.gui.butterflycurve; | ||
|
||
import javax.swing.SwingUtilities; | ||
|
||
/** | ||
* This project currently features a prototype parametric function - the butterfly function. Allowing | ||
* users to input their own parametric functions is the next step. | ||
*/ | ||
public class Main { | ||
public static void main(String[] args) { | ||
SwingUtilities.invokeLater(new Runnable() { | ||
@Override | ||
public void run() { | ||
new Gui().setUpGui(); | ||
} | ||
}); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
package echau.gui.butterflycurve; | ||
|
||
import java.awt.Color; | ||
import java.awt.Dimension; | ||
import java.awt.Graphics; | ||
import java.awt.event.ActionEvent; | ||
import java.awt.event.ActionListener; | ||
|
||
import javax.swing.JPanel; | ||
|
||
@SuppressWarnings("serial") | ||
/** | ||
* The Screen renders the ParametricCurve. | ||
*/ | ||
public class Screen extends JPanel { | ||
/* Size of the window depends on these constants */ | ||
private static final int WIDTH = 1024; | ||
private static final int HEIGHT = 780; | ||
|
||
// The curve being drawn on the screen | ||
private ButterflyCurve curve; | ||
|
||
// The ActionListener that paints the screen | ||
private final ActionListener painter; | ||
|
||
/* | ||
* An integer from 0 to 2. Each time the curve changes direction, the cycle number increases. | ||
* Every number corresponds to a certain colour with which the curve is drawn. | ||
*/ | ||
private int currentCycle; | ||
|
||
/* Cycle numbers */ | ||
private static final int RED_CYCLE = 0; | ||
private static final int GREEN_CYCLE = 1; | ||
private static final int BLUE_CYCLE = 2; | ||
|
||
// REMEMBER TO CHANGE THIS WHEN YOU ADD MORE CYCLES! | ||
private static final int NUMBER_OF_CYCLES = 3; | ||
|
||
/** | ||
* Construct a Screen on which the specified ParametricCurve will be drawn. | ||
*/ | ||
public Screen(ButterflyCurve curve) { | ||
this.setPreferredSize(new Dimension(WIDTH, HEIGHT)); | ||
this.painter = new ActionListener() { | ||
@Override | ||
public void actionPerformed(ActionEvent e) { | ||
repaint(); | ||
} | ||
}; | ||
|
||
this.curve = curve; | ||
this.currentCycle = 0; | ||
} | ||
|
||
@Override | ||
public void paintComponent(Graphics g) { | ||
curve.update(); | ||
|
||
this.setCurveColour(g); | ||
|
||
if (curve.isChangingDirection()) { | ||
// Change cycle | ||
if (currentCycle == NUMBER_OF_CYCLES - 1) { | ||
currentCycle = 0; | ||
} else { | ||
currentCycle++; | ||
} | ||
} | ||
|
||
g.fillOval((int) (curve.getCurrentXCoord() * 100 + WIDTH * 0.5), (int) (curve.getCurrentYCoord() * -120 + HEIGHT * 0.6), 10, 10); | ||
} | ||
|
||
private void setCurveColour(Graphics g) { | ||
if (currentCycle == RED_CYCLE) { | ||
g.setColor(Color.RED); | ||
} else if (currentCycle == GREEN_CYCLE) { | ||
g.setColor(Color.GREEN); | ||
} else if (currentCycle == BLUE_CYCLE) { | ||
g.setColor(Color.BLUE); | ||
} | ||
} | ||
|
||
/** | ||
* Returns the ActionListener that paints the Screen. | ||
*/ | ||
public ActionListener getPainter() { | ||
return this.painter; | ||
} | ||
} |