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 }