Clipper
coords.h
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_COORDS
00046 #define CLIPPER_COORDS
00047 
00048 
00049 #include "cell.h"
00050 #include "spacegroup.h"
00051 #include "clipper_stats.h"
00052 
00053 
00054 namespace clipper
00055 {
00056   // forward definitions
00057   class Grid; class Grid_sampling; class Grid_range;
00058   class Coord_grid; class Coord_map;
00059   class Coord_reci_frac; class Coord_reci_orth;
00060   class Coord_frac; class Coord_orth;
00061   class U_aniso_frac; class U_aniso_orth;
00062 
00063 
00065 
00068   class Resolution
00069   {
00070   public:
00071     inline Resolution() : resol(0.0) {}          
00072     explicit Resolution( const ftype& resol_ );  
00073     void init( const ftype& resol_ );            
00074     const ftype& limit() const;                  
00075     ftype invresolsq_limit() const;  
00076     bool is_null() const;            
00077   private:
00078     ftype resol;
00079   };
00080 
00081 
00083 
00086   class HKL_class
00087   {
00088   public:
00090     inline HKL_class() { epsilon_ = 0; allowed_ = 255; }
00092     HKL_class( const Spacegroup& spgr, const HKL& hkl );
00094     inline ftype epsilon() const { return ftype(epsilon_); }
00096     inline ftype epsilonc() const
00097       { if ( centric() ) return 2.0*ftype(epsilon_);
00098         else             return ftype(epsilon_); }
00100     inline ftype allowed() const { return ftype(allowed_) * (Util::pi()/12.0); }
00101     inline bool centric() const { return allowed_ != 255; } 
00102     inline bool sys_abs() const { return epsilon_ == 0; }   
00103   private:
00104     unsigned char epsilon_, allowed_;
00105   };
00106 
00107 
00109 
00112   class RTop_orth : public RTop<>
00113   {
00114   public:
00116     inline RTop_orth() {}
00118     inline explicit RTop_orth( const RTop<>& o ) : RTop<>( o ) {}
00120     inline explicit RTop_orth( const Mat33<>& r ) : RTop<>( r ) {}
00122     inline RTop_orth( const Mat33<>& r, const Vec3<>& t ) : RTop<>( r, t ) {}
00124     RTop_orth( const std::vector<Coord_orth>& src, const std::vector<Coord_orth>& tgt );
00126     RTop_orth( const std::vector<Coord_orth>& src, const std::vector<Coord_orth>& tgt, const std::vector<ftype>& wgt );
00128     template<class T> RTop_orth( const T& src, const T& tgt );
00130     RTop_frac rtop_frac( const Cell& cell ) const;
00132     RTop_orth inverse() const;
00134     Coord_orth axis_coordinate_near( const Coord_orth& centre ) const;
00136     Coord_orth screw_translation() const;
00138     static RTop_orth identity();
00140     static RTop_orth null();
00141   };
00142 
00143 
00145   class HKL : public Vec3<int>
00146   {
00147   public:
00148     inline HKL() {}                
00149     inline explicit HKL( const Vec3<int>& v ) :
00150       Vec3<int>( v ) {}            
00151     inline HKL( const int& h, const int& k, const int& l ) :
00152       Vec3<int>( h, k, l ) {}      
00153     inline const int& h() const { return (*this)[0]; }  
00154     inline const int& k() const { return (*this)[1]; }  
00155     inline const int& l() const { return (*this)[2]; }  
00156     inline int& h() { return (*this)[0]; }  
00157     inline int& k() { return (*this)[1]; }  
00158     inline int& l() { return (*this)[2]; }  
00159 
00160     inline ftype invresolsq( const Cell& cell ) const;
00162     inline Coord_reci_frac coord_reci_frac() const;
00164     inline Coord_reci_orth coord_reci_orth( const Cell& cell ) const;
00166     inline HKL transform( const Symop& op ) const;
00168     inline HKL transform( const Isymop& op ) const;
00170     inline ftype sym_phase_shift( const Symop& op ) const;
00171     String format() const;  
00172     friend inline HKL operator -(const HKL& h1)
00173       { return HKL( -h1.h(), -h1.k(), -h1.l() ); }
00174     friend inline HKL operator +(const HKL& h1, const HKL& h2)
00175       { return HKL( h1.h()+h2.h(), h1.k()+h2.k(), h1.l()+h2.l() ); }
00176     friend inline HKL operator -(const HKL& h1, const HKL& h2)
00177       { return HKL( h1.h()-h2.h(), h1.k()-h2.k(), h1.l()-h2.l() ); }
00178     friend inline HKL operator *(const int& s, const HKL& h1)
00179       { return HKL( s*h1.h(), s*h1.k(), s*h1.l() ); }
00180     friend inline HKL operator *(const Isymop& op, const HKL& h1)
00181       { return HKL( h1 * op.rot() ); }
00182   };
00183 
00184 
00186   class Coord_reci_orth : public Vec3<>
00187   {
00188   public:
00189     inline Coord_reci_orth() {}           
00190     inline explicit Coord_reci_orth( const Vec3<>& v ) :
00191       Vec3<>( v ) {}          
00192     inline Coord_reci_orth( const ftype& xs, const ftype& ys, const ftype& zs ) : Vec3<>( xs, ys, zs ) {} 
00193     inline const ftype& xs() const { return (*this)[0]; }  
00194     inline const ftype& ys() const { return (*this)[1]; }  
00195     inline const ftype& zs() const { return (*this)[2]; }  
00196 
00197     inline ftype invresolsq() const;
00199     inline Coord_reci_frac coord_reci_frac( const Cell& cell ) const;
00201     inline Coord_reci_orth transform( const RTop_orth& op ) const
00202       { return Coord_reci_orth( (*this) * op.rot() ); }
00203     String format() const;  
00204   };
00205 
00206 
00208   class Coord_reci_frac : public Vec3<>
00209   {
00210   public:
00211     inline Coord_reci_frac() {}           
00212     inline explicit Coord_reci_frac( const Vec3<>& v ) :
00213       Vec3<>( v ) {}          
00214     inline Coord_reci_frac( const ftype& us, const ftype& vs, const ftype& ws ) : Vec3<>( us, vs, ws ) {} 
00215 
00216     inline Coord_reci_frac( const HKL& hkl ) :
00217       Vec3<>( ftype(hkl[0]), ftype(hkl[1]), ftype(hkl[2]) ) {}
00219     inline HKL hkl() const
00220       { return HKL( Util::intr(us()), Util::intr(vs()), Util::intr(ws()) ); }
00222     inline ftype invresolsq( const Cell& cell ) const;
00223     inline const ftype& us() const { return (*this)[0]; }  
00224     inline const ftype& vs() const { return (*this)[1]; }  
00225     inline const ftype& ws() const { return (*this)[2]; }  
00226 
00227     inline Coord_reci_orth coord_reci_orth( const Cell& cell ) const;
00229     inline Coord_reci_frac transform( const RTop_frac& op ) const
00230       { return Coord_reci_frac( (*this) * op.rot() ); }
00231     String format() const;  
00232   };
00233 
00234 
00236   class Coord_grid : public Vec3<int>
00237   {
00238   public:
00239     inline Coord_grid() {}  
00240 
00241     inline explicit Coord_grid( const Vec3<int> v ) : Vec3<int>( v ) {}
00243     inline Coord_grid( const int& u, const int& v, const int& w ) :
00244       Vec3<int>(u,v,w) {}
00246     inline Coord_grid( const Grid& g, const int& index )
00247       { deindex( g, index ); }
00248     inline const int& u() const { return (*this)[0]; }  
00249     inline const int& v() const { return (*this)[1]; }  
00250     inline const int& w() const { return (*this)[2]; }  
00251     inline int& u() { return (*this)[0]; }  
00252     inline int& v() { return (*this)[1]; }  
00253     inline int& w() { return (*this)[2]; }  
00254 
00256     inline Coord_map coord_map() const;
00258     inline Coord_frac coord_frac( const Grid_sampling& g ) const;
00260     inline Coord_grid transform( const Isymop& op ) const
00261       { return op * (*this); }
00262 
00264     inline Coord_grid unit( const Grid_sampling& g ) const;
00265 
00267 
00268     inline const Coord_grid& next( const Grid& g );
00270 
00271     inline const Coord_grid& next( const Grid_range& g );
00273     inline bool last( const Grid& g ) const;
00275     inline bool last( const Grid_range& g ) const;
00277     inline int index( const Grid& g ) const;
00279     inline void deindex( const Grid& g, const int& index );
00280     // grid indexing operator
00281     //inline int index( const Grid_range& g ) const;
00282     // grid deindexing operator
00283     //inline void deindex( const Grid_range& g, const int& index );
00284 
00285     String format() const;  
00286     friend inline Coord_grid operator -(const Coord_grid& r1)
00287       { return ( Coord_grid( -r1.u(), -r1.v(), -r1.w() ) ); }
00288     friend inline Coord_grid operator +(const Coord_grid& r1, const Coord_grid& r2) { return ( Coord_grid( r1.u()+r2.u(), r1.v()+r2.v(), r1.w()+r2.w() ) ); }
00289     friend inline Coord_grid operator -(const Coord_grid& r1, const Coord_grid& r2) { return ( Coord_grid( r1.u()-r2.u(), r1.v()-r2.v(), r1.w()-r2.w() ) ); }
00290     friend inline Coord_grid operator *(const int& s, const Coord_grid& r1)
00291       { return ( Coord_grid( s*r1.u(), s*r1.v(), s*r1.w() ) ); }
00292     friend inline int operator == (const Coord_grid& r1,  const Coord_grid& r2)
00293       { return (r1.u()==r2.u() && r1.v()==r2.v() && r1.w()==r2.w()); }
00294     friend inline int operator != (const Coord_grid& r1,  const Coord_grid& r2)
00295       { return (r1.u()!=r2.u() || r1.v()!=r2.v() || r1.w()!=r2.w()); }
00296     friend inline Coord_grid operator *(const Isymop& op, const Coord_grid& r1)
00297       { return Coord_grid( op.rot() * r1 + op.trn() ); }
00298   };
00299 
00300 
00302   class Coord_orth : public Vec3<>
00303   {
00304   public:
00305     inline Coord_orth() {}                
00306     inline explicit Coord_orth( const Vec3<>& v ) :
00307       Vec3<>( v ) {}          
00308     inline Coord_orth( const ftype& x, const ftype& y, const ftype& z ) :
00309       Vec3<>( x, y, z ) {}    
00310 
00311     Coord_orth( const Coord_orth& x1, const Coord_orth& x2, const Coord_orth& x3, const ftype& length, const ftype& angle, const ftype& torsion );
00312     inline const ftype& x() const { return (*this)[0]; }  
00313     inline const ftype& y() const { return (*this)[1]; }  
00314     inline const ftype& z() const { return (*this)[2]; }  
00315 
00316     inline ftype lengthsq() const;
00318     inline Coord_frac coord_frac( const Cell& cell ) const;
00320     inline Coord_orth transform( const RTop_orth& op ) const
00321       { return op*(*this); }
00322     String format() const;  
00323 
00324     static ftype length( const Coord_orth& x1, const Coord_orth& x2);
00326     static ftype angle( const Coord_orth& x1, const Coord_orth& x2, 
00327                         const Coord_orth& x3);
00329     static ftype torsion( const Coord_orth& x1, const Coord_orth& x2,
00330                           const Coord_orth& x3, const Coord_orth& x4);
00331     friend inline Coord_orth operator -(const Coord_orth& x1)
00332       { return Coord_orth( -x1.x(), -x1.y(), -x1.z() ); }
00333     friend inline Coord_orth operator +(const Coord_orth& x1, const Coord_orth& x2) { return Coord_orth( x1.x()+x2.x(), x1.y()+x2.y(), x1.z()+x2.z() ); }
00334     friend inline Coord_orth operator -(const Coord_orth& x1, const Coord_orth& x2) { return Coord_orth( x1.x()-x2.x(), x1.y()-x2.y(), x1.z()-x2.z() ); }
00335     friend inline Coord_orth operator *(const ftype& s, const Coord_orth& x1)
00336       { return Coord_orth( s*x1.x(), s*x1.y(), s*x1.z() ); }
00337     friend inline Coord_orth operator *(const RTop_orth& op, const Coord_orth& x1) { return Coord_orth( op.rot() * x1 + op.trn() ); }
00338   };
00339 
00340 
00342   class Coord_frac : public Vec3<>
00343   {
00344   public:
00345     inline Coord_frac() {}                
00346     inline explicit Coord_frac( const Vec3<>& v ) :
00347       Vec3<>( v ) {}          
00348     inline Coord_frac( const ftype& u, const ftype& v, const ftype& w ) :
00349       Vec3<>( u, v, w ) {}    
00350     inline const ftype& u() const { return (*this)[0]; }  
00351     inline const ftype& v() const { return (*this)[1]; }  
00352     inline const ftype& w() const { return (*this)[2]; }  
00353 
00354     inline ftype lengthsq( const Cell& cell ) const;
00356     inline Coord_orth coord_orth( const Cell& cell ) const;
00358     inline Coord_map coord_map( const Grid& g ) const;
00360     inline Coord_grid coord_grid( const Grid& g ) const;
00362     inline Coord_frac transform( const RTop_frac& op ) const
00363       { return op*(*this); }
00365     inline Coord_frac lattice_copy_zero() const
00366       { return Coord_frac(u()-rint(u()),v()-rint(v()),w()-rint(w())); }
00368     inline Coord_frac lattice_copy_unit() const
00369       { return Coord_frac(u()-floor(u()),v()-floor(v()),w()-floor(w())); }
00371     inline Coord_frac lattice_copy_near(const Coord_frac& n) const
00372       { return (*this-n).lattice_copy_zero()+n; }
00374     Coord_frac symmetry_copy_near(const Spacegroup& spgr, const Cell& cell, const Coord_frac& n) const;
00375     String format() const;  
00376     friend inline Coord_frac operator -(const Coord_frac& u1)
00377       { return Coord_frac( -u1.u(), -u1.v(), -u1.w() ); }
00378     friend inline Coord_frac operator +(const Coord_frac& u1, const Coord_frac& u2) { return Coord_frac( u1.u()+u2.u(), u1.v()+u2.v(), u1.w()+u2.w() ); }
00379     friend inline Coord_frac operator -(const Coord_frac& u1, const Coord_frac& u2) { return Coord_frac( u1.u()-u2.u(), u1.v()-u2.v(), u1.w()-u2.w() ); }
00380     friend inline Coord_frac operator *(const ftype& s, const Coord_frac& u1)
00381       { return Coord_frac( s*u1.u(), s*u1.v(), s*u1.w() ); }
00382     friend inline Coord_frac operator *(const RTop_frac& op, const Coord_frac& x1) { return Coord_frac( op.rot() * x1 + op.trn() ); }
00383   };
00384 
00385 
00387   class Coord_map : public Vec3<>
00388   {
00389   public:
00390     inline Coord_map() {}  
00391 
00392     inline explicit Coord_map( const Vec3<>& v ) :
00393       Vec3<>( v ) {}
00395     inline explicit Coord_map( const Coord_grid& c ) :
00396       Vec3<>( ftype(c[0]), ftype(c[1]), ftype(c[2]) ) {}
00398     inline Coord_map( const ftype& u, const ftype& v, const ftype& w ) :
00399       Vec3<>( u, v, w ) {}
00401     inline Coord_frac coord_frac( const Grid& g ) const;
00403     inline Coord_grid coord_grid() const { return Coord_grid( Util::intr((*this)[0]), Util::intr((*this)[1]), Util::intr((*this)[2]) ); }
00405     inline Coord_grid floor() const { return Coord_grid( Util::intf((*this)[0]), Util::intf((*this)[1]), Util::intf((*this)[2]) ); }
00407     inline Coord_grid ceil() const { return Coord_grid( Util::intc((*this)[0]), Util::intc((*this)[1]), Util::intc((*this)[2]) ); }
00408     inline const ftype& u() const { return (*this)[0]; }  
00409     inline const ftype& v() const { return (*this)[1]; }  
00410     inline const ftype& w() const { return (*this)[2]; }  
00411     String format() const;  
00412     friend inline Coord_map operator -(const Coord_map& u1)
00413       { return Coord_map( -u1.u(), -u1.v(), -u1.w() ); }
00414     friend inline Coord_map operator +(const Coord_map& u1, const Coord_map& u2)
00415       { return Coord_map( u1.u()+u2.u(), u1.v()+u2.v(), u1.w()+u2.w() ); }
00416     friend inline Coord_map operator -(const Coord_map& u1, const Coord_map& u2)
00417       { return Coord_map( u1.u()-u2.u(), u1.v()-u2.v(), u1.w()-u2.w() ); }
00418     friend inline Coord_map operator *(const ftype& s, const Coord_map& u1)
00419       { return Coord_map( s*u1.u(), s*u1.v(), s*u1.w() ); }
00420   };
00421 
00422 
00424 
00426   class U_aniso_orth : public Mat33sym<>
00427   {
00428   public:
00430     inline U_aniso_orth() {};
00432     inline explicit U_aniso_orth( const Mat33sym<>& m ) : Mat33sym<>(m) {}
00434     inline explicit U_aniso_orth( const ftype& u ) :
00435       Mat33sym<>( u, u, u, 0.0, 0.0, 0.0 ) {}
00437     U_aniso_orth( const ftype& u11, const ftype& u22, const ftype& u33,
00438                   const ftype& u12, const ftype& u13, const ftype& u23 ) :
00439       Mat33sym<>( u11, u22, u33, u12, u13, u23 ) {}
00441     ftype u_iso() const;
00443     U_aniso_frac u_aniso_frac( const Cell& cell ) const;
00445     U_aniso_orth transform( const RTop_orth& op ) const;
00446     friend U_aniso_orth operator +(const U_aniso_orth& u1, const U_aniso_orth& u2) { return U_aniso_orth( u1.mat00()+u2.mat00(), u1.mat11()+u2.mat11(), u1.mat22()+u2.mat22(), u1.mat01()+u2.mat01(), u1.mat02()+u2.mat02(), u1.mat12()+u2.mat12() ); }
00447     friend U_aniso_orth operator -(const U_aniso_orth& u) { return U_aniso_orth( -u.mat00(), -u.mat11(), -u.mat22(), -u.mat01(), -u.mat02(), -u.mat12() ); }
00448     friend U_aniso_orth operator *(const ftype& s, const U_aniso_orth& u) { return U_aniso_orth( s*u.mat00(), s*u.mat11(), s*u.mat22(), s*u.mat01(), s*u.mat02(), s*u.mat12() ); }
00449   };
00450 
00451 
00453 
00455   class U_aniso_frac : public Mat33sym<>
00456   {
00457   public:
00459     inline U_aniso_frac() {};
00461     inline explicit U_aniso_frac( const Mat33sym<>& m ) : Mat33sym<>(m) {}
00463     U_aniso_frac( const ftype& u11, const ftype& u22, const ftype& u33,
00464                   const ftype& u12, const ftype& u13, const ftype& u23 ) :
00465       Mat33sym<>( u11, u22, u33, u12, u13, u23 ) {}
00467     U_aniso_orth u_aniso_orth( const Cell& cell ) const;
00469     U_aniso_frac transform( const RTop_frac& op ) const;
00470     friend U_aniso_frac operator +(const U_aniso_frac& u1, const U_aniso_frac& u2) { return U_aniso_frac( u1.mat00()+u2.mat00(), u1.mat11()+u2.mat11(), u1.mat22()+u2.mat22(), u1.mat01()+u2.mat01(), u1.mat02()+u2.mat02(), u1.mat12()+u2.mat12() ); }
00471     friend U_aniso_frac operator -(const U_aniso_frac& u) { return U_aniso_frac( -u.mat00(), -u.mat11(), -u.mat22(), -u.mat01(), -u.mat02(), -u.mat12() ); }
00472     friend U_aniso_frac operator *(const ftype& s, const U_aniso_frac& u) { return U_aniso_frac( s*u.mat00(), s*u.mat11(), s*u.mat22(), s*u.mat01(), s*u.mat02(), s*u.mat12() ); }
00473   };
00474 
00475 
00477 
00479   class Grid : public Vec3<int>
00480   {
00481   public:
00482     inline Grid() {}                     
00483     inline Grid( const int& nu, const int& nv, const int& nw ) :
00484       Vec3<int>( nu, nv, nw ) {}  
00485     inline const int& nu() const { return (*this)[0]; } 
00486     inline const int& nv() const { return (*this)[1]; } 
00487     inline const int& nw() const { return (*this)[2]; } 
00488 
00489     inline int size() const { return nu()*nv()*nw(); }
00491     inline bool in_grid( Coord_grid g ) const { return (g.u() >= 0 && g.u() < nu() && g.v() >= 0 && g.v() < nv() && g.w() >= 0 && g.w() < nw()); }
00492 
00494     inline int index( const Coord_grid& c ) const { return c.index(*this); }
00496     inline Coord_grid deindex( const int& index ) const { return Coord_grid( *this, index ); }
00497     String format() const;  
00498     void debug() const;
00499   };
00500 
00501 
00503 
00515   class Grid_sampling : public Grid
00516   {
00517   public:
00519     inline Grid_sampling() : Grid(Grid(0,0,0)) {}
00521     inline Grid_sampling( const int& nu, const int& nv, const int& nw ) :
00522       Grid( nu, nv, nw ) {}
00524     Grid_sampling( const Spacegroup& spacegroup, const Cell& cell, const Resolution& resol, const ftype rate = 1.5 );
00526     void init( const Spacegroup& spacegroup, const Cell& cell, const Resolution& resol, const ftype rate = 1.5 );
00527 
00529     Mat33<> matrix_grid_frac() const;
00531     Mat33<> matrix_frac_grid() const;
00532 
00534     bool is_null() const;
00535 
00536     // inherited functions listed for documentation purposes
00537     //-- const int& nu() const;
00538     //-- const int& nv() const;
00539     //-- const int& nw() const;
00540     //-- int size() const;
00541     //-- int index( const Coord_grid& c ) const;
00542     //-- Coord_grid deindex( const int& index ) const;
00543     //-- const String format() const;
00544   };
00545 
00546 
00548 
00552   class HKL_sampling
00553   {
00554   public:
00556     HKL_sampling(); 
00557 
00558     HKL_sampling( const Cell& cell, const Resolution& resolution );
00560     HKL hkl_limit() const;
00562     Resolution resolution( const Cell& cell ) const;
00564     inline bool in_resolution( const HKL& h ) const
00565       { return ( m00*itype64(h.h()*h.h()) + m11*itype64(h.k()*h.k()) +
00566                  m22*itype64(h.l()*h.l()) + m01*itype64(h.h()*h.k()) +
00567                  m02*itype64(h.h()*h.l()) + m12*itype64(h.k()*h.l()) )
00568           <=   ( sqrt_limit_value*sqrt_limit_value ); }
00570     bool is_null() const;
00571     String format() const;  
00572     friend inline int operator == (const HKL_sampling& h1, const HKL_sampling& h2)
00573       { return ( h1.m00==h2.m00 && h1.m11==h2.m11 && h1.m22==h2.m22 &&
00574                  h1.m01==h2.m01 && h1.m02==h2.m02 && h1.m12==h2.m12 ); }
00575   private:
00576     static itype64 sqrt_limit_value;
00577     itype64 m00, m11, m22, m01, m02, m12;
00578   };
00579 
00580 
00582 
00584   class Grid_range : public Grid
00585   {
00586   public:
00588     inline Grid_range() {}
00590     Grid_range( const Coord_grid& min, const Coord_grid& max );
00592     Grid_range( const Grid& grid, const Coord_frac& min, const Coord_frac& max );
00594     Grid_range( const Cell& cell, const Grid& grid, const ftype& radius );
00596     const Coord_grid& min() const { return min_; }
00598     const Coord_grid& max() const { return max_; }
00600     void add_border( const int b );
00602     bool in_grid( Coord_grid g ) const { return (g.u() >= min_.u() && g.u() <= max_.u() && g.v() >= min_.v() && g.v() <= max_.v() && g.w() >= min_.w() && g.w() <= max_.w()); }
00603 
00605     int index( const Coord_grid& c ) const { return (c - min_).index(*this); } 
00607     Coord_grid deindex( const int& index ) const { return Coord_grid( *this, index ) + min_; }
00608   private:
00609     Coord_grid min_, max_;
00610   };
00612   typedef Grid_range Grid_map;
00613 
00614 
00616 
00620   class Atom
00621   {
00622   public:
00624     Atom() {}
00626     template<class T> Atom( const T& atom ) : element_(atom.element()), coord_orth_(atom.coord_orth()), u_aniso_orth_(atom.u_aniso_orth()) , occupancy_(atom.occupancy()), u_iso_(atom.u_iso()){}
00628     const String& element() const { return element_; }
00630     const Coord_orth& coord_orth() const { return coord_orth_; }
00632     const ftype& occupancy() const { return occupancy_; }
00634     const ftype& u_iso() const { return u_iso_; }
00636     const U_aniso_orth& u_aniso_orth() const { return u_aniso_orth_; }
00637     void set_element( const String& s );             
00638     void set_coord_orth( const Coord_orth& s );      
00639     void set_occupancy( const ftype& s );            
00640     void set_u_iso( const ftype& s );                
00641     void set_u_aniso_orth( const U_aniso_orth& s );  
00642 
00643     void transform( const RTop_orth rt );
00645     bool is_null() const { return coord_orth_.is_null(); }
00647     static Atom null();
00648   private:
00649     String element_;
00650     Coord_orth coord_orth_;
00651     U_aniso_orth u_aniso_orth_;
00652     ftype occupancy_, u_iso_;
00653   };
00654 
00655 
00657 
00662   class Atom_list : public std::vector<Atom>
00663   {
00664   public:
00666     Atom_list() {}
00668     Atom_list( const std::vector<Atom>& list ) : std::vector<Atom>( list ) {}
00670     template<class T> Atom_list( const T& list ) { for ( int i = 0; i < list.size(); i++ ) push_back( Atom( list[i] ) ); }
00671   };
00672 
00673 
00674   // some template function definitions
00675 
00683   template<class T> RTop_orth::RTop_orth( const T& src, const T& tgt )
00684   {
00685     std::vector<Coord_orth> vsrc( src.size() );
00686     std::vector<Coord_orth> vtgt( tgt.size() );
00687     for ( int i = 0; i < src.size(); i++ ) vsrc[i] = src[i].coord_orth();
00688     for ( int i = 0; i < tgt.size(); i++ ) vtgt[i] = tgt[i].coord_orth();
00689     (*this) = RTop_orth( vsrc, vtgt );
00690   }
00691 
00692   // some inline function definitions
00696   HKL HKL::transform( const Symop& op ) const
00697     { return Coord_reci_frac(*this).transform(op).hkl(); }
00701   HKL HKL::transform( const Isymop& op ) const
00702     { return op*(*this); }
00707   ftype HKL::sym_phase_shift( const Symop& op ) const
00708     { return -Util::twopi()*( Coord_reci_frac(*this) * op.trn() ); }
00709 
00713   const Coord_grid& Coord_grid::next( const Grid& g )
00714     { w()++; if ( w() >= g.nw() ) { w() = 0; v()++; if ( v() >= g.nv() ) { v() = 0; u()++; } } return *this; }
00718   const Coord_grid& Coord_grid::next( const Grid_range& g )
00719     { w()++; if ( w() > g.max().w() ) { w() = g.min().w(); v()++; if ( v() > g.max().v() ) { v() = g.min().v(); u()++; } } return *this; }
00723   bool Coord_grid::last( const Grid& g ) const
00724     { return ( u() >= g.nu() ); }
00728   bool Coord_grid::last( const Grid_range& g ) const
00729     { return ( u() > g.max().u() ); }
00734   int Coord_grid::index( const Grid& g ) const
00735     { return ( u()*g.nv() + v() )*g.nw() + w(); }
00740   void Coord_grid::deindex( const Grid& g, const int& index )
00741     { u() = index/(g.nv()*g.nw()); v() = (index/g.nw()) % g.nv(); w() = (index) % g.nw(); }
00742 
00744   Coord_grid Coord_grid::unit( const Grid_sampling& g ) const
00745     { return Coord_grid( Util::mod(u(), g.nu()), Util::mod(v(), g.nv()), Util::mod(w(), g.nw()) ); }
00747   Coord_map Coord_grid::coord_map() const
00748     { return Coord_map( *this ); }
00752   Coord_frac Coord_grid::coord_frac( const Grid_sampling& g ) const
00753     { return Coord_frac( ftype(u())/ftype(g.nu()), ftype(v())/ftype(g.nv()), ftype(w())/ftype(g.nw()) ); }
00754 
00757   ftype HKL::invresolsq( const Cell& cell ) const
00758     { return cell.metric_reci().lengthsq( Coord_reci_frac( *this ) ); }
00760   Coord_reci_frac HKL::coord_reci_frac() const
00761     { return Coord_reci_frac( *this ); }
00763   Coord_reci_orth HKL::coord_reci_orth( const Cell& cell ) const
00764     { return coord_reci_frac().coord_reci_orth( cell ); }
00766   ftype Coord_reci_orth::invresolsq() const
00767     { return xs()*xs() + ys()*ys() + zs()*zs(); }
00769   Coord_reci_frac Coord_reci_orth::coord_reci_frac( const Cell& cell ) const
00770     { return Coord_reci_frac( (*this) * cell.matrix_orth() ); }
00772   ftype Coord_reci_frac::invresolsq( const Cell& cell ) const
00773     { return cell.metric_reci().lengthsq( *this ); }
00775   Coord_reci_orth Coord_reci_frac::coord_reci_orth( const Cell& cell ) const
00776     { return Coord_reci_orth( (*this) * cell.matrix_frac() ); }
00777 
00779   ftype Coord_orth::lengthsq() const
00780     { return x()*x()+y()*y()+z()*z(); }
00782   Coord_frac Coord_orth::coord_frac( const Cell& cell ) const
00783     { return Coord_frac( cell.matrix_frac() * (*this) ); }
00785   ftype Coord_frac::lengthsq( const Cell& cell ) const
00786     { return cell.metric_real().lengthsq( *this ); }
00788   Coord_orth Coord_frac::coord_orth( const Cell& cell ) const
00789     { return Coord_orth( cell.matrix_orth() * (*this) ); }
00791   Coord_map Coord_frac::coord_map( const Grid& g ) const
00792     { return Coord_map( u()*ftype(g.nu()), v()*ftype(g.nv()), w()*ftype(g.nw()) ); }
00794   Coord_grid Coord_frac::coord_grid( const Grid& g ) const
00795     { return Coord_grid( Util::intr(u()*ftype(g.nu())), Util::intr(v()*ftype(g.nv())), Util::intr(w()*ftype(g.nw())) ); }
00797   Coord_frac Coord_map::coord_frac( const Grid& g ) const
00798     { return Coord_frac( u()/ftype(g.nu()), v()/ftype(g.nv()), w()/ftype(g.nw()) ); }
00799 
00800 } // namespace clipper
00801 
00802 #endif