1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98
package sample; import javafx.application.Application; import javafx.scene.Scene; import javafx.scene.canvas.Canvas; import javafx.scene.canvas.GraphicsContext; import javafx.scene.layout.BorderPane; import javafx.scene.paint.Color; import javafx.stage.Stage; public class _tree3d extends Application { public static void main(String... args) { Application.launch(args); } private static final int VIEW_W = 400, VIEW_H = 300; private GraphicsContext gc; private _transform tf; @Override public void start(Stage stage) throws Exception { BorderPane pane = new BorderPane(); stage.setScene(new Scene(pane)); Canvas view = new Canvas(VIEW_W, VIEW_H); gc = view.getGraphicsContext2D(); tf = new _transform(); tf.angle(-10, 15); tf.position(0, -80, 0); tf.add_angle_listener(stage.getScene(), () -> { draw(); }); pane.setCenter(view); draw(); stage.show(); } private double[][] rot_x(double t) { t *= Math.PI / 180; double ct = Math.cos(t), st = Math.sin(t); return new double[][] { {1, 0, 0}, {0, ct, st}, {0, -st, ct} }; } private double[][] rot_y(double t) { t *= Math.PI / 180; double ct = Math.cos(t), st = Math.sin(t); return new double[][] { {ct, 0, -st}, {0, 1, 0}, {st, 0, ct} }; } private double[] mul(double[][] m, double[] v) { double[] ret_v = new double[3]; for (int i = 0; i < 3; i++) ret_v[i] = m[0][i] * v[0] + m[1][i] * v[1] + m[2][i] * v[2]; return ret_v; } private double[][] mul(double[][] m, double[][] n) { double[][] ret_m = new double[3][]; for (int i = 0; i < 3; i++) ret_m[i] = mul(m, n[i]); return ret_m; } private static final int N = 6, A = 22, BRANCH_N = 3; private double[][] points = new double[N + 1][]; private void add_vector_and_draw(double[] v, int n) { double[] curr = project(tf.mul(v[0], v[1], v[2])); points[n] = curr; if (n == N) return; double[] prev = points[n + 1]; gc.beginPath(); gc.moveTo(prev[0], prev[1]); gc.lineTo(curr[0], curr[1]); gc.stroke(); } private double[][] curr_m = {{1, 0, 0}, {0, 1, 0}, {0, 0, 1}}; private void draw() { gc.setTransform(1, 0, 0, 1, 0, 0); gc.clearRect(0, 0, VIEW_W, VIEW_H); gc.setTransform(1, 0, 0, -1, VIEW_W / 2, VIEW_H / 2); double[] p = {0, 0, 0}; add_vector_and_draw(p, N); tree(p, 45, N); } private double[][] enter_x = rot_x(A), exit_x = rot_x(-A); private double[][] turn_y = rot_y(360.0 / BRANCH_N); private void tree(double[] p, double len, int n) { n--; double[] q = new double[3], y = curr_m[1]; gc.setStroke(Color.BLACK); for (int i = 0; i < 3; i++) q[i] = p[i] + y[i] * len; add_vector_and_draw(q, n); if (n == 0) return; for (int i = 0; i < BRANCH_N; i++) { curr_m = mul(curr_m, enter_x); tree(q, len * 0.8, n); curr_m = mul(curr_m, exit_x); curr_m = mul(curr_m, turn_y); } } private double[] project(double[] v) { double z = v[2] / 200 + 1; v[0] *= 1.5 / z; v[1] *= 1.5 / z; return v; } }