From 0263ae480120e8a062d4e41a6aa5f03a69a9a4d9 Mon Sep 17 00:00:00 2001 From: Frank Gaede <frank.gaede@desy.de> Date: Thu, 15 Oct 2015 13:04:18 +0000 Subject: [PATCH] - added implemation of conical surfaces - ICone, VolConeImpl, VolCone, ConeSurface --- DDRec/include/DDRec/Surface.h | 96 ++++++++++-- DDRec/src/DetectorSurfaces.cpp | 11 +- DDRec/src/Surface.cpp | 185 +++++++++++++++++++++-- DDSurfaces/include/DDSurfaces/ISurface.h | 45 +++++- DDSurfaces/include/DDSurfaces/Vector3D.h | 17 +-- 5 files changed, 318 insertions(+), 36 deletions(-) diff --git a/DDRec/include/DDRec/Surface.h b/DDRec/include/DDRec/Surface.h index cfb96df1f..2a3481c97 100644 --- a/DDRec/include/DDRec/Surface.h +++ b/DDRec/include/DDRec/Surface.h @@ -53,6 +53,8 @@ namespace DD4hep { virtual void setV(const Vector3D& v) ; /// setter for daughter classes virtual void setNormal(const Vector3D& n) ; + /// setter for daughter classes + virtual void setOrigin(const Vector3D& o) ; public: @@ -354,6 +356,7 @@ namespace DD4hep { _type.setProperty( SurfaceType::Plane , true ) ; _type.setProperty( SurfaceType::Cylinder , false ) ; + _type.setProperty( SurfaceType::Cone , false ) ; _type.checkParallelToZ( *this ) ; _type.checkOrthogonalToZ( *this ) ; } @@ -382,7 +385,6 @@ namespace DD4hep { */ VolCylinderImpl( Geometry::Volume vol, SurfaceType type, double thickness_inner ,double thickness_outer, Vector3D origin ) ; - /** First direction of measurement U - rotated to point projected onto the cylinder. * No check is done whether the point actually is on the cylinder surface */ @@ -396,13 +398,62 @@ namespace DD4hep { /** Distance to surface */ virtual double distance(const Vector3D& point ) const ; - /** Convert the global position to the local position (u,v) on the surface - u runs along the axis of the cylinder, v is r*phi */ + /** Convert the global position to the local position (u,v) on the surface - v runs along the axis of the cylinder, u is r*phi */ virtual Vector2D globalToLocal( const Vector3D& point) const ; - /** Convert the local position (u,v) on the surface to the global position - u runs along the axis of the cylinder, v is r*phi*/ + /** Convert the local position (u,v) on the surface to the global position - v runs along the axis of the cylinder, u is r*phi*/ virtual Vector3D localToGlobal( const Vector2D& point) const ; } ; + //====================================================================================================== + /** Implementation of conical surface attached to a volume + * @author F.Gaede, DESY + * @date Nov, 6 2015 + * @version $Id$ + */ + class VolConeImpl : public VolSurfaceBase { + + public: + + /// default c'tor + VolConeImpl() : VolSurfaceBase() { } + + + /** The standard constructor. The origin vector points to the origin of the coordinate system on the cone, + * its rho defining the mean radius of the cone (z-component of the origin is ignored !). + * The measurement direction v defines the opening angle of the cone, + * the normal is chosen to be orthogonal to v. NB: the cone is always parallel to the local z axis. + */ + VolConeImpl( Geometry::Volume vol, SurfaceType type, double thickness_inner ,double thickness_outer, + Vector3D v, Vector3D origin ) ; + + /** First direction of measurement U - rotated to point projected onto the cone. + * No check is done whether the point actually is on the cone surface + */ + virtual Vector3D u( const Vector3D& point = Vector3D() ) const ; + + /** Second direction of measurement V - rotated to point projected onto the cone. + * No check is done whether the point actually is on the cone surface + */ + virtual Vector3D v( const Vector3D& point = Vector3D() ) const ; + + /** The normal direction at the given point, projected onto the cone. + * No check is done whether the point actually is on the cone surface + */ + virtual Vector3D normal(const Vector3D& point = Vector3D() ) const ; + + /** Distance to surface */ + virtual double distance(const Vector3D& point ) const ; + + /** Convert the global position to the local position (u,v) on the surface - v runs along the axis of the cone, u is r*phi */ + virtual Vector2D globalToLocal( const Vector3D& point) const ; + + /** Convert the local position (u,v) on the surface to the global position - v runs along the axis of the cone, u is r*phi*/ + virtual Vector3D localToGlobal( const Vector2D& point) const ; + + virtual std::vector< std::pair<DDSurfaces::Vector3D, DDSurfaces::Vector3D> > getLines(unsigned nMax=100) ; + } ; + //====================================================================================================== @@ -436,6 +487,12 @@ namespace DD4hep { VolSurface( new VolCylinderImpl( vol, type, thickness_inner , thickness_outer, origin ) ) {} } ; + class VolCone : public VolSurface{ + public: + VolCone( Geometry::Volume vol, SurfaceType type, double thickness_inner ,double thickness_outer, Vector3D v, Vector3D origin ) : + VolSurface( new VolConeImpl( vol, type, thickness_inner , thickness_outer, v, origin ) ) {} + } ; + //====================================================================================================== /** Implementation of Surface class holding a local surface attached to a volume and the DetElement @@ -539,12 +596,6 @@ namespace DD4hep { */ virtual double length_along_v() const ; - //--------------------------------------------------- - /** Get vertices constraining the surface for drawing ( might not be exact boundaries) - - * at most nMax points are returned. - */ - // std::vector< Vector3D > getVertices( unsigned nMax=360 ) ; - /** Get lines constraining the surface for drawing ( might not be exact boundaries) - * at most nMax lines are returned. */ @@ -596,10 +647,33 @@ namespace DD4hep { /// the center of the cylinder virtual Vector3D center() const ; - - } ; + //====================================================================================================== + + /** Specialization of Surface for cones - specializes CyliderSurface (for lazyness ...) + * @author F.Gaede, DESY + * @date May, 10 2014 + */ + class ConeSurface : public CylinderSurface, public ICone { + public: + ConeSurface( Geometry::DetElement det, VolSurface volSurf ) : CylinderSurface( det, volSurf ) { } + + /// the start radius of the cone + virtual double radius0() const ; + + /// the end radius of the cone + virtual double radius1() const ; + /// the start z of the cone + virtual double z0() const ; + + /// the end z of the cone + virtual double z1() const ; + + /// the center of the cone + virtual Vector3D center() const ; + + }; //====================================================================================================== /** std::list of Surfaces that optionally takes ownership. * @author F.Gaede, DESY diff --git a/DDRec/src/DetectorSurfaces.cpp b/DDRec/src/DetectorSurfaces.cpp index 632021ab4..1885133b7 100644 --- a/DDRec/src/DetectorSurfaces.cpp +++ b/DDRec/src/DetectorSurfaces.cpp @@ -43,8 +43,17 @@ namespace DD4hep { VolSurface volSurf = *it ; - Surface* surf = ( volSurf.type().isCylinder() ? new CylinderSurface( det, volSurf ) : new Surface( det, volSurf ) ) ; + Surface* surf = 0 ; + if( volSurf.type().isCylinder() ) + surf = new CylinderSurface( det, volSurf ) ; + + else if( volSurf.type().isCone() ) + surf = new ConeSurface( det, volSurf ) ; + + else + surf = new Surface( det, volSurf ) ; + // std::cout << " ------------------------- " // << " surface: " << *surf << std::endl // << " ------------------------- " << std::endl ; diff --git a/DDRec/src/Surface.cpp b/DDRec/src/Surface.cpp index 65d146bf7..7f22f0a71 100644 --- a/DDRec/src/Surface.cpp +++ b/DDRec/src/Surface.cpp @@ -25,6 +25,7 @@ namespace DD4hep { void VolSurfaceBase::setU(const Vector3D& u_val) { _u = u_val ; } void VolSurfaceBase::setV(const Vector3D& v_val) { _v = v_val ; } void VolSurfaceBase::setNormal(const Vector3D& n) { _n = n ; } + void VolSurfaceBase::setOrigin(const Vector3D& o) { _o = o ; } long64 VolSurfaceBase::id() const { return _id ; } @@ -268,6 +269,7 @@ namespace DD4hep { _type.setProperty( SurfaceType::Plane , false ) ; _type.setProperty( SurfaceType::Cylinder , true ) ; + _type.setProperty( SurfaceType::Cone , false ) ; _type.checkParallelToZ( *this ) ; _type.checkOrthogonalToZ( *this ) ; } @@ -316,7 +318,140 @@ namespace DD4hep { } //================================================================================================================ + VolConeImpl::VolConeImpl( Geometry::Volume vol, SurfaceType typ, + double thickness_inner ,double thickness_outer, Vector3D v, Vector3D o ) : + + VolSurfaceBase(typ, thickness_inner, thickness_outer, Vector3D() , v , Vector3D() , Vector3D() , vol, 0) { + + Vector3D o_rphi( o.x() , o.y() , 0. ) ; + + // sanity check: v and o have to have a common phi + double dphi = v.phi() - o_rphi.phi() ; + while( dphi < -M_PI ) dphi += 2.*M_PI ; + while( dphi > M_PI ) dphi -= 2.*M_PI ; + + if( std::fabs( dphi ) > 1e-6 ){ + std::stringstream sst ; sst << "VolConeImpl::VolConeImpl() - incompatibel vector v and o given " + << v << " - " << o ; + throw std::runtime_error( sst.str() ) ; + } + + Vector3D n( 1. , v.phi() , ( v.theta() + M_PI/2. ) , Vector3D::spherical ) ; + Vector3D u = v.cross( n ) ; + + setU( u ) ; + setOrigin( o_rphi ) ; + setNormal( n ) ; + + _type.setProperty( SurfaceType::Plane , false ) ; + _type.setProperty( SurfaceType::Cylinder, false ) ; + _type.setProperty( SurfaceType::Cone , true ) ; + _type.setProperty( SurfaceType::ParallelToZ, true ) ; + _type.setProperty( SurfaceType::OrthogonalToZ, false ) ; + } + + Vector3D VolConeImpl::v(const Vector3D& point ) const { + // just take phi from point + Vector3D av( 1. , point.phi() , _v.theta() , Vector3D::spherical ) ; + return av ; + } + + Vector3D VolConeImpl::u(const Vector3D& point ) const { + // compute from v X n + const Vector3D& av = this->v( point ) ; + const Vector3D& n = normal( point ) ; + return av.cross( n ) ; + } + + Vector3D VolConeImpl::normal(const Vector3D& point ) const { + // just take phi from point + Vector3D n( 1. , point.phi() , _n.theta() , Vector3D::spherical ) ; + return n ; + } + + Vector2D VolConeImpl::globalToLocal( const Vector3D& point) const { + + // cone is parallel to z here, so u is r *Phi and v is "along" z + double phi = point.phi() - origin().phi() ; + + while( phi < -M_PI ) phi += 2.*M_PI ; + while( phi > M_PI ) phi -= 2.*M_PI ; + + return Vector2D( origin().rho()*phi, ( point.z() - origin().z() ) / cos( _v.theta() ) ) ; + } + + + Vector3D VolConeImpl::localToGlobal( const Vector2D& point) const { + + double z = point.v() * cos( _v.theta() ) + origin().z() ; + + double phi = point.u() / origin().rho() + origin().phi() ; + + while( phi < -M_PI ) phi += 2.*M_PI ; + while( phi > M_PI ) phi -= 2.*M_PI ; + + return Vector3D( origin().rho() , phi, z , Vector3D::cylindrical ) ; + } + + + /** Distance to surface */ + double VolConeImpl::distance(const Vector3D& point ) const { + + //fixme: there are probably faster ways to compute this + // e.g by using the intercept theorem - tbd. ... + const Vector2D& lp = globalToLocal( point ) ; + const Vector3D& gp = localToGlobal( lp ) ; + + Vector3D dz = point - gp ; + + return dz * normal( point ) ; + } + + /// create outer bounding lines for the given symmetry of the polyhedron + std::vector< std::pair<DDSurfaces::Vector3D, DDSurfaces::Vector3D> > VolConeImpl::getLines(unsigned nMax){ + + std::vector< std::pair<DDSurfaces::Vector3D, DDSurfaces::Vector3D> > lines ; + + lines.reserve( nMax ) ; + + double theta = v().theta() ; + double half_length = 0.5 * length_along_v() * cos( theta ) ; + + Vector3D zv( 0. , 0. , half_length ) ; + + double dr = half_length * tan( theta ) ; + + double r0 = origin().rho() - dr ; + double r1 = origin().rho() + dr ; + + + unsigned n = nMax / 4 ; + double dPhi = 2.* ROOT::Math::Pi() / double( n ) ; + + for( unsigned i = 0 ; i < n ; ++i ) { + + Vector3D r0v0( r0*sin( i *dPhi ) , r0*cos( i *dPhi ) , 0. ) ; + Vector3D r0v1( r0*sin( (i+1)*dPhi ) , r0*cos( (i+1)*dPhi ) , 0. ) ; + + Vector3D r1v0( r1*sin( i *dPhi ) , r1*cos( i *dPhi ) , 0. ) ; + Vector3D r1v1( r1*sin( (i+1)*dPhi ) , r1*cos( (i+1)*dPhi ) , 0. ) ; + + Vector3D pl0 = zv + r1v0 ; + Vector3D pl1 = zv + r1v1 ; + Vector3D pl2 = -zv + r0v1 ; + Vector3D pl3 = -zv + r0v0 ; + + lines.push_back( std::make_pair( pl0, pl1 ) ) ; + lines.push_back( std::make_pair( pl1, pl2 ) ) ; + lines.push_back( std::make_pair( pl2, pl3 ) ) ; + lines.push_back( std::make_pair( pl3, pl0 ) ) ; + } + return lines; + } + + //================================================================================================================ + VolSurfaceList::~VolSurfaceList(){ // // delete all surfaces attached to this volume @@ -527,7 +662,6 @@ namespace DD4hep { Vector3D localPoint( pa ) ; return _volSurf.distance( localPoint ) ; - //FG return ( _volSurf.type().isPlane() ? VolPlane(_volSurf).distance( localPoint ) : VolCylinder(_volSurf).distance( localPoint ) ) ; } bool Surface::insideBounds(const Vector3D& point, double epsilon) const { @@ -537,8 +671,6 @@ namespace DD4hep { Vector3D localPoint( pa ) ; return _volSurf.insideBounds( localPoint , epsilon) ; - - //FG return ( _volSurf.type().isPlane() ? VolPlane(_volSurf).insideBounds( localPoint, epsilon ) : VolCylinder(_volSurf).insideBounds( localPoint , epsilon) ) ; } void Surface::initialize() { @@ -554,11 +686,6 @@ namespace DD4hep { throw std::runtime_error( sst.str() ) ; } - // std::cout << " **** Surface::initialize() # placements for surface = " << pVList.size() - // << " worldTransform : " - // << std::endl ; - - //=========== compute and cache world transform for surface ========== const TGeoHMatrix& wm = _det.worldTransformation() ; @@ -674,8 +801,8 @@ namespace DD4hep { for( unsigned i=0;i<n;++i){ DDSurfaces::Vector3D av,bv; - _wtM->LocalToMasterVect( local_lines[i].first , av.array() ) ; - _wtM->LocalToMasterVect( local_lines[i].second , bv.array() ) ; + _wtM->LocalToMaster( local_lines[i].first , av.array() ) ; + _wtM->LocalToMaster( local_lines[i].second , bv.array() ) ; lines.push_back( std::make_pair( av, bv ) ); } @@ -1075,6 +1202,44 @@ namespace DD4hep { //================================================================================================================ + + double ConeSurface::radius0() const { + + double theta = _volSurf.v().theta() ; + double l = length_along_v() * cos( theta ) ; + + return origin().rho() - 0.5 * l * tan( theta ) ; + } + + double ConeSurface::radius1() const { + + double theta = _volSurf.v().theta() ; + double l = length_along_v() * cos( theta ) ; + + return origin().rho() + 0.5 * l * tan( theta ) ; + } + + double ConeSurface::z0() const { + + double theta = _volSurf.v().theta() ; + double l = length_along_v() * cos( theta ) ; + + return origin().z() - 0.5 * l ; + } + + double ConeSurface::z1() const { + + double theta = _volSurf.v().theta() ; + double l = length_along_v() * cos( theta ) ; + + return origin().z() + 0.5 * l ; + } + + Vector3D ConeSurface::center() const { return volumeOrigin() ; } + + + //================================================================================================================ + } // namespace } // namespace diff --git a/DDSurfaces/include/DDSurfaces/ISurface.h b/DDSurfaces/include/DDSurfaces/ISurface.h index 5c37a7cc2..38d7bfdc5 100644 --- a/DDSurfaces/include/DDSurfaces/ISurface.h +++ b/DDSurfaces/include/DDSurfaces/ISurface.h @@ -98,6 +98,23 @@ namespace DDSurfaces { virtual double radius() const=0 ; virtual Vector3D center() const=0 ; }; + //============================================================================================== + /** Minimal interface to provide acces to radii of conical surfaces. + * @author F. Gaede, DESY + * @version $Id$ + * @date Nov 6 2015 + */ + class ICone { + + public: + /// Destructor + virtual ~ICone() {} + virtual double radius0() const=0 ; + virtual double radius1() const=0 ; + virtual double z0() const=0 ; + virtual double z1() const=0 ; + virtual Vector3D center() const=0 ; + }; //============================================================================================== @@ -120,7 +137,8 @@ namespace DDSurfaces { ParallelToZ, OrthogonalToZ, Invisible, - Measurement1D + Measurement1D, + Cone } ; ///default c'tor @@ -176,6 +194,9 @@ namespace DDSurfaces { /// true if this a cylindrical surface bool isCylinder() const { return _bits[ SurfaceType::Cylinder ] ; } + /// true if this a conical surface + bool isCone() const { return _bits[ SurfaceType::Cone ] ; } + /// true if surface is parallel to Z bool isParallelToZ() const { return _bits[ SurfaceType::ParallelToZ ] ; } @@ -188,6 +209,9 @@ namespace DDSurfaces { /// true if this is a cylinder parallel to Z bool isZCylinder() const { return ( _bits[ SurfaceType::Cylinder ] && _bits[ SurfaceType::ParallelToZ ] ) ; } + /// true if this is a cone parallel to Z + bool isZCone() const { return ( _bits[ SurfaceType::Cone ] && _bits[ SurfaceType::ParallelToZ ] ) ; } + /// true if this is a plane parallel to Z bool isZPlane() const { return ( _bits[ SurfaceType::Plane ] && _bits[ SurfaceType::ParallelToZ ] ) ; } @@ -246,9 +270,17 @@ namespace DDSurfaces { /// dump SurfaceType operator inline std::ostream& operator<<( std::ostream& os , const SurfaceType& t ) { - os << "sensitive[" << t.isSensitive() << "] helper[" << t.isHelper() << "] plane[" << t.isPlane() << "] cylinder[" << t.isCylinder() - << "] parallelToZ[" << t.isParallelToZ() << "] orthogonalToZ[" << t. isOrthogonalToZ() << "] zCylinder[" << t.isZCylinder() - << "] zPlane[" << t.isZPlane() << "] zDisk[" << t.isZDisk() << "]" ; + os << "sensitive[" << t.isSensitive() + << "] helper[" << t.isHelper() + << "] plane[" << t.isPlane() + << "] cylinder[" << t.isCylinder() + << "] cone[" << t.isCone() + << "] parallelToZ[" << t.isParallelToZ() + << "] orthogonalToZ[" << t.isOrthogonalToZ() + << "] zCylinder[" << t.isZCylinder() + << "] zCone[" << t.isZCone() + << "] zPlane[" << t.isZPlane() + << "] zDisk[" << t.isZDisk() << "]" ; return os ; } @@ -264,10 +296,13 @@ namespace DDSurfaces { << " outerMaterial : " << s.outerMaterial() << " thickness: " << s.outerThickness() << std::endl ; const ICylinder* cyl = dynamic_cast< const ICylinder* > ( &s ) ; - if( cyl ) os << " cylinder radius : " << cyl->radius() << std::endl ; + const ICone* cone = dynamic_cast< const ICone* > ( &s ) ; + if( cone ) + os << " cone radius0: " << cone->radius0() << " cone radius1: " << cone->radius1() << std::endl ; + return os ; } diff --git a/DDSurfaces/include/DDSurfaces/Vector3D.h b/DDSurfaces/include/DDSurfaces/Vector3D.h index 819de8b88..23a826e30 100644 --- a/DDSurfaces/include/DDSurfaces/Vector3D.h +++ b/DDSurfaces/include/DDSurfaces/Vector3D.h @@ -344,15 +344,14 @@ namespace DDSurfaces { /** Output operator */ inline std::ostream & operator << (std::ostream & os, const Vector3D &v) { - os << "( " << v[0] << ", " << v[1] << ", " << v[2] << " )" ; - - // os << " ( " << v[0] - // << ", " << v[1] - // << ", " << v[2] - // << " ) - [ phi: " << v.phi() - // << " , rho: " << v.rho() << " ] " - // << " [ theta: " << v.theta() - // << " , r: " << v.r() << " ] " ; + // os << "( " << v[0] << ", " << v[1] << ", " << v[2] << " )" ; + os << " ( " << v[0] + << ", " << v[1] + << ", " << v[2] + << " ) - [ phi: " << v.phi() + << " , rho: " << v.rho() << " ] " + << " [ theta: " << v.theta() + << " , r: " << v.r() << " ] " ; return os ; } -- GitLab