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); }
}