00001
00002
00003
00004
00005
00006
00007 #include <set>
00008 #include <functional>
00009 #include <algorithm>
00010
00012
00013 #include "GaudiKernel/AlgFactory.h"
00014 #include "GaudiKernel/IRndmGenSvc.h"
00015 #include "GaudiKernel/RndmGenerators.h"
00016 #include "GaudiKernel/SystemOfUnits.h"
00017 #include "GaudiKernel/Vector3DTypes.h"
00018
00019
00020
00021 #include "GaudiAlg/GaudiAlgorithm.h"
00022
00023
00024
00025 #include "DetDesc/ILVolume.h"
00026 #include "DetDesc/IPVolume.h"
00027 #include "DetDesc/ISolid.h"
00028 #include "DetDesc/Material.h"
00029 #include "DetDesc/SolidBox.h"
00030 #include "DetDesc/VolumeIntersectionIntervals.h"
00031 #include "DetDesc/IntersectionErrors.h"
00032 #include "DetDesc/ITransportSvc.h"
00033
00034
00035
00036 #include "boost/progress.hpp"
00037 #include "boost/format.hpp"
00038
00039
00040
00041 #include "gsl/gsl_sys.h"
00042
00048
00049 namespace DetDesc
00050 {
00051
00052 bool isOK ( const ILVolume::Intersections& cnt )
00053 {
00054 for ( ILVolume::Intersections::const_iterator i1 = cnt.begin() ;
00055 cnt.end() != i1 ; ++i1 )
00056 {
00057 const double x1 = i1->first.first ;
00058 const double x2 = i1->first.second ;
00059 for ( ILVolume::Intersections::const_iterator i2 = i1 + 1 ;
00060 cnt.end() != i2 ; ++i2 )
00061 {
00062 if ( 0 == VolumeIntersectionIntervals::intersect ( *i1 , *i2 ) )
00063 { return false ; }
00064
00065 const double y1 = i2->first.first ;
00066 const double y2 = i2->first.second ;
00067 if ( x2 < y1 || y2 < x1 ) { continue ; }
00068 const double z1 = std::max ( x1 , y1 ) ;
00069 const double z2 = std::min ( x2 , y2 ) ;
00070
00071 if ( z1 < z2 ) { return false ; }
00072
00073 }
00074 }
00075 return true ;
00076 }
00077 std::pair<std::pair<int,int>,double>
00078 notOK ( const ILVolume::Intersections& cnt )
00079 {
00080 for ( ILVolume::Intersections::const_iterator i1 = cnt.begin() ;
00081 cnt.end() != i1 ; ++i1 )
00082 {
00083 const double x1 = i1->first.first ;
00084 const double x2 = i1->first.second ;
00085 for ( ILVolume::Intersections::const_iterator i2 = i1 + 1 ;
00086 cnt.end() != i2 ; ++i2 )
00087 {
00088 const double y1 = i2->first.first ;
00089 const double y2 = i2->first.second ;
00090 if ( x2 < y1 || y2 < x1 ) { continue ; }
00091 const double z1 = std::max ( x1 , y1 ) ;
00092 const double z2 = std::min ( x2 , y2 ) ;
00093 if ( z1 < z2 )
00094 {
00095 std::pair<int,int> p = std::make_pair
00096 ( i1 - cnt.begin() , i2 - cnt.begin () ) ;
00097 return std::make_pair ( p , z2 - z1 ) ;
00098 }
00099 }
00100 }
00101 return std::pair<std::pair<int,int>,double>() ;
00102 }
00103
00109 class CheckOverlap : public GaudiAlgorithm
00110 {
00112 friend class AlgFactory<DetDesc::CheckOverlap> ;
00113 public:
00114
00119 virtual StatusCode initialize () ;
00120
00125 virtual StatusCode execute () ;
00126
00131 virtual StatusCode finalize () ;
00132
00133 protected:
00134
00139 CheckOverlap
00140 ( const std::string& name ,
00141 ISvcLocator* svcloc ) ;
00143 virtual ~CheckOverlap(){};
00144
00145 private:
00147 StatusCode checkVolume
00148 ( const ILVolume* volume , const unsigned int level ) const ;
00150 StatusCode makeShots ( const ILVolume* volume ) const ;
00151 private:
00152
00153 std::string m_volumeName ;
00154
00155 const ILVolume* m_volume ;
00156
00157
00158 double m_minx ;
00159 double m_maxx ;
00160 double m_miny ;
00161 double m_maxy ;
00162 double m_minz ;
00163 double m_maxz ;
00164
00165
00166 int m_shots ;
00167
00168
00169 std::vector<double> m_vrtx ;
00170 Gaudi::XYZPoint m_vertex ;
00171 mutable std::set<const ILVolume*> m_checked ;
00172 } ;
00173 }
00174
00175
00176
00177
00178
00179
00180 DetDesc::CheckOverlap::CheckOverlap
00181 ( const std::string& name ,
00182 ISvcLocator* svcloc )
00183 : GaudiAlgorithm( name , svcloc )
00184 , m_volumeName ( "Undefined Volume" )
00185 , m_volume ( 0 )
00186 , m_minx ( -10 * Gaudi::Units::m )
00187 , m_maxx ( 10 * Gaudi::Units::m )
00188 , m_miny ( -10 * Gaudi::Units::m )
00189 , m_maxy ( 10 * Gaudi::Units::m )
00190 , m_minz ( -10 * Gaudi::Units::m )
00191 , m_maxz ( 10 * Gaudi::Units::m )
00192 , m_shots ( 10000 )
00193 , m_vrtx ( 3 , 0 )
00194 , m_vertex ( )
00195 , m_checked ()
00196 {
00197 declareProperty ( "Volume" , m_volumeName ) ;
00198 declareProperty ( "MinX" , m_minx ) ;
00199 declareProperty ( "MinY" , m_miny ) ;
00200 declareProperty ( "MinZ" , m_minz ) ;
00201 declareProperty ( "MaxX" , m_maxx ) ;
00202 declareProperty ( "MaxY" , m_maxy ) ;
00203 declareProperty ( "MaxZ" , m_maxz ) ;
00204 declareProperty ( "Shots" , m_shots ) ;
00205 declareProperty ( "Null" , m_vrtx ) ;
00206 }
00207
00208
00209
00210
00211
00212
00213 StatusCode DetDesc::CheckOverlap::initialize()
00214 {
00215 StatusCode sc = GaudiAlgorithm::initialize() ;
00216 if ( sc.isFailure() ) { return sc ; }
00217
00218 Assert ( 0 != randSvc () , "randSvc() points to NULL!" ) ;
00219 Assert ( 0 != detSvc () , "detSvc() points to NULL!" ) ;
00220
00221 if ( !exist<ILVolume> ( detSvc() , m_volumeName ) &&
00222 exist<ILVolume> ( detSvc() , "/dd/Geometry/"+ m_volumeName ) )
00223 {
00224 m_volumeName = "/dd/Geometry/" + m_volumeName ;
00225 }
00226
00227 m_volume = getDet<ILVolume> ( m_volumeName ) ;
00228
00229
00230 if ( m_vrtx.size() <= 3 )
00231 { while ( 3 != m_vrtx.size() ) { m_vrtx.push_back( 0.0 ); } }
00232 else
00233 {
00234 warning() << " Ignore extra fields in 'ShootingPoint' "<< endreq ;
00235 }
00236 m_vertex.SetXYZ( m_vrtx[0], m_vrtx[1], m_vrtx[2] ) ;
00237
00238 if ( !m_volume->isAssembly() && 0 != m_volume->solid() )
00239 {
00240 const ISolid* top = m_volume->solid()->coverTop();
00241 if( 0 == top )
00242 { return Error( "CoverTop* points to NULL!" ) ; }
00243 const SolidBox* box = dynamic_cast<const SolidBox*> ( top );
00244 if( 0 == box )
00245 { return Error("SolidBox* points to NULL!"); }
00246
00247 m_minx = -1 * box->xHalfLength() * 1.05 ;
00248 m_maxx = box->xHalfLength() * 1.05 ;
00249 m_miny = -1 * box->yHalfLength() * 1.05 ;
00250 m_maxy = box->yHalfLength() * 1.05 ;
00251 m_minz = -1 * box->zHalfLength() * 1.05 ;
00252 m_maxz = box->zHalfLength() * 1.05 ;
00253 }
00254
00256 svc<ITransportSvc> ( "TransportSvc" , true ) ;
00257
00258 always() << " ATTENTION! THIS ALGORITHM DOES DESTROY THE GEOMETRY TREE" << endreq ;
00259 always() << " ATTENTION! NEVER USED IT IN THE REAL JOB OR RELY ON THE " << endreq ;
00260 always() << " ATTENTION! RESULT OF ANY OTHER 'GEOMETRY' TOOL/ALGORITHM" << endreq ;
00261
00262 return StatusCode::SUCCESS ;
00263 }
00264
00265
00266
00267
00268
00269
00270 StatusCode DetDesc::CheckOverlap::execute()
00271 {
00272 StatusCode sc = checkVolume ( m_volume , 0 ) ;
00273
00274 always() << " ATTENTION! THIS ALGORITHM DOES DESTROY THE GEOMETRY TREE" << endreq ;
00275 always() << " ATTENTION! NEVER USED IT IN THE REAL JOB OR RELY ON THE " << endreq ;
00276 always() << " ATTENTION! RESULT OF ANY OTHER 'GEOMETRY' TOOL/ALGORITHM" << endreq ;
00277
00278 return sc ;
00279 }
00280
00281
00282
00283 StatusCode DetDesc::CheckOverlap::checkVolume
00284 ( const ILVolume* volume ,
00285 const unsigned int level ) const
00286 {
00287 if ( 0 == volume ) { return Error ( "Invalid pointer to ILVolume!" ) ; }
00288
00289 boost::format fmt ( "%-3d") ;
00290 const std::string lev = ( fmt % level ).str() ;
00291
00292
00293 if ( m_checked.end() != m_checked.find ( volume ) )
00294 { return StatusCode::SUCCESS ; }
00295
00296
00297 always()
00298 << lev << std::string ( 2*level , ' ' )
00299 << "Checking: " << volume -> name () << endreq ;
00300
00301
00302
00303 const ILVolume::PVolumes& pvs = volume->pvolumes() ;
00304 for ( ILVolume::PVolumes::const_iterator ipv =
00305 pvs.begin() ; pvs.end() != ipv ; ++ipv )
00306 {
00307 const IPVolume* pv = *ipv ;
00308 if ( 0 == pv ) { return Error ( "IPVolume* points to NULL!" ) ; }
00309 const ILVolume* lv = pv->lvolume () ;
00310 if ( 0 == lv ) { return Error ( "ILVolume* points to NULL!" ) ; }
00311
00312 StatusCode sc = checkVolume ( lv , level + 1) ;
00313 if ( sc.isFailure() ) { return sc ; }
00314 }
00315
00316
00317
00318
00319 const StatusCode result = makeShots ( volume ) ;
00320
00321 {
00322
00323
00324 ILVolume* vol = const_cast<ILVolume*>( volume ) ;
00325 vol -> pvolumes().clear() ;
00326 }
00327
00328
00329 always()
00330 << lev << std::string ( 2*level , ' ' )
00331 << "Checked: " << volume -> name () << endreq ;
00332
00333 counter ("#volumes") += 1 ;
00334 if ( volume->isAssembly() ) { counter ("#assembly") += 1 ; }
00335
00336 m_checked.insert ( volume ) ;
00337
00338 return result ;
00339 }
00340
00341
00342
00343 StatusCode DetDesc::CheckOverlap::makeShots
00344 ( const ILVolume* volume ) const
00345 {
00346
00347 if ( 0 == volume )
00348 { return Error ( "Invalid pointer to ILVolume!" ) ; }
00349
00350
00351 DetDesc::IntersectionErrors::setCode ( StatusCode::SUCCESS , volume ) ;
00352
00353 typedef std::vector<Gaudi::XYZVector> Vectors ;
00354 Vectors vcts ;
00355
00356
00357 vcts.push_back ( Gaudi::XYZVector ( 0 , 0 , 1 ) ) ;
00358 vcts.push_back ( Gaudi::XYZVector ( 0 , 1 , 0 ) ) ;
00359 vcts.push_back ( Gaudi::XYZVector ( 1 , 0 , 0 ) ) ;
00360
00361 vcts.push_back ( Gaudi::XYZVector ( 1 , 1 , 0 ) ) ;
00362 vcts.push_back ( Gaudi::XYZVector ( 1 , -1 , 0 ) ) ;
00363 vcts.push_back ( Gaudi::XYZVector ( 0 , 1 , 1 ) ) ;
00364 vcts.push_back ( Gaudi::XYZVector ( 0 , -1 , 1 ) ) ;
00365
00366
00367 double xmin = m_minx ;
00368 double xmax = m_maxx ;
00369 double ymin = m_miny ;
00370 double ymax = m_maxy ;
00371 double zmin = m_minz ;
00372 double zmax = m_maxz ;
00373
00374 if ( !volume->isAssembly() && 0 != volume->solid() )
00375 {
00376 const ISolid* top = volume->solid()->coverTop();
00377 if( 0 == top ) { return Error ( "CoverTop* points to NULL!" ) ; }
00378 const SolidBox* box = dynamic_cast<const SolidBox*> ( top );
00379 if( 0 == box ) { return Error ("SolidBox* points to NULL!" ) ; }
00380
00381 xmin = -1 * box -> xHalfLength () * 1.01 ;
00382 xmax = box -> xHalfLength () * 1.01 ;
00383 ymin = -1 * box -> yHalfLength () * 1.01 ;
00384 ymax = box -> yHalfLength () * 1.01 ;
00385 zmin = -1 * box -> zHalfLength () * 1.01 ;
00386 zmax = box -> zHalfLength () * 1.01 ;
00387 }
00388
00389
00390 int nShots = m_shots ;
00391
00392
00393 if ( !volume ->isAssembly() && volume -> pvolumes().empty() )
00394 {
00395 const ISolid* solid = volume->solid() ;
00396 if ( 0 != solid && 0 != dynamic_cast<const SolidBox*> ( solid ) )
00397 {
00398
00399 nShots = 0 ;
00400 return StatusCode::SUCCESS ;
00401 }
00402 }
00403
00404 {
00405 boost::format fmt ( "Shooting #%8d:") ;
00406 info () << ( fmt % nShots ).str()
00407 << volume -> name ()
00408 << " #pv=" << volume->pvolumes().size()
00409 << endreq ;
00410 }
00411
00412
00413 boost::progress_display progress ( nShots ) ;
00414
00415
00416 Rndm::Numbers flat ( randSvc() , Rndm::Flat ( 0.0 , 1.0 ) );
00417 Rndm::Numbers flat1 ( randSvc() , Rndm::Flat ( -1.0 , 1.0 ) );
00418
00419 for ( int iShoot = 0 ; iShoot < nShots ; ++iShoot )
00420 {
00421
00422 const double x1 = xmin + flat.shoot() * ( xmax - xmin ) ;
00423 const double y1 = ymin + flat.shoot() * ( ymax - ymin ) ;
00424 const double z1 = zmin + flat.shoot() * ( zmax - zmin ) ;
00425
00426 const double x2 = xmin + flat.shoot() * ( xmax - xmin ) ;
00427 const double y2 = ymin + flat.shoot() * ( ymax - ymin ) ;
00428 const double z2 = zmin + flat.shoot() * ( zmax - zmin ) ;
00429
00430 Gaudi::XYZPoint point ( x1 , y1 , z1 ) ;
00431 Gaudi::XYZPoint p2 ( x2 , y2 , z2 ) ;
00432
00433 vcts.push_back ( p2 - point ) ;
00434 vcts.push_back ( m_vertex - point ) ;
00435 vcts.push_back ( m_vertex - point ) ;
00436
00437 vcts.push_back ( Gaudi::XYZVector ( flat1() , flat1() , flat1() ) ) ;
00438 vcts.push_back ( Gaudi::XYZVector ( flat1() , flat1() , flat1() ) ) ;
00439 vcts.push_back ( Gaudi::XYZVector ( flat1() , flat1() , flat1() ) ) ;
00440
00441 vcts.push_back ( Gaudi::XYZVector ( 0 , 0 , 1 + 0.1 * flat1() ) ) ;
00442 vcts.push_back ( Gaudi::XYZVector ( 0 , 1 + 0.1 * flat1() , 0 ) ) ;
00443 vcts.push_back ( Gaudi::XYZVector ( 1 + 0.1 * flat1() , 0 , 0 ) ) ;
00444
00445 vcts.push_back ( Gaudi::XYZVector ( 0 , 0 , 1 + 0.1 * flat1() ) ) ;
00446 vcts.push_back ( Gaudi::XYZVector ( 0 , 1 + 0.1 * flat1() , 0 ) ) ;
00447 vcts.push_back ( Gaudi::XYZVector ( 1 + 0.1 * flat1() , 0 , 0 ) ) ;
00448
00449 for ( Vectors::const_iterator iv = vcts.begin() ; vcts.end() != iv ; ++iv )
00450 {
00451
00452 DetDesc::IntersectionErrors::setCode ( StatusCode::SUCCESS , volume ) ;
00453
00454 ILVolume::Intersections intersections;
00455 volume -> intersectLine ( point , *iv , intersections , 0 );
00456
00457
00458 StatusCode sc = DetDesc::IntersectionErrors::code() ;
00459
00460 if ( sc.isFailure() )
00461 {
00462
00463 error() << "Problem is detected with volume "
00464 << volume->name ()
00465 << " With P/V="
00466 << point << "/" << (*iv) << endreq ;
00467
00468 DetDesc::IntersectionErrors::inspect
00469 ( volume , point , *iv , intersections ) ;
00470
00471 return Error ( "Intersection problems with " + volume->name() , sc ) ;
00472 }
00473 }
00474
00475 while ( 7 < vcts.size() ) { vcts.pop_back() ; }
00476
00477 ++progress ;
00478 }
00479
00480 return StatusCode::SUCCESS ;
00481 }
00482
00483
00484
00485
00486
00487
00488 StatusCode DetDesc::CheckOverlap::finalize ()
00489 {
00490 always () << " ATTENTION! THIS ALGORITHM DOES DESTROY THE GEOMETRY TREE" << endreq ;
00491 always () << " ATTENTION! NEVER USED IT IN THE REAL JOB OR RELY ON THE " << endreq ;
00492 always () << " ATTENTION! RESULT OF ANY OTHER 'GEOMETRY' TOOL/ALGORITHM" << endreq ;
00493
00494 return GaudiAlgorithm::finalize () ;
00495 }
00496
00498 DECLARE_NAMESPACE_ALGORITHM_FACTORY(DetDesc,CheckOverlap);
00499
00500
00501
00502
00503
00504
00505