View Javadoc
1   /*
2    * Copyright (C) 2023 Alberto Irurueta Carro (alberto@irurueta.com)
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *         http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package com.irurueta.numerical.interpolation;
17  
18  import com.irurueta.algebra.Matrix;
19  import com.irurueta.algebra.WrongSizeException;
20  
21  /**
22   * Interpolates sparsely defined points of dimension "dim" using Shepard interpolation, which is
23   * a simplification of Radial Basis Function interpolation that achieves less accurate results but
24   * having less computational cost.
25   */
26  public class ShepardInterpolator extends BaseRadialBasisFunctionInterpolator {
27      /**
28       * Values of function at provided points. Must have the same length as the number of rows of
29       * provided points matrix.
30       */
31      private final double[] vals;
32  
33      /**
34       * Negative value of p parameter controlling Shepard power-law function phi(r) = r^-p.
35       * Typically, p lies between 1 and 3.
36       */
37      private final double pneg;
38  
39      /**
40       * Constructor.
41       *
42       * @param ptss  Matrix containing points to interpolate from. Each row contains one point.
43       *              Matrix will have n points (rows) having a dimension (columns) equal to dim.
44       * @param valss values of function at provided points. Must have the same length as the number
45       *              of rows of provided points matrix.
46       * @param p     p parameter controlling Shepard power-law function phi(r) = r^-p. Typically, p
47       *              lies between 1 and 3.
48       * @throws IllegalArgumentException if provided values array does not match the number of
49       *                                  points (rows) in provided matrix.
50       */
51      public ShepardInterpolator(final Matrix ptss, final double[] valss, final double p) {
52          super(ptss);
53  
54          if (valss.length != n) {
55              throw new IllegalArgumentException("wrong length of values");
56          }
57  
58          vals = valss;
59          pneg = -p;
60      }
61  
62      /**
63       * Constructor using default p parameter, which is equal to 2.0.
64       *
65       * @param ptss  Matrix containing points to interpolate from. Each row contains one point.
66       *              Matrix will have n points (rows) having a dimension (columns) equal to dim.
67       * @param valss values of function at provided points. Must have the same length as the number
68       *              of rows of provided points matrix.
69       * @throws IllegalArgumentException if provided values array does not match the number of
70       *                                  points (rows) in provided matrix.
71       */
72      public ShepardInterpolator(final Matrix ptss, final double[] valss) {
73          this(ptss, valss, 2.0);
74      }
75  
76      /**
77       * Returns the interpolated function value at a dim-dimensional point pt.
78       *
79       * @param pt dim-dimensional point where interpolation must be computed.
80       * @return result of interpolation.
81       * @throws IllegalArgumentException if provided point has an invalid length.
82       */
83      public double interpolate(final double[] pt) {
84          double r;
85          double w;
86          var sum = 0.0;
87          var sumw = 0.0;
88          if (pt.length != dim) {
89              throw new IllegalArgumentException("Wrong point length");
90          }
91  
92          try {
93              for (var i = 0; i < n; i++) {
94                  final var endCol = dim - 1;
95                  pts.getSubmatrixAsArray(i, 0, i, endCol, pi);
96                  if ((r = rad(pt, pi)) == 0.0) return vals[i];
97                  sum += (w = Math.pow(r, pneg));
98                  sumw += w * vals[i];
99              }
100         } catch (final WrongSizeException ignore) {
101             // never happens
102         }
103 
104         return sumw / sum;
105     }
106 }