Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

PhotonUtil.cxx

Go to the documentation of this file.
00001 #include "PhotonUtil.h"
00002 #include <TMath.h>
00003 
00004 #include "MessageService/MsgService.h"
00005 
00006 CVSID(" $Id: PhotonUtil.cxx,v 1.5 2005/02/02 16:44:33 tagg Exp $ " );
00007 
00008 ClassImp(PhotonUtil)
00009 
00010 Bool_t PhotonUtil::Refract(const TVector3& v1,
00011                            Double_t n1, 
00012                            Double_t n2, 
00013                            const TVector3& norm,
00014                            TVector3& v2)
00015 {
00016   // 3-d version of snell's law. 
00017   // Refracts ray with direction v1 as it goes through surface with normal norm
00018   // if v1 is in medium with refractive index n1 and v2 is in refractive
00019   // index n2. Returns v2, the final direction.
00020   // v1 and norm must be unit vectors.
00021   // Return true for refraction, false for total internal reflection.
00022 
00023   // Decompose v1 into two components: along normal, and in the plane of the
00024   // refraction:
00025   double ns = 1;
00026   double b1 = norm.Dot(v1);
00027   if(b1<0) {
00028     b1 = -b1;
00029     ns = -1;
00030   };
00031 
00032   if(b1>1.0) {
00033     MSG("Photon",Msg::kWarning) << "Bad arguments to Refract()" << endl;
00034     return false;
00035   }
00036   double a1 = sqrt(1.0-b1*b1);
00037 
00038   // The vector tangent to the surface, and in the plane of the refraction:
00039   TVector3        a = ((1./a1)*v1) - (((b1/a1)*ns)*norm);
00040   //const TVector3& b = norm; // For completeness.
00041 
00042   // After refraction:
00043   double a2 = a1*n1/n2;
00044   if(a2>=1.0) {
00045     // Reflection.
00046     // For completeness, actually do the reflection:
00047 
00048     v2 = v1 - 2.0*b1*ns*norm;
00049     return false;
00050   }
00051   
00052   double b2 = sqrt(1.0-a2*a2);
00053   
00054   // Finally, compose the final direction:
00055   v2 = a2*a + (b2*ns)*norm;
00056   return true;
00057 }
00058 
00059 
00060 Bool_t PhotonUtil::IntersectCylinder(const TVector3& x,  // Position, with cylinder centered on x-axis
00061                                      const TVector3& v,  // Direction
00062                                      Double_t R, // Radius.
00063                                      Double_t &d1, // Distance to first intersection
00064                                      Double_t &d2  // Distance to second intesection
00065                                      )
00066 {
00067   // Find the intersection of a line with a cylinder
00068   // given that the cylinder is radius R parallel to the x-axis
00069   // centered on the origin.
00070   // Sets d1 and d2, the distances to the first and second positions respectively.
00071   // d2-d1 is the chord.
00072   // Return false if there is no intersection.
00073   
00074   d1=d2=0;
00075 
00076   double v2  = (v.y()*v.y() + v.z()*v.z());
00077   if(v2==0) return false; // going exactly along the x-axis.
00078   
00079   double vdotdx = (v.y() * x.y()) + (v.z() * x.z());
00080   double insqrt =  (vdotdx*vdotdx) - 
00081     (v2)*((x.y()*x.y()) + (x.z()*x.z()) - (R*R));
00082 
00083   // The track does not intersect the fibre ever.
00084   if(insqrt<0) return false;
00085 
00086   double a = -vdotdx/v2;
00087   double b = TMath::Sqrt(insqrt)/v2;
00088 
00089   // the first solution:
00090   d1 = a-b;
00091 
00092   // the second solution:
00093   d2 = a+b;
00094 
00095   return true;
00096 }
00097 
00098 
00099 Int_t PhotonUtil::InteractWithCylinder(  TVector3& x, // pos (at cylinder!)
00100                                           TVector3& v, // direction
00101                                           Double_t R,  // cylinder radius
00102                                           Double_t n1,
00103                                           Double_t n2)
00104 {
00105   // Move the photon along v to the first intesection point.
00106   // Reflect or refract off the surface.
00107   // Return 0 for refraction, 1 for reflection, -1 for no hit.
00108   // (i.e. return 0 if it goes inside)
00109   // Change x and v to match the new position, direction.
00110 
00111   double d1, d2;
00112   bool intersect = PhotonUtil::IntersectCylinder( x, 
00113                                                   v, 
00114                                                   R, 
00115                                                   d1,d2);
00116 
00117   if(!intersect) return -1;
00118   
00119   // Otherwise, move to the closest intercept point.
00120   // If we are on the cylinder or have not yet hit the cylinder, this 
00121   // should always be the d1.
00122   x += v*d1;
00123 
00124   // x is now at the surface of the cylinder. Find the surface 
00125   // normal at this point.
00126 
00127   TVector3 normal(0,x.y(),x.z());
00128 
00129   if(normal.Mag2()==0.0) {
00130     // Hmm... just skimmed it.
00131     // Assume it's a reflection and return nothing.
00132     return 1;
00133   }
00134   normal.SetMag(1.0);
00135   
00136   bool refract = PhotonUtil::Refract(v,n1,n2,normal,v);
00137   if(refract) return 0;
00138 
00139   return 1; // Reflection
00140 }

Generated on Mon Feb 15 11:07:22 2010 for loon by  doxygen 1.3.9.1