    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.math3.analysis.interpolation;
    018
    019    import org.apache.commons.math3.analysis.MultivariateFunction;
    020    import org.apache.commons.math3.exception.NotPositiveException;
    021    import org.apache.commons.math3.exception.NotStrictlyPositiveException;
    022    import org.apache.commons.math3.exception.NoDataException;
    023    import org.apache.commons.math3.exception.DimensionMismatchException;
    024    import org.apache.commons.math3.exception.NullArgumentException;
    025    import org.apache.commons.math3.random.UnitSphereRandomVectorGenerator;
    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 2.1
    033     * @version $Id: MicrosphereInterpolator.java 1379904 2012-09-01 23:54:52Z erans $
    034     */
    035    public class MicrosphereInterpolator
    036        implements MultivariateInterpolator {
    037        /**
    038         * Default number of surface elements that composes the microsphere.
    039         */
    040        public static final int DEFAULT_MICROSPHERE_ELEMENTS = 2000;
    041        /**
    042         * Default exponent used the weights calculation.
    043         */
    044        public static final int DEFAULT_BRIGHTNESS_EXPONENT = 2;
    045        /**
    046         * Number of surface elements of the microsphere.
    047         */
    048        private final int microsphereElements;
    049        /**
    050         * Exponent used in the power law that computes the weights of the
    051         * sample data.
    052         */
    053        private final int brightnessExponent;
    054
    055        /**
    056         * Create a microsphere interpolator with default settings.
    057         * Calling this constructor is equivalent to call {@link
    058         * #MicrosphereInterpolator(int, int)
    059         * MicrosphereInterpolator(MicrosphereInterpolator.DEFAULT_MICROSPHERE_ELEMENTS,
    060         * MicrosphereInterpolator.DEFAULT_BRIGHTNESS_EXPONENT)}.
    061         */
    062        public MicrosphereInterpolator() {
    063            this(DEFAULT_MICROSPHERE_ELEMENTS, DEFAULT_BRIGHTNESS_EXPONENT);
    064        }
    065
    066        /** Create a microsphere interpolator.
    067         * @param elements Number of surface elements of the microsphere.
    068         * @param exponent Exponent used in the power law that computes the
    069         * weights (distance dimming factor) of the sample data.
    070         * @throws NotPositiveException if {@code exponent < 0}.
    071         * @throws NotStrictlyPositiveException if {@code elements <= 0}.
    072         */
    073        public MicrosphereInterpolator(final int elements,
    074                                       final int exponent)
    075            throws NotPositiveException,
    076                   NotStrictlyPositiveException {
    077            if (exponent < 0) {
    078                throw new NotPositiveException(exponent);
    079            }
    080            if (elements <= 0) {
    081                throw new NotStrictlyPositiveException(elements);
    082            }
    083
    084            microsphereElements = elements;
    085            brightnessExponent = exponent;
    086        }
    087
    088        /**
    089         * {@inheritDoc}
    090         */
    091        public MultivariateFunction interpolate(final double[][] xval,
    092                                                final double[] yval)
    093            throws DimensionMismatchException,
    094                   NoDataException,
    095                   NullArgumentException {
    096            final UnitSphereRandomVectorGenerator rand
    097                = new UnitSphereRandomVectorGenerator(xval[0].length);
    098            return new MicrosphereInterpolatingFunction(xval, yval,
    099                                                        brightnessExponent,
    100                                                        microsphereElements,
    101                                                        rand);
    102        }
    103    }