00001
00002
00003 #ifndef DETDESC_VOLUMEINTERSECTIONIINTERVALS_H
00004 #define DETDESC_VOLUMEINTERSECTIONIINTERVALS_H
00005
00006
00007
00008 #include <algorithm>
00009 #include <functional>
00010 #include <numeric>
00011
00012
00013
00014 #include "GaudiKernel/Kernel.h"
00015 #include "GaudiKernel/StatusCode.h"
00016
00017
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 ; }
00097 const int res2 = DetDesc::compare ( i2.second , i1.first ) ;
00098 if ( ! ( 0 < res2 ) ) { return 1 ; }
00099 return 0 ;
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 ,
00121 OUTPUTTYPE out )
00122 {
00123
00124 if( ticks.size() < 2 ) { return 0 ; }
00125
00126 unsigned int res = 0 ;
00127
00128 ISolid::Ticks::const_iterator it = ticks.begin();
00129 ISolid::Tick tickPrevious = *it++;
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* ,
00187 const double )
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;
00199 for( Iter iterTop = own.begin(); own.end() != iterTop ; ++iterTop ) {
00200 const Interval& intervalTop = iterTop->first ;
00201 const Material* matTop = iterTop->second ;
00202
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 ;
00209 } else if( intervalTop.first <= (intervalLoc.first+tol) &&
00210 intervalLoc.second <= (intervalTop.second+tol) ) {
00211
00212 tmpIndex.push_back( iter - child.begin() );
00213 } else if( intervalTop.second <= (intervalLoc.first+tol) ) {
00214 ;
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
00231 }
00233
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 {
00257 return StatusCode(16) ;
00258 }
00259
00260
00261
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 {
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 }
00281 leftTick = intervalLocal.second;
00282 prevMatLocal = matLocal;
00283 }
00284
00285 if( leftTick <= (mostRightTick - tol) ) {
00286 *out++ = ILVolume::Intersection( Interval( leftTick , mostRightTick ) ,
00287 matTop ) ;
00288 }
00289 leftTick = mostRightTick;
00290 }
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
00313
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
00320 for ( Iter iterTop = own.begin(); own.end() != iterTop ; ++iterTop )
00321 {
00322 const Interval& intervalTop = iterTop->first ;
00323 const Material* matTop = iterTop->second ;
00324
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 ) { }
00334 else
00335 {
00336
00337
00338 tmpIndex.push_back ( iter - child.begin() );
00339 }
00340 }
00341
00342
00343
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
00385
00386
00387 if ( DetDesc::IntersectionErrors::recovery() )
00388 {
00389
00390 if ( 0 < rL && rR < 0 )
00391 {
00392 *out++ = ILVolume::Intersection
00393 ( ILVolume::Interval ( leftTick , intervalLocal.second ) , matLocal ) ;
00394
00395 DetDesc::IntersectionErrors::recovered
00396 ( volume , matTop , matLocal ,
00397 length * ( leftTick - intervalLocal.first ) ) ;
00398
00399 leftTick = intervalLocal.second ;
00400 }
00401
00402 else if ( 0 < rL && rR == 0 )
00403 {
00404 *out++ = ILVolume::Intersection
00405 ( ILVolume::Interval ( leftTick , mostRightTick ) , matLocal ) ;
00406
00407
00408 DetDesc::IntersectionErrors::recovered
00409 ( volume , matTop , matLocal ,
00410 length * ( leftTick - intervalLocal.first ) ) ;
00411
00412 leftTick = mostRightTick ;
00413 }
00414
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
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
00440 DetDesc::IntersectionErrors::recovered
00441 ( volume , matTop , matLocal ,
00442 length * ( intervalLocal.second - mostRightTick +
00443 leftTick - intervalLocal.first ) ) ;
00444
00445 leftTick = mostRightTick ;
00446 }
00447 }
00448 else
00449 {
00450 DetDesc::IntersectionErrors::setCode ( 17 , volume ) ;
00451 return StatusCode ( 17 ) ;
00452 }
00453 }
00454 }
00455
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
00463 leftTick = mostRightTick;
00464 }
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
00497 if ( 2 + index > cnt.size() ) { return 0 ; }
00498 ILVolume::Intersections::iterator i1 = cnt.begin() + index ;
00499
00500 for ( ILVolume::Intersections::iterator i2 = i1 + 1 ;
00501 i2 != cnt.end() ; ++i1 , ++i2 , ++index )
00502 {
00503
00504
00505
00506 const int length = DetDesc::compare ( i1->first.first , i1->first.second ) ;
00507
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 ;
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 ;
00527 }
00528
00529
00530
00531
00532 const int result = DetDesc::compare ( i1->first.second , i2->first.first ) ;
00533
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 ;
00547 }
00548 DetDesc::IntersectionErrors::setCode ( 27 , volume ) ;
00549 return 0 ;
00550 }
00551
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 ;
00564 }
00565 DetDesc::IntersectionErrors::setCode ( 28 , volume ) ;
00566 return 0 ;
00567 }
00568
00569 if ( 0 == result )
00570 {
00571
00572 i1 -> first.second = i2->first.first ;
00573
00574
00575 if ( i1->second == i2->second )
00576 {
00577 i1->first.second = i2->first.second ;
00578 cnt.erase ( i2 ) ;
00579 return correct ( volume , cnt , tick , index ) + 1 ;
00580 }
00581 }
00582 }
00583 return 0 ;
00584 }
00585
00586 }
00587
00588
00589
00590 #endif // __DETDESC_VOLUMES_VOLUMEINTERSECTIONIINTERVALS_H__
00591