add initial files

added files from own repo, updated readme
This commit is contained in:
wompmacho
2020-11-03 14:59:03 -05:00
parent 4c929b3515
commit 93adc494c2
5 changed files with 299 additions and 2 deletions

205
Controller.java Normal file
View 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
View 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);
}
}

View File

@@ -1,2 +1,9 @@
# fractal-tree-draw # Fractal Tree Viewer
Simple Java application that demonstrates recursion by visualizing a fractal tree.
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
View 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>

19
style.css Normal file
View File

@@ -0,0 +1,19 @@
#ANCHORPANE{
-fx-background-color: #87ceeb;
}
#BRANCH_ANGLE_LABEL{
-fx-color: white;
}
.slider{
-fx-color: blue;
}
.slider .axis .axis-tick-mark{
-fx-stroke: green;
}
.slider .axis .axis-minor-tick-mark {
-fx-stroke: grey;
}