Main Page   Namespace List   Class Hierarchy   Compound List   File List   Compound Members   File Members  

LayeredMedium.cxx

Go to the documentation of this file.
00001 //  $Id: LayeredMedium.cxx,v 1.5 2001/10/06 14:18:52 burnett Exp $
00002 
00003 #include "gismo/LayeredMedium.h"
00004 
00005 #include "geometry/Surface.h"
00006 #include "geometry/Ray.h"
00007 #include <cassert>
00009 //      LayeredMedium::Volume implementation
00010 
00011 LayeredMedium::Volume::Volume(int n)
00012 : ::Volume(n)
00013 {}
00014 void
00015 LayeredMedium::Volume::setOffsets(double inner, double outer)
00016 {
00017     surface(0).setOffset(-inner);
00018     surface(1).setOffset(outer);
00019 }
00020 
00021 
00023 //      LayeredMedium::Slice implementation
00024 LayeredMedium::Slice::Slice(LayeredMedium& mother, int index)
00025 : ::Volume(0)   // don't own any surfaces
00026 , m_mother(mother)
00027 , m_index(index)
00028 {}
00029 
00030 LayeredMedium::Slice::~Slice()
00031 {}
00032 
00033 const Volume& LayeredMedium::Slice::setMotherVolume()const
00034 {
00035     LayeredMedium* mom = const_cast<LayeredMedium*>(&m_mother);
00036     LayeredMedium::Volume* mom_vol= mom->m_vol;
00037 
00038     // Since we share the main volume, adjust the inner and outer surface, use it
00039     mom_vol->setOffsets( mom->m_offset[m_index], mom->m_offset[m_index+1]);
00040     return *mom_vol;
00041 }
00042 
00043 const Volume& LayeredMedium::Slice::resetMotherVolume()const
00044 {
00045     LayeredMedium* mom = const_cast<LayeredMedium*>(&m_mother);
00046     LayeredMedium::Volume* mom_vol= mom->m_vol;
00047     
00048     // Since we share the main volume, adjust the inner and outer surface, use it
00049     mom_vol->setOffsets( mom->m_offset[0], mom->m_offset[mom->size()]);
00050     return *mom_vol;
00051 }
00052 
00053 double
00054 LayeredMedium::Slice::distanceToLeave(  const Ray& r, double dmax) const
00055 {
00056     //CEnter1("LayeredMedium::Slice::distanceToLeave", "at z=%g\n", r.position().z());
00057     // get (non-const) volume to manipulate surfaces
00058     LayeredMedium* mom = const_cast<LayeredMedium*>(&m_mother);
00059     LayeredMedium::Volume* mom_vol= mom->m_vol;
00060 
00061     // Since we share the main volume, adjust the inner and outer surface, use it
00062     mom_vol->setOffsets( mom->m_offset[m_index], mom->m_offset[m_index+1]);
00063     double d = mom_vol->distanceToLeave( r, dmax);
00064     mom_vol->setOffsets(mom->m_offset[0], mom->m_offset[mom->size()]);
00065 
00066     // if we really left, identify the surface, and our index,
00067     //  for use by LayeredMedium::distanceToLeave
00068     if( d== dmax ){
00069         mom->m_last_boundary = -1;
00070         mom->m_select_index = -1;
00071     }else {
00072         mom->m_last_boundary = lastBoundaryIndex();
00073         mom->m_select_index = m_index;
00074     }
00075     return d;
00076 }
00077 void
00078 LayeredMedium::Slice::printOn(std::ostream& out)const
00079 {
00080     // get (non-const) volume to manipulate surfaces
00081     LayeredMedium* mom = const_cast<LayeredMedium*>(&m_mother);
00082     LayeredMedium::Volume* mom_vol= mom->m_vol;
00083 
00084 
00085     mom_vol->setOffsets( mom->m_offset[m_index], mom->m_offset[m_index+1]);
00086     mom_vol->printOn(out);
00087     mom_vol->setOffsets(mom->m_offset[0], mom->m_offset[mom->size()]);
00088 }
00089 
00091 //      LayeredMedium implementation
00092 LayeredMedium::LayeredMedium(Medium* mother, int num_surfaces, double inner_offset)
00093 : CompositeMedium(mother, (Shape*)0)
00094 , m_vol(new Volume(num_surfaces))
00095 , m_select_index(-1)
00096 , m_last_boundary(-1)
00097 {
00098     setVolume(m_vol);
00099     m_offset.push_back(inner_offset); // first offset, corresponding to inner surface
00100 }
00101 LayeredMedium::~LayeredMedium()
00102 {}
00103 
00104 
00105 Medium &
00106 LayeredMedium::addLayer(Medium * inner_medium, double thickness)
00107 {
00108     // following conditions enforced by subclass
00109     assert(inner_medium->parent() == this);
00110     assert(&(inner_medium->volume()) == 0);
00111 
00112     m_offset.push_back( m_offset[size()-1]+thickness);
00113 
00114     inner_medium->setVolume( new LayeredMedium::Slice(*this, size()-1 ) );
00115     m_vol->setOffsets(m_offset[0], m_offset[size()]);
00116     return *inner_medium;
00117 }
00118 
00119 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
00120 //                 Tracking
00121 double
00122 LayeredMedium::distanceToEnter(const Ray& r, const Medium*& m, double t)const
00123 {
00124     // override this to select a Layer to enter.
00125     // first, do we enter the overall volume?
00126     double d = Medium::distanceToEnter(r,m,t);
00127 
00128     if( d != FLT_MAX ){
00129         m = select(r.position(d));
00130     }
00131     return d;
00132 
00133 }
00134 
00135 double
00136 LayeredMedium::distanceToLeave(const Ray& r, const Medium*& nextMedium
00137                                , double /* maxDist*/)const
00138 {
00139     double distance = 0;
00140 
00141         if(r.getFlag() == 0){
00142         LayeredMedium* me = const_cast<LayeredMedium*>(this);
00143                 me->m_select_index = -1;
00144                 me->m_last_boundary = -1;
00145         }
00146                 
00147         if( m_select_index==-1)
00148     {   // here if returning to a previous interaction. Should be inside a slice!
00149         nextMedium =select(r.position());
00150         return 0;
00151     }
00152 
00153     int sel = m_select_index;
00154     if( m_last_boundary ==0 && sel >0) {
00155         nextMedium = operator[](--sel);
00156     }else if( (m_last_boundary==1)
00157               && ( sel < static_cast<int>(size()-1) )   ) {
00158         nextMedium = operator[](++sel);
00159     }else {
00160         nextMedium = parent();
00161 #ifdef _DEBUG
00162         int check = m_vol->getBoundaryIndex(r.position()); // verify on boundary
00163 #endif //_DEBUG
00164         sel = -1;
00165     }
00166     // update tags
00167     LayeredMedium* me = const_cast<LayeredMedium*>(this);
00168     me->m_last_boundary=-1;
00169     me->m_select_index=sel;
00170     return distance;
00171 }
00172 const Surface&
00173 LayeredMedium::referenceSurface()const
00174 {
00175     return m_vol->surface(0);
00176 }
00177 const Medium*
00178 LayeredMedium::select(const Point& x)const
00179 {
00180     // assume point is within over-all volume, find out which division
00181    // CEnter1("LayeredMedium::select", "point.z= %g\n", x.z() );
00182     LayeredMedium* me = const_cast<LayeredMedium*>(this);
00183 
00184     double d = referenceSurface().how_near(x);
00185     unsigned int i;
00186     for(  i=0; i< size()-1; i++) {
00187         if( m_offset[i+1]>= d) break;
00188     }
00189     me->m_select_index = i;
00190     me->m_last_boundary=-1;
00191     return operator[](i);
00192 }
00193 const Medium*
00194 LayeredMedium::inside(const Point& x)const
00195 {
00196     if( ! volume().inside(x) ) return parent();
00197     const Medium* m = select(x);
00198     LayeredMedium* me = const_cast<LayeredMedium*>(this);
00199     me->m_select_index = -1;
00200 
00201     return m;
00202 }
00203 
00204 
00205 

Generated at Wed Nov 21 12:20:26 2001 by doxygen1.2.3 written by Dimitri van Heesch, © 1997-2000