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.analysis.MultivariateRealFunction;
021    import org.apache.commons.math.exception.NotPositiveException;
022    import org.apache.commons.math.exception.NotStrictlyPositiveException;
023    import org.apache.commons.math.random.UnitSphereRandomVectorGenerator;
024    
025    /**
026     * Interpolator that implements the algorithm described in
027     * <em>William Dudziak</em>'s
028     * <a href="http://www.dudziak.com/microsphere.pdf">MS thesis</a>.
029     * @since 2.1
030     *
031     * @version $Revision: 980944 $ $Date: 2010-07-30 22:31:11 +0200 (ven. 30 juil. 2010) $
032     */
033    public class MicrosphereInterpolator
034        implements MultivariateRealInterpolator {
035    
036        /**
037         * Default number of surface elements that composes the microsphere.
038         */
039        public static final int DEFAULT_MICROSPHERE_ELEMENTS = 2000;
040    
041        /**
042         * Default exponent used the weights calculation.
043         */
044        public static final int DEFAULT_BRIGHTNESS_EXPONENT = 2;
045    
046        /**
047         * Number of surface elements of the microsphere.
048         */
049        private int microsphereElements;
050    
051        /**
052         * Exponent used in the power law that computes the weights of the
053         * sample data.
054         */
055        private int brightnessExponent;
056    
057        /** Create a microsphere interpolator with default settings.
058         * <p>Calling this constructor is equivalent to call {@link
059         * #MicrosphereInterpolator(int, int)
060         * MicrosphereInterpolator(MicrosphereInterpolator.DEFAULT_MICROSPHERE_ELEMENTS,
061         * MicrosphereInterpolator.DEFAULT_BRIGHTNESS_EXPONENT)}.</p>
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 NotPositiveException 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 exponent Exponent for computing the distance dimming
097         * factor.
098         * @throws NotPositiveException if {@code exponent < 0}.
099         */
100        public void setBrightnessExponent(final int exponent) {
101            if (exponent < 0) {
102                throw new NotPositiveException(exponent);
103            }
104            brightnessExponent = exponent;
105        }
106    
107        /**
108         * Set the number of microsphere elements.
109         * @param elements Number of surface elements of the microsphere.
110         * @throws NotStrictlyPositiveException if {@code elements <= 0}.
111         */
112        public void setMicropshereElements(final int elements) {
113            if (elements <= 0) {
114                throw new NotStrictlyPositiveException(elements);
115            }
116            microsphereElements = elements;
117        }
118    }