add initial files
added files from own repo, updated readme
This commit is contained in:
205
Controller.java
Normal file
205
Controller.java
Normal file
@@ -0,0 +1,205 @@
|
||||
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");
|
||||
}
|
||||
}
|
||||
27
Main.java
Normal file
27
Main.java
Normal file
@@ -0,0 +1,27 @@
|
||||
package fractalTreeDraw;
|
||||
|
||||
import javafx.application.Application;
|
||||
import javafx.fxml.FXMLLoader;
|
||||
import javafx.scene.Parent;
|
||||
import javafx.scene.Scene;
|
||||
import javafx.stage.Stage;
|
||||
|
||||
public class Main extends Application {
|
||||
|
||||
@Override
|
||||
public void start(Stage stage) throws Exception {
|
||||
Parent root = FXMLLoader.load(getClass().getResource("scene.fxml"));
|
||||
root.getStylesheets().add(getClass().getResource("style.css").toExternalForm());
|
||||
stage.setTitle("Fractal Tree Viewer");
|
||||
stage.setScene(new Scene(root));
|
||||
stage.show();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param args the command line arguments
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
launch(args);
|
||||
}
|
||||
|
||||
}
|
||||
11
README.md
11
README.md
@@ -1,2 +1,9 @@
|
||||
# fractal-tree-draw
|
||||
Simple Java application that demonstrates recursion by visualizing a fractal tree.
|
||||
# Fractal Tree Viewer
|
||||
|
||||
This is a simple Java application that demonstrates recursion by visualizing a fractal tree. It takes in an input for
|
||||
length, angle and the number of child nodes and draws to a canvas. These inputs can then be manipulated by the sliders
|
||||
and text field. It utilizes Java, JavaFX, FXML and CSS.
|
||||
|
||||
// TODO:
|
||||
make object oriented for multiple tree and shape types
|
||||
remove canvas from controller so that we can resize canvas to parent but also draw on init
|
||||
39
scene.fxml
Normal file
39
scene.fxml
Normal file
@@ -0,0 +1,39 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<?import javafx.scene.canvas.Canvas?>
|
||||
<?import javafx.scene.control.CheckBox?>
|
||||
<?import javafx.scene.control.Label?>
|
||||
<?import javafx.scene.control.Slider?>
|
||||
<?import javafx.scene.control.TextField?>
|
||||
<?import javafx.scene.layout.AnchorPane?>
|
||||
<?import javafx.scene.text.Font?>
|
||||
|
||||
<AnchorPane fx:id="ANCHORPANE" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="500.0" prefWidth="800.0" xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="fractalTreeDraw.Controller">
|
||||
<children>
|
||||
<Canvas fx:id="CANVAS" height="500.0" onMouseClicked="#handleMouseClicked" width="800.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0" />
|
||||
<AnchorPane layoutX="14.0" layoutY="440.0" prefHeight="46.0" prefWidth="325.0" AnchorPane.bottomAnchor="14.0" AnchorPane.leftAnchor="14.0">
|
||||
<children>
|
||||
<TextField fx:id="TEXTFIELD" layoutX="216.0" layoutY="10.0" onKeyPressed="#handleKeyPressed" prefHeight="30.0" prefWidth="87.0" AnchorPane.bottomAnchor="10.0" AnchorPane.leftAnchor="216.0" AnchorPane.rightAnchor="22.0" AnchorPane.topAnchor="10.0" />
|
||||
<AnchorPane prefHeight="38.0" prefWidth="175.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.topAnchor="0.0">
|
||||
<children>
|
||||
<Slider fx:id="ANGLE_SLIDER" layoutX="16.0" layoutY="20.0" onMouseDragged="#handleSliderDrag" prefHeight="16.0" prefWidth="143.0" showTickMarks="true" AnchorPane.bottomAnchor="2.0" AnchorPane.leftAnchor="16.0" AnchorPane.rightAnchor="16.0" AnchorPane.topAnchor="20.0" />
|
||||
<Label fx:id="BRANCH_ANGLE_LABEL" layoutX="1.0" layoutY="-2.0" prefHeight="17.0" prefWidth="87.0" text="Branch Angle" AnchorPane.leftAnchor="0.0" AnchorPane.topAnchor="0.0">
|
||||
<font>
|
||||
<Font size="13.0" />
|
||||
</font></Label>
|
||||
<CheckBox fx:id="CHECKBOX_RANDOM" layoutX="109.0" layoutY="-1.0" mnemonicParsing="false" onAction="#handleCheckBox" text="Symmetrical" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0" />
|
||||
</children>
|
||||
</AnchorPane>
|
||||
</children>
|
||||
</AnchorPane>
|
||||
<AnchorPane layoutX="623.0" layoutY="259.0" prefHeight="227.0" prefWidth="163.0" AnchorPane.bottomAnchor="14.0" AnchorPane.rightAnchor="14.0">
|
||||
<children>
|
||||
<Slider fx:id="LENGTH_SLIDER" layoutX="142.0" layoutY="33.0" onMouseDragged="#handleSliderDrag" orientation="VERTICAL" showTickMarks="true" AnchorPane.bottomAnchor="11.0" AnchorPane.rightAnchor="16.0" AnchorPane.topAnchor="11.0" />
|
||||
<Label fx:id="BRANCH_LENGTH_LABEL" layoutX="43.0" layoutY="127.0" text="Branch Length" AnchorPane.bottomAnchor="43.0" AnchorPane.rightAnchor="43.0">
|
||||
<font>
|
||||
<Font size="14.0" />
|
||||
</font></Label>
|
||||
</children>
|
||||
</AnchorPane>
|
||||
</children>
|
||||
</AnchorPane>
|
||||
Reference in New Issue
Block a user