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
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.stage.Stage; public class _suzuka_circuit extends Application { public static void main(String... args) { Application.launch(args); } private static final int VIEW_W = 400, VIEW_H = 300; private GraphicsContext gc; @Override public void start(Stage stage) throws Exception { BorderPane pane = new BorderPane(); Scene scene = new Scene(pane); stage.setScene(scene); Canvas view = new Canvas(VIEW_W, VIEW_H); pane.setCenter(view); gc = view.getGraphicsContext2D(); draw(); stage.show(); } private double[][] circuit = { {60, 15, -15}, {20}, {4, 180}, {4, -30}, {4, 60}, {4, -60}, {4, 60}, {4, -105}, {15}, {4, 135}, {30}, {6, 15}, {10}, {3, -180}, {15}, {15, 120}, {6, -225}, {20}, {15, -15}, }; private double curr_x, curr_y, curr_a; private static final double MIN_A = 5, MAX_A = 270, MIN_R = 2; private static final String ERR_A = "最終コーナーの角度が範囲外", ERR_R = "最終コーナーの半径が小さい", ERR_L = "最終ストレートの距離がマイナス" ; private void draw() { gc.setTransform(4, 0, 0, 4, 0, 0); double[] part = circuit[0]; double start_x = part[0], start_y = part[1], start_a = part[2]; curr_x = start_x; curr_y = start_y; curr_a = start_a; gc.beginPath(); gc.moveTo(curr_x, curr_y); for (int i = 1; i < circuit.length; i++) draw_circuit_part(circuit[i]); // 最終ストレートとコーナーを求める double dx = start_x - curr_x, dy = start_y - curr_y; double l = dx * my_cos(curr_a) + dy * my_sin(curr_a); double r = dx * my_cos(curr_a + 90) + dy * my_sin(curr_a + 90); double sign = Math.signum(r); double da = Math.abs(start_a - curr_a); if ((curr_a > start_a) == (sign > 0)) da = 360 - da; if (da < MIN_A || da > MAX_A) throw new InternalError(ERR_A); r = Math.abs(r) / (1 - my_cos(da)); if (r < MIN_R) throw new InternalError(ERR_R); l -= r * my_sin(da); if (l < 0) throw new InternalError(ERR_L); draw_circuit_part(l); draw_circuit_part(r, sign * da); gc.stroke(); } private void draw_circuit_part(double... part) { if (part.length == 1) { // ストレート double l = part[0]; curr_x += l * my_cos(curr_a); curr_y += l * my_sin(curr_a); } else if (part.length == 2) { // コーナー double r = part[0]; double da = part[1]; double sign = Math.signum(da); double center_x = curr_x + sign * r * my_cos(curr_a + 90); double center_y = curr_y + sign * r * my_sin(curr_a + 90); gc.arc(center_x, center_y, r, r, sign * 90 - curr_a, -da); curr_a += da; curr_x = center_x + r * my_cos(curr_a - sign * 90); curr_y = center_y + r * my_sin(curr_a - sign * 90); } } private static final double RAD = Math.PI / 180; private double my_sin(double a) { return Math.sin(a * RAD); } private double my_cos(double a) { return Math.cos(a * RAD); } }