View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      https://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  
18  /*
19   * This is not the original file distributed by the Apache Software Foundation
20   * It has been modified by the Hipparchus project
21   */
22  package org.hipparchus.analysis.interpolation;
23  
24  import org.hipparchus.analysis.TrivariateFunction;
25  import org.hipparchus.exception.MathIllegalArgumentException;
26  import org.hipparchus.util.FastMath;
27  import org.junit.jupiter.api.Test;
28  
29  import static org.junit.jupiter.api.Assertions.assertEquals;
30  import static org.junit.jupiter.api.Assertions.assertFalse;
31  import static org.junit.jupiter.api.Assertions.assertTrue;
32  import static org.junit.jupiter.api.Assertions.fail;
33  
34  /**
35   * Test case for the {@link TricubicInterpolator tricubic interpolator}.
36   */
37  public final class TricubicInterpolatorTest {
38      /**
39       * Test preconditions.
40       */
41      @Test
42      void testPreconditions() {
43          double[] xval = new double[] {3, 4, 5, 6.5};
44          double[] yval = new double[] {-4, -3, -1, 2.5};
45          double[] zval = new double[] {-12, -8, -5.5, -3, 0, 2.5};
46          double[][][] fval = new double[xval.length][yval.length][zval.length];
47  
48          @SuppressWarnings("unused")
49          TrivariateFunction tcf = new TricubicInterpolator().interpolate(xval, yval, zval, fval);
50  
51          double[] wxval = new double[] {3, 2, 5, 6.5};
52          try {
53              tcf = new TricubicInterpolator().interpolate(wxval, yval, zval, fval);
54              fail("an exception should have been thrown");
55          } catch (MathIllegalArgumentException e) {
56              // Expected
57          }
58          double[] wyval = new double[] {-4, -1, -1, 2.5};
59          try {
60              tcf = new TricubicInterpolator().interpolate(xval, wyval, zval, fval);
61              fail("an exception should have been thrown");
62          } catch (MathIllegalArgumentException e) {
63              // Expected
64          }
65          double[] wzval = new double[] {-12, -8, -9, -3, 0, 2.5};
66          try {
67              tcf = new TricubicInterpolator().interpolate(xval, yval, wzval, fval);
68              fail("an exception should have been thrown");
69          } catch (MathIllegalArgumentException e) {
70              // Expected
71          }
72          double[][][] wfval = new double[xval.length - 1][yval.length][zval.length];
73          try {
74              tcf = new TricubicInterpolator().interpolate(xval, yval, zval, wfval);
75              fail("an exception should have been thrown");
76          } catch (MathIllegalArgumentException e) {
77              // Expected
78          }
79          wfval = new double[xval.length][yval.length - 1][zval.length];
80          try {
81              tcf = new TricubicInterpolator().interpolate(xval, yval, zval, wfval);
82              fail("an exception should have been thrown");
83          } catch (MathIllegalArgumentException e) {
84              // Expected
85          }
86          wfval = new double[xval.length][yval.length][zval.length - 1];
87          try {
88              tcf = new TricubicInterpolator().interpolate(xval, yval, zval, wfval);
89              fail("an exception should have been thrown");
90          } catch (MathIllegalArgumentException e) {
91              // Expected
92          }
93      }
94  
95      public void testIsValid() {
96          double[] xval = new double[] {3, 4, 5, 6.5};
97          double[] yval = new double[] {-4, -3, -1, 2.5};
98          double[] zval = new double[] {-12, -8, -5.5, -3, 0, 2.5};
99          double[][][] fval = new double[xval.length][yval.length][zval.length];
100 
101         TricubicInterpolatingFunction tcf = new TricubicInterpolator().interpolate(xval, yval, zval, fval);
102 
103         // Valid.
104         assertTrue(tcf.isValidPoint(4, -3, -8));
105         assertTrue(tcf.isValidPoint(5, -3, -8));
106         assertTrue(tcf.isValidPoint(4, -1, -8));
107         assertTrue(tcf.isValidPoint(5, -1, -8));
108         assertTrue(tcf.isValidPoint(4, -3, 0));
109         assertTrue(tcf.isValidPoint(5, -3, 0));
110         assertTrue(tcf.isValidPoint(4, -1, 0));
111         assertTrue(tcf.isValidPoint(5, -1, 0));
112 
113         // Invalid.
114         assertFalse(tcf.isValidPoint(3.5, -3, -8));
115         assertFalse(tcf.isValidPoint(4.5, -3.1, -8));
116         assertFalse(tcf.isValidPoint(4.5, -2, 0));
117         assertFalse(tcf.isValidPoint(4.5, 0, -3.5));
118         assertFalse(tcf.isValidPoint(-10, 4.1, -1));
119     }
120 
121     /**
122      * Test for a plane.
123      * <p>
124      *  f(x, y, z) = 2 x - 3 y - 4 z + 5
125      * </p>
126      */
127     @Test
128     void testPlane() {
129         double[] xval = new double[] {3, 4, 5, 6.5};
130         double[] yval = new double[] {-4, -3, -1, 2, 2.5};
131         double[] zval = new double[] {-12, -8, -5.5, -3, 0, 2.5};
132 
133         // Function values
134         TrivariateFunction f = new TrivariateFunction() {
135                 @Override
136                 public double value(double x, double y, double z) {
137                     return 2 * x - 3 * y - 4 * z + 5;
138                 }
139             };
140 
141         double[][][] fval = new double[xval.length][yval.length][zval.length];
142 
143         for (int i = 0; i < xval.length; i++) {
144             for (int j = 0; j < yval.length; j++) {
145                 for (int k = 0; k < zval.length; k++) {
146                     fval[i][j][k] = f.value(xval[i], yval[j], zval[k]);
147                 }
148             }
149         }
150 
151         TrivariateFunction tcf = new TricubicInterpolator().interpolate(xval,
152                                                                         yval,
153                                                                         zval,
154                                                                         fval);
155         double x, y, z;
156         double expected, result;
157 
158         x = 4;
159         y = -3;
160         z = 0;
161         expected = f.value(x, y, z);
162         result = tcf.value(x, y, z);
163         assertEquals(expected, result, 1e-15, "On sample point");
164 
165         x = 4.5;
166         y = -1.5;
167         z = -4.25;
168         expected = f.value(x, y, z);
169         result = tcf.value(x, y, z);
170         assertEquals(expected, result, 1e-14, "Half-way between sample points (middle of the patch)");
171     }
172 
173     /**
174      * Sine wave.
175      * <p>
176      *  f(x, y, z) = a cos [&omega; z - k<sub>y</sub> x - k<sub>y</sub> y]
177      * </p>
178      * with A = 0.2, &omega; = 0.5, k<sub>x</sub> = 2, k<sub>y</sub> = 1.
179      */
180     @Test
181     void testWave() {
182         double[] xval = new double[] {3, 4, 5, 6.5};
183         double[] yval = new double[] {-4, -3, -1, 2, 2.5};
184         double[] zval = new double[] {-12, -8, -5.5, -3, 0, 4};
185 
186         final double a = 0.2;
187         final double omega = 0.5;
188         final double kx = 2;
189         final double ky = 1;
190 
191         // Function values
192         TrivariateFunction f = new TrivariateFunction() {
193                 @Override
194                 public double value(double x, double y, double z) {
195                     return a * FastMath.cos(omega * z - kx * x - ky * y);
196                 }
197             };
198 
199         double[][][] fval = new double[xval.length][yval.length][zval.length];
200         for (int i = 0; i < xval.length; i++) {
201             for (int j = 0; j < yval.length; j++) {
202                 for (int k = 0; k < zval.length; k++) {
203                     fval[i][j][k] = f.value(xval[i], yval[j], zval[k]);
204                 }
205             }
206         }
207 
208         TrivariateFunction tcf = new TricubicInterpolator().interpolate(xval,
209                                                                         yval,
210                                                                         zval,
211                                                                         fval);
212 
213         double x, y, z;
214         double expected, result;
215 
216         x = 4;
217         y = -3;
218         z = 0;
219         expected = f.value(x, y, z);
220         result = tcf.value(x, y, z);
221         assertEquals(expected, result, 1e-14, "On sample point");
222 
223         x = 4.5;
224         y = -1.5;
225         z = -4.25;
226         expected = f.value(x, y, z);
227         result = tcf.value(x, y, z);
228         assertEquals(expected, result, 1e-1, "Half-way between sample points (middle of the patch)"); // XXX Too high tolerance!
229     }
230 }