00001
00002
00003
00004
00005
00006
00007
00008 #ifdef __GNUG__
00009 #pragma implementation
00010 #endif
00011
00012 #include "gismo/Medium.h"
00013
00014 #include "gismo/Detector.h"
00015 #include "gismo/Material.h"
00016
00017 #include "gismo/Field.h"
00018 #include "gismo/MCParticle.h"
00019 #include "facilities/error.h"
00020
00021 #include "geometry/Box.h"
00022 #include "geometry/Ray.h"
00023
00024 #include "geomrep/BoxRep.h"
00025 #include "geomrep/TubeRep.h"
00026
00027 #include <typeinfo>
00028 #include <cassert>
00029
00031
00032
00033 Medium::Medium(Medium * prnt, float size)
00034 : _volume(new Box(size,size,size))
00035 , _material(0)
00036 , _detector(0)
00037 , _field(0)
00038 , _parent(prnt)
00039 , _title(0)
00040 {
00041 set_defaults();
00042 }
00043 Medium::Medium(Medium* parent, Shape* vol, const char* matName, Detector* det)
00044 : _volume(vol)
00045 , _material(Material::hatch(matName))
00046 , _detector(det)
00047 , _field(0)
00048 , _parent(parent)
00049 , _title(0)
00050 {
00051 set_defaults();
00052 }
00053
00054 Medium::Medium(const Medium & old)
00055 : _volume(&old._volume->copy())
00056 , _material(old._material)
00057 , _detector(new Detector(*old._detector))
00058 , _field(old._field)
00059 , _parent(old._parent)
00060 , _title(0)
00061 {
00062 set_defaults();
00063 }
00064 void Medium::set_defaults()
00065 {
00066
00067 if(_parent) {
00068
00069 _keCutOff = _parent->kECutOff();
00070 _maxStep = _parent->maxStep();
00071 if(!_material) _material = &_parent->material();
00072 if(!_field) _field = &(_parent->field());
00073 _parent->addMedium(this);
00074 }
00075 else {
00076
00077 _keCutOff = 0.1f;
00078 _maxStep = 100.;
00079 if(!_material) _material = Material::hatch("vacuum");
00080 }
00081 s_count ++;
00082 }
00083
00084
00085 Medium& Medium::setTitle(const char* newTitle)
00086 {
00087 if( _title) delete [] _title;
00088 strcpy(_title = new char[strlen(newTitle)+1], newTitle);
00089 return *this;
00090 }
00091 Medium::~Medium()
00092 {
00093 if(_title) delete [] _title;
00094 if(_volume) delete _volume;
00095 if(_detector) delete _detector;
00096 s_count--;
00097 }
00098
00100
00101
00102 Medium& Medium::setKECutOff(float keCut) {
00103 _keCutOff = keCut;
00104 return *this;
00105 }
00106
00107 Medium& Medium::setMaxStep(float mxStep) {
00108 _maxStep = mxStep;
00109 return *this;
00110 }
00111
00112 Medium& Medium::setField(Field* fld)
00113 {
00114 if(_parent)
00115 if(&_parent->field() != _field) delete _field;
00116 _field = fld;
00117 return *this;
00118 }
00119
00120 const char* Medium::nameOf() const {
00121 return "Medium";
00122 }
00123
00124 int Medium::isComposite() const {
00125 return 0;
00126 }
00127
00129
00130
00131 Medium& Medium::addMedium ( Medium* nextMedium)
00132 {
00133 FATAL("Non-composite Medium tried to add medium");
00134 return *nextMedium;
00135 }
00136
00137 Medium& Medium::removeMedium (Medium* oldMedium)
00138 {
00139 FATAL("Non-composite Medium tried to remove medium");
00140 return *oldMedium;
00141 }
00142
00144
00145 GeomObject&
00146 Medium::transform(const CoordTransform& T)
00147 {
00148
00149 if( _volume )
00150 _volume->transform(T);
00151 if( _detector )
00152 _detector->transform(T);
00153 return *this;
00154 }
00155
00157
00158 void Medium::clear(){
00159 if(_detector) _detector->clear();}
00160 void Medium::generateResponse(){
00161 if(_detector) _detector->generateResponse();}
00162 void Medium::accept(DetectorVisitor& a){
00163 if(_detector) _detector->accept(a);}
00164 void Medium::writeData(std::ostream & os){
00165 if(_detector) _detector->writeData(os);}
00166 void Medium::readData(std::istream & is){
00167 if(_detector) _detector->readData(is); }
00168 void Medium::printResponse(std::ostream& os)const{
00169 if(_detector) _detector->printOn(os);}
00170 void Medium::createResponseView(gui::DisplayRep& v) {
00171 if( _detector) _detector->draw(v);}
00172
00173 void Medium::notify() {
00174 if( _detector) _detector->notify();}
00175
00177
00178
00179 const Medium * Medium::inside(const Point& r)const
00180 {
00181 const Medium* which = this;
00182 while (which && which->_volume && ! which->volume().inside(r))
00183 which = which->parent();
00184 return which;
00185
00186 }
00187
00188 Ray * Medium::CreateRay(const Point& r, const Vector& p, float q,float maxStep )const
00189 {
00190
00191
00192
00193
00194
00195
00196
00197
00198 if( maxStep ==0 ) return new Ray(r,Vector(0,0,1));
00199 if( _field )
00200 return _field->CreateRay(r,p,q);
00201 else
00202 return new Ray(r, p);
00203 }
00204
00205
00206 double Medium::distanceToLeave( const Ray& r,
00207 const Medium* & newStuff,
00208 double maxS ) const
00209 {
00210 assert(maxS>=0);
00211
00212
00213
00214
00215 if( !_volume ) {
00216
00217 newStuff = this;
00218 return maxS;
00219 }
00220
00221 double distance = volume().distanceToLeave( r, maxS );
00222 newStuff = distance>=maxS? this : parent();
00223
00224 if( distance == FLT_MAX) {
00225
00226
00227 const Medium *testStuff = inside(r.position());
00228 if( this != testStuff) {
00229 std::ostrstream cerr;
00230 cerr << "Medium::distanceToLeave: geometry error at " << r.position()
00231 << "\n\ttrying to leave \"" << title() << "\""; ;
00232 if( testStuff )
00233 cerr << "\tbut actually inside \"" << testStuff->title() << "\"\n";
00234 else
00235 cerr << " but beyond known world?\n";
00236 cerr << '\0'; WARNING(cerr.str());
00237 return distance;
00238 }
00239 }
00240
00241
00242 if(distance > maxStep())
00243 { distance = maxStep();
00244 newStuff = this;
00245 }
00246 return distance;
00247 }
00248
00249 double Medium::distanceToEnter( const Ray& r,
00250 const Medium* & newStuff,
00251 double maxDist ) const
00252 {
00253
00254
00255
00256
00257 newStuff = this;
00258 double distance = volume().distanceToEnter( r, maxDist );
00259
00260 if(distance == FLT_MAX) {
00261 if( this != lastMedium && volume().inside(r.position(Volume::Surface_EPSILON)))
00262 distance = 0.;
00263 else
00264 newStuff = parent();
00265
00266 }
00267 return distance;
00268 }
00269
00271
00272
00273 void Medium::printOn( std::ostream& os ) const
00274 {
00275 os << " Medium subClass:" << nameOf() <<" - title: "<< title() <<"\n"
00276 << " maxStep = " << maxStep()
00277 << " keCutOff = "<< kECutOff() << " \n";
00278 volume().printOn(os);
00279 if(_field)
00280 _field->printOn(os);
00281 os << " Material Name: "
00282 << _material->name() << '\n';
00283
00284 }
00285
00286 void Medium::createDetectorView(gui::DisplayRep& v) {
00287 const type_info& t = typeid(volume());
00288
00289 if( t==typeid(Box) ) v.append(BoxRep(volume() ));
00290 else if (t==typeid(Tube) )v.append(TubeRep(volume() ));
00291 else {
00292 #if 0 // disable if want other volumes (like LayeredMedium::Slice) to be ignored
00293 WARNING_MACRO("no display representation was set for volume " << t.name() );
00294 #endif
00295 }
00296 }
00297
00298
00299
00300 const Medium * Medium::lastMedium = 0;
00301 unsigned Medium::s_count=0;
00302
00303