00001
00002
00003
00004
00005
00006 #ifdef HAVE_CONFIG_H
00007 #include "config.h"
00008 #endif
00009
00010 #include "LayeredTube.h"
00011
00012 #include "gismo/Detector.h"
00013 #include "gismo/Material.h"
00014
00015 #include "geometry/Tube.h"
00016 #include "geometry/Ray.h"
00017 #include "geometry/Intersection.h"
00018
00019 #include "geomrep/TubeRep.h"
00020
00021 #include <strstream>
00022 #include <cassert>
00023
00024
00026
00027
00028 LayeredTube::LayeredTube(Medium* parent, float dz, float r)
00029 : CompositeMedium(parent)
00030 , m_dz(dz)
00031 , m_r_inner(r)
00032 , first(0), last(0)
00033 {
00034 }
00035 LayeredTube::Layer::Layer(Medium* parent, const char* matname, Detector* det)
00036 : Medium(parent, (Shape*) 0, matname, det) {}
00037
00038 Medium&
00039 LayeredTube::addLayer(float thickness, const char* matname, Detector* det)
00040 {
00041 Layer* newLayer = new Layer(this, matname, det);
00042
00043 if( first == 0 )
00044 {
00045 first = last = newLayer;
00046 first->min_r = m_r_inner;
00047 m_r_outer = first->max_r = first->min_r+thickness;
00048 first->previous = 0;
00049 first->next = 0;
00050 setVolume( new Tube(m_dz, m_r_inner, m_r_outer) );
00051 }
00052 else
00053 {
00054 newLayer->min_r = last->max_r;
00055 m_r_outer =newLayer->max_r = newLayer->min_r+thickness;
00056 newLayer->previous = last;
00057 newLayer->next = 0;
00058 last->next = newLayer;
00059 last = newLayer;
00060 delete &tube();
00061 setVolume(new Tube(m_dz, m_r_inner, m_r_outer) );
00062 }
00063
00064 newLayer->setVolume(new Tube(m_dz, newLayer->min_r, newLayer->max_r) );
00065 std::ostrstream label;
00066 label << "Layer " << innerMediaCount() << '\0';
00067 newLayer->setTitle(label.str());
00068 return *newLayer;
00069 }
00070
00072
00073
00074
00075 double
00076 LayeredTube::distanceToEnter(const Ray& r, const Medium*& m, double t)const
00077 {
00078
00079
00080 double d = Medium::distanceToEnter(r,m,t);
00081
00082 if( d != FLT_MAX ){
00083
00084 m = select(r.position(d));
00085 }
00086 return d;
00087
00088 }
00089
00090 double
00091 LayeredTube::distanceToLeave(const Ray& r, const Medium*& newStuff
00092 , double maxDist)const
00093 {
00094 newStuff = parent();
00095 return 0.;
00096 }
00097
00098 const LayeredTube::Layer*
00099 LayeredTube::select(const Point& x)const
00100 {
00101 Vector r = x - origin();
00102 double rlocal = sqrt( r.mag2() - sqr(r*axis()) );
00103 const Layer* layer=first;
00104
00105 while( (rlocal>layer->max_r) && layer->next)
00106 {
00107 layer = layer->next;
00108 }
00109 return layer;
00110 }
00111
00112 const Medium*
00113 LayeredTube::inside(const Point& x)const
00114 {
00115 if( ! tube().inside(x) ) return parent();
00116 return select(x);
00117 }
00118
00119 double
00120 LayeredTube::Layer::distanceToLeave(const Ray& x, const Medium*& nextMed
00121 , double maxStep)const
00122 {
00123 #ifdef _DEBUG
00124 const Tube* mytube=(const Tube*)(&volume());
00125 for( int i=0; i< mytube->surfaceCount(); i++){
00126 double dist = mytube->surface(i).how_near(x.position());
00127
00128 assert( dist > -5e-6);
00129 }
00130 #endif
00131
00132 double d = volume().distanceToLeave(x, maxStep);
00133
00134 if( d==FLT_MAX ) {
00135 std::ostrstream error_text;
00136 Vector r = x.position()-origin();
00137
00138 error_text << "LayeredTube::Layer::distanceToLeave: point not inside??\n"
00139 << "\tRay= " << x << '\n'
00140 << "\tlocal radius, z = " << sqrt( r.mag2() - sqr(r*axis()) )
00141 << ", " << r*axis() << '\n'
00142 << "\tOrigin= " << origin() << "; axis= "<< axis() << '\n'
00143 << "\tmin_r, max_r = " << min_r << " " << max_r << '\n';
00144 error_text << '\0';
00145 WARNING(error_text.str());
00146 return d;
00147 }
00148 else if( d < maxStep) {
00149
00150 Vector r = x.position(d)-origin();
00151 double local_z = r*axis();
00152 if( fabs(local_z)>= parentTube().length()/2.0)
00153 nextMed=0;
00154 else {
00155 Vector rhohat = (r - local_z*axis()).unit();
00156 double slope = x.direction(d)*rhohat;
00157 nextMed = slope>0 ? next : previous;
00158 }
00159 d += 1e-7;
00160 }
00161 if( nextMed==0 ) {
00162 nextMed = parent();
00163 }
00164 #ifdef _DEBUG
00165 {
00166 mytube=(const Tube*)(&nextMed->volume());
00167 for( int i=0; i< mytube->surfaceCount(); i++){
00168 double dist = mytube->surface(i).how_near(x.position(d));
00169
00170 assert( dist > -1e-7);
00171 }
00172 }
00173 #endif
00174
00175 return d;
00176 }
00178
00179 GeomObject&
00180 LayeredTube::transform(const CoordTransform& T)
00181 {
00182 CompositeMedium::transform(T);
00183 m_origin.transform(T);
00184 return *this;
00185 }
00186
00187
00188 GeomObject&
00189 LayeredTube::Layer::transform(const CoordTransform& T)
00190 {
00191 Medium::transform(T);
00192 return *this;
00193 }
00194
00195
00197
00198 static const Tube* motherTube;
00199 static bool even;
00200 void
00201 LayeredTube::createDetectorView(gui::DisplayRep& view)
00202 {
00203 motherTube = &tube();
00204 even = true;
00205 CompositeMedium::createDetectorView(view);
00206 }
00207 void
00208 LayeredTube::Layer::createDetectorView(gui::DisplayRep& view)
00209 {
00210 if( even ) view.append( TubeRep( (Tube&)volume()) );
00211 even = ! even;
00212 }
00214
00215 void
00216 LayeredTube::Layer::printOn(std::ostream& os)const
00217 {
00218 os << " LayeredTube::Layer - title: "<<_title<<"\n"
00219 << " _maxStep = " << maxStep()
00220 << " keCutOff = "<< kECutOff() << " \n";
00221
00222 os << " Material: "
00223 << _material->name() << "\tr-range: "<< min_r << " to " << max_r << "\n";
00224
00225 }
00226