001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.commons.math4.legacy.analysis.interpolation; 018 019import org.apache.commons.rng.simple.RandomSource; 020import org.apache.commons.rng.sampling.UnitSphereSampler; 021import org.apache.commons.math4.legacy.analysis.MultivariateFunction; 022import org.apache.commons.math4.legacy.exception.DimensionMismatchException; 023import org.apache.commons.math4.legacy.exception.NoDataException; 024import org.apache.commons.math4.legacy.exception.NotPositiveException; 025import org.apache.commons.math4.legacy.exception.NullArgumentException; 026 027/** 028 * Interpolator that implements the algorithm described in 029 * <em>William Dudziak</em>'s 030 * <a href="http://www.dudziak.com/microsphere.pdf">MS thesis</a>. 031 * 032 * @since 3.6 033 */ 034public class MicrosphereProjectionInterpolator 035 implements MultivariateInterpolator { 036 /** Brightness exponent. */ 037 private final double exponent; 038 /** Microsphere. */ 039 private final InterpolatingMicrosphere microsphere; 040 /** Whether to share the sphere. */ 041 private final boolean sharedSphere; 042 /** Tolerance value below which no interpolation is necessary. */ 043 private final double noInterpolationTolerance; 044 045 /** 046 * Create a microsphere interpolator. 047 * 048 * @param dimension Space dimension. 049 * @param elements Number of surface elements of the microsphere. 050 * @param exponent Exponent used in the power law that computes the 051 * @param maxDarkFraction Maximum fraction of the facets that can be dark. 052 * If the fraction of "non-illuminated" facets is larger, no estimation 053 * of the value will be performed, and the {@code background} value will 054 * be returned instead. 055 * @param darkThreshold Value of the illumination below which a facet is 056 * considered dark. 057 * @param background Value returned when the {@code maxDarkFraction} 058 * threshold is exceeded. 059 * @param sharedSphere Whether the sphere can be shared among the 060 * interpolating function instances. If {@code true}, the instances 061 * will share the same data, and thus will <em>not</em> be thread-safe. 062 * @param noInterpolationTolerance When the distance between an 063 * interpolated point and one of the sample points is less than this 064 * value, no interpolation will be performed (the value of the sample 065 * will be returned). 066 * @throws org.apache.commons.math4.legacy.exception.NotStrictlyPositiveException 067 * if {@code dimension <= 0} or {@code elements <= 0}. 068 * @throws NotPositiveException if {@code exponent < 0}. 069 * @throws NotPositiveException if {@code darkThreshold < 0}. 070 * @throws org.apache.commons.math4.legacy.exception.OutOfRangeException if 071 * {@code maxDarkFraction} does not belong to the interval {@code [0, 1]}. 072 */ 073 public MicrosphereProjectionInterpolator(int dimension, 074 int elements, 075 double maxDarkFraction, 076 double darkThreshold, 077 double background, 078 double exponent, 079 boolean sharedSphere, 080 double noInterpolationTolerance) { 081 this(new InterpolatingMicrosphere(dimension, 082 elements, 083 maxDarkFraction, 084 darkThreshold, 085 background, 086 UnitSphereSampler.of(RandomSource.MT_64.create(), 087 dimension)), 088 exponent, 089 sharedSphere, 090 noInterpolationTolerance); 091 } 092 093 /** 094 * Create a microsphere interpolator. 095 * 096 * @param microsphere Microsphere. 097 * @param exponent Exponent used in the power law that computes the 098 * weights (distance dimming factor) of the sample data. 099 * @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}