Clipper
|
00001 00004 //C Copyright (C) 2000-2006 Kevin Cowtan and University of York 00005 //L 00006 //L This library is free software and is distributed under the terms 00007 //L and conditions of version 2.1 of the GNU Lesser General Public 00008 //L Licence (LGPL) with the following additional clause: 00009 //L 00010 //L `You may also combine or link a "work that uses the Library" to 00011 //L produce a work containing portions of the Library, and distribute 00012 //L that work under terms of your choice, provided that you give 00013 //L prominent notice with each copy of the work that the specified 00014 //L version of the Library is used in it, and that you include or 00015 //L provide public access to the complete corresponding 00016 //L machine-readable source code for the Library including whatever 00017 //L changes were used in the work. (i.e. If you make changes to the 00018 //L Library you must distribute those, but you do not need to 00019 //L distribute source or object code to those portions of the work 00020 //L not covered by this licence.)' 00021 //L 00022 //L Note that this clause grants an additional right and does not impose 00023 //L any additional restriction, and so does not affect compatibility 00024 //L with the GNU General Public Licence (GPL). If you wish to negotiate 00025 //L other terms, please contact the maintainer. 00026 //L 00027 //L You can redistribute it and/or modify the library under the terms of 00028 //L the GNU Lesser General Public License as published by the Free Software 00029 //L Foundation; either version 2.1 of the License, or (at your option) any 00030 //L later version. 00031 //L 00032 //L This library is distributed in the hope that it will be useful, but 00033 //L WITHOUT ANY WARRANTY; without even the implied warranty of 00034 //L MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00035 //L Lesser General Public License for more details. 00036 //L 00037 //L You should have received a copy of the CCP4 licence and/or GNU 00038 //L Lesser General Public License along with this library; if not, write 00039 //L to the CCP4 Secretary, Daresbury Laboratory, Warrington WA4 4AD, UK. 00040 //L The GNU Lesser General Public can also be obtained by writing to the 00041 //L Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, 00042 //L MA 02111-1307 USA 00043 00044 00045 #ifndef CLIPPER_MAP_INTERP 00046 #define CLIPPER_MAP_INTERP 00047 00048 #include "derivs.h" 00049 00050 00051 namespace clipper 00052 { 00053 00055 00066 class Interp_nearest 00067 { 00068 public: 00069 template<class M> static bool can_interp( const M& map, const Coord_map& pos ); 00070 template<class T, class M> static void interp( const M& map, const Coord_map& pos, T& val ); 00071 inline static int order() { return 0; } 00072 }; 00073 00075 00087 class Interp_linear 00088 { 00089 public: 00090 template<class M> static bool can_interp( const M& map, const Coord_map& pos ); 00091 template<class T, class M> static void interp( const M& map, const Coord_map& pos, T& val ); 00092 inline static int order() { return 1; } 00093 }; 00094 00096 00108 class Interp_cubic 00109 { 00110 public: 00111 template<class M> static bool can_interp( const M& map, const Coord_map& pos ); 00112 template<class T, class M> static void interp( const M& map, const Coord_map& pos, T& val ); 00113 template<class T, class M> static void interp_grad( const M& map, const Coord_map& pos, T& val, Grad_map<T>& grad ); 00114 template<class T, class M> static void interp_curv( const M& map, const Coord_map& pos, T& val, Grad_map<T>& grad, Curv_map<T>& curv ); 00115 inline static int order() { return 3; } 00116 }; 00117 00118 00119 00120 // template implementations 00121 00128 template<class M> bool Interp_nearest::can_interp( const M& map, const Coord_map& pos ) 00129 { return map.in_map( pos.coord_grid() ); } 00130 00138 template<class T, class M> void Interp_nearest::interp( const M& map, const Coord_map& pos, T& val ) 00139 { val = map.get_data( pos.coord_grid() ); } 00140 00141 00148 template<class M> bool Interp_linear::can_interp( const M& map, const Coord_map& pos ) 00149 { 00150 Coord_grid c( pos.floor() ); // for even order change floor to coord_grid 00151 c.u() -= order()/2; c.v() -= order()/2; c.w() -= order()/2; 00152 if ( map.in_map( c ) ) { 00153 c.u() += order(); c.v() += order(); c.w() += order(); 00154 return map.in_map( c ); 00155 } 00156 return false; 00157 } 00158 00166 template<class T, class M> void Interp_linear::interp( const M& map, const Coord_map& pos, T& val ) 00167 { 00168 ftype u0 = floor( pos.u() ); 00169 ftype v0 = floor( pos.v() ); 00170 ftype w0 = floor( pos.w() ); 00171 typename M::Map_reference_coord 00172 r( map, Coord_grid( int(u0), int(v0), int(w0) ) ); 00173 T cu1( pos.u() - u0 ); 00174 T cv1( pos.v() - v0 ); 00175 T cw1( pos.w() - w0 ); 00176 T cu0( 1.0 - cu1 ); 00177 T cv0( 1.0 - cv1 ); 00178 T cw0( 1.0 - cw1 ); 00179 T r00 = cw0 * map[ r ]; // careful with evaluation order 00180 r00 += cw1 * map[ r.next_w() ]; 00181 T r01 = cw1 * map[ r.next_v() ]; 00182 r01 += cw0 * map[ r.prev_w() ]; 00183 T r11 = cw0 * map[ r.next_u() ]; 00184 r11 += cw1 * map[ r.next_w() ]; 00185 T r10 = cw1 * map[ r.prev_v() ]; 00186 r10 += cw0 * map[ r.prev_w() ]; 00187 val = ( cu0*( cv0*r00 + cv1*r01 ) + cu1*( cv0*r10 + cv1*r11 ) ); 00188 } 00189 00190 00197 template<class M> bool Interp_cubic::can_interp( const M& map, const Coord_map& pos ) 00198 { 00199 Coord_grid c( pos.floor() ); // for even order change floor to coord_grid 00200 c.u() -= order()/2; c.v() -= order()/2; c.w() -= order()/2; 00201 if ( map.in_map( c ) ) { 00202 c.u() += order(); c.v() += order(); c.w() += order(); 00203 return map.in_map( c ); 00204 } 00205 return false; 00206 } 00207 00213 template<class T, class M> void Interp_cubic::interp( const M& map, const Coord_map& pos, T& val ) 00214 { 00215 ftype u0 = floor( pos.u() ); 00216 ftype v0 = floor( pos.v() ); 00217 ftype w0 = floor( pos.w() ); 00218 typename M::Map_reference_coord iw, iv, 00219 iu( map, Coord_grid( int(u0)-1, int(v0)-1, int(w0)-1 ) ); 00220 T su, sv, sw, cu[4], cv[4], cw[4]; 00221 T cu1( pos.u() - u0 ); 00222 T cv1( pos.v() - v0 ); 00223 T cw1( pos.w() - w0 ); 00224 T cu0( 1.0 - cu1 ); 00225 T cv0( 1.0 - cv1 ); 00226 T cw0( 1.0 - cw1 ); 00227 cu[0] = -0.5*cu1*cu0*cu0; // cubic spline coeffs: u 00228 cu[1] = cu0*( -1.5*cu1*cu1 + cu1 + 1.0 ); 00229 cu[2] = cu1*( -1.5*cu0*cu0 + cu0 + 1.0 ); 00230 cu[3] = -0.5*cu1*cu1*cu0; 00231 cv[0] = -0.5*cv1*cv0*cv0; // cubic spline coeffs: v 00232 cv[1] = cv0*( -1.5*cv1*cv1 + cv1 + 1.0 ); 00233 cv[2] = cv1*( -1.5*cv0*cv0 + cv0 + 1.0 ); 00234 cv[3] = -0.5*cv1*cv1*cv0; 00235 cw[0] = -0.5*cw1*cw0*cw0; // cubic spline coeffs: w 00236 cw[1] = cw0*( -1.5*cw1*cw1 + cw1 + 1.0 ); 00237 cw[2] = cw1*( -1.5*cw0*cw0 + cw0 + 1.0 ); 00238 cw[3] = -0.5*cw1*cw1*cw0; 00239 su = 0.0; 00240 int i, j; 00241 for ( j = 0; j < 4; j++ ) { 00242 iv = iu; 00243 sv = 0.0; 00244 for ( i = 0; i < 4; i++ ) { 00245 iw = iv; 00246 sw = cw[0] * T( map[ iw ] ); 00247 sw += cw[1] * T( map[ iw.next_w() ] ); 00248 sw += cw[2] * T( map[ iw.next_w() ] ); 00249 sw += cw[3] * T( map[ iw.next_w() ] ); 00250 sv += cv[i] * sw; 00251 iv.next_v(); 00252 } 00253 su += cu[j] * sv; 00254 iu.next_u(); 00255 } 00256 val = su; 00257 } 00258 00259 00267 template<class T, class M> void Interp_cubic::interp_grad( const M& map, const Coord_map& pos, T& val, Grad_map<T>& grad ) 00268 { 00269 ftype u0 = floor( pos.u() ); 00270 ftype v0 = floor( pos.v() ); 00271 ftype w0 = floor( pos.w() ); 00272 typename M::Map_reference_coord iw, iv, 00273 iu( map, Coord_grid( int(u0)-1, int(v0)-1, int(w0)-1 ) ); 00274 T s1, s2, s3, du1, dv1, dv2, dw1, dw2, dw3; 00275 T cu[4], cv[4], cw[4], gu[4], gv[4], gw[4]; 00276 T cu1( pos.u() - u0 ); 00277 T cv1( pos.v() - v0 ); 00278 T cw1( pos.w() - w0 ); 00279 T cu0( 1.0 - cu1 ); 00280 T cv0( 1.0 - cv1 ); 00281 T cw0( 1.0 - cw1 ); 00282 cu[0] = -0.5*cu1*cu0*cu0; // cubic spline coeffs: u 00283 cu[1] = cu0*( -1.5*cu1*cu1 + cu1 + 1.0 ); 00284 cu[2] = cu1*( -1.5*cu0*cu0 + cu0 + 1.0 ); 00285 cu[3] = -0.5*cu1*cu1*cu0; 00286 cv[0] = -0.5*cv1*cv0*cv0; // cubic spline coeffs: v 00287 cv[1] = cv0*( -1.5*cv1*cv1 + cv1 + 1.0 ); 00288 cv[2] = cv1*( -1.5*cv0*cv0 + cv0 + 1.0 ); 00289 cv[3] = -0.5*cv1*cv1*cv0; 00290 cw[0] = -0.5*cw1*cw0*cw0; // cubic spline coeffs: w 00291 cw[1] = cw0*( -1.5*cw1*cw1 + cw1 + 1.0 ); 00292 cw[2] = cw1*( -1.5*cw0*cw0 + cw0 + 1.0 ); 00293 cw[3] = -0.5*cw1*cw1*cw0; 00294 gu[0] = cu0*( 1.5*cu1 - 0.5 ); // cubic spline grad coeffs: u 00295 gu[1] = cu1*( 4.5*cu1 - 5.0 ); 00296 gu[2] = -cu0*( 4.5*cu0 - 5.0 ); 00297 gu[3] = -cu1*( 1.5*cu0 - 0.5 ); 00298 gv[0] = cv0*( 1.5*cv1 - 0.5 ); // cubic spline grad coeffs: v 00299 gv[1] = cv1*( 4.5*cv1 - 5.0 ); 00300 gv[2] = -cv0*( 4.5*cv0 - 5.0 ); 00301 gv[3] = -cv1*( 1.5*cv0 - 0.5 ); 00302 gw[0] = cw0*( 1.5*cw1 - 0.5 ); // cubic spline grad coeffs: w 00303 gw[1] = cw1*( 4.5*cw1 - 5.0 ); 00304 gw[2] = -cw0*( 4.5*cw0 - 5.0 ); 00305 gw[3] = -cw1*( 1.5*cw0 - 0.5 ); 00306 s1 = du1 = dv1 = dw1 = 0.0; 00307 int i, j; 00308 for ( j = 0; j < 4; j++ ) { 00309 iv = iu; 00310 s2 = dv2 = dw2 = 0.0; 00311 for ( i = 0; i < 4; i++ ) { 00312 iw = iv; 00313 s3 = cw[0] * T( map[ iw ] ); 00314 dw3 = gw[0] * T( map[ iw ] ); 00315 iw.next_w(); 00316 s3 += cw[1] * T( map[ iw ] ); 00317 dw3 += gw[1] * T( map[ iw ] ); 00318 iw.next_w(); 00319 s3 += cw[2] * T( map[ iw ] ); 00320 dw3 += gw[2] * T( map[ iw ] ); 00321 iw.next_w(); 00322 s3 += cw[3] * T( map[ iw ] ); 00323 dw3 += gw[3] * T( map[ iw ] ); 00324 s2 += cv[i] * s3; 00325 dv2 += gv[i] * s3; 00326 dw2 += cv[i] * dw3; 00327 iv.next_v(); 00328 } 00329 s1 += cu[j] * s2; 00330 du1 += gu[j] * s2; 00331 dv1 += cu[j] * dv2; 00332 dw1 += cu[j] * dw2; 00333 iu.next_u(); 00334 } 00335 val = s1; 00336 grad = Grad_map<T>( du1, dv1, dw1 ); 00337 } 00338 00339 00347 template<class T, class M> void Interp_cubic::interp_curv( const M& map, const Coord_map& pos, T& val, Grad_map<T>& grad, Curv_map<T>& curv ) 00348 { 00349 ftype u0 = floor( pos.u() ); 00350 ftype v0 = floor( pos.v() ); 00351 ftype w0 = floor( pos.w() ); 00352 typename M::Map_reference_coord iw, iv, 00353 iu( map, Coord_grid( int(u0)-1, int(v0)-1, int(w0)-1 ) ); 00354 T s1, s2, s3, du1, dv1, dv2, dw1, dw2, dw3; 00355 T duv1, duw1, dvw1, dvw2, duu1, dvv1, dvv2, dww1, dww2, dww3; 00356 T cu[4], cv[4], cw[4], gu[4], gv[4], gw[4], ggu[4], ggv[4], ggw[4]; 00357 T cu1( pos.u() - u0 ); 00358 T cv1( pos.v() - v0 ); 00359 T cw1( pos.w() - w0 ); 00360 T cu0( 1.0 - cu1 ); 00361 T cv0( 1.0 - cv1 ); 00362 T cw0( 1.0 - cw1 ); 00363 cu[0] = -0.5*cu1*cu0*cu0; // cubic spline coeffs: u 00364 cu[1] = cu0*( -1.5*cu1*cu1 + cu1 + 1.0 ); 00365 cu[2] = cu1*( -1.5*cu0*cu0 + cu0 + 1.0 ); 00366 cu[3] = -0.5*cu1*cu1*cu0; 00367 cv[0] = -0.5*cv1*cv0*cv0; // cubic spline coeffs: v 00368 cv[1] = cv0*( -1.5*cv1*cv1 + cv1 + 1.0 ); 00369 cv[2] = cv1*( -1.5*cv0*cv0 + cv0 + 1.0 ); 00370 cv[3] = -0.5*cv1*cv1*cv0; 00371 cw[0] = -0.5*cw1*cw0*cw0; // cubic spline coeffs: w 00372 cw[1] = cw0*( -1.5*cw1*cw1 + cw1 + 1.0 ); 00373 cw[2] = cw1*( -1.5*cw0*cw0 + cw0 + 1.0 ); 00374 cw[3] = -0.5*cw1*cw1*cw0; 00375 gu[0] = cu0*( 1.5*cu1 - 0.5 ); // cubic spline grad coeffs: u 00376 gu[1] = cu1*( 4.5*cu1 - 5.0 ); 00377 gu[2] = -cu0*( 4.5*cu0 - 5.0 ); 00378 gu[3] = -cu1*( 1.5*cu0 - 0.5 ); 00379 gv[0] = cv0*( 1.5*cv1 - 0.5 ); // cubic spline grad coeffs: v 00380 gv[1] = cv1*( 4.5*cv1 - 5.0 ); 00381 gv[2] = -cv0*( 4.5*cv0 - 5.0 ); 00382 gv[3] = -cv1*( 1.5*cv0 - 0.5 ); 00383 gw[0] = cw0*( 1.5*cw1 - 0.5 ); // cubic spline grad coeffs: w 00384 gw[1] = cw1*( 4.5*cw1 - 5.0 ); 00385 gw[2] = -cw0*( 4.5*cw0 - 5.0 ); 00386 gw[3] = -cw1*( 1.5*cw0 - 0.5 ); 00387 ggu[0] = 2.0 - 3.0*cu1; // cubic spline curv coeffs: u 00388 ggu[1] = 9.0*cu1 - 5.0; 00389 ggu[2] = 9.0*cu0 - 5.0; 00390 ggu[3] = 2.0 - 3.0*cu0; 00391 ggv[0] = 2.0 - 3.0*cv1; // cubic spline curv coeffs: v 00392 ggv[1] = 9.0*cv1 - 5.0; 00393 ggv[2] = 9.0*cv0 - 5.0; 00394 ggv[3] = 2.0 - 3.0*cv0; 00395 ggw[0] = 2.0 - 3.0*cw1; // cubic spline curv coeffs: w 00396 ggw[1] = 9.0*cw1 - 5.0; 00397 ggw[2] = 9.0*cw0 - 5.0; 00398 ggw[3] = 2.0 - 3.0*cw0; 00399 s1 = du1 = dv1 = dw1 = duv1 = duw1 = dvw1 = duu1 = dvv1 = dww1 = 0.0; 00400 int i, j; 00401 for ( j = 0; j < 4; j++ ) { 00402 iv = iu; 00403 s2 = dv2 = dw2 = dvw2 = dvv2 = dww2 = 0.0; 00404 for ( i = 0; i < 4; i++ ) { 00405 iw = iv; 00406 s3 = cw[0] * T( map[ iw ] ); 00407 dw3 = gw[0] * T( map[ iw ] ); 00408 dww3 = ggw[0] * T( map[ iw ] ); 00409 iw.next_w(); 00410 s3 += cw[1] * T( map[ iw ] ); 00411 dw3 += gw[1] * T( map[ iw ] ); 00412 dww3 += ggw[1] * T( map[ iw ] ); 00413 iw.next_w(); 00414 s3 += cw[2] * T( map[ iw ] ); 00415 dw3 += gw[2] * T( map[ iw ] ); 00416 dww3 += ggw[2] * T( map[ iw ] ); 00417 iw.next_w(); 00418 s3 += cw[3] * T( map[ iw ] ); 00419 dw3 += gw[3] * T( map[ iw ] ); 00420 dww3 += ggw[3] * T( map[ iw ] ); 00421 s2 += cv[i] * s3; 00422 dv2 += gv[i] * s3; 00423 dw2 += cv[i] * dw3; 00424 dvw2 += gv[i] * dw3; 00425 dvv2 += ggv[i] * s3; 00426 dww2 += cv[i] * dww3; 00427 iv.next_v(); 00428 } 00429 s1 += cu[j] * s2; 00430 du1 += gu[j] * s2; 00431 dv1 += cu[j] * dv2; 00432 dw1 += cu[j] * dw2; 00433 duv1 += gu[j] * dv2; 00434 duw1 += gu[j] * dw2; 00435 dvw1 += cu[j] * dvw2; 00436 duu1 += ggu[j] * s2; 00437 dvv1 += cu[j] * dvv2; 00438 dww1 += cu[j] * dww2; 00439 iu.next_u(); 00440 } 00441 val = s1; 00442 grad = Grad_map<T>( du1, dv1, dw1 ); 00443 curv = Curv_map<T>( Mat33<T>( duu1, duv1, duw1, 00444 duv1, dvv1, dvw1, 00445 duw1, dvw1, dww1 ) ); 00446 } 00447 00448 00449 } // namespace clipper 00450 00451 00452 #endif