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     */
017    package org.apache.commons.math.analysis.interpolation;
018    
019    import org.apache.commons.math.MathException;
020    import org.apache.commons.math.MathRuntimeException;
021    import org.apache.commons.math.analysis.MultivariateRealFunction;
022    import org.apache.commons.math.random.UnitSphereRandomVectorGenerator;
023    
024    /**
025     * Interpolator that implements the algorithm described in
026     * <em>William Dudziak</em>'s
027     * <a href="http://www.dudziak.com/microsphere.pdf">MS thesis</a>
028     * @since 2.1
029     *
030     * @version $Revision: 924794 $ $Date: 2010-03-18 10:15:50 -0400 (Thu, 18 Mar 2010) $
031     */
032    public class MicrosphereInterpolator
033        implements MultivariateRealInterpolator {
034    
035        /**
036         * Default number of surface elements that composes the microsphere.
037         */
038        public static final int DEFAULT_MICROSPHERE_ELEMENTS = 2000;
039    
040        /**
041         * Default exponent used the weights calculation.
042         */
043        public static final int DEFAULT_BRIGHTNESS_EXPONENT = 2;
044    
045        /**
046         * Number of surface elements of the microsphere.
047         */
048        private int microsphereElements;
049    
050        /**
051         * Exponent used in the power law that computes the weights of the
052         * sample data.
053         */
054        private int brightnessExponent;
055    
056        /** Create a microsphere interpolator with default settings.
057         * <p>Calling this constructor is equivalent to call {@link
058         * #MicrosphereInterpolator(int, int)
059         * MicrosphereInterpolator(MicrosphereInterpolator.DEFAULT_MICROSPHERE_ELEMENTS,
060         * MicrosphereInterpolator.DEFAULT_BRIGHTNESS_EXPONENT)}.</p>
061         * weights of the sample data
062         */
063        public MicrosphereInterpolator() {
064            this(DEFAULT_MICROSPHERE_ELEMENTS, DEFAULT_BRIGHTNESS_EXPONENT);
065        }
066    
067        /** Create a microsphere interpolator.
068         * @param microsphereElements number of surface elements of the microsphere
069         * @param brightnessExponent exponent used in the power law that computes the
070         * weights of the sample data
071         * @throws IllegalArgumentException if {@code microsphereElements <= 0}
072         * or {@code brightnessExponent < 0}
073         */
074        public MicrosphereInterpolator(final int microsphereElements,
075                                       final int brightnessExponent) {
076            setMicropshereElements(microsphereElements);
077            setBrightnessExponent(brightnessExponent);
078        }
079    
080        /**
081         * {@inheritDoc}
082         */
083        public MultivariateRealFunction interpolate(final double[][] xval,
084                                                    final double[] yval)
085            throws MathException, IllegalArgumentException {
086            final UnitSphereRandomVectorGenerator rand
087                = new UnitSphereRandomVectorGenerator(xval[0].length);
088            return new MicrosphereInterpolatingFunction(xval, yval,
089                                                        brightnessExponent,
090                                                        microsphereElements,
091                                                        rand);
092        }
093    
094        /**
095         * Set the brightness exponent.
096         * @param brightnessExponent Exponent for computing the distance dimming
097         * factor.
098         * @throws IllegalArgumentException if {@code brightnessExponent < 0}.
099         */
100        public void setBrightnessExponent(final int brightnessExponent) {
101            if (brightnessExponent < 0) {
102                throw MathRuntimeException.createIllegalArgumentException(
103                    "brightness exponent should be positive or null, but got {0}",
104                    brightnessExponent);
105            }
106            this.brightnessExponent = brightnessExponent;
107        }
108    
109        /**
110         * Set the number of microsphere elements.
111         * @param elements Number of surface elements of the microsphere.
112         * @throws IllegalArgumentException if {@code microsphereElements <= 0}.
113         */
114        public void setMicropshereElements(final int elements) {
115            if (microsphereElements < 0) {
116                throw MathRuntimeException.createIllegalArgumentException(
117                    "number of microsphere elements must be positive, but got {0}",
118                    microsphereElements);
119            }
120            this.microsphereElements = elements;
121        }
122    
123    }