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 }