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.BivariateFunction;
25  import org.hipparchus.exception.MathIllegalArgumentException;
26  import org.hipparchus.random.RandomDataGenerator;
27  import org.junit.Assert;
28  import org.junit.Test;
29  
30  /**
31   * Test case for the bicubic interpolator.
32   */
33  public final class BicubicInterpolatorTest {
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[xval.length][yval.length];
42  
43          BivariateGridInterpolator interpolator = new BicubicInterpolator();
44  
45          @SuppressWarnings("unused")
46          BivariateFunction p = interpolator.interpolate(xval, yval, zval);
47  
48          double[] wxval = new double[] {3, 2, 5, 6.5};
49          try {
50              p = interpolator.interpolate(wxval, yval, zval);
51              Assert.fail("an exception should have been thrown");
52          } catch (MathIllegalArgumentException e) {
53              // Expected
54          }
55  
56          double[] wyval = new double[] {-4, -3, -1, -1};
57          try {
58              p = interpolator.interpolate(xval, wyval, zval);
59              Assert.fail("an exception should have been thrown");
60          } catch (MathIllegalArgumentException e) {
61              // Expected
62          }
63  
64          double[][] wzval = new double[xval.length][yval.length + 1];
65          try {
66              p = interpolator.interpolate(xval, yval, wzval);
67              Assert.fail("an exception should have been thrown");
68          } catch (MathIllegalArgumentException e) {
69              // Expected
70          }
71          wzval = new double[xval.length - 1][yval.length];
72          try {
73              p = interpolator.interpolate(xval, yval, wzval);
74              Assert.fail("an exception should have been thrown");
75          } catch (MathIllegalArgumentException e) {
76              // Expected
77          }
78      }
79  
80      /**
81       * Interpolating a plane.
82       * <p>
83       * z = 2 x - 3 y + 5
84       */
85      @Test
86      public void testPlane() {
87          BivariateFunction f = new BivariateFunction() {
88                  @Override
89                  public double value(double x, double y) {
90                      return 2 * x - 3 * y + 5;
91                  }
92              };
93  
94          testInterpolation(3000,
95                            1e-13,
96                            f,
97                            false);
98      }
99  
100     /**
101      * Interpolating a paraboloid.
102      * <p>
103      * z = 2 x<sup>2</sup> - 3 y<sup>2</sup> + 4 x y - 5
104      */
105     @Test
106     public void testParaboloid() {
107         BivariateFunction f = new BivariateFunction() {
108                 @Override
109                 public double value(double x, double y) {
110                     return 2 * x * x - 3 * y * y + 4 * x * y - 5;
111                 }
112             };
113 
114         testInterpolation(3000,
115                           1e-12,
116                           f,
117                           false);
118     }
119 
120     /**
121      * @param numSamples Number of test samples.
122      * @param tolerance Allowed tolerance on the interpolated value.
123      * @param f Test function.
124      * @param print Whether to print debugging output to the console.
125      */
126     private void testInterpolation(int numSamples,
127                                    double tolerance,
128                                    BivariateFunction f,
129                                    boolean print) {
130         final int sz = 21;
131         final double[] xval = new double[sz];
132         final double[] yval = new double[sz];
133         // Coordinate values
134         final double delta = 1d / (sz - 1);
135         for (int i = 0; i < sz; i++) {
136             xval[i] = -1 + 15 * i * delta;
137             yval[i] = -20 + 30 * i * delta;
138         }
139 
140         final double[][] zval = new double[xval.length][yval.length];
141         for (int i = 0; i < xval.length; i++) {
142             for (int j = 0; j < yval.length; j++) {
143                 zval[i][j] = f.value(xval[i], yval[j]);
144             }
145         }
146 
147         final BicubicInterpolator interpolator = new BicubicInterpolator();
148         final BicubicInterpolatingFunction p = interpolator.interpolate(xval, yval, zval);
149         double x, y;
150 
151         final RandomDataGenerator gen = new RandomDataGenerator(1234567L);
152         int count = 0;
153         while (true) {
154             x = gen.nextUniform(xval[0], xval[xval.length - 1]);
155             y = gen.nextUniform(yval[0], yval[yval.length - 1]);
156             if (!p.isValidPoint(x, y)) {
157                 if (print) {
158                     System.out.println("# " + x + " " + y);
159                 }
160                 continue;
161             }
162 
163             if (count++ > numSamples) {
164                 break;
165             }
166             final double expected = f.value(x, y);
167             final double actual = p.value(x, y);
168 
169             if (print) {
170                 System.out.println(x + " " + y + " " + expected + " " + actual);
171             }
172 
173             Assert.assertEquals(expected, actual, tolerance);
174         }
175     }
176 }