00001
00002
00003 #ifndef DETDESC_SOLIDTICKS_H
00004 #define DETDESC_SOLIDTICKS_H 1
00006 #include <cmath>
00007 #include <functional>
00008 #include <algorithm>
00009
00010 #include "GaudiKernel/Point3DTypes.h"
00011 #include "GaudiKernel/Vector3DTypes.h"
00012 #include "GaudiKernel/Plane3DTypes.h"
00013
00014 #include "DetDesc/ISolid.h"
00015 #include "DetDesc/SolidMath.h"
00016
00036 namespace SolidTicks
00037 {
00038
00049 template <class SOLID, class aPoint, class aVector>
00050 inline unsigned int
00051 RemoveAdjancent
00052 ( ISolid::Ticks & ticks ,
00053 const aPoint & point ,
00054 const aVector & vect ,
00055 const SOLID & solid )
00056 {
00057
00058 typedef std::vector<size_t> Indexes ;
00059 typedef ISolid::Tick Tick ;
00060 typedef ISolid::Ticks::iterator iterator ;
00061
00062 if ( ticks.size() < 2 ) { ticks.clear() ; return 0 ; }
00063 else if( ticks.size() == 2 )
00064 {
00065 Tick tick1 = ticks.front () ;
00066 Tick tick2 = ticks.back () ;
00067 Tick tick = 0.5 * ( tick1 + tick2 ) ;
00068 if( solid.isInside( point + vect * tick ) ) { return 2 ; }
00069 else { ticks.clear() ; return 0 ; }
00070 }
00071
00072 Indexes tmp ;
00073 Tick tickNext = 0.0 ;
00074 Tick tickPrev = 0.0 ;
00075 bool boolPrev = true ;
00076 bool boolNext = true ;
00077 for ( iterator it = ticks.begin() ; it != ticks.end() ; ++it )
00078 {
00079
00080 if ( ticks.end () != it + 1 )
00081 { tickNext = 0.5 * ( (*it) + *(it+1) ) ;
00082 boolNext = solid.isInside( point + vect * tickNext ); }
00083
00084 unsigned int index = it - ticks.begin();
00088 if ( ticks.end () == it + 1 )
00089 { if( !boolPrev ) { tmp.push_back( index ) ; } }
00093 else if ( ticks.begin() == it )
00094 { if( !boolNext ) { tmp.push_back( index ) ; } }
00098 else
00099 { if( boolPrev == boolNext ) { tmp.push_back( index ) ; } }
00101 boolPrev = boolNext;
00102 tickPrev = tickNext;
00103 }
00104
00105 Indexes::reverse_iterator cri = tmp.rbegin();
00106 while( cri != tmp.rend() ) { ticks.erase( ticks.begin() + *cri++ ); }
00107
00108 return ticks.size();
00109 };
00110
00121 template <class SOLID, class aPoint, class aVector>
00122 inline unsigned int
00123 RemoveAdjancentTicks
00124 ( ISolid::Ticks & ticks ,
00125 const aPoint & point ,
00126 const aVector & vect ,
00127 const SOLID & solid )
00128 {
00129
00130 typedef ISolid::Tick Tick ;
00131 typedef ISolid::Ticks::iterator iterator ;
00132
00133 std::sort( ticks.begin() , ticks.end() ) ;
00134
00135 ticks.erase( std::unique( ticks.begin() , ticks.end() ) , ticks.end() );
00136
00137 return RemoveAdjancent( ticks , point , vect , solid );
00138 };
00139
00140
00155 template <class SOLID, class aPoint, class aVector>
00156 inline unsigned int
00157 RemoveAdjancentTicks
00158 ( ISolid::Ticks & ticks ,
00159 const aPoint & point ,
00160 const aVector & vect ,
00161 const ISolid::Tick & tickMin ,
00162 const ISolid::Tick & tickMax ,
00163 const SOLID & solid )
00164 {
00165
00166 typedef ISolid::Tick Tick ;
00167 typedef ISolid::Ticks::iterator iterator ;
00168
00169 if( tickMin >= tickMax ) { ticks.clear(); return 0 ; }
00170
00171 iterator itMin =
00172 std::remove_if( ticks.begin () ,
00173 ticks.end () ,
00174 std::bind2nd( std::less<Tick> () , tickMin ) );
00175
00176 iterator itMax =
00177 std::remove_if( ticks.begin () ,
00178 itMin ,
00179 std::bind2nd( std::greater<Tick> () , tickMax ) );
00180 ticks.erase ( itMax , ticks.end() ) ;
00181
00182
00183 if( ticks.empty() )
00184 {
00185 const Tick middle = 0.5 * ( tickMin + tickMax ) ;
00186 if( solid.isInside( point + middle * vect ) )
00187 {
00188 ticks.push_back( tickMin ) ;
00189 ticks.push_back( tickMax ) ;
00190 }
00191 return ticks.size() ;
00192 }
00193
00194
00195 if( ticks.front () != tickMin )
00196 {
00197 const Tick middle = 0.5 * ( tickMin + ticks.front() ) ;
00198 if( solid.isInside ( point + middle * vect ) )
00199 { ticks.insert ( ticks.begin() , tickMin ) ; }
00200 }
00201
00202
00203 if( ticks.back () != tickMax )
00204 {
00205 const Tick middle = 0.5 * ( ticks.back() + tickMax ) ;
00206 if( solid.isInside ( point + middle * vect ) )
00207 { ticks.push_back ( tickMax ) ; }
00208 }
00209
00210 return ticks.size () ;
00211 };
00212
00228 template <class SOLID, class aPoint, class aVector, class TickContainer>
00229 inline unsigned int RemoveAdjacentTicksFast ( TickContainer & ticks ,
00230 const aPoint & point ,
00231 const aVector & vect ,
00232 const SOLID & solid )
00233 {
00234
00235 typename TickContainer::iterator newend = std::unique( ticks.begin() , ticks.end() ) ;
00236 if( newend != ticks.end() || ticks.size()%2 != 0 ) {
00237 ticks.erase( newend, ticks.end()) ;
00238 RemoveAdjancent( ticks , point , vect , solid );
00239 }
00240 return ticks.size() ;
00241 } ;
00242
00254 template <class TickContainer>
00255 unsigned int adjustToTickRange( TickContainer& ticks, const ISolid::Tick & tickMin, const ISolid::Tick & tickMax )
00256 {
00257
00258 typedef ISolid::Tick Tick ;
00259 typedef ISolid::Ticks::iterator iterator ;
00260 if( !ticks.empty() ) {
00261 static ISolid::Ticks validticks ; validticks.clear() ;
00262
00263 for( typename TickContainer::const_iterator it = ticks.begin() ; it+1 < ticks.end(); it +=2)
00264 if( *it <= tickMax && *(it+1) >= tickMin ) {
00265 validticks.push_back( std::max( tickMin, *it) ) ;
00266 validticks.push_back( std::min( tickMax, *(it+1)) ) ;
00267 }
00268 ticks.swap(validticks) ;
00269 }
00270 return ticks.size () ;
00271 };
00272
00273 };
00274
00275
00276
00277
00278 #endif
00279 // ============================================================================
00280
00281
00282
00283
00284
00285