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