00001
00002
00003 #include "gismo/LayeredMedium.h"
00004
00005 #include "geometry/Surface.h"
00006 #include "geometry/Ray.h"
00007 #include <cassert>
00009
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
00024 LayeredMedium::Slice::Slice(LayeredMedium& mother, int index)
00025 : ::Volume(0)
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
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
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
00057
00058 LayeredMedium* mom = const_cast<LayeredMedium*>(&m_mother);
00059 LayeredMedium::Volume* mom_vol= mom->m_vol;
00060
00061
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
00067
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
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
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);
00100 }
00101 LayeredMedium::~LayeredMedium()
00102 {}
00103
00104
00105 Medium &
00106 LayeredMedium::addLayer(Medium * inner_medium, double thickness)
00107 {
00108
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
00121 double
00122 LayeredMedium::distanceToEnter(const Ray& r, const Medium*& m, double t)const
00123 {
00124
00125
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 )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 {
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());
00163 #endif //_DEBUG
00164 sel = -1;
00165 }
00166
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
00181
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