001/**
002 * Copyright (c) 2011, The University of Southampton and the individual contributors.
003 * All rights reserved.
004 *
005 * Redistribution and use in source and binary forms, with or without modification,
006 * are permitted provided that the following conditions are met:
007 *
008 *   *  Redistributions of source code must retain the above copyright notice,
009 *      this list of conditions and the following disclaimer.
010 *
011 *   *  Redistributions in binary form must reproduce the above copyright notice,
012 *      this list of conditions and the following disclaimer in the documentation
013 *      and/or other materials provided with the distribution.
014 *
015 *   *  Neither the name of the University of Southampton nor the names of its
016 *      contributors may be used to endorse or promote products derived from this
017 *      software without specific prior written permission.
018 *
019 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
020 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
021 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
022 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
023 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
024 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
025 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
026 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
027 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
028 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
029 */
030package org.openimaj.math.util;
031
032/**
033 * Static methods for performing interpolation
034 * 
035 * @author Jonathon Hare (jsh2@ecs.soton.ac.uk)
036 */
037public class Interpolation {
038        /**
039         * Linear interpolation of y at x given x0,y0 and x1,y1.
040         * 
041         * @param x
042         *            the x position
043         * @param x0
044         *            the first x position
045         * @param y0
046         *            the first y position
047         * @param x1
048         *            the second x position
049         * @param y1
050         *            the second y position
051         * @return the interpolated value (y) at x
052         */
053        public static float lerp(float x, float x0, float y0, float x1, float y1) {
054                if (x == x0)
055                        return y0;
056                return y0 + (x - x0) * ((y1 - y0) / (x1 - x0));
057        }
058
059        /**
060         * Linear interpolation of y at x given x0,y0 and x1,y1.
061         * 
062         * @param x
063         *            the x position
064         * @param x0
065         *            the first x position
066         * @param y0
067         *            the first y position
068         * @param x1
069         *            the second x position
070         * @param y1
071         *            the second y position
072         * @return the interpolated value (y) at x
073         */
074        public static double lerp(double x, double x0, double y0, double x1, double y1) {
075                if (x == x0)
076                        return y0;
077                return y0 + (x - x0) * ((y1 - y0) / (x1 - x0));
078        }
079
080        /**
081         * Cubic interpolation of y at x (in 0..1) given y at x=[-1, 0, 1, 2]
082         * 
083         * @param x
084         *            the x value to compute
085         * @param y0
086         *            y value at x=-1
087         * @param y1
088         *            y value at x=0
089         * @param y2
090         *            y value at x=1
091         * @param y3
092         *            y value at x=2
093         * @return the interpolated value
094         */
095        public static double cubicInterp(double x, double y0, double y1, double y2, double y3) {
096                return y1 + 0.5 * x * (y2 - y0 + x * (2.0 * y0 - 5.0 * y1 + 4.0 * y2 - y3 + x * (3.0 * (y1 - y2) + y3 - y0)));
097        }
098
099        /**
100         * Cubic interpolation of y at x (in 0..1) given y at x=[-1, 0, 1, 2]
101         * 
102         * @param x
103         *            the x value to compute
104         * @param y0
105         *            y value at x=-1
106         * @param y1
107         *            y value at x=0
108         * @param y2
109         *            y value at x=1
110         * @param y3
111         *            y value at x=2
112         * @return the interpolated value
113         */
114        public static float cubicInterp(float x, float y0, float y1, float y2, float y3) {
115                return (float) (y1 + 0.5 * x
116                                * (y2 - y0 + x * (2.0 * y0 - 5.0 * y1 + 4.0 * y2 - y3 + x * (3.0 * (y1 - y2) + y3 - y0))));
117        }
118
119        /**
120         * Cubic interpolation of y at x (in 0..1) given y at x=[-1, 0, 1, 2]
121         * 
122         * @param x
123         *            the x value to compute
124         * @param y
125         *            an array of 4 y values at x=[-1, 0, 1, 2]
126         * @return the interpolated value
127         */
128        public static double cubicInterp(double x, double[] y) {
129                return y[1] + 0.5 * x * (y[2] - y[0] + x
130                                * (2.0 * y[0] - 5.0 * y[1] + 4.0 * y[2] - y[3] + x * (3.0 * (y[1] - y[2]) + y[3] - y[0])));
131        }
132
133        /**
134         * Cubic interpolation of y at x (in 0..1) given y at x=[-1, 0, 1, 2]
135         * 
136         * @param x
137         *            the x value to compute
138         * @param y
139         *            an array of 4 y values at x=[-1, 0, 1, 2]
140         * @return the interpolated value
141         */
142        public static float cubicInterp(float x, float[] y) {
143                return (float) (y[1] + 0.5 * x * (y[2] - y[0] + x
144                                * (2.0 * y[0] - 5.0 * y[1] + 4.0 * y[2] - y[3] + x * (3.0 * (y[1] - y[2]) + y[3] - y[0]))));
145        }
146
147        /**
148         * Bilinear interpolation of the value at x,y where 0<=x<=1 and 0<=y<=1
149         * given the values at (0,0), (0,1), (1,0) and (1,1). Note: This will work
150         * for other values of (x,y) but doesn't normally make sense.
151         * 
152         * @param x
153         *            the x position (in 0..1)
154         * @param y
155         *            the y position (in 0..1)
156         * @param f00
157         *            the value at (0,0)
158         * @param f01
159         *            the value at (0,1)
160         * @param f10
161         *            the value at (1,0)
162         * @param f11
163         *            the value at (1,1)
164         * @return the interpolated value (x,y)
165         */
166        public static double bilerp(double x, double y, double f00, double f01, double f10, double f11) {
167                return f00 * (1.0 - x) * (1.0 - y) + f10 * x * (1.0 - y) + f01 * (1.0 - x) * y + f11 * x * y;
168        }
169
170        /**
171         * Bilinear interpolation of the value at x,y where 0<=x<=1 and 0<=y<=1
172         * given the values at (0,0), (0,1), (1,0) and (1,1). Note: This will work
173         * for other values of (x,y) but doesn't normally make sense.
174         * 
175         * @param x
176         *            the x position (in 0..1)
177         * @param y
178         *            the y position (in 0..1)
179         * @param f00
180         *            the value at (0,0)
181         * @param f01
182         *            the value at (0,1)
183         * @param f10
184         *            the value at (1,0)
185         * @param f11
186         *            the value at (1,1)
187         * @return the interpolated value (x,y)
188         */
189        public static float bilerpf(float x, float y, float f00, float f01, float f10, float f11) {
190                return f00 * (1.0f - x) * (1.0f - y) + f10 * x * (1.0f - y) + f01 * (1.0f - x) * y + f11 * x * y;
191        }
192
193        /**
194         * Bilinear interpolation of the value at x,y where 0<=x<=1 and 0<=y<=1
195         * given the values at (0,0), (0,1), (1,0) and (1,1). Note: This will work
196         * for other values of (x,y) but doesn't normally make sense.
197         * 
198         * @param x
199         *            the x position (in 0..1)
200         * @param y
201         *            the y position (in 0..1)
202         * @param f00
203         *            the value at (0,0)
204         * @param f01
205         *            the value at (0,1)
206         * @param f10
207         *            the value at (1,0)
208         * @param f11
209         *            the value at (1,1)
210         * @return the interpolated value (x,y)
211         */
212        public static float bilerp(float x, float y, float f00, float f01, float f10, float f11) {
213                return f00 * (1.0f - x) * (1.0f - y) + f10 * x * (1.0f - y) + f01 * (1.0f - x) * y + f11 * x * y;
214        }
215
216        /**
217         * Bicubic interpolation of the value at x,y where 0<=x<=1 and 0<=y<=1 given
218         * the values at integer coordinates from (-1,-1) to (3,3).
219         * 
220         * @param x
221         *            the x position (in 0..1)
222         * @param y
223         *            the y position (in 0..1)
224         * @param p
225         *            a 4x4 array of known values at (-1,-1) to (3,3)
226         * 
227         * @return the interpolated value (x,y)
228         */
229        public static double bicubicInterp(double x, double y, double[][] p) {
230                final double y0 = cubicInterp(y, p[0]);
231                final double y1 = cubicInterp(y, p[1]);
232                final double y2 = cubicInterp(y, p[2]);
233                final double y3 = cubicInterp(y, p[3]);
234                return cubicInterp(x, y0, y1, y2, y3);
235        }
236
237        /**
238         * Bicubic interpolation of the value at x,y where 0<=x<=1 and 0<=y<=1 given
239         * the values at integer coordinates from (-1,-1) to (3,3).
240         * 
241         * @param x
242         *            the x position (in 0..1)
243         * @param y
244         *            the y position (in 0..1)
245         * @param p
246         *            a 4x4 array of known values at (-1,-1) to (3,3)
247         * 
248         * @return the interpolated value (x,y)
249         */
250        public static float bicubicInterp(float x, float y, float[][] p) {
251                final float y0 = cubicInterp(y, p[0]);
252                final float y1 = cubicInterp(y, p[1]);
253                final float y2 = cubicInterp(y, p[2]);
254                final float y3 = cubicInterp(y, p[3]);
255                return cubicInterp(x, y0, y1, y2, y3);
256        }
257}