source: src/main/java/agents/anac/y2019/harddealer/math3/analysis/interpolation/MicrosphereInterpolatingFunction.java

Last change on this file was 204, checked in by Katsuhide Fujita, 5 years ago

Fixed errors of ANAC2019 agents

  • Property svn:executable set to *
File size: 9.2 KB
Line 
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 */
17package agents.anac.y2019.harddealer.math3.analysis.interpolation;
18
19import java.util.ArrayList;
20import java.util.HashMap;
21import java.util.List;
22import java.util.Map;
23
24import agents.anac.y2019.harddealer.math3.analysis.MultivariateFunction;
25import agents.anac.y2019.harddealer.math3.exception.DimensionMismatchException;
26import agents.anac.y2019.harddealer.math3.exception.NoDataException;
27import agents.anac.y2019.harddealer.math3.exception.NullArgumentException;
28import agents.anac.y2019.harddealer.math3.linear.ArrayRealVector;
29import agents.anac.y2019.harddealer.math3.linear.RealVector;
30import agents.anac.y2019.harddealer.math3.random.UnitSphereRandomVectorGenerator;
31import agents.anac.y2019.harddealer.math3.util.FastMath;
32
33/**
34 * Interpolating function that implements the
35 * <a href="http://www.dudziak.com/microsphere.php">Microsphere Projection</a>.
36 *
37 * @deprecated Code will be removed in 4.0. Use {@link InterpolatingMicrosphere}
38 * and {@link MicrosphereProjectionInterpolator} instead.
39 */
40@Deprecated
41public class MicrosphereInterpolatingFunction
42 implements MultivariateFunction {
43 /**
44 * Space dimension.
45 */
46 private final int dimension;
47 /**
48 * Internal accounting data for the interpolation algorithm.
49 * Each element of the list corresponds to one surface element of
50 * the microsphere.
51 */
52 private final List<MicrosphereSurfaceElement> microsphere;
53 /**
54 * Exponent used in the power law that computes the weights of the
55 * sample data.
56 */
57 private final double brightnessExponent;
58 /**
59 * Sample data.
60 */
61 private final Map<RealVector, Double> samples;
62
63 /**
64 * Class for storing the accounting data needed to perform the
65 * microsphere projection.
66 */
67 private static class MicrosphereSurfaceElement {
68 /** Normal vector characterizing a surface element. */
69 private final RealVector normal;
70 /** Illumination received from the brightest sample. */
71 private double brightestIllumination;
72 /** Brightest sample. */
73 private Map.Entry<RealVector, Double> brightestSample;
74
75 /**
76 * @param n Normal vector characterizing a surface element
77 * of the microsphere.
78 */
79 MicrosphereSurfaceElement(double[] n) {
80 normal = new ArrayRealVector(n);
81 }
82
83 /**
84 * Return the normal vector.
85 * @return the normal vector
86 */
87 RealVector normal() {
88 return normal;
89 }
90
91 /**
92 * Reset "illumination" and "sampleIndex".
93 */
94 void reset() {
95 brightestIllumination = 0;
96 brightestSample = null;
97 }
98
99 /**
100 * Store the illumination and index of the brightest sample.
101 * @param illuminationFromSample illumination received from sample
102 * @param sample current sample illuminating the element
103 */
104 void store(final double illuminationFromSample,
105 final Map.Entry<RealVector, Double> sample) {
106 if (illuminationFromSample > this.brightestIllumination) {
107 this.brightestIllumination = illuminationFromSample;
108 this.brightestSample = sample;
109 }
110 }
111
112 /**
113 * Get the illumination of the element.
114 * @return the illumination.
115 */
116 double illumination() {
117 return brightestIllumination;
118 }
119
120 /**
121 * Get the sample illuminating the element the most.
122 * @return the sample.
123 */
124 Map.Entry<RealVector, Double> sample() {
125 return brightestSample;
126 }
127 }
128
129 /**
130 * @param xval Arguments for the interpolation points.
131 * {@code xval[i][0]} is the first component of interpolation point
132 * {@code i}, {@code xval[i][1]} is the second component, and so on
133 * until {@code xval[i][d-1]}, the last component of that interpolation
134 * point (where {@code dimension} is thus the dimension of the sampled
135 * space).
136 * @param yval Values for the interpolation points.
137 * @param brightnessExponent Brightness dimming factor.
138 * @param microsphereElements Number of surface elements of the
139 * microsphere.
140 * @param rand Unit vector generator for creating the microsphere.
141 * @throws DimensionMismatchException if the lengths of {@code yval} and
142 * {@code xval} (equal to {@code n}, the number of interpolation points)
143 * do not match, or the the arrays {@code xval[0]} ... {@code xval[n]},
144 * have lengths different from {@code dimension}.
145 * @throws NoDataException if there an array has zero-length.
146 * @throws NullArgumentException if an argument is {@code null}.
147 */
148 public MicrosphereInterpolatingFunction(double[][] xval,
149 double[] yval,
150 int brightnessExponent,
151 int microsphereElements,
152 UnitSphereRandomVectorGenerator rand)
153 throws DimensionMismatchException,
154 NoDataException,
155 NullArgumentException {
156 if (xval == null ||
157 yval == null) {
158 throw new NullArgumentException();
159 }
160 if (xval.length == 0) {
161 throw new NoDataException();
162 }
163 if (xval.length != yval.length) {
164 throw new DimensionMismatchException(xval.length, yval.length);
165 }
166 if (xval[0] == null) {
167 throw new NullArgumentException();
168 }
169
170 dimension = xval[0].length;
171 this.brightnessExponent = brightnessExponent;
172
173 // Copy data samples.
174 samples = new HashMap<RealVector, Double>(yval.length);
175 for (int i = 0; i < xval.length; ++i) {
176 final double[] xvalI = xval[i];
177 if (xvalI == null) {
178 throw new NullArgumentException();
179 }
180 if (xvalI.length != dimension) {
181 throw new DimensionMismatchException(xvalI.length, dimension);
182 }
183
184 samples.put(new ArrayRealVector(xvalI), yval[i]);
185 }
186
187 microsphere = new ArrayList<MicrosphereSurfaceElement>(microsphereElements);
188 // Generate the microsphere, assuming that a fairly large number of
189 // randomly generated normals will represent a sphere.
190 for (int i = 0; i < microsphereElements; i++) {
191 microsphere.add(new MicrosphereSurfaceElement(rand.nextVector()));
192 }
193 }
194
195 /**
196 * @param point Interpolation point.
197 * @return the interpolated value.
198 * @throws DimensionMismatchException if point dimension does not math sample
199 */
200 public double value(double[] point) throws DimensionMismatchException {
201 final RealVector p = new ArrayRealVector(point);
202
203 // Reset.
204 for (MicrosphereSurfaceElement md : microsphere) {
205 md.reset();
206 }
207
208 // Compute contribution of each sample points to the microsphere elements illumination
209 for (Map.Entry<RealVector, Double> sd : samples.entrySet()) {
210
211 // Vector between interpolation point and current sample point.
212 final RealVector diff = sd.getKey().subtract(p);
213 final double diffNorm = diff.getNorm();
214
215 if (FastMath.abs(diffNorm) < FastMath.ulp(1d)) {
216 // No need to interpolate, as the interpolation point is
217 // actually (very close to) one of the sampled points.
218 return sd.getValue();
219 }
220
221 for (MicrosphereSurfaceElement md : microsphere) {
222 final double w = FastMath.pow(diffNorm, -brightnessExponent);
223 md.store(cosAngle(diff, md.normal()) * w, sd);
224 }
225
226 }
227
228 // Interpolation calculation.
229 double value = 0;
230 double totalWeight = 0;
231 for (MicrosphereSurfaceElement md : microsphere) {
232 final double iV = md.illumination();
233 final Map.Entry<RealVector, Double> sd = md.sample();
234 if (sd != null) {
235 value += iV * sd.getValue();
236 totalWeight += iV;
237 }
238 }
239
240 return value / totalWeight;
241 }
242
243 /**
244 * Compute the cosine of the angle between 2 vectors.
245 *
246 * @param v Vector.
247 * @param w Vector.
248 * @return the cosine of the angle between {@code v} and {@code w}.
249 */
250 private double cosAngle(final RealVector v, final RealVector w) {
251 return v.dotProduct(w) / (v.getNorm() * w.getNorm());
252 }
253}
Note: See TracBrowser for help on using the repository browser.