Question
I am working on a java project which asks me to draw four fractals. Koch Curve, Tree, Sierpinski Triangle, and Sierpinski Carpet. I have three
I am working on a java project which asks me to draw four fractals. Koch Curve, Tree, Sierpinski Triangle, and Sierpinski Carpet.
I have three java files, one is the Fractal.java which I have to work on. The second file turtle.java is a helper class to assist me drawing fractals. The third file is a FractalGUI.java.
Here is the Fractal.java:
package fractal;
import fractal.Turtle;
import java.awt.*;
import java.awt.geom.*;
/**
* A class that implements some basic fractal drawing methods using recursion.
* These methods include the Koch curve, tree, Sierpinski triangle and carpet.
*/
public class Fractal {
private Graphics2D g2d = null; // a Graphics2D object as canvas for drawing
private int width=0, height=0; // image width and height
private int max_recursion_level = 0; // maximum recursion level
private String fractal_type = "Koch Curve"; // type of fractal
private Color color = Color.green; // draw color
public void setGraphics(Graphics g, int w, int h) {
g2d = (Graphics2D)g; width = w; height = h;
}
public void setFractalType(String t) { fractal_type = t; }
public void setColor(Color c) { color = c; }
public void setMaxRecursion(int n) { max_recursion_level = n; }
// Recursive method for drawing the Koch curve given two points and the recursion level
private void drawKochCurve(Point2D p1, Point2D p2, int level) {
if(level==0) { // base case
drawLine(p1, p2);
return;
}
// TODO
// Koch subdivision rule: ___ -> _/\_
}
// Recursive method for drawing a fractal Tree given two points and the recursion level
private void drawTree(Point2D p1, Point2D p2, int level) {
if(level==0) { // base case
drawLine(p1, p2);
return;
}
// TODO
}
// Recursive method for drawing the Sierpinski Triangle given the three points
// that define the triangle and the recursion level
private void drawSierpinskiTriangle(Point2D p1, Point2D p2, Point2D p3, int level) {
if(level==0) { // base case
drawTriangle(p1, p2, p3);
return;
}
// TODO
}
// Recursive method for drawing the Sierpinski Carpet given the lower-left corner
// of the square (p), the side length (a) of the square, and the recursion level
private void drawSierpinskiCarpet(Point2D p, double a, int level) {
if(level==0) { // base case
drawRectangle(p, a, a);
return;
}
// TODO
}
// This method is left for you to experiment with creative fractals
// designed by yourself. You will NOT be graded on this method
void drawMyFractal(/* other parameters that you may need */ int level) {
if(level==0) { // base case
return;
}
/* Your creative fractal shape */
}
/** The code below provides utility methods.
* You should NOT need to modify any code below.
*/
public void draw() {
if(g2d==null || width==0 || height==0) return;
g2d.setBackground(Color.black);
g2d.clearRect(0, 0, width, height);
g2d.setColor(color);
if(fractal_type.equalsIgnoreCase("Koch Curve")) {
drawKochCurve(new Point2D.Double(0.0, 0.4), new Point2D.Double(1.0, 0.4), max_recursion_level);
} else if(fractal_type.equalsIgnoreCase("Snowflake")) {
double r = 0.5;
Point2D p1 = new Point2D.Double(r*Math.cos(Math.toRadians(150))+0.5,
r*Math.sin(Math.toRadians(150))+0.5);
Point2D p2 = new Point2D.Double(r*Math.cos(Math.toRadians(30))+0.5,
r*Math.sin(Math.toRadians(30))+0.5);
Point2D p3 = new Point2D.Double(r*Math.cos(Math.toRadians(-90))+0.5,
r*Math.sin(Math.toRadians(-90))+0.5);
// Snowflake is made of three Koch curves segments
// p1____p2
// \ /
// \/
// p3
drawKochCurve(p1, p2, max_recursion_level);
drawKochCurve(p2, p3, max_recursion_level);
drawKochCurve(p3, p1, max_recursion_level);
} else if(fractal_type.equalsIgnoreCase("Tree")) {
// double the maximum recursion level because tree subdivides very slowly
drawTree(new Point2D.Double(0.6, 0.1), new Point2D.Double(0.6, 0.9),
max_recursion_level*2);
} else if(fractal_type.equalsIgnoreCase("Sp Triangle")) {
double r = 0.5;
Point2D p1 = new Point2D.Double(r*Math.cos(Math.toRadians(90))+0.5,
r*Math.sin(Math.toRadians(90))+0.5);
Point2D p2 = new Point2D.Double(r*Math.cos(Math.toRadians(-150))+0.5,
r*Math.sin(Math.toRadians(-150))+0.5);
Point2D p3 = new Point2D.Double(r*Math.cos(Math.toRadians(-30))+0.5,
r*Math.sin(Math.toRadians(-30))+0.5);
drawSierpinskiTriangle(p1, p2, p3, max_recursion_level);
} else if(fractal_type.equalsIgnoreCase("Sp Carpet")) {
drawSierpinskiCarpet(new Point2D.Double(0, 0), 1, max_recursion_level);
} else {
drawMyFractal(/* other parameters that you may need */ max_recursion_level);
}
}
/** Draw a straight line between two points P1 and P2.
* The given x and y values of p1 and p2 are assumed to be within [0, 1] (i.e. normalized).
* This allows our fractals to be resolution-independent. The method below converts the normalized
* coordinates to integer coordinates based on the actual image resolution.
*/
private void drawLine(Point2D p1, Point2D p2) {
int x1 = (int)(p1.getX()*width);
int x2 = (int)(p2.getX()*width);
// flip the Y coordinate
// because screen Y axis is flipped from mathematical Y axis
int y1 = (int)((1.0-p1.getY())*height);
int y2 = (int)((1.0-p2.getY())*height);
g2d.drawLine(x1, y1, x2, y2);
}
// Draw a solid rectangle given its lower left corner and its size
private void drawRectangle(Point2D p, double w, double h) {
int x0 = (int)(p.getX()*width);
int y0 = (int)((1.0-p.getY())*height);
int x1 = (int)((p.getX()+w)*width);;
int y1 = (int)((1.0-(p.getY()+h))*height);
int xpoints[] = {x0, x0, x1, x1};
int ypoints[] = {y0, y1, y1, y0};
g2d.fillPolygon(xpoints, ypoints, 4);
}
// Draw a solid triangle given its three vertices
private void drawTriangle(Point2D p1, Point2D p2, Point2D p3) {
int xpoints[] = {(int)(p1.getX()*width),
(int)(p2.getX()*width),
(int)(p3.getX()*width)};
int ypoints[] = {(int)((1.0-p1.getY())*height),
(int)((1.0-p2.getY())*height),
(int)((1.0-p3.getY())*height)};
g2d.fillPolygon(xpoints, ypoints, 3);
}
}
Here is the Turtle.java:
package fractal;
import java.awt.geom.Point2D;
/** This is a helper class to assist you in drawing fractals
* YOU DO NOT NEED TO MODIFY ANYTHING HERE
*/
public class Turtle {
private Point2D pos; // current position
private Point2D dir; // direction the turtle is heading to
/** Constructor: the arguments are the initial position of the turtle
* and the target position it's heading to.
*/
public Turtle(Point2D start, Point2D target) {
pos = new Point2D.Double(start.getX(), start.getY()); // clone the position
double dx = target.getX()-pos.getX();
double dy = target.getY()-pos.getY();
double length = start.distance(target);
dir = new Point2D.Double(dx/length, dy/length); // normalize the direction vector
}
// return the current position
public Point2D getPosition() { return pos; }
// move by a given distance, for example 0.1
// this distance can also be negative, in which case if will move backward
public void move(double distance) {
pos = new Point2D.Double(pos.getX(), pos.getY()); // clone to a new point
pos.setLocation(pos.getX()+distance*dir.getX(),
pos.getY()+distance*dir.getY());
}
// set the direction of the turtle to turn left by a certain number of degrees, e.g. 60
// you can also use a negative number, in which case it turns right
public void turnLeft(double degrees) {
double radians = Math.toRadians(degrees);
double new_dx = Math.cos(radians)*dir.getX() - Math.sin(radians)*dir.getY();
double new_dy = Math.sin(radians)*dir.getX() + Math.cos(radians)*dir.getY();
dir.setLocation(new_dx, new_dy);
}
// set the direction of the turtle to turn left by a certain number of degrees, e.g. 60
public void turnRight(double degrees) {
turnLeft(-degrees);
}
}
Here is the FractalGUI.java:
package fractal;
import java.awt.*;
import java.awt.image.*;
import java.io.File;
import javax.imageio.ImageIO;
import javax.swing.*;
@SuppressWarnings("serial")
class FractalGUI extends JFrame {
// Window size. Reduce if it doesn't fit your screen
private static final int winw = 650, winh = 650;
private JButton jButton1;
private JButton jButton2;
private JButton jButton3;
private JButton jButton4;
private JButton jButton5;
private JButton jButton6;
private JSlider jSlider1;
private BufferedImage image = new BufferedImage(winw, winh, BufferedImage.TYPE_INT_RGB);
private JPanel jPanel1;
private Fractal fractal;
public FractalGUI() {
jButton1 = new JButton();
jButton2 = new JButton();
jButton3 = new JButton();
jButton4 = new JButton();
jButton5 = new JButton();
jButton6 = new JButton();
jSlider1 = new JSlider();
JLabel jLabel1 = new JLabel();
jPanel1 = new JPanel();
jButton1.setText("Koch Curve");
jButton1.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
jButtonActionPerformed(evt);
}
});
jButton2.setText("Snowflake");
jButton2.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
jButtonActionPerformed(evt);
}
});
jButton3.setText("Tree");
jButton3.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
jButtonActionPerformed(evt);
}
});
jButton4.setText("Sp Triangle");
jButton4.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
jButtonActionPerformed(evt);
}
});
jButton5.setText("Sp Carpet");
jButton5.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
jButtonActionPerformed(evt);
}
});
jButton6.setText("My Fractal");
jButton6.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
jButtonActionPerformed(evt);
}
});
jSlider1.setMajorTickSpacing(1);
jSlider1.setMaximum(6);
jSlider1.setMinimum(0);
jSlider1.setMinorTickSpacing(1);
jSlider1.setPaintTicks(true);
jSlider1.setSnapToTicks(true);
jSlider1.createStandardLabels(1);
jSlider1.setPaintLabels(true);
jSlider1.setValue(0);
jSlider1.addChangeListener(new javax.swing.event.ChangeListener() {
public void stateChanged(javax.swing.event.ChangeEvent evt) {
jSlider1StateChanged(evt);
}
});
jLabel1.setText("Recursion Level");
jPanel1.setBackground(Color.black);
jPanel1.setPreferredSize(new java.awt.Dimension(winw, winh));
javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1);
jPanel1.setLayout(jPanel1Layout);
jPanel1Layout.setHorizontalGroup(
jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, winw, Short.MAX_VALUE)
);
jPanel1Layout.setVerticalGroup(
jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, winh, Short.MAX_VALUE)
);
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
getContentPane().setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false)
.addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createSequentialGroup()
.addComponent(jLabel1)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(jSlider1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
.addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createSequentialGroup()
.addComponent(jButton1)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jButton2)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jButton3)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jButton4)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jButton5)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jButton6))))
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(jButton1)
.addComponent(jButton2)
.addComponent(jButton3)
.addComponent(jButton4)
.addComponent(jButton5)
.addComponent(jButton6))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jLabel1)
.addComponent(jSlider1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addGap(18, 18, 18)
.addComponent(jPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addContainerGap())
);
pack();
fractal = new Fractal();
fractal.setGraphics(image.getGraphics(), winw, winh);
}
public void initdraw() {
jButton1.doClick();
}
public void redraw() {
fractal.draw();
jPanel1.getGraphics().drawImage(image, 0, 0, null);
// enable the section below to save the image to a PNG file
/*try {
File file = new File("output.png");
ImageIO.write(image, "png", file);
} catch(Exception e) {}*/
}
private void jButtonActionPerformed(java.awt.event.ActionEvent evt) {
fractal.setFractalType(evt.getActionCommand());
redraw();
}
private void jSlider1StateChanged(javax.swing.event.ChangeEvent evt) {
fractal.setMaxRecursion(jSlider1.getValue());
redraw();
}
public static void main(String[] args) {
// initialization code to set up Jframe
FractalGUI gui = new FractalGUI();
gui.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
gui.setTitle("Fun with Fractals");
gui.setLocationRelativeTo(null);
gui.setVisible(true);
gui.initdraw();
}
}
Please help me on this one and I will rate.
Step by Step Solution
There are 3 Steps involved in it
Step: 1
Get Instant Access to Expert-Tailored Solutions
See step-by-step solutions with expert insights and AI powered tools for academic success
Step: 2
Step: 3
Ace Your Homework with AI
Get the answers you need in no time with our AI-driven, step-by-step assistance
Get Started