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    *      http://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  package org.apache.commons.math4.legacy.analysis.interpolation;
18  
19  import org.apache.commons.math4.legacy.analysis.TrivariateFunction;
20  import org.apache.commons.math4.legacy.exception.DimensionMismatchException;
21  import org.apache.commons.math4.legacy.exception.MathIllegalArgumentException;
22  import org.apache.commons.math4.core.jdkmath.JdkMath;
23  import org.junit.Assert;
24  import org.junit.Test;
25  
26  /**
27   * Test case for the {@link TricubicInterpolator tricubic interpolator}.
28   */
29  public final class TricubicInterpolatorTest {
30      /**
31       * Test preconditions.
32       */
33      @Test
34      public void testPreconditions() {
35          double[] xval = new double[] {3, 4, 5, 6.5};
36          double[] yval = new double[] {-4, -3, -1, 2.5};
37          double[] zval = new double[] {-12, -8, -5.5, -3, 0, 2.5};
38          double[][][] fval = new double[xval.length][yval.length][zval.length];
39  
40          @SuppressWarnings("unused")
41          TrivariateFunction tcf = new TricubicInterpolator().interpolate(xval, yval, zval, fval);
42  
43          double[] wxval = new double[] {3, 2, 5, 6.5};
44          try {
45              tcf = new TricubicInterpolator().interpolate(wxval, yval, zval, fval);
46              Assert.fail("an exception should have been thrown");
47          } catch (MathIllegalArgumentException e) {
48              // Expected
49          }
50          double[] wyval = new double[] {-4, -1, -1, 2.5};
51          try {
52              tcf = new TricubicInterpolator().interpolate(xval, wyval, zval, fval);
53              Assert.fail("an exception should have been thrown");
54          } catch (MathIllegalArgumentException e) {
55              // Expected
56          }
57          double[] wzval = new double[] {-12, -8, -9, -3, 0, 2.5};
58          try {
59              tcf = new TricubicInterpolator().interpolate(xval, yval, wzval, fval);
60              Assert.fail("an exception should have been thrown");
61          } catch (MathIllegalArgumentException e) {
62              // Expected
63          }
64          double[][][] wfval = new double[xval.length - 1][yval.length][zval.length];
65          try {
66              tcf = new TricubicInterpolator().interpolate(xval, yval, zval, wfval);
67              Assert.fail("an exception should have been thrown");
68          } catch (DimensionMismatchException e) {
69              // Expected
70          }
71          wfval = new double[xval.length][yval.length - 1][zval.length];
72          try {
73              tcf = new TricubicInterpolator().interpolate(xval, yval, zval, wfval);
74              Assert.fail("an exception should have been thrown");
75          } catch (DimensionMismatchException e) {
76              // Expected
77          }
78          wfval = new double[xval.length][yval.length][zval.length - 1];
79          try {
80              tcf = new TricubicInterpolator().interpolate(xval, yval, zval, wfval);
81              Assert.fail("an exception should have been thrown");
82          } catch (DimensionMismatchException e) {
83              // Expected
84          }
85      }
86  
87      @Test
88      public void testIsValid() {
89          double[] xval = new double[] {3, 4, 5, 6.5};
90          double[] yval = new double[] {-4, -3, -1, 2.5};
91          double[] zval = new double[] {-12, -8, -5.5, -3, 0, 2.5};
92          double[][][] fval = new double[xval.length][yval.length][zval.length];
93  
94          TricubicInterpolatingFunction tcf = new TricubicInterpolator().interpolate(xval, yval, zval, fval);
95  
96          // Valid.
97          Assert.assertTrue(tcf.isValidPoint(4, -3, -8));
98          Assert.assertTrue(tcf.isValidPoint(5, -3, -8));
99          Assert.assertTrue(tcf.isValidPoint(4, -1, -8));
100         Assert.assertTrue(tcf.isValidPoint(5, -1, -8));
101         Assert.assertTrue(tcf.isValidPoint(4, -3, 0));
102         Assert.assertTrue(tcf.isValidPoint(5, -3, 0));
103         Assert.assertTrue(tcf.isValidPoint(4, -1, 0));
104         Assert.assertTrue(tcf.isValidPoint(5, -1, 0));
105 
106         // Invalid.
107         Assert.assertFalse(tcf.isValidPoint(3.5, -3, -8));
108         Assert.assertFalse(tcf.isValidPoint(4.5, -3.1, -8));
109         Assert.assertFalse(tcf.isValidPoint(4.5, -2, 0.1));
110         Assert.assertFalse(tcf.isValidPoint(4.5, 0, -3.5));
111         Assert.assertFalse(tcf.isValidPoint(4.1, -1, -10));
112     }
113 
114     /**
115      * Test for a plane.
116      * <p>
117      *  f(x, y, z) = 2 x - 3 y - 4 z + 5
118      * </p>
119      */
120     @Test
121     public void testPlane() {
122         double[] xval = new double[] {3, 4, 5, 6.5};
123         double[] yval = new double[] {-4, -3, -1, 2, 2.5};
124         double[] zval = new double[] {-12, -8, -5.5, -3, 0, 2.5};
125 
126         // Function values
127         TrivariateFunction f = new TrivariateFunction() {
128                 @Override
129                 public double value(double x, double y, double z) {
130                     return 2 * x - 3 * y - 4 * z + 5;
131                 }
132             };
133 
134         double[][][] fval = new double[xval.length][yval.length][zval.length];
135 
136         for (int i = 0; i < xval.length; i++) {
137             for (int j = 0; j < yval.length; j++) {
138                 for (int k = 0; k < zval.length; k++) {
139                     fval[i][j][k] = f.value(xval[i], yval[j], zval[k]);
140                 }
141             }
142         }
143 
144         TrivariateFunction tcf = new TricubicInterpolator().interpolate(xval,
145                                                                         yval,
146                                                                         zval,
147                                                                         fval);
148         double x;
149         double y;
150         double z;
151         double expected;
152         double 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 * JdkMath.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;
212         double y;
213         double z;
214         double expected;
215         double result;
216 
217         x = 4;
218         y = -3;
219         z = 0;
220         expected = f.value(x, y, z);
221         result = tcf.value(x, y, z);
222         Assert.assertEquals("On sample point",
223                             expected, result, 1e-14);
224 
225         x = 4.5;
226         y = -1.5;
227         z = -4.25;
228         expected = f.value(x, y, z);
229         result = tcf.value(x, y, z);
230         Assert.assertEquals("Half-way between sample points (middle of the patch)",
231                             expected, result, 1e-1); // XXX Too high tolerance!
232     }
233 }