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.math3.analysis.interpolation; 018 019import org.apache.commons.math3.analysis.MultivariateFunction; 020import org.apache.commons.math3.exception.DimensionMismatchException; 021import org.apache.commons.math3.exception.NoDataException; 022import org.apache.commons.math3.exception.NotPositiveException; 023import org.apache.commons.math3.exception.NullArgumentException; 024import org.apache.commons.math3.random.UnitSphereRandomVectorGenerator; 025 026/** 027 * Interpolator that implements the algorithm described in 028 * <em>William Dudziak</em>'s 029 * <a href="http://www.dudziak.com/microsphere.pdf">MS thesis</a>. 030 * 031 * @since 3.6 032 */ 033public class MicrosphereProjectionInterpolator 034 implements MultivariateInterpolator { 035 /** Brightness exponent. */ 036 private final double exponent; 037 /** Microsphere. */ 038 private final InterpolatingMicrosphere microsphere; 039 /** Whether to share the sphere. */ 040 private final boolean sharedSphere; 041 /** Tolerance value below which no interpolation is necessary. */ 042 private final double noInterpolationTolerance; 043 044 /** 045 * Create a microsphere interpolator. 046 * 047 * @param dimension Space dimension. 048 * @param elements Number of surface elements of the microsphere. 049 * @param exponent Exponent used in the power law that computes the 050 * @param maxDarkFraction Maximum fraction of the facets that can be dark. 051 * If the fraction of "non-illuminated" facets is larger, no estimation 052 * of the value will be performed, and the {@code background} value will 053 * be returned instead. 054 * @param darkThreshold Value of the illumination below which a facet is 055 * considered dark. 056 * @param background Value returned when the {@code maxDarkFraction} 057 * threshold is exceeded. 058 * @param sharedSphere Whether the sphere can be shared among the 059 * interpolating function instances. If {@code true}, the instances 060 * will share the same data, and thus will <em>not</em> be thread-safe. 061 * @param noInterpolationTolerance When the distance between an 062 * interpolated point and one of the sample points is less than this 063 * value, no interpolation will be performed (the value of the sample 064 * will be returned). 065 * @throws org.apache.commons.math3.exception.NotStrictlyPositiveException 066 * if {@code dimension <= 0} or {@code elements <= 0}. 067 * @throws NotPositiveException if {@code exponent < 0}. 068 * @throws NotPositiveException if {@code darkThreshold < 0}. 069 * @throws org.apache.commons.math3.exception.OutOfRangeException if 070 * {@code maxDarkFraction} does not belong to the interval {@code [0, 1]}. 071 */ 072 public MicrosphereProjectionInterpolator(int dimension, 073 int elements, 074 double maxDarkFraction, 075 double darkThreshold, 076 double background, 077 double exponent, 078 boolean sharedSphere, 079 double noInterpolationTolerance) { 080 this(new InterpolatingMicrosphere(dimension, 081 elements, 082 maxDarkFraction, 083 darkThreshold, 084 background, 085 new UnitSphereRandomVectorGenerator(dimension)), 086 exponent, 087 sharedSphere, 088 noInterpolationTolerance); 089 } 090 091 /** 092 * Create a microsphere interpolator. 093 * 094 * @param microsphere Microsphere. 095 * @param exponent Exponent used in the power law that computes the 096 * weights (distance dimming factor) of the sample data. 097 * @param sharedSphere Whether the sphere can be shared among the 098 * interpolating function instances. If {@code true}, the instances 099 * will share the same data, and thus will <em>not</em> be thread-safe. 100 * @param noInterpolationTolerance When the distance between an 101 * interpolated point and one of the sample points is less than this 102 * value, no interpolation will be performed (the value of the sample 103 * will be returned). 104 * @throws NotPositiveException if {@code exponent < 0}. 105 */ 106 public MicrosphereProjectionInterpolator(InterpolatingMicrosphere microsphere, 107 double exponent, 108 boolean sharedSphere, 109 double noInterpolationTolerance) 110 throws NotPositiveException { 111 if (exponent < 0) { 112 throw new NotPositiveException(exponent); 113 } 114 115 this.microsphere = microsphere; 116 this.exponent = exponent; 117 this.sharedSphere = sharedSphere; 118 this.noInterpolationTolerance = noInterpolationTolerance; 119 } 120 121 /** 122 * {@inheritDoc} 123 * 124 * @throws DimensionMismatchException if the space dimension of the 125 * given samples does not match the space dimension of the microsphere. 126 */ 127 public MultivariateFunction interpolate(final double[][] xval, 128 final double[] yval) 129 throws DimensionMismatchException, 130 NoDataException, 131 NullArgumentException { 132 if (xval == null || 133 yval == null) { 134 throw new NullArgumentException(); 135 } 136 if (xval.length == 0) { 137 throw new NoDataException(); 138 } 139 if (xval.length != yval.length) { 140 throw new DimensionMismatchException(xval.length, yval.length); 141 } 142 if (xval[0] == null) { 143 throw new NullArgumentException(); 144 } 145 final int dimension = microsphere.getDimension(); 146 if (dimension != xval[0].length) { 147 throw new DimensionMismatchException(xval[0].length, dimension); 148 } 149 150 // Microsphere copy. 151 final InterpolatingMicrosphere m = sharedSphere ? microsphere : microsphere.copy(); 152 153 return new MultivariateFunction() { 154 /** {inheritDoc} */ 155 public double value(double[] point) { 156 return m.value(point, 157 xval, 158 yval, 159 exponent, 160 noInterpolationTolerance); 161 } 162 }; 163 } 164}