205 lines
6.5 KiB
Java
205 lines
6.5 KiB
Java
package fractalTreeDraw;
|
|
|
|
import javafx.event.ActionEvent;
|
|
import javafx.fxml.FXML;
|
|
import javafx.fxml.Initializable;
|
|
import javafx.scene.canvas.Canvas;
|
|
import javafx.scene.canvas.GraphicsContext;
|
|
import javafx.scene.control.CheckBox;
|
|
import javafx.scene.control.Slider;
|
|
import javafx.scene.control.TextField;
|
|
import javafx.scene.control.Tooltip;
|
|
import javafx.scene.input.KeyCode;
|
|
import javafx.scene.input.KeyEvent;
|
|
import javafx.scene.input.MouseEvent;
|
|
import javafx.scene.layout.AnchorPane;
|
|
import javafx.scene.paint.Color;
|
|
import javafx.scene.shape.StrokeLineCap;
|
|
|
|
import java.net.URL;
|
|
import java.util.ResourceBundle;
|
|
import java.util.concurrent.TimeUnit;
|
|
|
|
public class Controller extends Canvas implements Initializable {
|
|
|
|
@FXML
|
|
private Canvas CANVAS = new Canvas();
|
|
|
|
@FXML
|
|
private AnchorPane ANCHORPANE = new AnchorPane();
|
|
|
|
@FXML
|
|
private Slider ANGLE_SLIDER = new Slider();
|
|
|
|
@FXML
|
|
private Slider LENGTH_SLIDER = new Slider();
|
|
|
|
@FXML
|
|
private TextField TEXTFIELD = new TextField();
|
|
|
|
@FXML
|
|
private CheckBox CHECKBOX_RANDOM = new CheckBox();
|
|
|
|
private GraphicsContext GRAPHICSCONTEXT;
|
|
private double ANGLE = 25;
|
|
private double TRUNK_LENGTH = 165;
|
|
private double TRUNK_WIDTH = 15;
|
|
private double DEPTH = 10;
|
|
private double RIGHT_BRANCH_RANDOM_NUMBER = 1;
|
|
private double LEFT_BRANCH_RANDOM_NUMBER = 1;
|
|
//private double GOLDEN_RATIO = (1 - Math.sqrt(5)) / 2;
|
|
|
|
// Clears canvas, moves to drawing position, calls branch(), moves back to start
|
|
private void drawFractalTree(double TRUNK_LENGTH, double TRUNK_WIDTH, double DEPTH) {
|
|
|
|
// set center translation
|
|
double width = CANVAS.getWidth();
|
|
double height = CANVAS.getHeight();
|
|
|
|
// Clear Canvas
|
|
GRAPHICSCONTEXT.clearRect(0, 0, width, height);
|
|
|
|
// move to Start position
|
|
GRAPHICSCONTEXT.translate(width / 2, height);
|
|
|
|
// create tree
|
|
GRAPHICSCONTEXT.setLineWidth(1);
|
|
branch(TRUNK_LENGTH, TRUNK_WIDTH, DEPTH);
|
|
|
|
// return to Start
|
|
GRAPHICSCONTEXT.translate(0, TRUNK_LENGTH);
|
|
|
|
// return to 0,0
|
|
GRAPHICSCONTEXT.translate(-(width / 2), -height);
|
|
}
|
|
|
|
// draws branches
|
|
private void branch(double TRUNK_LENGTH, double TRUNK_WIDTH, double DEPTH) {
|
|
|
|
// Set trunk width
|
|
GRAPHICSCONTEXT.setLineWidth(TRUNK_WIDTH);
|
|
|
|
GRAPHICSCONTEXT.setLineCap(StrokeLineCap.ROUND);
|
|
|
|
// Set color based on trunkSize
|
|
if (DEPTH <= 2) {
|
|
GRAPHICSCONTEXT.setStroke(Color.rgb(0, 50, 0));
|
|
} else {
|
|
GRAPHICSCONTEXT.setStroke(Color.rgb(50, 25, 0));
|
|
}
|
|
|
|
// draw line
|
|
GRAPHICSCONTEXT.strokeLine(0, 0, 0, -TRUNK_LENGTH);
|
|
|
|
// translate to end of line drawn
|
|
GRAPHICSCONTEXT.translate(0, -TRUNK_LENGTH);
|
|
|
|
// return if at end of depth
|
|
if (DEPTH < 1) {
|
|
GRAPHICSCONTEXT.setStroke(Color.rgb(50, 150, 0));
|
|
GRAPHICSCONTEXT.strokeOval(-TRUNK_WIDTH, -TRUNK_WIDTH, 5, 10);
|
|
return;
|
|
}
|
|
|
|
// Right Branch
|
|
GRAPHICSCONTEXT.rotate(ANGLE * RIGHT_BRANCH_RANDOM_NUMBER);
|
|
branch(TRUNK_LENGTH * 2/3, TRUNK_WIDTH * 2/3, DEPTH - 1);
|
|
GRAPHICSCONTEXT.translate(0, TRUNK_LENGTH * 2/3);
|
|
GRAPHICSCONTEXT.rotate(-ANGLE * RIGHT_BRANCH_RANDOM_NUMBER);
|
|
|
|
// Left Branch
|
|
GRAPHICSCONTEXT.rotate(-ANGLE * LEFT_BRANCH_RANDOM_NUMBER);
|
|
branch(TRUNK_LENGTH * 2/3, TRUNK_WIDTH * 2/3, DEPTH - 1);
|
|
GRAPHICSCONTEXT.translate(0, TRUNK_LENGTH * 2/3);
|
|
GRAPHICSCONTEXT.rotate(ANGLE * LEFT_BRANCH_RANDOM_NUMBER);
|
|
|
|
}
|
|
|
|
private void sleep(int i) {
|
|
try {
|
|
TimeUnit.MICROSECONDS.sleep(100);
|
|
} catch (Exception e) {
|
|
e.printStackTrace();
|
|
}
|
|
}
|
|
|
|
public void handleKeyPressed(KeyEvent keyEvent) {
|
|
//System.out.println(keyEvent.getCode());
|
|
if (keyEvent.getCode().equals(KeyCode.ENTER)) {
|
|
|
|
try {
|
|
double MESSAGE = Integer.parseInt(TEXTFIELD.getText());
|
|
DEPTH = MESSAGE;
|
|
drawFractalTree(TRUNK_LENGTH, TRUNK_WIDTH, DEPTH);
|
|
} catch (NumberFormatException nfe) {
|
|
TEXTFIELD.setText("# please");
|
|
System.out.println("NumberFormatException: " + nfe.getMessage());
|
|
}
|
|
}
|
|
}
|
|
|
|
public void handleMouseClicked(MouseEvent mouseEvent) {
|
|
TEXTFIELD.setText("Children: " + DEPTH);
|
|
|
|
drawFractalTree(TRUNK_LENGTH, TRUNK_WIDTH, DEPTH);
|
|
System.out.println("Mouse click");
|
|
}
|
|
|
|
public void handleSliderDrag(MouseEvent mouseEvent) {
|
|
ANGLE = ANGLE_SLIDER.getValue();
|
|
TRUNK_LENGTH = LENGTH_SLIDER.getValue();
|
|
drawFractalTree(TRUNK_LENGTH, TRUNK_WIDTH, DEPTH);
|
|
System.out.println("DRAGGED. Angle :" + ANGLE + "| LENGTH: " + TRUNK_LENGTH);
|
|
}
|
|
|
|
public void handleCheckBox(ActionEvent event) {
|
|
|
|
// If box checked
|
|
if (CHECKBOX_RANDOM.isSelected()) {
|
|
CHECKBOX_RANDOM.setText("Asymmetrical");
|
|
randomNumber();
|
|
System.out.println("Asymmetrical: " + RIGHT_BRANCH_RANDOM_NUMBER + "|" + LEFT_BRANCH_RANDOM_NUMBER);
|
|
} else {
|
|
CHECKBOX_RANDOM.setText("Symmetrical");
|
|
RIGHT_BRANCH_RANDOM_NUMBER = 1;
|
|
LEFT_BRANCH_RANDOM_NUMBER = 1;
|
|
ANGLE = ANGLE_SLIDER.getValue();
|
|
System.out.println("Binary tree selected");
|
|
}
|
|
drawFractalTree(TRUNK_LENGTH, TRUNK_WIDTH, DEPTH);
|
|
}
|
|
|
|
private void randomNumber() {
|
|
// define the range
|
|
double min = 1;
|
|
double max = Math.PI;
|
|
double range = max - min + 1;
|
|
|
|
// generate random number within range
|
|
RIGHT_BRANCH_RANDOM_NUMBER = (Math.random() * range) + min;
|
|
LEFT_BRANCH_RANDOM_NUMBER = (Math.random() * range) + min;
|
|
}
|
|
|
|
@Override
|
|
public void initialize(URL url, ResourceBundle resourceBundle) {
|
|
// Set angle slider Defaults
|
|
ANGLE_SLIDER.setMax(90);
|
|
ANGLE_SLIDER.setValue(25);
|
|
ANGLE_SLIDER.setTooltip(new Tooltip("0-180"));
|
|
|
|
// Set length slider Defaults
|
|
LENGTH_SLIDER.setMax(1000);
|
|
LENGTH_SLIDER.setValue(165);
|
|
LENGTH_SLIDER.setTooltip(new Tooltip("0-1000"));
|
|
|
|
// Tooltip for depth
|
|
Tooltip tip = new Tooltip("Careful... this is recursive...");
|
|
TEXTFIELD.setTooltip(tip);
|
|
|
|
// Resizable Canvas
|
|
CANVAS.widthProperty().bind(ANCHORPANE.widthProperty());
|
|
CANVAS.heightProperty().bind(ANCHORPANE.heightProperty());
|
|
GRAPHICSCONTEXT = CANVAS.getGraphicsContext2D();
|
|
System.out.println("INIT");
|
|
}
|
|
} |