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.Assert;
28  import org.junit.Test;
29  
30  /**
31   * Test case for the {@link TricubicInterpolator tricubic interpolator}.
32   */
33  public final class TricubicInterpolatorTest {
34      /**
35       * Test preconditions.
36       */
37      @Test
38      public void testPreconditions() {
39          double[] xval = new double[] {3, 4, 5, 6.5};
40          double[] yval = new double[] {-4, -3, -1, 2.5};
41          double[] zval = new double[] {-12, -8, -5.5, -3, 0, 2.5};
42          double[][][] fval = new double[xval.length][yval.length][zval.length];
43  
44          @SuppressWarnings("unused")
45          TrivariateFunction tcf = new TricubicInterpolator().interpolate(xval, yval, zval, fval);
46  
47          double[] wxval = new double[] {3, 2, 5, 6.5};
48          try {
49              tcf = new TricubicInterpolator().interpolate(wxval, yval, zval, fval);
50              Assert.fail("an exception should have been thrown");
51          } catch (MathIllegalArgumentException e) {
52              // Expected
53          }
54          double[] wyval = new double[] {-4, -1, -1, 2.5};
55          try {
56              tcf = new TricubicInterpolator().interpolate(xval, wyval, zval, fval);
57              Assert.fail("an exception should have been thrown");
58          } catch (MathIllegalArgumentException e) {
59              // Expected
60          }
61          double[] wzval = new double[] {-12, -8, -9, -3, 0, 2.5};
62          try {
63              tcf = new TricubicInterpolator().interpolate(xval, yval, wzval, fval);
64              Assert.fail("an exception should have been thrown");
65          } catch (MathIllegalArgumentException e) {
66              // Expected
67          }
68          double[][][] wfval = new double[xval.length - 1][yval.length][zval.length];
69          try {
70              tcf = new TricubicInterpolator().interpolate(xval, yval, zval, wfval);
71              Assert.fail("an exception should have been thrown");
72          } catch (MathIllegalArgumentException e) {
73              // Expected
74          }
75          wfval = new double[xval.length][yval.length - 1][zval.length];
76          try {
77              tcf = new TricubicInterpolator().interpolate(xval, yval, zval, wfval);
78              Assert.fail("an exception should have been thrown");
79          } catch (MathIllegalArgumentException e) {
80              // Expected
81          }
82          wfval = new double[xval.length][yval.length][zval.length - 1];
83          try {
84              tcf = new TricubicInterpolator().interpolate(xval, yval, zval, wfval);
85              Assert.fail("an exception should have been thrown");
86          } catch (MathIllegalArgumentException e) {
87              // Expected
88          }
89      }
90  
91      public void testIsValid() {
92          double[] xval = new double[] {3, 4, 5, 6.5};
93          double[] yval = new double[] {-4, -3, -1, 2.5};
94          double[] zval = new double[] {-12, -8, -5.5, -3, 0, 2.5};
95          double[][][] fval = new double[xval.length][yval.length][zval.length];
96  
97          TricubicInterpolatingFunction tcf = new TricubicInterpolator().interpolate(xval, yval, zval, fval);
98  
99          // Valid.
100         Assert.assertTrue(tcf.isValidPoint(4, -3, -8));
101         Assert.assertTrue(tcf.isValidPoint(5, -3, -8));
102         Assert.assertTrue(tcf.isValidPoint(4, -1, -8));
103         Assert.assertTrue(tcf.isValidPoint(5, -1, -8));
104         Assert.assertTrue(tcf.isValidPoint(4, -3, 0));
105         Assert.assertTrue(tcf.isValidPoint(5, -3, 0));
106         Assert.assertTrue(tcf.isValidPoint(4, -1, 0));
107         Assert.assertTrue(tcf.isValidPoint(5, -1, 0));
108 
109         // Invalid.
110         Assert.assertFalse(tcf.isValidPoint(3.5, -3, -8));
111         Assert.assertFalse(tcf.isValidPoint(4.5, -3.1, -8));
112         Assert.assertFalse(tcf.isValidPoint(4.5, -2, 0));
113         Assert.assertFalse(tcf.isValidPoint(4.5, 0, -3.5));
114         Assert.assertFalse(tcf.isValidPoint(-10, 4.1, -1));
115     }
116 
117     /**
118      * Test for a plane.
119      * <p>
120      *  f(x, y, z) = 2 x - 3 y - 4 z + 5
121      * </p>
122      */
123     @Test
124     public void testPlane() {
125         double[] xval = new double[] {3, 4, 5, 6.5};
126         double[] yval = new double[] {-4, -3, -1, 2, 2.5};
127         double[] zval = new double[] {-12, -8, -5.5, -3, 0, 2.5};
128 
129         // Function values
130         TrivariateFunction f = new TrivariateFunction() {
131                 @Override
132                 public double value(double x, double y, double z) {
133                     return 2 * x - 3 * y - 4 * z + 5;
134                 }
135             };
136 
137         double[][][] fval = new double[xval.length][yval.length][zval.length];
138 
139         for (int i = 0; i < xval.length; i++) {
140             for (int j = 0; j < yval.length; j++) {
141                 for (int k = 0; k < zval.length; k++) {
142                     fval[i][j][k] = f.value(xval[i], yval[j], zval[k]);
143                 }
144             }
145         }
146 
147         TrivariateFunction tcf = new TricubicInterpolator().interpolate(xval,
148                                                                         yval,
149                                                                         zval,
150                                                                         fval);
151         double x, y, z;
152         double expected, result;
153 
154         x = 4;
155         y = -3;
156         z = 0;
157         expected = f.value(x, y, z);
158         result = tcf.value(x, y, z);
159         Assert.assertEquals("On sample point",
160                             expected, result, 1e-15);
161 
162         x = 4.5;
163         y = -1.5;
164         z = -4.25;
165         expected = f.value(x, y, z);
166         result = tcf.value(x, y, z);
167         Assert.assertEquals("Half-way between sample points (middle of the patch)",
168                             expected, result, 1e-14);
169     }
170 
171     /**
172      * Sine wave.
173      * <p>
174      *  f(x, y, z) = a cos [&omega; z - k<sub>y</sub> x - k<sub>y</sub> y]
175      * </p>
176      * with A = 0.2, &omega; = 0.5, k<sub>x</sub> = 2, k<sub>y</sub> = 1.
177      */
178     @Test
179     public void testWave() {
180         double[] xval = new double[] {3, 4, 5, 6.5};
181         double[] yval = new double[] {-4, -3, -1, 2, 2.5};
182         double[] zval = new double[] {-12, -8, -5.5, -3, 0, 4};
183 
184         final double a = 0.2;
185         final double omega = 0.5;
186         final double kx = 2;
187         final double ky = 1;
188 
189         // Function values
190         TrivariateFunction f = new TrivariateFunction() {
191                 @Override
192                 public double value(double x, double y, double z) {
193                     return a * FastMath.cos(omega * z - kx * x - ky * y);
194                 }
195             };
196 
197         double[][][] fval = new double[xval.length][yval.length][zval.length];
198         for (int i = 0; i < xval.length; i++) {
199             for (int j = 0; j < yval.length; j++) {
200                 for (int k = 0; k < zval.length; k++) {
201                     fval[i][j][k] = f.value(xval[i], yval[j], zval[k]);
202                 }
203             }
204         }
205 
206         TrivariateFunction tcf = new TricubicInterpolator().interpolate(xval,
207                                                                         yval,
208                                                                         zval,
209                                                                         fval);
210 
211         double x, y, z;
212         double expected, result;
213 
214         x = 4;
215         y = -3;
216         z = 0;
217         expected = f.value(x, y, z);
218         result = tcf.value(x, y, z);
219         Assert.assertEquals("On sample point",
220                             expected, result, 1e-14);
221 
222         x = 4.5;
223         y = -1.5;
224         z = -4.25;
225         expected = f.value(x, y, z);
226         result = tcf.value(x, y, z);
227         Assert.assertEquals("Half-way between sample points (middle of the patch)",
228                             expected, result, 1e-1); // XXX Too high tolerance!
229     }
230 }