Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-07-11 08:29:57

0001 //==========================================================================
0002 //  AIDA Detector description implementation 
0003 //--------------------------------------------------------------------------
0004 // Copyright (C) Organisation europeenne pour la Recherche nucleaire (CERN)
0005 // All rights reserved.
0006 //
0007 // For the licensing terms see $DD4hepINSTALL/LICENSE.
0008 // For the list of contributors see $DD4hepINSTALL/doc/CREDITS.
0009 //
0010 // Author     : M.Frank
0011 //
0012 //==========================================================================
0013 #ifndef DD4HEP_VOLUMES_H
0014 #define DD4HEP_VOLUMES_H
0015 
0016 // Framework include files
0017 #include <DD4hep/Handle.h>
0018 #include <DD4hep/Shapes.h>
0019 #include <DD4hep/Objects.h>
0020 #include <DD4hep/BitField64.h>
0021 
0022 // C/C++ include files
0023 #include <string>
0024 #include <utility>
0025 #include <vector>
0026 
0027 // ROOT include file (includes TGeoVolume + TGeoShape)
0028 #include <TGeoNode.h>
0029 #include <TGeoPatternFinder.h>
0030 #include <TGeoExtension.h>
0031 
0032 /// Namespace for the AIDA detector description toolkit
0033 namespace dd4hep {
0034 
0035   class  Detector;
0036   class  Region;
0037   class  LimitSet;
0038   class  Material;
0039   class  VisAttr;
0040   class  DetElement;
0041   class  SensitiveDetector;
0042 
0043   // Forward declarations
0044   class  Volume;
0045   class  PlacedVolume;
0046 
0047   /// Scan geometry and create reflected volumes
0048   /**
0049    *   Build reflections the ROOT way. 
0050    *   To be called once the geometry is closed.
0051    *   This entity can only be invoked once.
0052    *
0053    *   For any further documentation please see the following ROOT documentation:
0054    *   \see http://root.cern.ch/root/html/TGeoManager.html
0055    *
0056    *   \author  M.Frank
0057    *   \version 1.0
0058    *   \ingroup DD4HEP_CORE
0059    */
0060   class  ReflectionBuilder   {
0061     Detector& detector;
0062   public:
0063     /// Initializing constructor
0064     ReflectionBuilder(Detector& desc) : detector(desc) {}
0065     /// Default descructor
0066     ~ReflectionBuilder() = default;
0067     /// Perform scan
0068     void execute()  const;
0069   };
0070     
0071   /// Implementation class extending the ROOT placed volume
0072   /**
0073    *   For any further documentation please see the following ROOT documentation:
0074    *   \see http://root.cern.ch/root/html/TGeoExtension.html
0075    *
0076    *   \author  M.Frank
0077    *   \version 1.0
0078    *   \ingroup DD4HEP_CORE
0079    */
0080   class PlacedVolumeExtension : public TGeoExtension  {
0081   public:
0082     typedef std::pair<std::string, int> VolID;
0083     /// Volume ID container
0084     /**
0085      *   \author  M.Frank
0086      *   \version 1.0
0087      *   \ingroup DD4HEP_CORE
0088      */
0089     class VolIDs: public std::vector<VolID> {
0090     public:
0091       typedef std::vector<VolID> Base;
0092       /// Default constructor
0093       VolIDs() = default;
0094       /// Move constructor
0095       VolIDs(VolIDs&& copy) = default;
0096       /// Copy constructor
0097       VolIDs(const VolIDs& copy) = default;
0098       /// Move assignment
0099       VolIDs& operator=(VolIDs&& copy)  = default;
0100       /// Assignment operator
0101       VolIDs& operator=(const VolIDs& c)  = default;
0102       /// Find entry
0103       std::vector<VolID>::const_iterator find(const std::string& name) const;
0104       /// Insert new entry
0105       std::pair<std::vector<VolID>::iterator, bool> insert(const std::string& name, int value);
0106       /// Insert bunch of entries
0107       template< class InputIt>
0108       iterator insert(InputIt first, InputIt last)
0109       {  return this->Base::insert(this->Base::end(), first, last);    }
0110 #if !defined __GNUCC__ || (defined __GNUCC__ && __GNUC__ > 5)
0111       /// Insert bunch of entries
0112       template< class InputIt>
0113       iterator insert(std::vector<VolID>::const_iterator pos, InputIt first, InputIt last)
0114       {  return this->Base::insert(pos, first, last);    }
0115 #endif
0116       /// String representation for debugging
0117       std::string str()  const;
0118     };
0119     class Parameterisation;
0120 
0121     /// Magic word to detect memory corruptions
0122     unsigned long magic { 0 };
0123     /// Reference count on object (used to implement Grab/Release)
0124     long   refCount     { 0 };
0125     /// Reference to the parameterised transformation
0126     Parameterisation* params   { nullptr };
0127     /// ID container
0128     VolIDs volIDs;
0129 
0130   public:
0131     /// Default constructor
0132     PlacedVolumeExtension();
0133     /// Default move
0134     PlacedVolumeExtension(PlacedVolumeExtension&& copy);
0135     /// Copy constructor
0136     PlacedVolumeExtension(const PlacedVolumeExtension& c);
0137     /// Default destructor
0138     virtual ~PlacedVolumeExtension();
0139     /// Move assignment
0140     PlacedVolumeExtension& operator=(PlacedVolumeExtension&& copy);
0141     /// Assignment operator
0142     PlacedVolumeExtension& operator=(const PlacedVolumeExtension& copy);
0143     /// TGeoExtension overload: Method called whenever requiring a pointer to the extension
0144     virtual TGeoExtension *Grab()  override;
0145     /// TGeoExtension overload: Method called always when the pointer to the extension is not needed anymore
0146     virtual void Release() const  override;
0147     /// Enable ROOT persistency
0148     ClassDefOverride(PlacedVolumeExtension,200);
0149   };
0150   class PlacedVolumeFeatureExtension : public  PlacedVolumeExtension {
0151   public:
0152   public:
0153   };
0154 
0155   /// Handle class holding a placed volume (also called physical volume)
0156   /**
0157    *   For any further documentation please see the following ROOT documentation:
0158    *   \see http://root.cern.ch/root/html/TGeoNode.html
0159    *
0160    *   \author  M.Frank
0161    *   \version 1.0
0162    *   \ingroup DD4HEP_CORE
0163    */
0164   class PlacedVolume : public Handle<TGeoNode> {
0165   public:
0166     typedef PlacedVolumeExtension         Object;
0167     typedef PlacedVolumeExtension::VolIDs VolIDs;
0168 
0169     /// Abstract base for processing callbacks to PlacedVolume objects
0170     /** Helper to facilitate building plugins, which instrument
0171      *  placements and volumes e.g. during geometry scans.
0172      *
0173      *  \author  M.Frank
0174      *  \version 1.0
0175      *  \ingroup DD4HEP_CORE
0176      */
0177     class Processor {
0178     public:
0179       /// Default constructor
0180       Processor();
0181       /// Default destructor
0182       virtual ~Processor();
0183       /// Container callback for object processing
0184       virtual int processPlacement(PlacedVolume pv) = 0;
0185     };
0186 
0187     /// Default constructor
0188     PlacedVolume() = default;
0189     /// Move constructor
0190     PlacedVolume(PlacedVolume&& e) = default;
0191     /// Copy assignment
0192     PlacedVolume(const PlacedVolume& e) = default;
0193     /// Copy assignment from other handle type
0194     template <typename T> PlacedVolume(const Handle<T>& e) : Handle<TGeoNode>(e) {  }
0195     /// Constructor taking implementation object pointer
0196     PlacedVolume(const TGeoNode* e) : Handle<TGeoNode>(e) {  }
0197     /// Assignment operator (must match copy constructor)
0198     PlacedVolume& operator=(PlacedVolume&& v)  = default;
0199     /// Assignment operator (must match copy constructor)
0200     PlacedVolume& operator=(const PlacedVolume& v)  = default;
0201     /// Equality operator
0202     template <typename T> bool operator ==(const Handle<T>& e) const {
0203       return ptr() == e.ptr();
0204     }
0205     /// Non-Equality operator
0206     template <typename T> bool operator !=(const Handle<T>& e) const {
0207       return ptr() != e.ptr();
0208     }
0209 
0210     /// Check if placement is properly instrumented
0211     Object* data() const;
0212     /// Access the object type from the class information
0213     const char* type() const;
0214     /// Access the copy number of this placement within its mother
0215     int copyNumber() const;
0216     /// Volume material
0217     Material material() const;
0218     /// Logical volume of this placement
0219     Volume volume() const;
0220     /// Parent volume (envelope)
0221     Volume motherVol() const;
0222     /// Number of daughters placed in this volume
0223     std::size_t num_daughters()  const;
0224     /// Access the daughter by index
0225     PlacedVolume daughter(std::size_t which)  const;
0226     /// Access the full transformation matrix to the parent volume
0227     const TGeoMatrix& matrix()  const;
0228     /// Access the translation vector to the parent volume
0229     Position position()  const;
0230     /// Access to the volume IDs
0231     const PlacedVolumeExtension::VolIDs& volIDs() const;
0232     /// Add identifier
0233     PlacedVolume& addPhysVolID(const std::string& name, int value);
0234     /// String dump
0235     std::string toString() const;
0236   };
0237 
0238   // This needs full knowledge of the PlacedVolume class, at least for ROOT 6.28/04
0239   // so we place it here
0240   /// Optional parameters to implement special features such as parametrization
0241   /**
0242    *
0243    *   \author  M.Frank
0244    *   \version 1.0
0245    *   \ingroup DD4HEP_CORE
0246    */
0247   class PlacedVolumeExtension::Parameterisation {
0248   public:
0249     /** Feature: Geant4 parameterised volumes  */
0250     using Dimension = std::pair<Transform3D, size_t>;
0251     /// Reference to the starting point of the parameterisation
0252     Transform3D   start    {   };
0253     /// Reference to the parameterised transformation for dimension 1
0254     Dimension     trafo1D  { {}, 0UL };
0255     /// Reference to the parameterised transformation for dimension 2
0256     Dimension     trafo2D  { {}, 0UL };
0257     /// Reference to the parameterised transformation for dimension 3
0258     Dimension     trafo3D  { {}, 0UL };
0259     /// Number of entries for the parameterisation in dimension 2
0260     unsigned long flags    { 0 };
0261     /// Number of entries for the parameterisation in dimension 2
0262     unsigned long refCount { 0 };
0263     /// Reference to the placements of this volume
0264     std::vector<PlacedVolume> placements {  };
0265     /// Bitfield from sensitive detector to encode the volume ID on the fly
0266     const detail::BitFieldElement* field { nullptr };
0267 
0268   public:
0269     /// Default constructor
0270     Parameterisation() = default;
0271     /// Default move
0272     Parameterisation(Parameterisation&& copy) = default;
0273     /// Copy constructor
0274     Parameterisation(const Parameterisation& c) = default;
0275     /// Default destructor
0276     virtual ~Parameterisation() = default;
0277     /// Move assignment
0278     Parameterisation& operator=(Parameterisation&& copy) = default;
0279     /// Assignment operator
0280     Parameterisation& operator=(const Parameterisation& copy) = default;
0281     /// Increase ref count
0282     Parameterisation* addref();
0283     /// Decrease ref count
0284     void release();
0285     /// Enable ROOT persistency
0286     ClassDef(Parameterisation,200);
0287   };
0288 
0289 
0290   /// Implementation class extending the ROOT volume (TGeoVolume)
0291   /**
0292    *   Internal data structure optional to TGeo data.
0293    *
0294    *   For any further documentation please see the following ROOT documentation:
0295    *   \see http://root.cern.ch/root/html/TGeoExtension.html
0296    *
0297    *   \author  M.Frank
0298    *   \version 1.0
0299    *   \ingroup DD4HEP_CORE
0300    */
0301   class VolumeExtension : public TGeoExtension {
0302   public:
0303     /// Magic word to detect memory corruptions
0304     unsigned long       magic      = 0;
0305     /// Reference count on object (used to implement Grab/Release)
0306     long                refCount   = 0;
0307     ///
0308     int                 referenced = 0;
0309     /// Bit field to determine the usage. Bit 0...15 reserverd for system usage. 16...31 user space.
0310     int                 flags      = 0;
0311     /// Region reference
0312     Region              region;
0313     /// Limit sets used for simulation
0314     LimitSet            limits;
0315     /// Reference to visualization attributes
0316     VisAttr             vis;
0317     /// Reference to the sensitive detector
0318     Handle<NamedObject> sens_det;
0319     /// Reference to the reflected volume (or to the original volume for reflections)
0320     Handle<TGeoVolume>  reflected;
0321     /// Reference to properties
0322     TList* properties  { nullptr };
0323     /// Geant4 optimization flag: Smartless
0324     unsigned char       smartLess  = 0xFF;  // MUST match Volume::NO_SMARTLESS_OPTIMIZATION
0325 
0326     /// Default destructor
0327     virtual ~VolumeExtension();
0328     /// Default constructor
0329     VolumeExtension();
0330     /// No move
0331     VolumeExtension(VolumeExtension&& copy) = delete;
0332     /// Copy constructor
0333     VolumeExtension(const VolumeExtension& copy);
0334     /// No move assignment
0335     VolumeExtension& operator=(VolumeExtension&& copy) = delete;
0336     /// Copy assignment
0337     VolumeExtension& operator=(const VolumeExtension& copy);
0338     /// Copy the object
0339     void copy(const VolumeExtension& c);
0340     /// TGeoExtension overload: Method called whenever requiring a pointer to the extension
0341     virtual TGeoExtension *Grab()  override;
0342     /// TGeoExtension overload: Method called always when the pointer to the extension is not needed anymore
0343     virtual void Release() const  override;
0344     /// Enable ROOT persistency
0345     ClassDefOverride(VolumeExtension,200);
0346   };
0347 
0348   /// Handle class holding a placed volume (also called physical volume)
0349   /**
0350    *   Handle describing a Volume
0351    *
0352    *   One note about divisions:
0353    *   =========================
0354    *   Since dd4hep requires Volumes (aka TGeoVolume) and PlacedVolumes (aka TGeoNode)
0355    *   to be enhaced with the user extension mechanism shape divisions MUST be
0356    *   done using the division mechanism of the dd4hep shape or volume wrapper.
0357    *   Otherwise the enhancements are not added and you shall get exception
0358    *   when dd4hep is closing the geometry.
0359    *   The same argument holds when a division is made from a Volume.
0360    *   Unfortunately there is no reasonable way to intercept this call to the
0361    *   TGeo objects - except to sub-class each of them, which is not really 
0362    *   acceptable either.
0363    *
0364    *   For any further documentation please see the following ROOT documentation:
0365    *   \see http://root.cern.ch/root/html/TGeoVolume.html
0366    *
0367    *   \author  M.Frank
0368    *   \version 1.0
0369    *   \ingroup DD4HEP_CORE
0370    */
0371   class Volume: public Handle<TGeoVolume> {
0372   public:
0373     typedef VolumeExtension Object;
0374     /// Flag bit numbers for special volume treatments
0375     enum  {
0376       VETO_SIMU     = 1,
0377       VETO_RECO     = 2,
0378       VETO_DISPLAY  = 3,
0379       REFLECTED     = 10,
0380     };
0381     enum ReplicationAxis  {
0382       REPLICATED    = 1UL << 4,
0383       PARAMETERIZED = 1UL << 5,
0384       Undefined     = 1UL << 7,
0385       X_axis        = 1UL << 8,
0386       Y_axis        = 1UL << 9,
0387       Z_axis        = 1UL << 10,
0388       Rho_axis      = 1UL << 11,
0389       Phi_axis      = 1UL << 12,
0390     };
0391     enum g4_optimizations  {
0392       NO_SMARTLESS_OPTIMIZATION = 0xFF,
0393     };
0394   public:
0395     /// Default constructor
0396     Volume() = default;
0397     /// Move from handle
0398     Volume(Volume&& v) = default;
0399     /// Copy from handle
0400     Volume(const Volume& v) = default;
0401     /// Copy from handle
0402     Volume(const TGeoVolume* v) : Handle<TGeoVolume>(v) { }
0403     /// Copy from arbitrary Element
0404     template <typename T> Volume(const Handle<T>& v) : Handle<TGeoVolume>(v) {  }
0405 
0406     /// Constructor to be used when creating a new geometry tree.
0407     Volume(const std::string& name);
0408     /// Constructor to be used when creating a new geometry tree. Sets also title
0409     Volume(const std::string& name, const std::string& title);
0410 
0411     /// Constructor to be used when creating a new geometry tree. Also sets materuial and solid attributes
0412     Volume(const std::string& name, const Solid& s, const Material& m);
0413 
0414     /// Constructor to be used when creating a new geometry tree. Also sets materuial and solid attributes
0415     Volume(const std::string& name, const std::string& title, const Solid& s, const Material& m);
0416 
0417     /// Assignment operator (must match move constructor)
0418     Volume& operator=(Volume&& a)  = default;
0419     /// Assignment operator (must match copy constructor)
0420     Volume& operator=(const Volume& a)  = default;
0421     /// Equality operator
0422     template <typename T> bool operator ==(const Handle<T>& e) const {
0423       return ptr() == e.ptr();
0424     }
0425     /// Non-Equality operator
0426     template <typename T> bool operator !=(const Handle<T>& e) const {
0427       return ptr() != e.ptr();
0428     }
0429 
0430     /// Set flag to enable copy number checks when inserting new nodes
0431     /** By default checks are enabled. If you want to disable, call this function */
0432     static void enableCopyNumberCheck(bool value);
0433     
0434     /// Check if placement is properly instrumented
0435     Object* data() const;
0436 
0437     /// Access the object type from the class information
0438     const char* type() const;
0439 
0440     /// Create a reflected volume tree. The reflected volume has left-handed coordinates
0441     Volume reflect()  const;
0442 
0443     /// Create a reflected volume tree. The reflected volume has left-handed coordinates.
0444     /** Swap the sensitive detector - if valid - on all sensitive sub-volumes
0445      */
0446     Volume reflect(SensitiveDetector sd)  const;
0447     
0448     /// If we import volumes from external sources, we have to attach the extensions to the tree
0449     Volume& import();
0450 
0451     /// Divide volume into subsections (See the ROOT manual for details)
0452     Volume divide(const std::string& divname, int iaxis, int ndiv, double start, double step, int numed = 0, const char* option = "");
0453     /** Daughter placements with auto-generated copy number for the daughter volume  */
0454     /// Place daughter volume. The position and rotation are the identity
0455     PlacedVolume placeVolume(const Volume& volume) const;
0456     /// Place daughter volume according to a generic Transform3D
0457     PlacedVolume placeVolume(const Volume& volume, const Transform3D& tr) const;
0458     /// Place un-rotated daughter volume at the given position.
0459     PlacedVolume placeVolume(const Volume& volume, const Position& pos) const;
0460     /// Place rotated daughter volume. The position is automatically the identity position
0461     PlacedVolume placeVolume(const Volume& volume, const RotationZYX& rot) const;
0462     /// Place rotated daughter volume. The position is automatically the identity position
0463     PlacedVolume placeVolume(const Volume& volume, const Rotation3D& rot) const;
0464 
0465     /** Daughter placements with user supplied copy number for the daughter volume  */
0466     /// Place daughter volume. The position and rotation are the identity
0467     PlacedVolume placeVolume(const Volume& volume, int copy_no) const;
0468     /// Place daughter volume according to a generic Transform3D
0469     PlacedVolume placeVolume(const Volume& volume, int copy_no, const Transform3D& tr) const;
0470     /// Place un-rotated daughter volume at the given position.
0471     PlacedVolume placeVolume(const Volume& volume, int copy_no, const Position& pos) const;
0472     /// Place rotated daughter volume. The position is automatically the identity position
0473     PlacedVolume placeVolume(const Volume& volume, int copy_no, const RotationZYX& rot) const;
0474     /// Place rotated daughter volume. The position is automatically the identity position
0475     PlacedVolume placeVolume(const Volume& volume, int copy_no, const Rotation3D& rot) const;
0476     /// Place daughter volume with generic TGeo matrix
0477     PlacedVolume placeVolume(const Volume& volume, TGeoMatrix* tr) const;
0478     /// Place daughter volume with generic TGeo matrix
0479     PlacedVolume placeVolume(const Volume& volume, int copy_nr, TGeoMatrix* tr) const;
0480     /// 1D volume replication implementation
0481     /** Embedding parameterised daughter placements in a mother volume
0482      *  @param entity Daughter volume to be placed
0483      *  @param axis   Replication axis direction in the frame of the mother
0484      *  @param count  Number of entities to be placed
0485      *  @param inc    Transformation increment for each iteration
0486      *  @param start  start transormation for the first placement
0487      */
0488     PlacedVolume replicate(const Volume entity, ReplicationAxis axis, size_t count, double inc, double start=0e0);
0489     /// 1D Parameterised volume implementation
0490     /** Embedding parameterised daughter placements in a mother volume
0491      *  @param start  start transormation for the first placement
0492      *  @param entity Daughter volume to be placed
0493      *  @param count  Number of entities to be placed
0494      *  @param inc    Transformation increment for each iteration
0495      */
0496     PlacedVolume paramVolume1D(const Transform3D& start, Volume entity, size_t count, const Transform3D& inc);
0497     /// 1D Parameterised volume implementation
0498     /** Embedding parameterised daughter placements in a mother volume
0499      *  @param entity Daughter volume to be placed
0500      *  @param count  Number of entities to be placed
0501      *  @param inc    Transformation increment for each iteration
0502      */
0503     PlacedVolume paramVolume1D(Volume entity, size_t count, const Transform3D& trafo);
0504     /// 1D Parameterised volume implementation
0505     /** Embedding parameterised daughter placements in a mother volume
0506      *  @param entity Daughter volume to be placed
0507      *  @param count  Number of entities to be placed
0508      *  @param inc    Transformation increment for each iteration
0509      */
0510     PlacedVolume paramVolume1D(Volume entity, size_t count, const Position& inc);
0511     /// 1D Parameterised volume implementation
0512     /** Embedding parameterised daughter placements in a mother volume
0513      *  @param entity Daughter volume to be placed
0514      *  @param count  Number of entities to be placed
0515      *  @param inc    Transformation increment for each iteration
0516      */
0517     PlacedVolume paramVolume1D(Volume entity, size_t count, const RotationZYX& inc);
0518 
0519     /// 2D Parameterised volume implementation
0520     /** Embedding parameterised daughter placements in a mother volume
0521      *  @param entity   Daughter volume to be placed
0522      *  @param count_1  Number of entities to be placed in dimension 1
0523      *  @param inc_1    Transformation increment for each iteration in dimension 1
0524      *  @param count_2  Number of entities to be placed in dimension 2
0525      *  @param inc_2    Transformation increment for each iteration in dimension 2
0526      */
0527     PlacedVolume paramVolume2D(Volume entity, 
0528                    size_t count_1, const Transform3D& inc_1,
0529                    size_t count_2, const Transform3D& inc_2);
0530 
0531     /// Constructor to be used when creating a new parameterised volume object
0532     /** Embedding parameterised daughter placements in a mother volume
0533      *  @param start    start transormation for the first placement
0534      *  @param entity   Daughter volume to be placed
0535      *  @param count_1  Number of entities to be placed in dimension 1
0536      *  @param inc_1    Transformation increment for each iteration in dimension 1
0537      *  @param count_2  Number of entities to be placed in dimension 2
0538      *  @param inc_2    Transformation increment for each iteration in dimension 2
0539      */
0540     PlacedVolume paramVolume2D(const Transform3D& start,
0541                    Volume entity,
0542                    size_t count_1,
0543                    const Position& inc_1,
0544                    size_t count_2,
0545                    const Position& inc_2);
0546 
0547     /// Constructor to be used when creating a new parameterised volume object
0548     /** Embedding parameterised daughter placements in a mother volume
0549      *  @param start    start transormation for the first placement
0550      *  @param entity   Daughter volume to be placed
0551      *  @param count_1  Number of entities to be placed in dimension 1
0552      *  @param inc_1    Transformation increment for each iteration in dimension 1
0553      *  @param count_2  Number of entities to be placed in dimension 2
0554      *  @param inc_2    Transformation increment for each iteration in dimension 2
0555      */
0556     PlacedVolume paramVolume2D(Volume entity,
0557                    size_t count_1,
0558                    const Position& inc_1,
0559                    size_t count_2,
0560                    const Position& inc_2);
0561 
0562     /// 2D Parameterised volume implementation
0563     /** Embedding parameterised daughter placements in a mother volume
0564      *  @param start    start transormation for the first placement
0565      *  @param entity   Daughter volume to be placed
0566      *  @param count_1  Number of entities to be placed in dimension 1
0567      *  @param inc_1    Transformation increment for each iteration in dimension 1
0568      *  @param count_2  Number of entities to be placed in dimension 2
0569      *  @param inc_2    Transformation increment for each iteration in dimension 2
0570      */
0571     PlacedVolume paramVolume2D(const Transform3D& start, Volume entity, 
0572                    size_t count_1, const Transform3D& inc_1,
0573                    size_t count_2, const Transform3D& inc_2);
0574 
0575     /// 3D Parameterised volume implementation
0576     /** Embedding parameterised daughter placements in a mother volume
0577      *  @param entity   Daughter volume to be placed
0578      *  @param count_1  Number of entities to be placed in dimension 1
0579      *  @param inc_1    Transformation increment for each iteration in dimension 1
0580      *  @param count_2  Number of entities to be placed in dimension 2
0581      *  @param inc_2    Transformation increment for each iteration in dimension 2
0582      *  @param count_3  Number of entities to be placed in dimension 3
0583      *  @param inc_3    Transformation increment for each iteration in dimension 3
0584      */
0585     PlacedVolume paramVolume3D(Volume entity, 
0586                    size_t count_1, const Transform3D& inc_1,
0587                    size_t count_2, const Transform3D& inc_2,
0588                    size_t count_3, const Transform3D& inc_3);
0589 
0590     /// 3D Parameterised volume implementation
0591     /** Embedding parameterised daughter placements in a mother volume
0592      *  @param start    start transormation for the first placement
0593      *  @param entity   Daughter volume to be placed
0594      *  @param count_1  Number of entities to be placed in dimension 1
0595      *  @param inc_1    Transformation increment for each iteration in dimension 1
0596      *  @param count_2  Number of entities to be placed in dimension 2
0597      *  @param inc_2    Transformation increment for each iteration in dimension 2
0598      *  @param count_3  Number of entities to be placed in dimension 3
0599      *  @param inc_3    Transformation increment for each iteration in dimension 3
0600      */
0601     PlacedVolume paramVolume3D(const Transform3D& start, Volume entity, 
0602                    size_t count_1, const Transform3D& inc_1,
0603                    size_t count_2, const Transform3D& inc_2,
0604                    size_t count_3, const Transform3D& inc_3);
0605 
0606     /// 3D Parameterised volume implementation
0607     /** Embedding parameterised daughter placements in a mother volume
0608      *  @param entity   Daughter volume to be placed
0609      *  @param count_1  Number of entities to be placed in dimension 1
0610      *  @param inc_1    Transformation increment for each iteration in dimension 1
0611      *  @param count_2  Number of entities to be placed in dimension 2
0612      *  @param inc_2    Transformation increment for each iteration in dimension 2
0613      *  @param count_3  Number of entities to be placed in dimension 3
0614      *  @param inc_3    Transformation increment for each iteration in dimension 3
0615      */
0616     PlacedVolume paramVolume3D(Volume entity, 
0617                    size_t count_1, const Position& inc_1,
0618                    size_t count_2, const Position& inc_2,
0619                    size_t count_3, const Position& inc_3);
0620 
0621     /// 3D Parameterised volume implementation
0622     /** Embedding parameterised daughter placements in a mother volume
0623      *  @param start    start transormation for the first placement
0624      *  @param entity   Daughter volume to be placed
0625      *  @param count_1  Number of entities to be placed in dimension 1
0626      *  @param inc_1    Transformation increment for each iteration in dimension 1
0627      *  @param count_2  Number of entities to be placed in dimension 2
0628      *  @param inc_2    Transformation increment for each iteration in dimension 2
0629      *  @param count_3  Number of entities to be placed in dimension 3
0630      *  @param inc_3    Transformation increment for each iteration in dimension 3
0631      */
0632     PlacedVolume paramVolume3D(const Transform3D& start, Volume entity, 
0633                    size_t count_1, const Position& inc_1,
0634                    size_t count_2, const Position& inc_2,
0635                    size_t count_3, const Position& inc_3);
0636 
0637     /// Set user flags in bit-field
0638     void setFlagBit(unsigned int bit);
0639     /// Test the user flag bit
0640     bool testFlagBit(unsigned int bit)   const;
0641 
0642     /// Test if this volume was reflected
0643     bool isReflected()   const;
0644     
0645     /// Test if this volume is an assembly structure
0646     bool isAssembly()   const;
0647 
0648     /// Set the smartless option for G4 voxelization. Returns previous value
0649     unsigned char setSmartlessValue(unsigned char value);
0650     /// access the smartless option for G4 voxelization
0651     unsigned char smartlessValue()  const;
0652     
0653     /// Set the volume's option value
0654     const Volume& setOption(const std::string& opt) const;
0655     /// Access the volume's option value
0656     std::string option() const;
0657 
0658     /// Attach attributes to the volume
0659     const Volume& setAttributes(const Detector& description, const std::string& region, const std::string& limits,
0660                                 const std::string& vis) const;
0661 
0662     /// Set the regional attributes to the volume. Note: If the name string is empty, the action is ignored.
0663     const Volume& setRegion(const Detector& description, const std::string& name) const;
0664     /// Set the regional attributes to the volume
0665     const Volume& setRegion(const Region& obj) const;
0666     /// Access to the handle to the region structure
0667     Region region() const;
0668 
0669     /// Set the limits to the volume. Note: If the name string is empty, the action is ignored.
0670     const Volume& setLimitSet(const Detector& description, const std::string& name) const;
0671     /// Set the limits to the volume
0672     const Volume& setLimitSet(const LimitSet& obj) const;
0673     /// Access to the limit set
0674     LimitSet limitSet() const;
0675 
0676     /// Set Visualization attributes to the volume
0677     const Volume& setVisAttributes(const VisAttr& obj) const;
0678     /// Set Visualization attributes to the volume. Note: If the name string is empty, the action is ignored.
0679     const Volume& setVisAttributes(const Detector& description, const std::string& name) const;
0680     /// Access the visualisation attributes
0681     VisAttr visAttributes() const;
0682 
0683     /// Assign the sensitive detector structure
0684     const Volume& setSensitiveDetector(const SensitiveDetector& obj) const;
0685     /// Access to the handle to the sensitive detector
0686     Handle<NamedObject> sensitiveDetector() const;
0687     /// Accessor if volume is sensitive (ie. is attached to a sensitive detector)
0688     bool isSensitive() const;
0689 
0690     /// Set the volume's solid shape
0691     const Volume& setSolid(const Solid& s) const;
0692     /// Access to Solid (Shape)
0693     Solid solid() const;
0694     /// Access the bounding box of the volume (if available)
0695     Box boundingBox() const;
0696 
0697     /// Set the volume's material
0698     const Volume& setMaterial(const Material& m) const;
0699     /// Access to the Volume material
0700     Material material() const;
0701 
0702     /// Check for existence of properties
0703     bool hasProperties()  const;
0704 
0705     /// Add Volume property (name-value pair)
0706     void addProperty(const std::string& nam, const std::string& val)  const;
0707 
0708     /// Access property value. Returns default_value if the property is not present
0709     std::string getProperty(const std::string& nam, const std::string& default_val="")  const;
0710 
0711     /// Auto conversion to underlying ROOT object
0712     operator TGeoVolume*() const {
0713       return m_element;
0714     }
0715   };
0716 
0717   /// Implementation class extending the ROOT mulit-volumes (TGeoVolumeMulti)
0718   /**
0719    *  Handle describing a multi volume.
0720    *
0721    *   For any further documentation please see the following ROOT documentation:
0722    *   \see http://root.cern.ch/root/html/TGeoVolumeMulti.html
0723    *
0724    *   \author  M.Frank
0725    *   \version 1.0
0726    *   \ingroup DD4HEP_CORE
0727    */
0728   class VolumeMulti : public Volume   {
0729     /// Import volume from pointer as a result of Solid->Divide()
0730     void verifyVolumeMulti();
0731 
0732   public:
0733     /// Default constructor
0734     VolumeMulti() = default;
0735     /// Copy from handle
0736     VolumeMulti(const VolumeMulti& v) = default;
0737     /// Copy from pointer as a result of Solid->Divide()
0738     VolumeMulti(TGeoVolume* v) : Volume(v)  {
0739       verifyVolumeMulti();
0740     }
0741     /// Copy from arbitrary Element
0742     template <typename T> VolumeMulti(const Handle<T>& v) : Volume(v) {
0743       verifyVolumeMulti();
0744     }
0745     /// Constructor to be used when creating a new multi-volume object
0746     VolumeMulti(const std::string& name, Material material);
0747     /// Assignment operator (must match copy constructor)
0748     VolumeMulti& operator=(const VolumeMulti& a) = default;
0749   };
0750 
0751   /// Implementation class extending the ROOT assembly volumes (TGeoVolumeAssembly)
0752   /**
0753    *  Handle describing a volume assembly.
0754    *
0755    *   For any further documentation please see the following ROOT documentation:
0756    *   \see http://root.cern.ch/root/html/TGeoVolumeAssembly.html
0757    *
0758    *   \author  M.Frank
0759    *   \version 1.0
0760    *   \ingroup DD4HEP_CORE
0761    */
0762   class Assembly: public Volume {
0763   public:
0764     /// Default constructor
0765     Assembly() = default;
0766     /// Copy from handle
0767     Assembly(const Assembly& v) = default;
0768     /// Copy from arbitrary Element
0769     template <typename T> Assembly(const Handle<T>& v) : Volume(v) {  }
0770     /// Constructor to be used when creating a new assembly object
0771     Assembly(const std::string& name);
0772     /// Assignment operator (must match copy constructor)
0773     Assembly& operator=(const Assembly& a) = default;
0774   };
0775 
0776   /// Output mesh vertices to string
0777   std::string toStringMesh(PlacedVolume solid, int precision=2);
0778 }         /* End namespace dd4hep          */
0779 #endif // DD4HEP_VOLUMES_H