1 package org.opentrafficsim.core.geometry;
2
3 import java.util.Arrays;
4
5 import org.djutils.draw.point.Point2d;
6 import org.djutils.exceptions.Throw;
7
8
9
10
11
12
13
14
15
16
17
18
19 public class ContinuousBezier
20 {
21
22
23 private static final double[] T =
24 new double[] {-0.0640568928626056260850430826247450385909, 0.0640568928626056260850430826247450385909,
25 -0.1911188674736163091586398207570696318404, 0.1911188674736163091586398207570696318404,
26 -0.3150426796961633743867932913198102407864, 0.3150426796961633743867932913198102407864,
27 -0.4337935076260451384870842319133497124524, 0.4337935076260451384870842319133497124524,
28 -0.5454214713888395356583756172183723700107, 0.5454214713888395356583756172183723700107,
29 -0.6480936519369755692524957869107476266696, 0.6480936519369755692524957869107476266696,
30 -0.7401241915785543642438281030999784255232, 0.7401241915785543642438281030999784255232,
31 -0.8200019859739029219539498726697452080761, 0.8200019859739029219539498726697452080761,
32 -0.8864155270044010342131543419821967550873, 0.8864155270044010342131543419821967550873,
33 -0.9382745520027327585236490017087214496548, 0.9382745520027327585236490017087214496548,
34 -0.9747285559713094981983919930081690617411, 0.9747285559713094981983919930081690617411,
35 -0.9951872199970213601799974097007368118745, 0.9951872199970213601799974097007368118745};
36
37
38 private static final double[] C =
39 new double[] {0.1279381953467521569740561652246953718517, 0.1279381953467521569740561652246953718517,
40 0.1258374563468282961213753825111836887264, 0.1258374563468282961213753825111836887264,
41 0.121670472927803391204463153476262425607, 0.121670472927803391204463153476262425607,
42 0.1155056680537256013533444839067835598622, 0.1155056680537256013533444839067835598622,
43 0.1074442701159656347825773424466062227946, 0.1074442701159656347825773424466062227946,
44 0.0976186521041138882698806644642471544279, 0.0976186521041138882698806644642471544279,
45 0.086190161531953275917185202983742667185, 0.086190161531953275917185202983742667185,
46 0.0733464814110803057340336152531165181193, 0.0733464814110803057340336152531165181193,
47 0.0592985849154367807463677585001085845412, 0.0592985849154367807463677585001085845412,
48 0.0442774388174198061686027482113382288593, 0.0442774388174198061686027482113382288593,
49 0.0285313886289336631813078159518782864491, 0.0285313886289336631813078159518782864491,
50 0.0123412297999871995468056670700372915759, 0.0123412297999871995468056670700372915759};
51
52
53 protected Point2d[] points;
54
55
56
57
58
59 public ContinuousBezier(final Point2d... points)
60 {
61 Throw.whenNull(points, "Points may not be null.");
62 Throw.when(points.length < 2, IllegalArgumentException.class, "Minimum number of points is 2.");
63 for (Point2d point : points)
64 {
65 Throw.whenNull(point, "One of the points is null.");
66 }
67 this.points = points;
68 }
69
70
71
72
73
74 public ContinuousBezier derivative()
75 {
76 Throw.when(this.points.length < 2, IllegalStateException.class,
77 "Requesting derivative on Bezier with less than 2 points");
78 int n = this.points.length - 1;
79 Point2d[] derivativePoints = new Point2d[n];
80 for (int i = 0; i < n; i++)
81 {
82 derivativePoints[i] =
83 new Point2d(n * (this.points[i + 1].x - this.points[i].x), n * (this.points[i + 1].y - this.points[i].y));
84 }
85 return new ContinuousBezier(derivativePoints);
86 }
87
88
89
90
91
92 public double length()
93 {
94 double len = 0.0;
95 for (int i = 0; i < T.length; i++)
96 {
97 double t = 0.5 * T[i] + 0.5;
98 Point2d p = derivative().at(t);
99 len += C[i] * Math.hypot(p.x, p.y);
100 }
101 len *= 0.5;
102 return len;
103 }
104
105
106
107
108
109
110 public Point2d at(final double t)
111 {
112 double[] x = new double[this.points.length];
113 double[] y = new double[this.points.length];
114 for (int j = 0; j < this.points.length; j++)
115 {
116 x[j] = this.points[j].x;
117 y[j] = this.points[j].y;
118 }
119 return new Point2d(Bezier.Bn(t, x), Bezier.Bn(t, y));
120 }
121
122
123
124
125
126
127 public double curvature(final double t)
128 {
129 ContinuousBezier der = derivative();
130 Point2d d = der.at(t);
131 double denom = Math.pow(d.x * d.x + d.y * d.y, 3.0 / 2.0);
132 if (denom == 0.0)
133 {
134 return Double.POSITIVE_INFINITY;
135 }
136 Point2d dd = der.derivative().at(t);
137 double numer = d.x * dd.y - dd.x * d.y;
138 return numer / denom;
139 }
140
141
142 @Override
143 public String toString()
144 {
145 return "ContinuousBezier [points=" + Arrays.toString(this.points) + "]";
146 }
147
148 }