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.MultivariateFunction;
25  import org.hipparchus.exception.LocalizedCoreFormats;
26  import org.hipparchus.exception.MathIllegalArgumentException;
27  import org.hipparchus.exception.NullArgumentException;
28  import org.hipparchus.random.UnitSphereRandomVectorGenerator;
29  
30  /**
31   * Interpolator that implements the algorithm described in
32   * <em>William Dudziak</em>'s
33   * <a href="http://www.dudziak.com/microsphere.pdf">MS thesis</a>.
34   *
35   */
36  public class MicrosphereProjectionInterpolator
37      implements MultivariateInterpolator {
38      /** Brightness exponent. */
39      private final double exponent;
40      /** Microsphere. */
41      private final InterpolatingMicrosphere microsphere;
42      /** Whether to share the sphere. */
43      private final boolean sharedSphere;
44      /** Tolerance value below which no interpolation is necessary. */
45      private final double noInterpolationTolerance;
46  
47      /**
48       * Create a microsphere interpolator.
49       *
50       * @param dimension Space dimension.
51       * @param elements Number of surface elements of the microsphere.
52       * @param exponent Exponent used in the power law that computes the
53       * @param maxDarkFraction Maximum fraction of the facets that can be dark.
54       * If the fraction of "non-illuminated" facets is larger, no estimation
55       * of the value will be performed, and the {@code background} value will
56       * be returned instead.
57       * @param darkThreshold Value of the illumination below which a facet is
58       * considered dark.
59       * @param background Value returned when the {@code maxDarkFraction}
60       * threshold is exceeded.
61       * @param sharedSphere Whether the sphere can be shared among the
62       * interpolating function instances.  If {@code true}, the instances
63       * will share the same data, and thus will <em>not</em> be thread-safe.
64       * @param noInterpolationTolerance When the distance between an
65       * interpolated point and one of the sample points is less than this
66       * value, no interpolation will be performed (the value of the sample
67       * will be returned).
68       * @throws org.hipparchus.exception.MathIllegalArgumentException
69       * if {@code dimension <= 0} or {@code elements <= 0}.
70       * @throws MathIllegalArgumentException if {@code exponent < 0}.
71       * @throws MathIllegalArgumentException if {@code darkThreshold < 0}.
72       * @throws org.hipparchus.exception.MathIllegalArgumentException if
73       * {@code maxDarkFraction} does not belong to the interval {@code [0, 1]}.
74       */
75      public MicrosphereProjectionInterpolator(int dimension,
76                                               int elements,
77                                               double maxDarkFraction,
78                                               double darkThreshold,
79                                               double background,
80                                               double exponent,
81                                               boolean sharedSphere,
82                                               double noInterpolationTolerance) {
83          this(new InterpolatingMicrosphere(dimension,
84                                            elements,
85                                            maxDarkFraction,
86                                            darkThreshold,
87                                            background,
88                                            new UnitSphereRandomVectorGenerator(dimension)),
89               exponent,
90               sharedSphere,
91               noInterpolationTolerance);
92      }
93  
94      /**
95       * Create a microsphere interpolator.
96       *
97       * @param microsphere Microsphere.
98       * @param exponent Exponent used in the power law that computes the
99       * weights (distance dimming factor) of the sample data.
100      * @param sharedSphere Whether the sphere can be shared among the
101      * interpolating function instances.  If {@code true}, the instances
102      * will share the same data, and thus will <em>not</em> be thread-safe.
103      * @param noInterpolationTolerance When the distance between an
104      * interpolated point and one of the sample points is less than this
105      * value, no interpolation will be performed (the value of the sample
106      * will be returned).
107      * @throws MathIllegalArgumentException if {@code exponent < 0}.
108      */
109     public MicrosphereProjectionInterpolator(InterpolatingMicrosphere microsphere,
110                                              double exponent,
111                                              boolean sharedSphere,
112                                              double noInterpolationTolerance)
113         throws MathIllegalArgumentException {
114         if (exponent < 0) {
115             throw new MathIllegalArgumentException(LocalizedCoreFormats.NUMBER_TOO_SMALL, exponent, 0);
116         }
117 
118         this.microsphere = microsphere;
119         this.exponent = exponent;
120         this.sharedSphere = sharedSphere;
121         this.noInterpolationTolerance = noInterpolationTolerance;
122     }
123 
124     /**
125      * {@inheritDoc}
126      *
127      * @throws MathIllegalArgumentException if the space dimension of the
128      * given samples does not match the space dimension of the microsphere.
129      */
130     @Override
131     public MultivariateFunction interpolate(final double[][] xval,
132                                             final double[] yval)
133         throws MathIllegalArgumentException, NullArgumentException {
134         if (xval == null ||
135             yval == null) {
136             throw new NullArgumentException();
137         }
138         if (xval.length == 0) {
139             throw new MathIllegalArgumentException(LocalizedCoreFormats.NO_DATA);
140         }
141         if (xval.length != yval.length) {
142             throw new MathIllegalArgumentException(LocalizedCoreFormats.DIMENSIONS_MISMATCH,
143                                                    xval.length, yval.length);
144         }
145         if (xval[0] == null) {
146             throw new NullArgumentException();
147         }
148         final int dimension = microsphere.getDimension();
149         if (dimension != xval[0].length) {
150             throw new MathIllegalArgumentException(LocalizedCoreFormats.DIMENSIONS_MISMATCH,
151                                                    xval[0].length, dimension);
152         }
153 
154         // Microsphere copy.
155         final InterpolatingMicrosphere m = sharedSphere ? microsphere : microsphere.copy();
156 
157         return new MultivariateFunction() {
158             /** {inheritDoc} */
159             @Override
160             public double value(double[] point) {
161                 return m.value(point,
162                                xval,
163                                yval,
164                                exponent,
165                                noInterpolationTolerance);
166             }
167         };
168     }
169 }