HG-MD  1
CWall.h
Go to the documentation of this file.
00001 
00002 
00003 
00004 
00005 
00006 #ifndef CWALL_H
00007 #define CWALL_H
00008 
00009 #include "CParticle.h"
00010 #include <algorithm>
00011 using std::min;
00012 
00013 
00014 
00024 class CWall 
00025 {
00026  public:
00028   CWall() {
00029     indSpecies = 0;
00030     is_hopper = false;
00031         isAxisymmetric = false;
00032         velocity.set_zero();
00033   }
00034 
00035   void set_is_hopper(){is_hopper=true;}
00036                 
00038   void set(Vec3D normal_, Mdouble position_) 
00039   {
00040     //factor is used to set n to unit length 
00041     factor = 1. / sqrt(Dot(normal_, normal_));
00042     normal = normal_ * factor;
00043     position = position_ * factor;              
00044     //this makes it a standard wall
00045     finite_walls.resize(0);
00046   }
00047 
00048   void is_finite() {finite_walls.resize(0);}
00049                 
00051   void add_finite_wall(Vec3D normal, Vec3D point) {
00052           add_finite_wall(normal,Dot(normal,point));
00053   }
00054 
00056   void add_finite_wall(Vec3D normal_, Mdouble position_) 
00057   {
00058     //n is the index of the new wall
00059     int n = finite_walls.size();
00060     finite_walls.resize(n+1);
00061     finite_walls[n].set(normal_,position_);
00062                 
00063     // AB[n*(n-1)/2+m] is the direction of the intersecting line between walls m and n, m<n
00064     // A[n*(n-1)/2+m] is a point on the intersecting line between walls m and n, m<n
00065     // See http://www.netcomuk.co.uk/~jenolive/vect18d.html for finding the line where two planes meet
00066     AB.resize(n*(n+1)/2);
00067     A.resize (n*(n+1)/2);
00068     for(int m=0; m<n; m++) 
00069       {
00070         int id = (n-1)*n/2+m;
00071         //first we cross the wall normals and normalize to obtain AB
00072         AB[id] = Cross(finite_walls[m].normal, finite_walls[n].normal);
00073         AB[id] /= sqrt(AB[id].GetLength2());
00074         //then we find a point A (using AB*x=0 as a third plane)
00075         Mdouble invdet = 1.0/(+finite_walls[n].normal.X*(finite_walls[m].normal.Y*AB[id].Z-AB[id].Y*finite_walls[m].normal.Z)
00076                              -finite_walls[n].normal.Y*(finite_walls[m].normal.X*AB[id].Z-finite_walls[m].normal.Z*AB[id].X)
00077                              +finite_walls[n].normal.Z*(finite_walls[m].normal.X*AB[id].Y-finite_walls[m].normal.Y*AB[id].X));
00078         A[id] = Vec3D(+(finite_walls[m].normal.Y*AB[id].Z-AB[id].Y*finite_walls[m].normal.Z)*finite_walls[n].position
00079                       -(finite_walls[n].normal.Y*AB[id].Z-finite_walls[n].normal.Z*AB[id].Y)*finite_walls[m].position
00080                       +(finite_walls[n].normal.Y*finite_walls[m].normal.Z-finite_walls[n].normal.Z*finite_walls[m].normal.Y)*0.0,
00081                       -(finite_walls[m].normal.X*AB[id].Z-finite_walls[m].normal.Z*AB[id].X)*finite_walls[n].position
00082                       +(finite_walls[n].normal.X*AB[id].Z-finite_walls[n].normal.Z*AB[id].X)*finite_walls[m].position
00083                       -(finite_walls[n].normal.X*finite_walls[m].normal.Z-finite_walls[m].normal.X*finite_walls[n].normal.Z)*0.0,
00084                       +(finite_walls[m].normal.X*AB[id].Y-AB[id].X*finite_walls[m].normal.Y)*finite_walls[n].position
00085                       -(finite_walls[n].normal.X*AB[id].Y-AB[id].X*finite_walls[n].normal.Y)*finite_walls[m].position
00086                       +(finite_walls[n].normal.X*finite_walls[m].normal.Y-finite_walls[m].normal.X*finite_walls[n].normal.Y)*0.0 ) * invdet;
00087       }
00088                 
00089     // C[(n-2)*(n-1)*n/6+(m-1)*m/2+l] is a point intersecting walls l, m and n, l<m<n
00090     C.resize((n-1)*n*(n+1)/6);
00091     for(int m=0; m<n; m++) 
00092       {
00093         for(int l=0; l<m; l++) 
00094           {
00095             int id = (n-2)*(n-1)*n/6+(m-1)*m/2+l;
00096             Mdouble invdet = 1.0/(+finite_walls[n].normal.X*(finite_walls[m].normal.Y*finite_walls[l].normal.Z-finite_walls[l].normal.Y*finite_walls[m].normal.Z)
00097                                  -finite_walls[n].normal.Y*(finite_walls[m].normal.X*finite_walls[l].normal.Z-finite_walls[m].normal.Z*finite_walls[l].normal.X)
00098                                  +finite_walls[n].normal.Z*(finite_walls[m].normal.X*finite_walls[l].normal.Y-finite_walls[m].normal.Y*finite_walls[l].normal.X));
00099             C[id] = Vec3D(+(finite_walls[m].normal.Y*finite_walls[l].normal.Z-finite_walls[l].normal.Y*finite_walls[m].normal.Z)*finite_walls[n].position
00100                           -(finite_walls[n].normal.Y*finite_walls[l].normal.Z-finite_walls[n].normal.Z*finite_walls[l].normal.Y)*finite_walls[m].position
00101                           +(finite_walls[n].normal.Y*finite_walls[m].normal.Z-finite_walls[n].normal.Z*finite_walls[m].normal.Y)*finite_walls[l].position,
00102                           -(finite_walls[m].normal.X*finite_walls[l].normal.Z-finite_walls[m].normal.Z*finite_walls[l].normal.X)*finite_walls[n].position
00103                           +(finite_walls[n].normal.X*finite_walls[l].normal.Z-finite_walls[n].normal.Z*finite_walls[l].normal.X)*finite_walls[m].position
00104                           -(finite_walls[n].normal.X*finite_walls[m].normal.Z-finite_walls[m].normal.X*finite_walls[n].normal.Z)*finite_walls[l].position,
00105                           +(finite_walls[m].normal.X*finite_walls[l].normal.Y-finite_walls[l].normal.X*finite_walls[m].normal.Y)*finite_walls[n].position
00106                           -(finite_walls[n].normal.X*finite_walls[l].normal.Y-finite_walls[l].normal.X*finite_walls[n].normal.Y)*finite_walls[m].position
00107                           +(finite_walls[n].normal.X*finite_walls[m].normal.Y-finite_walls[m].normal.X*finite_walls[n].normal.Y)*finite_walls[l].position ) * invdet;
00108           }
00109       }
00110   }
00111         
00113   void move(Mdouble position_) {
00114           position=position_*factor;
00115           //cout << "pos " << position << endl;
00116   }
00117 
00119   void move(Vec3D velocity_, Mdouble dt) {
00120           velocity=velocity_;
00121           position+=Dot(velocity,normal)*dt;
00122           //cout << "pos " << position << "vel " << velocity << endl;
00123   }
00124 
00127   Mdouble get_distance(Vec3D &Position) {return position - Dot(Position, normal);}
00128                 
00130   bool get_distance_and_normal(Particle &P, Mdouble &distance, Vec3D &normal_return) {
00131     if (isAxisymmetric) return get_distance_and_normal_for_axissymmetric_wall(P, distance, normal_return);
00132     static Mdouble distance_new;
00133     static Mdouble distance2;  
00134     static Mdouble distance3;
00135     static int id;  
00136     static int id2;  
00137     static int id3;  
00138                 
00139     if(is_hopper){//this is first becuase i dont know what it does if not
00140                   // Three posible normals for the hopper, they are averaged
00141                   // when a particle touch 2 walls
00142       Vec3D normalOuterCylinder = Vec3D(0,0,0);
00143       Vec3D normalInnerCylinder = Vec3D(0,0,0);
00144       Vec3D normalBase = Vec3D(0,0,0);
00145                   
00146                   
00147       //Radial coordinate of the particle
00148       Mdouble particleRadius = sqrt(sqr(P.get_Position().X) + sqr(P.get_Position().Y));
00149       Mdouble innerRadius = 20*P.get_Radius();// hardcoded geometry for the moment
00150       Mdouble outerRadius = 50*P.get_Radius();
00151       Mdouble distanceOuterCylinder = 0.0;
00152       Mdouble distanceInnerCylinder = 0.0;
00153       Mdouble distanceBase = 0.0;
00154                   
00155       //cout << "Mass of particles: " << P.get_restitution_coefficient() << endl;
00156       //set normal outer cilinder
00157       if(particleRadius + P.get_Radius() > outerRadius){
00158         normalOuterCylinder = Vec3D(P.get_Position().X, P.get_Position().Y, 0.0)/particleRadius;
00159         distanceOuterCylinder = outerRadius - particleRadius;
00160         //cout << "Outer Cylinder "<< endl;
00161       }
00162 
00163       //\todo set a real hopper with two more walls
00164      /*  if (P.get_Position().Z - P.Radius < 0.0 && particleRadius +  P.Radius >= innerRadius  */
00165 /*        && P.get_Position().Z > 0){// the particle feels the ground */
00166 /*      normalBase = Vec3D(0.0,0.0,-1.0);//normalized normal outer to the geometry  */
00167 /*      distanceBase = P.get_Position().Z;//the distance to the wall from the center of the particle */
00168 /*      //cout << "Base "<< endl; */
00169 /*       } */
00170       //\todo set a real hopper with two more walls
00171       if (abs(P.get_Position().Z) - P.get_Radius() < 0.0 
00172           && particleRadius > innerRadius){// the particle feels the ground
00173         
00174         normalBase = Vec3D(0.0,0.0,-1.0)*SIGN(P.get_Position().Z);
00175         distanceBase = P.get_Position().Z;
00176       }
00177       Vec3D dr = Vec3D(P.get_Position().X, P.get_Position().Y, 0.0)*innerRadius/particleRadius 
00178         - P.get_Position();
00179       if(dr.GetLength() < P.get_Radius() ){
00180         cout << " toy en el borde" << endl;
00181         distanceBase = dr.GetLength();
00182         normalBase = dr/distanceBase;
00183       }
00184       
00185       /*   if(particleRadius +  P.Radius > innerRadius  */
00186       /*         && P.get_Position().Z > -40*P.Radius  */
00187       /*         && P.get_Position().Z + P.Radius < 0.0 ){//inside wall */
00188       /*        normalInnerCylinder = Vec3D(-P.get_Position().X, -P.get_Position().Y, 0.0)/particleRadius; */
00189       /*        distanceInnerCylinder = innerRadius - particleRadius; */
00190       /*        //cout << "Inner Cylinder "<< endl; */
00191       /*       } */
00192 
00193       /*  if(P.get_Position().Z > 0.0 && P.get_Position().Z - P.Radius < 0.0 && particleRadius < innerRadius ){// Colliding with line */
00194       /*        normal_return =  Vec3D(P.get_Position().X,P.get_Position().Y,0)*(innerRadius/particleRadius - 1.0)+ */
00195       /*          Vec3D(0.0,0.0,-P.get_Position().Z); */
00196       /*        distance = normal_return.GetLength();  */
00197       /*        normal_return /= normal_return.GetLength(); */
00198       /*        if(distance < P.Radius){ */
00199       /*          cout << "Border normal " << normal_return << " distance " << distance<< endl; */
00200       /*          return true; */
00201       /*        } */
00202       /*       } */
00203 
00204       if(distanceOuterCylinder != 0.0 || distanceBase != 0.0){
00205         //average normals
00206                     
00207         normal_return  = distanceOuterCylinder*normalOuterCylinder 
00208           + distanceInnerCylinder*normalInnerCylinder 
00209           + distanceBase*normalBase;
00210         normal_return /= normal_return.GetLength();
00211         //  distance = sqrt(SQR(distanceBase) + SQR(distanceOuterCylinder) 
00212         //          + SQR(distanceInnerCylinder));
00213         distance = 0.5*(distanceBase + distanceOuterCylinder); 
00214         //cout << "normal " << normal_return << " distance " << distance<< endl;
00215         return true;                
00216       }
00217 
00218       /*     if(distanceBase != 0 || distanceInnerCylinder != 0.0){ //collision with inner walls */
00219       /*                     //average normals */
00220                     
00221       /*                    normal_return  = distanceInnerCylinder*normalInnerCylinder */
00222       /*                                     + distanceBase*normalBase; */
00223       /*                    normal_return /= normal_return.GetLength(); */
00224       /*                    //  distance = sqrt(SQR(distanceBase) + SQR(distanceOuterCylinder) */
00225       /*                    //      + SQR(distanceInnerCylinder)); */
00226       /*                    distance = 0.5*(distanceBase + distanceInnerCylinder); */
00227       /*                    //cout << "normal " << normal_return << " distance " << distance<< endl; */
00228       /*                    return true; */
00229       /*                  } */
00230 
00231 
00232       //cout << "False " << endl;
00233       //getchar();
00234       // no collision, so return false
00235       return false;               
00236                   
00237     }
00238                 
00239                   
00240                 
00241     if (!finite_walls.size()) {
00242       //for standard walls this function sets normal_return and distance and returns true if the particle is in contact
00243       distance = get_distance(P.get_Position());
00244       if (distance>=P.get_Radius()) return false;
00245       normal_return = normal; return true;
00246     } 
00247 
00248         
00249                 
00250     //if we are here, this is a finite wall
00251     distance = -1e20;
00252     distance2 = -1e20;
00253     distance3 = -1e20;
00254     //for all finite walls
00255     for (unsigned int i=0; i<finite_walls.size(); i++) {
00256       //calculate the distance to the particle
00257       distance_new = finite_walls[i].get_distance(P.get_Position());
00258       //return false if the distance to any one wall is too large (i.e. no contact)
00259       if (distance_new>=P.get_Radius()) return false;
00260       //store the minimum distance and the respective wall in "distance" and "id"
00261       //and store up to two walls (id2, id3) and their distances (distance2, distance3), if the possible contact point is near the intersection between id and id2 (and id3)
00262       if (distance_new>distance) {
00263         if (distance>-P.get_Radius()) {
00264           if (distance2>-P.get_Radius()) {distance3 = distance; id3 = id;}
00265           else {distance2 = distance; id2 = id;}
00266         } 
00267         distance = distance_new; id = i;
00268       } else if (distance_new>-P.get_Radius()) {
00269         if (distance2>-P.get_Radius()) {distance3 = distance_new; id3 = i;}
00270         else {distance2 = distance_new; id2 = i;}
00271       }
00272     }
00273                 
00274     //if we are here, the closest wall is id; 
00275     //if distance2>-P.Radius (and distance3>-P.Radius), the possible contact point is near the intersection between id and id2 (and id3)
00276     if (distance2>-P.get_Radius()) {
00277       //D is the point on wall id closest to P
00278       Vec3D D = P.get_Position() + finite_walls[id].normal * distance;
00279       //If the distance of D to id2 is positive, the contact is with the intersection
00280       bool intersection_with_id2 = (finite_walls[id2].get_distance(D)>0.0);
00281 
00282       if (distance3>-P.get_Radius()&&(finite_walls[id3].get_distance(D)>0.0)) {
00283         if (intersection_with_id2) { //possible contact is with intersection of id,id2,id3
00284           //we know id2<id3
00285           int index = 
00286             (id<id2)?( (id3-2)*(id3-1)*id3/6+(id2-1)*id2/2+id  ):
00287             (id<id3)?( (id3-2)*(id3-1)*id3/6+(id -1)*id /2+id2 ):
00288             ( (id -2)*(id -1)*id /6+(id3-1)*id3/2+id2 );
00289           normal_return = P.get_Position() - C[index];
00290           distance = sqrt(normal_return.GetLength2());
00291           if (distance>=P.get_Radius()) return false; //no contact
00292           normal_return /= -distance; 
00293           return true; //contact with id,id2,id3
00294         } else { intersection_with_id2 = true; distance2 = distance3; id2 = id3; }
00295       }
00296                         
00297       if (intersection_with_id2) { //possible contact is with intersection of id,id2
00298         int index = (id>id2)?((id-1)*id/2+id2):((id2-1)*id2/2+id);
00299         Vec3D AC = P.get_Position() - A[index];
00300         normal_return = AC - AB[index] * Dot(AC,AB[index]);
00301         distance = sqrt(normal_return.GetLength2());
00302         if (distance>=P.get_Radius()) return false; //no contact
00303         normal_return /= -distance; 
00304         return true; //contact with two walls
00305       }
00306     }
00307     //contact is with id
00308     normal_return = finite_walls[id].normal; 
00309     return true;
00310                 
00311   }
00312 
00314   friend inline std::ostream& operator<<(std::ostream& os, CWall &w) 
00315   {
00316     os << "numFiniteWalls " << w.finite_walls.size(); 
00317     if (w.finite_walls.size()) {
00318         for (vector<CWall>::iterator it = w.finite_walls.begin(); it!=w.finite_walls.end(); ++it) {
00319           os << " normal " << it->normal << " position " << it->position;
00320         }
00321     } else {
00322         os << " normal " << w.normal << " position " << w.position;
00323         //optional output
00324         if (w.velocity.GetLength2()) os << " velocity " << w.velocity;
00325     }
00326     return os;
00327   }
00328         
00330   friend inline std::istream& operator>>(std::istream& is, CWall &w) 
00331   {
00332     int n;
00333     is >> n;
00334     if (n!=0) {
00335         Vec3D normal;
00336         Mdouble position;
00337         for (int i=0; i<n; i++) {
00338           is >> normal >> position;
00339           w.add_finite_wall(normal,position);
00340         }               
00341     } else {
00342         is >> w.normal >> w.position;
00343     }
00344     return is;
00345   }
00346 
00348     void read(std::istream& is)  { 
00349         string dummy;
00350         int n;
00351         is >> dummy >> n;
00352         if (n!=0) {
00353             Vec3D normal;
00354             Mdouble position;
00355             for (int i=0; i<n; i++) {
00356                 is >> dummy >> normal >> dummy >> position;
00357                 add_finite_wall(normal,position);
00358             }           
00359         } else {
00360             //use stringstream to ensure that old restart files w/o velocity don't break the code
00361             stringstream ss("");
00362             string s;
00363             getline(is,s);
00364             ss << s;
00365             ss >> dummy >> normal >> dummy >> position >> dummy >> velocity;
00366 
00367         }
00368     }
00369         
00371     void print(std::ostream& os) { 
00372         if (finite_walls.size()) {
00373         os << "finite_wall( "; 
00374         for (vector<CWall>::iterator it = finite_walls.begin(); it!=finite_walls.end(); ++it)
00375             os << "normal:" << it->get_normal() << ", position:" << it->get_position() << " "; 
00376             os << " )"; 
00377         } else os << "wall( normal:" << normal << ", position:" << position << ")"; 
00378     }
00379         
00381     Vec3D get_normal() {return normal;}
00382     void set_normal(Vec3D new_) {normal=new_;}
00383 
00385     Mdouble get_position() {return position;}
00386 
00387 
00389     Vec3D get_velocity() {return velocity;}
00391     void set_velocity(Vec3D new_) {velocity = new_;}
00392 
00394     bool get_distance_and_normal_for_axissymmetric_wall(Particle &P, Mdouble &distance, Vec3D &normal_return) {
00395             //transform to axisymmetric coordinates
00396             Vec3D PO = P.get_Position() - axisOrigin;
00397             P.get_Position().Z = Dot(axisOrientation,PO);
00398             P.get_Position().Y = 0.0;
00399             Vec3D tangential = PO-P.get_Position().Z*axisOrientation;
00400             P.get_Position().X = tangential.GetLength();
00401             tangential /= P.get_Position().X;
00402             Vec3D normal_axisymmetric_coordinates;
00403             //determine wall distance, normal and contact in axosymmetric coordinates
00404             isAxisymmetric = false;
00405             bool retval = get_distance_and_normal(P, distance, normal_axisymmetric_coordinates);
00406             isAxisymmetric = true;
00407             //transform from axisymmetric coordinates
00408             normal_return = normal_axisymmetric_coordinates.Z * axisOrientation 
00409                     + tangential*normal_axisymmetric_coordinates.X;             
00410             P.set_Position(PO + axisOrigin);
00411             return retval;
00412     }
00413 
00415     void setSymmetryAxis(Vec3D new_axisOrigin, Vec3D new_axisOrientation) {
00416             axisOrigin = new_axisOrigin;
00417             axisOrientation = new_axisOrientation;
00418             axisOrientation.normalize();
00419             isAxisymmetric = true;
00420             cout 
00421             << "axisOrigin" << axisOrigin
00422             << "axisOrientation" << axisOrientation
00423             << "isAxisymmetric" << isAxisymmetric
00424             << endl;
00425     } 
00426     
00428     void removeSymmetryAxis() {
00429             isAxisymmetric = false;
00430     }           
00431                 
00432 private:
00433   vector<CWall> finite_walls;
00434   vector<Vec3D> A;  //<A[n*(n-1)/2+m] is a point on the intersecting line between walls m and n, m<n
00435   vector<Vec3D> AB; //<AB[n*(n-1)/2+m] is the direction of the intersecting line between walls m and n, m<n
00436   vector<Vec3D> C;  //<C[(n-2)*(n-1)*n/6+(m-1)*m/2+l] is a point intersecting walls l, m and n, l<m<n
00437         
00438   Vec3D normal;     //<outward unit normal vector
00439   Mdouble position;  //<position n*x=p
00440   Mdouble factor;    //<This is the normal to rescale to unit vectoers.
00441 
00442 
00443  public:
00444   Vec3D velocity;        
00445   int indSpecies;
00446   bool is_hopper;
00447  
00448  
00449   bool isAxisymmetric;
00450   Vec3D axisOrigin;
00451   Vec3D axisOrientation;
00452 
00453 };
00454 
00455 
00459 class CWallPeriodic 
00460 {
00461 public:
00462 
00463         CWallPeriodic() {}
00464 
00465         CWallPeriodic(const CWallPeriodic &p) {
00466                 left_wall = p.left_wall;
00467                 normal = p.normal;
00468                 position_left = p.position_left;
00469                 position_right = p.position_right;
00470                 factor = p.factor;
00471                 shift = p.shift;
00472         }
00473 
00479   void set(Vec3D normal_, Mdouble position_left_, Mdouble position_right_) {
00480     // factor is used to set normal to unit length
00481     factor = 1. / sqrt(Dot(normal_, normal_));
00482     normal = normal_ * factor;
00483     position_left = position_left_ * factor;
00484     position_right = position_right_ * factor;
00485     shift = normal * (position_right - position_left);
00486   }
00487 
00490   void set(Vec3D normal_, Mdouble position_left_, Mdouble position_right_, Vec3D shift_direction) {
00491     // factor is used to set normal to unit length
00492     factor = 1. / sqrt(Dot(normal_, normal_));
00493     normal = normal_ * factor;
00494     position_left = position_left_ * factor;
00495     position_right = position_right_ * factor;
00496     // factor is used to set shift vector to correct length
00497     factor = (position_right - position_left) * Dot(shift_direction, normal);
00498     shift = shift_direction * factor;
00499   }
00500   
00502   void move_left(Mdouble position_)
00503   {
00504           position_left=position_*factor;
00505           shift = normal * (position_right - position_left);
00506   }
00507   
00509   void move_right(Mdouble position_)
00510   {
00511           position_right=position_*factor;
00512           shift = normal * (position_right - position_left);
00513   }
00514 
00515 
00523   Mdouble distance(Particle &P) {
00524     return distance(P.get_Position());
00525   }
00526 
00527   Mdouble distance(Vec3D &P) {
00528     Mdouble position = Dot(P, normal);
00529 
00530     if (position - position_left < position_right - position) {
00531       left_wall = true;
00532       return position - position_left;
00533     } else {
00534       left_wall = false;
00535       return position_right - position;
00536     }
00537   }
00538 
00540         void shift_position(Vec3D &Position) {
00541                 if (left_wall) {
00542                         Position += shift;
00543                         left_wall = false;
00544                 }
00545                 else {
00546                         Position -= shift;
00547                         left_wall = true;
00548                 }
00549         }
00550 
00552         Vec3D get_shifted_position(Vec3D &Position) {
00553                 if (left_wall) {
00554                         return Position + shift;
00555                 }
00556                 else {
00557                         return Position - shift;
00558                 }
00559         }
00560         
00562         void shift_positions(Vec3D &PI, Vec3D &PJ) {
00563                 if (left_wall) {
00564                         PI += shift;
00565                         PJ += shift;
00566                         left_wall = false;
00567                 }
00568                 else {
00569                         PI -= shift;
00570                         PJ -= shift;
00571                         left_wall = true;
00572                 }
00573         }
00574                 
00576         void get_close_together(Vec3D &P,Vec3D &Q) {
00577                 Mdouble PQdotn = Dot(P-Q, normal);
00578                 Mdouble shift_norm2 = shift.GetLength2();
00579                 //Check if P is so far from Q that a shift would move it closer
00580                 if (sqr(PQdotn) > .25 * shift_norm2) {
00581                         //Now determine the direction of the shift
00582                         if (PQdotn>0.0) P -= shift;
00583                         else P += shift;
00584                 }
00585         }
00586                 
00588         friend inline std::ostream& operator<<(std::ostream& os, const CWallPeriodic &w) 
00589         {
00590                 os<< "normal " << w.normal 
00591       << " pos_left " << w.position_left 
00592       << " pos_right " << w.position_right 
00593       << " shift " << w.shift;
00594                 return os;
00595         }
00596         
00598         friend inline std::istream& operator>>(std::istream& is, CWallPeriodic &w) 
00599         {
00600                 is >> w.normal >> w.position_left >> w.position_right >> w.shift;
00601                 return is;
00602         }
00603 
00605         void read(std::istream& is)  { 
00606     string dummy;
00607                 is >> dummy >> normal >> dummy >> position_left >> dummy >> position_right >> dummy >> shift;
00608         }
00609         
00611         void print(std::ostream& os, bool print_all=false) {
00612                 os << "periodic_wall( normal:" << normal 
00613                          << ", position_left:" << position_left 
00614                          << ", position_right:" << position_right;
00615                 if (print_all) os       << ", shift:" << shift << ", left_wall:" << left_wall;
00616                 os << ")";
00617         }
00618                 
00619         Vec3D& get_normal() {return normal;}
00620         void set_normal(Vec3D new_) {normal=new_;}
00621         //~ Vec3D get_normal() const {return normal;}
00622         bool get_left_wall() const {return left_wall;}
00623 
00624  private:
00625   bool left_wall;        
00626   Vec3D normal;          
00627   Mdouble position_left;  
00628   Mdouble position_right; 
00629   Mdouble factor;        
00630   Vec3D shift;           
00631 };
00632 
00633 #endif
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines