1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package com.irurueta.numerical.interpolation;
17
18 import com.irurueta.algebra.Matrix;
19 import com.irurueta.algebra.WrongSizeException;
20
21
22
23
24
25
26 public class CurveInterpolator {
27
28
29
30
31 private final int dim;
32
33
34
35
36 private final boolean cls;
37
38
39
40
41 private final double[] ans;
42
43
44
45
46 private final CubicSplineInterpolator[] srp;
47
48
49
50
51
52
53
54
55
56
57 public CurveInterpolator(final Matrix ptsin, final boolean close) throws InterpolationException {
58 try {
59 final var n = ptsin.getRows();
60 dim = ptsin.getColumns();
61
62
63 final var in = close ? 2 * n : n;
64 cls = close;
65 final var pts = new Matrix(dim, in);
66 final var s = new double[in];
67 ans = new double[dim];
68 srp = new CubicSplineInterpolator[dim];
69
70 final var p1 = new double[dim];
71 final var p2 = new double[dim];
72 final var p = new double[in];
73 final var end = dim - 1;
74
75 int i;
76 int ii;
77 int im;
78 int j;
79 int ofs;
80 double ss;
81 double soff;
82 double db;
83 double de;
84 ofs = close ? n / 2 : 0;
85 s[0] = 0.;
86 for (i = 0; i < in; i++) {
87 ii = (i - ofs + n) % n;
88 im = (ii - 1 + n) % n;
89 for (j = 0; j < dim; j++) {
90
91 pts.setElementAt(j, i, ptsin.getElementAt(ii, j));
92 }
93
94 if (i > 0) {
95
96 ptsin.getSubmatrixAsArray(ii, 0, ii, end, p1);
97 ptsin.getSubmatrixAsArray(im, 0, im, end, p2);
98 s[i] = s[i - 1] + rad(p1, p2);
99 if (s[i] == s[i - 1]) {
100
101
102 throw new InterpolationException();
103 }
104 }
105 }
106
107
108 ss = close ? s[ofs + n] - s[ofs] : s[n - 1] - s[0];
109 soff = s[ofs];
110 for (i = 0; i < in; i++) {
111 s[i] = (s[i] - soff) / ss;
112 }
113
114
115 final var endPts = in - 1;
116 for (j = 0; j < dim; j++) {
117 if (in < 4) {
118 db = 1.e99;
119 de = 1.e99;
120 } else {
121 pts.getSubmatrixAsArray(j, 0, j, endPts, p);
122 db = fprime(s, p, 1, 0, 0);
123 de = fprime(s, p, -1, in - 1, in - 1);
124 }
125 pts.getSubmatrixAsArray(j, 0, j, endPts, p);
126 srp[j] = new CubicSplineInterpolator(s, p, db, de);
127 }
128 } catch (final WrongSizeException e) {
129 throw new InterpolationException(e);
130 }
131 }
132
133
134
135
136
137
138
139
140 public CurveInterpolator(final Matrix ptsin) throws InterpolationException {
141 this(ptsin, false);
142 }
143
144
145
146
147
148
149
150
151
152
153
154 public double[] interpolate(double t) throws InterpolationException {
155 if (cls) {
156 t = t - Math.floor(t);
157 }
158
159 for (var j = 0; j < dim; j++) {
160 ans[j] = srp[j].interpolate(t);
161 }
162 return ans;
163 }
164
165
166
167
168
169
170
171
172
173
174
175
176 private double fprime(final double[] x, final double[] y, final int pm, final int xoff, final int yoff) {
177 final var s1 = x[xoff] - x[xoff + pm];
178 final var s2 = x[xoff] - x[xoff + pm * 2];
179 final var s3 = x[xoff] - x[xoff + pm * 3];
180 final var s12 = s1 - s2;
181 final var s13 = s1 - s3;
182 final var s23 = s2 - s3;
183 return -(s1 * s2 / (s13 * s23 * s3)) * y[yoff + pm * 3] + (s1 * s3 / (s12 * s2 * s23)) * y[yoff + pm * 2]
184 - (s2 * s3 / (s1 * s12 * s13)) * y[yoff + pm] + (1.0 / s1 + 1.0 / s2 + 1.0 / s3) * y[yoff];
185 }
186
187
188
189
190
191
192
193
194 private double rad(final double[] p1, final double[] p2) {
195 var sum = 0.0;
196 for (var i = 0; i < dim; i++) {
197 final var value = p1[i] - p2[i];
198 sum += value * value;
199 }
200 return Math.sqrt(sum);
201 }
202 }