Rosetta
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
interpolate.cc
Go to the documentation of this file.
1 // -*- mode:c++;tab-width:2;indent-tabs-mode:t;show-trailing-whitespace:t;rm-trailing-spaces:t -*-
2 // vi: set ts=2 noet:
3 //
4 // (c) Copyright Rosetta Commons Member Institutions.
5 // (c) This file is part of the Rosetta software suite and is made available under license.
6 // (c) The Rosetta software is developed by the contributing members of the Rosetta Commons.
7 // (c) For more information, see http://www.rosettacommons.org. Questions about this can be
8 // (c) addressed to University of Washington UW TechTransfer, email: license@u.washington.edu.
9 
10 /// @file
11 /// @brief
12 /// @author
13 
14 
15 // Rosetta Headers
16 #include <basic/interpolate.hh>
17 #include <basic/basic.hh> // for subtract_degree_angles, angle_in_range
18 
19 namespace basic {
20 
21 ////////////////////////////////////////////////////////////////////////////////
22 ///
23 /// @brief get bilinear interpolate, given four points of a 2d periodic function
24 ///
25 /// @details
26 ///
27 /// Value and derivatives of bilinear interpolation between four
28 /// specified input values, which are the function values
29 /// corresponding to four points which bracket the interpolated point
30 /// in 2-dimensions. (see diagram below) (see Num. Recipes v2, sec
31 /// 3.6, "Interpolation in two or more dimensions")
32 ///
33 /// Note that it is automatically assumed that the arguments are
34 /// periodic, that is f(a,b),a,b=periodic value; the *value* of the
35 /// function can be treated as periodic ( fixed to a periodicity of
36 /// 360.) as well when the input parameter angle is set to true
37 ///
38 /// The derivatives are of the bilinear interpolation only. This is
39 /// not the same value as a numerical derivative of function
40 /// values. The derivatives here are discontinuous every time you
41 /// cross over a bin boundary in either dimension
42 ///
43 ///
44 /// - bilinear interpolation:
45 ///
46 /// x0y1 +----------+ x1y1
47 /// | |
48 /// 1-yd | (x,y) |
49 /// - - + |
50 /// yd | . |
51 /// | . |
52 /// x0y0 +---|------+ x1y0
53 /// xd 1-xd
54 ///
55 ///
56 ///
57 /// @param[in] x0y0 - in - input bracketing function value (see diagram)
58 /// @param[in] x1y0 - in - " "
59 /// @param[in] x0y1 - in - " "
60 /// @param[in] x1y1 - in - " "
61 /// @param[in] xd - in - error value in the 1st dim between lower lst dim
62 /// bracket value 'x0' and point to be interpolated, 'x'
63 /// @param[in] yd - in - " 2nd dim "
64 /// @param[in] binrange - in - range of bin in angles ( for both dimensions )
65 /// @param[in] angles - in - if true, treat the the *values* of xy_func as
66 /// as having a periodicity of 360. ( note that
67 /// the bin ranges are already assumed periodic )
68 /// @param[out] val - out - biliinear interpolated value
69 /// @param[out] dval_dx - out - derivative of 'val' in the 1st ('x') dim
70 /// @param[out] dval_dy - out - " 2nd dim "
71 ///
72 /// @remarks
73 ///
74 /// @references
75 ///
76 /// @author ctsa 8-19-03
77 ///
78 /////////////////////////////////////////////////////////////////////////////////
79 void
81  double const x0y0,
82  double const x1y0,
83  double const x0y1,
84  double const x1y1,
85  double const xd,
86  double const yd,
87  double const binrange,
88  bool const angles,
89  double & val,
90  double & dval_dx,
91  double & dval_dy
92 )
93 {
94  double const w1 = ( 1.0f - xd ) * ( 1.0f - yd );
95  double const w2 = xd * ( 1.0f - yd );
96  double const w3 = ( 1.0f - xd ) * yd;
97  double const w4 = xd * yd;
98 
99  if ( angles ) {
100  //// ctsa - hack method for weighted angle averaging, if we could burn
101  //// cpu time, then the right thing to do would probably be to
102  //// break func into x and y components, add up, interpolate,
103  //// and find the direction
104 
105  double const w12 = w1 + w2;
106  double a12;
107  if ( w12 != 0.0 ) {
108  a12 = ( w1 * x0y0 + w2 * ( subtract_degree_angles(x1y0,x0y0) + x0y0 ) ) / w12;
109  } else {
110  a12 = 0.0;
111  }
112 
113  double const w34 = w3 + w4;
114  double a34;
115  if ( w34 != 0.0 ) {
116  a34 = ( w3 * x0y1 + w4 * ( subtract_degree_angles(x1y1,x0y1) + x0y1 ) ) / w34;
117  } else {
118  a34 = 0.0;
119  }
120 
121  val = w12 * a12 + w34 * ( subtract_degree_angles(a34,a12) + a12 );
122  angle_in_range(val);
123 
124  dval_dx = ( ( 1.0f - yd ) * subtract_degree_angles(x1y0,x0y0) + yd * subtract_degree_angles(x1y1,x0y1) ) / binrange;
125  dval_dy = ( ( 1.0f - xd ) * subtract_degree_angles(x0y1,x0y0) + xd * subtract_degree_angles(x1y1,x1y0) ) / binrange;
126  } else {
127  val = x0y0 * w1 + x1y0 * w2 + x0y1 * w3 + x1y1 * w4;
128 
129  dval_dx = ( ( 1.0f - yd ) * ( x1y0 - x0y0 ) + yd * ( x1y1 - x0y1 ) ) / binrange;
130  dval_dy = ( ( 1.0f - xd ) * ( x0y1 - x0y0 ) + xd * ( x1y1 - x1y0 ) ) / binrange;
131  }
132 }
133 
134 /// @brief paraphazed from above for three dimentions
135 /// Without additional scaling this will only work if
136 /// the bin sizes in each dimention are equal I think.
137 /// Otherwise it could be computed as the product of
138 /// three linear interpolations
139 ///
140 /// Perform linear interpolation between x0y0z0 and x1y0z0 to find y0z0
141 /// Preform linear interpolation between x0y0z1 and x1y0z1 to find y0z1
142 /// Preform linear interpolation between x0y1z1 and x1y1z1 to find y1z1
143 /// Preform linear interpolation between x0y1z0 and x1y1z0 to find y1z0
144 /// Preform linear interpolation between y0z0 and y1z0 to find z0
145 /// Preform linear interpolation between y0z1 and y1z1 to find z1
146 /// Preform linear interpolation between z0 and z1 to find val
147 
148 void
150  double const x0y0z0,
151  double const x1y0z0,
152  double const x0y1z0,
153  double const x1y1z0,
154  double const x0y0z1,
155  double const x1y0z1,
156  double const x0y1z1,
157  double const x1y1z1,
158  double const xd,
159  double const yd,
160  double const zd,
161  double const binrange,
162  bool const angles,
163  double & val,
164  double & dval_dx,
165  double & dval_dy,
166  double & dval_dz
167 )
168 {
169  double const w1 = ( 1.0f - xd ) * ( 1.0f - yd ) * ( 1.0f -zd );
170  double const w2 = xd * ( 1.0f - yd ) * ( 1.0f -zd );
171  double const w3 = ( 1.0f - xd ) * yd * ( 1.0f -zd );
172  double const w4 = ( 1.0f - xd ) * ( 1.0f - yd ) * zd;
173  double const w5 = xd * yd * ( 1.0f -zd );
174  double const w6 = xd * ( 1.0f - yd ) * zd;
175  double const w7 = ( 1.0f - xd ) * yd * zd;
176  double const w8 = xd * yd * zd;
177 
178  if ( angles ) {
179  // not sure why angles need to be treated differently
180  val = x0y0z0 * w1 + x1y0z0 * w2 + x0y1z0 * w3 + x0y0z1 * w4 + x1y1z0 * w5 + x1y0z1 * w6 + x0y1z1 * w7 + x1y1z1 * w8;
181  dval_dx = ( -1.0f * x0y0z0 * ( 1.0f - yd ) * ( 1.0f - zd ) + x1y0z0 * ( 1.0f - yd ) * ( 1.0f - zd ) - x0y1z0 * yd * ( 1.0f - zd ) + x1y0z1 * yd * ( 1.0f - zd ) - x1y0z1 * ( 1.0f - yd ) * zd + x1y0z0 * ( 1.0f - yd ) * zd - x1y0z0 * yd * zd + x1y1z1 * yd * zd ) / binrange;
182  dval_dy = ( -1.0f * x0y0z0 * ( 1.0f - xd ) * ( 1.0f - zd ) + x0y1z0 * ( 1.0f - xd ) * ( 1.0f - zd ) - x1y0z0 * xd * ( 1.0f - zd ) + x1y0z1 * xd * ( 1.0f - zd ) - x1y0z1 * ( 1.0f - xd ) * zd + x1y0z0 * ( 1.0f - xd ) * zd - x1y0z0 * xd * zd + x1y1z1 * xd * zd ) / binrange;
183  dval_dz = ( -1.0f * x0y0z0 * ( 1.0f - xd ) * ( 1.0f - yd ) + x1y0z1 * ( 1.0f - xd ) * ( 1.0f - yd ) - x1y0z0 * xd * ( 1.0f - yd ) + x1y0z0 * xd * ( 1.0f - yd ) - x0y1z0 * ( 1.0f - xd ) * yd + x1y0z0 * ( 1.0f - xd ) * yd - x1y0z1 * xd * yd + x1y1z1 * xd * yd ) / binrange;
184 
185  } else {
186  val = x0y0z0 * w1 + x1y0z0 * w2 + x0y1z0 * w3 + x0y0z1 * w4 + x1y0z1 * w5 + x0y1z1 * w6 + x1y1z0 * w7 + x1y1z1 * w8;
187  dval_dx = ( -1.0f * x0y0z0 * ( 1.0f - yd ) * ( 1.0f - zd ) + x1y0z0 * ( 1.0f - yd ) * ( 1.0f - zd ) - x0y1z0 * yd * ( 1.0f - zd ) + x1y0z1 * yd * ( 1.0f - zd ) - x1y0z1 * ( 1.0f - yd ) * zd + x1y0z0 * ( 1.0f - yd ) * zd - x1y0z0 * yd * zd + x1y1z1 * yd * zd ) / binrange;
188  dval_dy = ( -1.0f * x0y0z0 * ( 1.0f - xd ) * ( 1.0f - zd ) + x0y1z0 * ( 1.0f - xd ) * ( 1.0f - zd ) - x1y0z0 * xd * ( 1.0f - zd ) + x1y0z1 * xd * ( 1.0f - zd ) - x1y0z1 * ( 1.0f - xd ) * zd + x1y0z0 * ( 1.0f - xd ) * zd - x1y0z0 * xd * zd + x1y1z1 * xd * zd ) / binrange;
189  dval_dz = ( -1.0f * x0y0z0 * ( 1.0f - xd ) * ( 1.0f - yd ) + x1y0z1 * ( 1.0f - xd ) * ( 1.0f - yd ) - x1y0z0 * xd * ( 1.0f - yd ) + x1y0z0 * xd * ( 1.0f - yd ) - x0y1z0 * ( 1.0f - xd ) * yd + x1y0z0 * ( 1.0f - xd ) * yd - x1y0z1 * xd * yd + x1y1z1 * xd * yd ) / binrange;
190 
191  }
192 }
193 
194 } // namespace basic
void interpolate_trilinear_by_value(double const x0y0z0, double const x1y0z0, double const x0y1z0, double const x1y1z0, double const x0y0z1, double const x1y0z1, double const x0y1z1, double const x1y1z1, double const xd, double const yd, double const zd, double const binrange, bool const angles, double &val, double &dval_dx, double &dval_dy, double &dval_dz)
paraphazed from above for three dimentions Without additional scaling this will only work if the bin ...
Definition: interpolate.cc:149
double subtract_degree_angles(double a, double b)
subtract angles in degrees, restricting the range of the result
Definition: basic.cc:104
void interpolate_bilinear_by_value(double const x0y0, double const x1y0, double const x0y1, double const x1y1, double const xd, double const yd, double const binrange, bool const angles, double &val, double &dval_dx, double &dval_dy)
get bilinear interpolate, given four points of a 2d periodic function
Definition: interpolate.cc:80
void angle_in_range(double &ang)
taken from wobble.cc
Definition: basic.cc:199