| Classes | Job Modules | Data Objects | Services | Algorithms | Tools | Packages | Directories | Tracs |

In This Package:

VolumeIntersectionIntervals.h

Go to the documentation of this file.
00001 // $Id: VolumeIntersectionIntervals.h,v 1.14 2007/12/19 09:42:39 ibelyaev Exp $ 
00002 // ==============================================================================
00003 #ifndef       DETDESC_VOLUMEINTERSECTIONIINTERVALS_H
00004 #define       DETDESC_VOLUMEINTERSECTIONIINTERVALS_H 
00005 // ==============================================================================
00006 // STD & STL  
00007 // ==============================================================================
00008 #include <algorithm>
00009 #include <functional>
00010 #include <numeric>
00011 // ==============================================================================
00012 // GaudiKernel
00013 // ==============================================================================
00014 #include "GaudiKernel/Kernel.h"
00015 #include "GaudiKernel/StatusCode.h"
00016 // ==============================================================================
00017 // DetDesc 
00018 // ==============================================================================
00019 #include "DetDesc/DetDesc.h"
00020 #include "DetDesc/ISolid.h"
00021 #include "DetDesc/ILVolume.h"
00022 #include "DetDesc/IPVolume.h"
00023 #include "DetDesc/Material.h"
00024 #include "DetDesc/Compare.h"
00025 #include "DetDesc/IntersectionErrors.h"
00026 // ==============================================================================
00036 // ==============================================================================
00038 inline bool operator< ( const ILVolume::Interval& Int , double Length ) 
00039 { return ( Int.second - Int.first ) <  Length ; }  
00041 inline bool operator==( const ILVolume::Interval& Int , double Length ) 
00042 { return ( Int.second - Int.first ) == Length ; }
00044 inline bool operator> ( const ILVolume::Interval& Int , double Length ) 
00045 { return ( Int.second - Int.first ) >  Length ; }  
00047 inline bool operator<=( const ILVolume::Interval& Int , double Length ) 
00048 { return ( Int.second - Int.first ) <= Length ; }  
00050 inline bool operator>=( const ILVolume::Interval& Int , double Length ) 
00051 { return ( Int.second - Int.first ) >= Length ; }  
00053 inline bool operator!=( const ILVolume::Interval& Int , double Length ) 
00054 { return ( Int.second - Int.first ) != Length ; }  
00055 
00056 
00058 inline bool operator< ( const ILVolume::Intersection& Int , double RadLength ) 
00059 { return ( ( 0 == Int.second ) ? true  :  
00060            Int.first <  RadLength * ( Int.second->radiationLength() ) ) ; } 
00061 
00063 inline bool operator<=( const ILVolume::Intersection& Int , double RadLength ) 
00064 { return ( ( 0 == Int.second ) ? true  :  
00065            Int.first <= RadLength * ( Int.second->radiationLength() ) ) ; } 
00066 
00068 inline bool operator> ( const ILVolume::Intersection& Int , double RadLength ) 
00069 { return ( ( 0 == Int.second ) ? false :  
00070            Int.first >  RadLength * ( Int.second->radiationLength() ) ) ; } 
00071 
00073 inline bool operator>=( const ILVolume::Intersection& Int , double RadLength ) 
00074 { return ( ( 0 == Int.second ) ? false :  
00075            Int.first >= RadLength * ( Int.second->radiationLength() ) ) ; } 
00076 
00078 inline bool operator==( const ILVolume::Intersection& Int , double RadLength ) 
00079 { return ( ( 0 == Int.second ) ? ( ( 0 == RadLength ) ? true : false )  :  
00080            Int.first >= RadLength * ( Int.second->radiationLength() ) ) ; }
00081 
00082 // ============================================================================
00087 namespace  VolumeIntersectionIntervals
00088 {
00089   // ==========================================================================
00091   inline int intersect 
00092   ( const ILVolume::Interval& i1 , 
00093     const ILVolume::Interval& i2 ) 
00094   {
00095     const int res1 = DetDesc::compare ( i1.second , i2.first ) ;
00096     if ( ! ( 0 < res1 ) ) { return -1 ; }                         // RETURN   
00097     const int res2 = DetDesc::compare ( i2.second , i1.first ) ;    
00098     if ( ! ( 0 < res2 ) ) { return  1 ; }                         // RETURN 
00099     return 0 ;                                                    // RETURN 
00100   }
00101   // ==========================================================================
00103   inline int intersect 
00104   ( const ILVolume::Intersection& i1 , 
00105     const ILVolume::Intersection& i2 ) 
00106   {
00107     return intersect ( i1.first , i2.first ) ;
00108   }
00109   // ==========================================================================
00118   template < class OUTPUTTYPE >
00119   inline  unsigned int TicksToIntervals 
00120   ( const ISolid::Ticks & ticks ,  // input "ticks", assumed to be sorted!
00121     OUTPUTTYPE            out   ) 
00122   {
00123     // interval can be constructed from at least 2 ticks!
00124     if( ticks.size() < 2 ) { return 0 ; } // RETURN!
00125     
00126     unsigned int res = 0 ;
00127     
00128     ISolid::Ticks::const_iterator it = ticks.begin();
00129     ISolid::Tick  tickPrevious = *it++;   // size tested. this is safe
00130     while( ticks.end() != it ) {
00131       ISolid::Tick tickCurrent = *it++;
00132       if( tickCurrent > tickPrevious ) {
00133         ++res;
00134         *out++ = ILVolume::Interval( tickPrevious , tickCurrent ) ;
00135       }
00136       if ( ticks.end() != it ) { tickPrevious = *it++; }
00137     }
00139     return res; 
00140   }
00141   // ==========================================================================  
00146   class AccumulateIntervals:  
00147     public std::binary_function<double,const ILVolume::Interval,double>
00148   {
00149   public: 
00150     inline double  operator() 
00151       ( double& Length  , const ILVolume::Interval& interval ) const  
00152     { return Length += (interval.second-interval.first); }  
00153   };
00154   // ==========================================================================
00159   class AccumulateIntersections:  
00160     public std::binary_function<double,const ILVolume::Intersection,double>
00161   {
00162   public: 
00163     inline double  operator() 
00164       ( double& Length  , const ILVolume::Intersection& intersection ) const  
00165     {
00166       const  Material*  mat          = intersection.second;     
00167       const  ILVolume::Interval& Int = intersection.first;   
00168       return 
00169         ( Length += ( ( 0 == mat ) ? 0 : 
00170                       (Int.second-Int.first) / mat->radiationLength() ) ) ; 
00171     }
00172   };
00173   // ==========================================================================
00181   template < class OUTPUTTYPE > 
00182   inline  StatusCode MergeOwnAndChildContainers
00183   ( const ILVolume::Intersections&   own       , 
00184     const ILVolume::Intersections&   child     ,
00185     OUTPUTTYPE                       out       , 
00186     const ILVolume*               /* volum */  , 
00187     const double                  /* length */ )    
00188   {
00192     typedef std::vector<ILVolume::Intersections::size_type> IndexCont ;
00193     typedef ILVolume::Intersections::const_iterator         Iter      ; 
00194     typedef ISolid::Tick                                    Tick      ;
00195     typedef ILVolume::Interval                              Interval  ; 
00196     const double tol = 1.e-6;  // Needed to test equalities...
00199     for( Iter iterTop = own.begin(); own.end() != iterTop ; ++iterTop ) {
00200       const Interval& intervalTop = iterTop->first  ;
00201       const Material* matTop      = iterTop->second ;
00202       // temporary container of indexes of related intervals 
00203       IndexCont tmpIndex; 
00204       for( Iter iter = child.begin();  child.end() != iter ; ++iter ) {
00205         const Interval& intervalLoc = iter->first;
00206         
00207         if( intervalLoc.second <= (intervalTop.first+tol)  ) {
00208           ; // the second interval is lower  then the first one! it's OK
00209         } else if( intervalTop.first  <= (intervalLoc.first+tol) && 
00210                    intervalLoc.second <= (intervalTop.second+tol) ) {
00211           // the second interval is inside      the first one! it's OK
00212           tmpIndex.push_back( iter - child.begin() );
00213         } else if( intervalTop.second <= (intervalLoc.first+tol)  ) {
00214           ; // the second interval in higher then the first one! it's OK 
00215         } else {
00219           DetDesc::Services* services = DetDesc::services();
00220           MsgStream log (services->msgSvc() , "TransportSvc");
00221           log << MSG::ERROR
00222               << "VolumeIntersection:Merge error 15 : interval " 
00223               << intervalLoc.first << " "
00224               << intervalLoc.second << " master "
00225               << intervalTop.first << " " 
00226               << intervalTop.second << endreq;
00227           services->release();
00228           return StatusCode(15) ;
00229         }
00230         // ? RETURN !!!
00231       }  // end of loop over the child container 
00233       // try to merge intervals 
00234       Tick leftTick       = intervalTop.first  ; 
00235       Tick mostRightTick  = intervalTop.second ;
00236       const  Material*  prevMatLocal = 0;
00237       for( IndexCont::const_iterator it = tmpIndex.begin(); 
00238            tmpIndex.end() != it ; ++it ) { 
00239         Iter              iterLocal     = child.begin() + (*it) ; 
00240         const  Interval&  intervalLocal = iterLocal->first  ;
00241         const  Material*  matLocal      = iterLocal->second ;
00243         if( leftTick <= (intervalLocal.first + tol) && 
00244             intervalLocal.first < mostRightTick ) {
00245           if( leftTick <= (intervalLocal.first - tol) ) { 
00246             *out++ =  ILVolume::Intersection( Interval( leftTick , 
00247                                                         intervalLocal.first ), 
00248                                               matTop  ) ; 
00249           }
00250           leftTick = intervalLocal.first;
00251                 
00252           if( intervalLocal.second <= (mostRightTick+tol) ) { 
00253             *out++ = ILVolume::Intersection( Interval( leftTick , 
00254                                                        intervalLocal.second), 
00255                                              matLocal ) ; 
00256           } else { // geometry error!!!
00257             return StatusCode(16) ; 
00258           }      // RETURN !!!
00259 
00260           //=== This is a hack, to accept overlaping volumes with same
00261           //=== material without complaining...
00262         } else if ( (matLocal == prevMatLocal) && 
00263                     (intervalLocal.second <= (mostRightTick+tol) ) ) {
00264           if ( intervalLocal.second > leftTick  ) {
00265             *out++ = ILVolume::Intersection( Interval( leftTick , 
00266                                                        intervalLocal.second), 
00267                                              matLocal ) ; 
00268           }
00269         } else {                                 // geometry error!!!
00270           DetDesc::Services* services = DetDesc::services();
00271           MsgStream log (services->msgSvc() , "TransportSvc");
00272           log << MSG::ERROR
00273               << "VolumeIntersection:Merge error 17 : interval " 
00274               << intervalLocal.first << " "
00275               << intervalLocal.second << " master "
00276               << leftTick << " " 
00277               << mostRightTick << endreq;
00278           services->release();
00279           return StatusCode(17) ; 
00280         }         // RETURN !!!
00281         leftTick     = intervalLocal.second;
00282         prevMatLocal = matLocal;
00283       }  // end of loop over temporary index container 
00284 
00285       if( leftTick <= (mostRightTick - tol) ) { 
00286         *out++ = ILVolume::Intersection( Interval( leftTick , mostRightTick ) ,
00287                                          matTop  ) ; 
00288       } 
00289       leftTick = mostRightTick;    
00290     }  // end of loop over own intervals
00291     
00293     return StatusCode::SUCCESS;
00294   }
00295   // ==========================================================================
00303   template < class OUTPUTTYPE > 
00304   inline  StatusCode 
00305   MergeOwnAndChildContainers2
00306   ( const ILVolume::Intersections& own    , 
00307     const ILVolume::Intersections& child  ,
00308     OUTPUTTYPE                     out    , 
00309     const ILVolume*                volume , 
00310     const double                   length ) 
00311   {
00312     /*  here we have both containers - own and child containers
00313      *  try to merge the containers
00314      */
00315     typedef std::vector<ILVolume::Intersections::size_type> IndexCont ;
00316     typedef ILVolume::Intersections::const_iterator         Iter      ; 
00317     typedef ISolid::Tick                                    Tick      ;
00318     typedef ILVolume::Interval                              Interval  ; 
00319     // loop over all "own" intervals 
00320     for ( Iter iterTop = own.begin(); own.end() != iterTop ; ++iterTop ) 
00321     {
00322       const Interval& intervalTop = iterTop->first  ;
00323       const Material* matTop      = iterTop->second ;
00324       // temporary container of indexes of related intervals 
00325       IndexCont tmpIndex; 
00326       for ( Iter iter = child.begin();  child.end() != iter ; ++iter ) 
00327       {
00328         const Interval& intervalLoc = iter->first ;
00329         
00330         const int result = VolumeIntersectionIntervals::intersect 
00331           ( intervalTop , intervalLoc ) ;
00332         
00333         if     ( 0 != result ) { /* it is OK */ }
00334         else 
00335         {
00336           // here we have either GOOD case or geometry error , 
00337           // keep them togather for a moment 
00338           tmpIndex.push_back ( iter - child.begin() ); 
00339         }
00340       }  
00341       // end of loop over the child container 
00342       //  
00343       // try to merge intervals 
00344       Tick leftTick       = intervalTop.first  ; 
00345       Tick mostRightTick  = intervalTop.second ;
00346       
00347       for ( IndexCont::const_iterator it = tmpIndex.begin(); 
00348             tmpIndex.end() != it ; ++it ) 
00349       { 
00350         Iter              iterLocal     = child.begin() + (*it) ; 
00351         const  Interval&  intervalLocal = iterLocal->first  ;
00352         const  Material*  matLocal      = iterLocal->second ;
00354         if ( matLocal == matTop ) { continue ; }
00355         //
00356         const int rL = DetDesc::compare ( leftTick , intervalLocal.first       ) ;
00357         const int rR = DetDesc::compare ( intervalLocal.second , mostRightTick ) ;
00358         
00359         if ( rL <= 0 && rR <=0 )
00360         {
00361           // 
00362           if      ( rL < 0 ) 
00363           {
00364             *out++ = ILVolume::Intersection 
00365               ( ILVolume::Interval ( leftTick , intervalLocal.first )  , matTop    ) ;
00366             leftTick = intervalLocal.first ;
00367           }
00368           //
00369           if      ( rR < 0 ) 
00370           {
00371             *out++ = ILVolume::Intersection 
00372               ( ILVolume::Interval ( leftTick , intervalLocal.second ) , matLocal ) ;
00373             leftTick = intervalLocal.second ;
00374           }
00375           else if ( rR ==0 ) 
00376           {
00377             *out++ = ILVolume::Intersection 
00378               ( ILVolume::Interval ( leftTick , mostRightTick )        , matLocal ) ;
00379             leftTick = mostRightTick ;
00380           }
00381         }
00382         else 
00383         { 
00384           /* here we have real problems */
00385           
00386           /* the problem is serious, but we have some guess how to solve it */
00387           if ( DetDesc::IntersectionErrors::recovery() ) 
00388           {
00389             // try to recover (1) 
00390             if ( 0 < rL && rR < 0 ) 
00391             {
00392               *out++ = ILVolume::Intersection 
00393                 ( ILVolume::Interval ( leftTick , intervalLocal.second ) , matLocal ) ;
00394               // report the problem 
00395               DetDesc::IntersectionErrors::recovered 
00396                 ( volume , matTop , matLocal , 
00397                   length * ( leftTick - intervalLocal.first  ) ) ;
00398               //
00399               leftTick = intervalLocal.second ;
00400             }
00401             // try to recover (2) 
00402             else if ( 0 < rL && rR == 0 ) 
00403             {
00404               *out++ = ILVolume::Intersection 
00405                 ( ILVolume::Interval ( leftTick , mostRightTick  ) , matLocal ) ;
00406               //
00407               // report the problem 
00408               DetDesc::IntersectionErrors::recovered 
00409                 ( volume , matTop , matLocal , 
00410                   length * ( leftTick - intervalLocal.first ) ) ;
00411               //
00412               leftTick = mostRightTick  ;
00413             }
00414             // try to recover (3) 
00415             else if ( rL <= 0 && 0 < rR  ) 
00416             {
00417               if ( rL < 0 ) 
00418               {
00419                 *out++ = ILVolume::Intersection 
00420                   ( ILVolume::Interval ( leftTick , intervalLocal.first ) , matTop ) ;
00421                 leftTick = intervalLocal.first ;
00422               }
00423               // 
00424               *out++ = ILVolume::Intersection 
00425                 ( ILVolume::Interval ( leftTick , mostRightTick  ) , matLocal ) ;
00426               //
00427               // report the problem 
00428               DetDesc::IntersectionErrors::recovered 
00429                 ( volume , matTop , matLocal , 
00430                   length * ( intervalLocal.second - mostRightTick ) )  ;
00431               //
00432               leftTick = mostRightTick ;
00433             }
00434             else if ( rL > 0 && rR > 0 ) 
00435             {
00436               *out++ = ILVolume::Intersection 
00437                 ( ILVolume::Interval ( leftTick , mostRightTick) , matLocal ) ;
00438               //
00439               // report the problem 
00440               DetDesc::IntersectionErrors::recovered 
00441                 ( volume , matTop ,  matLocal ,
00442                   length * ( intervalLocal.second - mostRightTick       +
00443                              leftTick             - intervalLocal.first ) ) ;
00444               //
00445               leftTick = mostRightTick ;
00446             }
00447           } // recover allowed? 
00448           else 
00449           {
00450             DetDesc::IntersectionErrors::setCode ( 17 , volume ) ;
00451             return StatusCode ( 17 ) ;
00452           }
00453         } // geometry problmes
00454       }// end of loop over the temporary index container
00455       // the last intersection 
00456       const int rF = DetDesc::compare ( leftTick , mostRightTick ) ;
00457       if ( rF < 0  ) 
00458       {
00459         *out++ = ILVolume::Intersection
00460           ( ILVolume::Interval ( leftTick , mostRightTick ) , matTop  ) ; 
00461       }
00462       // adjuts the left tick 
00463       leftTick = mostRightTick;    
00464     }  // end of loop over own intervals
00465     
00467     return StatusCode::SUCCESS;
00468   }
00469   // ======================================================================-===
00474   class CompareIntersections : 
00475     public std::binary_function<const ILVolume::Intersection&,
00476     const ILVolume::Intersection&,bool>                               
00477   {
00478   public:
00479     inline bool operator() 
00480       ( const ILVolume::Intersection& i1 , 
00481         const ILVolume::Intersection& i2 ) const 
00482     { return i1.first.first < i2.first.first; }
00483   };
00484   // ==========================================================================
00489   inline int 
00490   correct  
00491   ( const ILVolume*          volume , 
00492     ILVolume::Intersections& cnt    ,
00493     const double             tick   , 
00494     unsigned int index =     0      ) 
00495   {
00496     // nothing to correct? 
00497     if ( 2 + index > cnt.size()  ) { return 0 ; } // RETURN
00498     ILVolume::Intersections::iterator i1 = cnt.begin() + index ;
00499     // loop over all the intersections    
00500     for ( ILVolume::Intersections::iterator i2 = i1 + 1 ;
00501           i2 != cnt.end() ; ++i1 , ++i2 , ++index ) 
00502     {
00503       // OPTIONAL CHECK (could be removed) 
00504       // the intersection of the zero length 
00505       // check the length of the intersecion:
00506       const int length = DetDesc::compare ( i1->first.first , i1->first.second ) ;
00507       // invalid or empty intersection!!! 
00508       if        ( 0 <  length ) 
00509       { 
00510         if (  DetDesc::IntersectionErrors::recovery () ) 
00511         {        
00512           DetDesc::IntersectionErrors::skip 
00513             ( volume , i1->second , 
00514               tick *  ( i1->first.second - i1->first.first ) ) ;
00515           cnt.erase( i1 ) ;
00516           return correct ( volume , cnt , tick , index ) + 1 ;              // RETURN 
00517         }
00518         DetDesc::IntersectionErrors::setCode ( 26 , volume ) ;
00519         return 0 ;
00520       }
00521       else if        ( 0 ==  length ) 
00522       { 
00523         DetDesc::IntersectionErrors::skip 
00524           ( volume , i1->second , 0 ) ;
00525         cnt.erase ( i1 ) ;
00526         return correct ( volume , cnt , tick , index ) + 1 ;              // RETURN 
00527       }
00528       // ======================================================================
00529       /* check the end point of the first intersection 
00530        * and the begin point of the second intersection
00531        */
00532       const int result = DetDesc::compare ( i1->first.second , i2->first.first ) ;
00533       // invalid position of the points:
00534       if ( 0 < result  && i1->second != i2->second ) 
00535       {
00536         if ( DetDesc::IntersectionErrors::recovery() ) 
00537         {
00538           DetDesc::IntersectionErrors::recovered
00539             ( volume       , 
00540               i1 -> second , 
00541               i2 -> second , 
00542               tick *  ( i1->first.second - i2->first.first ) ) ;
00543           const double t1 = 0.5 * ( i1 -> first.second + i1 -> first.first) ;
00544           i1 -> first.second = t1 ;
00545           i2 -> first.first  = t1 ;
00546           return correct ( volume , cnt , tick , index ) + 1 ;              // RETURN 
00547         }
00548         DetDesc::IntersectionErrors::setCode ( 27 , volume ) ;
00549         return 0 ;
00550       }
00551       // try to recover this pathological case 
00552       if ( 0 < result  && i1->second == i2->second  ) 
00553       {
00554         if ( DetDesc::IntersectionErrors::recovery() ) 
00555         {
00556           DetDesc::IntersectionErrors::recovered
00557             ( volume       , 
00558               i1 -> second , 
00559               i2 -> second , 
00560               tick *  ( i1->first.second - i2->first.first ) ) ;
00561           i1->first.second = i2->first.second ;
00562           cnt.erase ( i2 ) ;
00563           return correct ( volume , cnt , tick , index ) + 1 ;              // RETURN
00564         }
00565         DetDesc::IntersectionErrors::setCode ( 28 , volume ) ;
00566         return 0 ;
00567       }
00568       // the points are "comparable" 
00569       if ( 0 == result ) 
00570       {
00571         // redefine the intersection for the exact match:
00572         i1 -> first.second = i2->first.first ;
00573         // but if we have the same material, 
00574         // we can "merge" both intersection togather:
00575         if ( i1->second == i2->second ) // the same material!
00576         {
00577           i1->first.second = i2->first.second ;
00578           cnt.erase ( i2 ) ;
00579           return correct ( volume , cnt , tick , index ) + 1 ;     // RETURN 
00580         } // the same material 
00581       } // the points are comparable
00582     } // loop over intersections
00583     return 0 ;                                                     // RETURN                                                  
00584   } // "correct"
00585   // ==========================================================================  
00586 } // end of namespace
00587 // ============================================================================
00588 // The End 
00589 // ============================================================================
00590 #endif   //   __DETDESC_VOLUMES_VOLUMEINTERSECTIONIINTERVALS_H__
00591 // ============================================================================
| Classes | Job Modules | Data Objects | Services | Algorithms | Tools | Packages | Directories | Tracs |

Generated on Mon Apr 11 20:00:13 2011 for DetDesc by doxygen 1.4.7