From 3b98f89dd04cd9cb70f3d1f26e799532217f519e Mon Sep 17 00:00:00 2001
From: Markus Frank <markus.frank@cern.ch>
Date: Tue, 20 Nov 2012 19:43:17 +0000
Subject: [PATCH] Add second placement option

---
 DDCore/include/DD4hep/Objects.h |  4 +++
 DDCore/include/DD4hep/Volumes.h |  4 ++-
 DDCore/src/Segementations.cpp   | 12 ++++-----
 DDCore/src/Shapes.cpp           | 32 ++++++++++++------------
 DDCore/src/Volumes.cpp          | 43 ++++++++++++++++++++++-----------
 5 files changed, 59 insertions(+), 36 deletions(-)

diff --git a/DDCore/include/DD4hep/Objects.h b/DDCore/include/DD4hep/Objects.h
index ec60a9a05..c7491033e 100644
--- a/DDCore/include/DD4hep/Objects.h
+++ b/DDCore/include/DD4hep/Objects.h
@@ -20,6 +20,7 @@ class TGeoMatrix;
 class TGeoRotation;
 class TGeoTranslation;
 class TGeoPhysicalNode;
+class TGeoIdentity;
 #include "TGeoPhysicalNode.h"
 
 // C/C++ include files
@@ -48,6 +49,9 @@ namespace DD4hep {
     class IDDescriptor;
 
 
+    /** Access to identity transformation  */
+    TGeoIdentity* identityTransform();
+
     /** @class Author Objects.h
      *  
      *  @author  M.Frank
diff --git a/DDCore/include/DD4hep/Volumes.h b/DDCore/include/DD4hep/Volumes.h
index 1c2f6aea1..161ec033d 100644
--- a/DDCore/include/DD4hep/Volumes.h
+++ b/DDCore/include/DD4hep/Volumes.h
@@ -129,8 +129,10 @@ namespace DD4hep {
       PlacedVolume placeVolume(const Volume& vol, const Position& pos)  const;
       /// Place rotated daughter volume. The position is automatically the identity position
       PlacedVolume placeVolume(const Volume& vol, const Rotation& rot)  const;
-      /// Place translated and rotated daughter volume
+      /// Place rotated and then translated daughter volume
       PlacedVolume placeVolume(const Volume& vol, const Position& pos, const Rotation& rot)  const;
+      /// Place daughter volume in rotated and then translated mother coordinate system
+      PlacedVolume placeVolumeEx(const Volume& vol, const Position& pos, const Rotation& rot)  const;
       
       /// Place daughter volume. The position and rotation are the identity
       PlacedVolume placeVolume(const Volume& vol, const IdentityPos& pos)  const;
diff --git a/DDCore/src/Segementations.cpp b/DDCore/src/Segementations.cpp
index 87f305cb9..01a235f03 100644
--- a/DDCore/src/Segementations.cpp
+++ b/DDCore/src/Segementations.cpp
@@ -71,22 +71,22 @@ ProjectiveCylinder::ProjectiveCylinder()
 : Segmentation("projective_cylinder")   {}
 
 /// Accessors: get number of bins in theta
-int ProjectiveCylinder::thetaBins() const  {
+int ProjectiveCylinder::thetaBins() const    {
   return _data().data.cylindrical_binning.ntheta;
 }
 
 /// Accessors: get number of bins in phi
-int ProjectiveCylinder::phiBins() const  {
+int ProjectiveCylinder::phiBins() const    {
   return _data().data.cylindrical_binning.nphi;
 }
 
 /// Accessors: set number of bins in theta
-void ProjectiveCylinder::setThetaBins(int value)  {
+void ProjectiveCylinder::setThetaBins(int value)    {
   _data().data.cylindrical_binning.ntheta = value;
 }
 
 /// Accessors: set grid size in Y
-void ProjectiveCylinder::setPhiBins(int value)  {
+void ProjectiveCylinder::setPhiBins(int value)   {
   _data().data.cylindrical_binning.nphi = value;
 }
 
@@ -95,11 +95,11 @@ NonProjectiveCylinder::NonProjectiveCylinder()
 {
 }
 
-double NonProjectiveCylinder::gridSizeZ() const  {
+double NonProjectiveCylinder::gridSizeZ()  const   {
   return _data().data.cylindrical_grid.grid_size_z;
 }
 
-double NonProjectiveCylinder::gridSizePhi() const  {
+double NonProjectiveCylinder::gridSizePhi()  const   {
   return _data().data.cylindrical_grid.grid_size_phi;
 }
 
diff --git a/DDCore/src/Shapes.cpp b/DDCore/src/Shapes.cpp
index 0d13630f7..627c51ccf 100644
--- a/DDCore/src/Shapes.cpp
+++ b/DDCore/src/Shapes.cpp
@@ -31,8 +31,10 @@
 using namespace std;
 using namespace DD4hep::Geometry;
 
-namespace {
-  static TGeoIdentity s_identity;
+
+TGeoIdentity* DD4hep::Geometry::identityTransform() {
+  if ( 0 == gGeoIdentity ) gGeoIdentity = new TGeoIdentity();
+  return gGeoIdentity;
 }
 
 template<typename T> void Solid_type<T>::_setDimensions(double* param) {
@@ -177,7 +179,7 @@ ConeSegment& ConeSegment::setDimensions(double dz, double rmin1, double rmax1, d
 }
 
 /// Constructor to be used when creating a new object with attribute initialization
-void Tube::make(const string& name, double rmin, double rmax, double startPhi, double z, double deltaPhi)
+void Tube::make(const string& name, double rmin, double rmax, double z, double startPhi, double deltaPhi)
 {
   _assign(new TGeoTubeSeg(rmin,rmax,z,RAD_2_DEGREE*startPhi,RAD_2_DEGREE*deltaPhi),name,"tube");
 }
@@ -443,7 +445,7 @@ PolyhedraRegular::PolyhedraRegular(int nsides, double rmin, double rmax, double
 /// Constructor to be used when creating a new object. Position is identity, Rotation is the identity rotation
 SubtractionSolid::SubtractionSolid(const Solid& shape1, const Solid& shape2)
 {
-  TGeoSubtraction* sub  = new TGeoSubtraction(shape1,shape2,&s_identity,&s_identity);
+  TGeoSubtraction* sub  = new TGeoSubtraction(shape1,shape2,identityTransform(),identityTransform());
   _assign(new TGeoCompositeShape("",sub), "", "subtraction");
 }
 
@@ -451,7 +453,7 @@ SubtractionSolid::SubtractionSolid(const Solid& shape1, const Solid& shape2)
 SubtractionSolid::SubtractionSolid(const Solid& shape1, const Solid& shape2, const Position& pos)
 {
   TGeoCombiTrans* trans = new TGeoCombiTrans(pos.x,pos.y,pos.z,0);
-  TGeoSubtraction* sub  = new TGeoSubtraction(shape1,shape2,&s_identity,trans);
+  TGeoSubtraction* sub  = new TGeoSubtraction(shape1,shape2,identityTransform(),trans);
   _assign(new TGeoCompositeShape("",sub), "", "subtraction");
 }
 
@@ -461,7 +463,7 @@ SubtractionSolid::SubtractionSolid(const Solid& shape1, const Solid& shape2, con
   TGeoRotation rotation("",rot.phi*RAD_2_DEGREE,rot.theta*RAD_2_DEGREE,rot.psi*RAD_2_DEGREE);
   TGeoCombiTrans*    trans = new TGeoCombiTrans(pos.x,pos.y,pos.z,0);
   trans->SetRotation(rotation.Inverse());
-  TGeoSubtraction*    sub  = new TGeoSubtraction(shape1,shape2,&s_identity,trans);
+  TGeoSubtraction*    sub  = new TGeoSubtraction(shape1,shape2,identityTransform(),trans);
   _assign(new TGeoCompositeShape("",sub), "", "subtraction");
 }
 
@@ -471,14 +473,14 @@ SubtractionSolid::SubtractionSolid(const string& name, const Solid& shape1, cons
   TGeoRotation rotation("",rot.phi*RAD_2_DEGREE,rot.theta*RAD_2_DEGREE,rot.psi*RAD_2_DEGREE);
   TGeoCombiTrans*    trans = new TGeoCombiTrans(pos.x,pos.y,pos.z,0);
   trans->SetRotation(rotation.Inverse());
-  TGeoSubtraction*    sub  = new TGeoSubtraction(shape1,shape2,&s_identity,trans);
+  TGeoSubtraction*    sub  = new TGeoSubtraction(shape1,shape2,identityTransform(),trans);
   _assign(new TGeoCompositeShape(name.c_str(),sub), name, "subtraction");
 }
 
 /// Constructor to be used when creating a new object. Position is identity, Rotation is identity rotation
 UnionSolid::UnionSolid(const Solid& shape1, const Solid& shape2)
 {
-  TGeoUnion*        uni = new TGeoUnion(shape1,shape2,&s_identity,&s_identity);
+  TGeoUnion*        uni = new TGeoUnion(shape1,shape2,identityTransform(),identityTransform());
   _assign(new TGeoCompositeShape("",uni), "", "union");
 }
 
@@ -486,7 +488,7 @@ UnionSolid::UnionSolid(const Solid& shape1, const Solid& shape2)
 UnionSolid::UnionSolid(const Solid& shape1, const Solid& shape2, const Position& pos)
 {
   TGeoCombiTrans* trans = new TGeoCombiTrans(pos.x,pos.y,pos.z,0);
-  TGeoUnion*        uni = new TGeoUnion(shape1,shape2,&s_identity,trans);
+  TGeoUnion*        uni = new TGeoUnion(shape1,shape2,identityTransform(),trans);
   _assign(new TGeoCompositeShape("",uni), "", "union");
 }
 
@@ -496,7 +498,7 @@ UnionSolid::UnionSolid(const Solid& shape1, const Solid& shape2, const Position&
   TGeoRotation rotation("",rot.phi*RAD_2_DEGREE,rot.theta*RAD_2_DEGREE,rot.psi*RAD_2_DEGREE);
   TGeoCombiTrans* trans = new TGeoCombiTrans(pos.x,pos.y,pos.z,0);
   trans->SetRotation(rotation.Inverse());
-  TGeoUnion*        uni = new TGeoUnion(shape1,shape2,&s_identity,trans);
+  TGeoUnion*        uni = new TGeoUnion(shape1,shape2,identityTransform(),trans);
   _assign(new TGeoCompositeShape("",uni), "", "union");
 }
 
@@ -506,20 +508,20 @@ UnionSolid::UnionSolid(const string& name, const Solid& shape1, const Solid& sha
   TGeoRotation rotation("",rot.phi*RAD_2_DEGREE,rot.theta*RAD_2_DEGREE,rot.psi*RAD_2_DEGREE);
   TGeoCombiTrans* trans = new TGeoCombiTrans(pos.x,pos.y,pos.z,0);
   trans->SetRotation(rotation.Inverse());
-  TGeoUnion* uni = new TGeoUnion(shape1,shape2,&s_identity,trans);
+  TGeoUnion* uni = new TGeoUnion(shape1,shape2,identityTransform(),trans);
   _assign(new TGeoCompositeShape(name.c_str(),uni), name, "union");
 }
 
 /// Constructor to be used when creating a new object. Position is identity.
 IntersectionSolid::IntersectionSolid(const Solid& shape1, const Solid& shape2, const Position& pos)    {
   TGeoCombiTrans*    trans = new TGeoCombiTrans(pos.x,pos.y,pos.z,0);
-  TGeoIntersection*  inter = new TGeoIntersection(shape1,shape2,&s_identity,trans);
+  TGeoIntersection*  inter = new TGeoIntersection(shape1,shape2,identityTransform(),trans);
   _assign(new TGeoCompositeShape("",inter), "", "intersection");
 }
 
 /// Constructor to be used when creating a new object. Position is identity, Rotation is identity rotation
 IntersectionSolid::IntersectionSolid(const Solid& shape1, const Solid& shape2)    {
-  TGeoIntersection* inter = new TGeoIntersection(shape1,shape2,&s_identity,&s_identity);
+  TGeoIntersection* inter = new TGeoIntersection(shape1,shape2,identityTransform(),identityTransform());
   _assign(new TGeoCompositeShape("",inter), "", "intersection");
 }
 
@@ -529,7 +531,7 @@ IntersectionSolid::IntersectionSolid(const Solid& shape1, const Solid& shape2, c
   TGeoRotation rotation("",rot.phi*RAD_2_DEGREE,rot.theta*RAD_2_DEGREE,rot.psi*RAD_2_DEGREE);
   TGeoCombiTrans*    trans = new TGeoCombiTrans(pos.x,pos.y,pos.z,0);
   trans->SetRotation(rotation.Inverse());
-  TGeoIntersection*  inter = new TGeoIntersection(shape1,shape2,&s_identity,trans);
+  TGeoIntersection*  inter = new TGeoIntersection(shape1,shape2,identityTransform(),trans);
   _assign(new TGeoCompositeShape("",inter), "", "intersection");
 }
 
@@ -539,7 +541,7 @@ IntersectionSolid::IntersectionSolid(const string& name, const Solid& shape1, co
   TGeoRotation rotation("",rot.phi*RAD_2_DEGREE,rot.theta*RAD_2_DEGREE,rot.psi*RAD_2_DEGREE);
   TGeoCombiTrans*    trans = new TGeoCombiTrans(pos.x,pos.y,pos.z,0);
   trans->SetRotation(rotation.Inverse());
-  TGeoIntersection*  inter = new TGeoIntersection(shape1,shape2,&s_identity,trans);
+  TGeoIntersection*  inter = new TGeoIntersection(shape1,shape2,identityTransform(),trans);
   _assign(new TGeoCompositeShape(name.c_str(),inter),name,"intersection");
 }
 
diff --git a/DDCore/src/Volumes.cpp b/DDCore/src/Volumes.cpp
index 09c7108d6..13376464c 100644
--- a/DDCore/src/Volumes.cpp
+++ b/DDCore/src/Volumes.cpp
@@ -273,18 +273,39 @@ static PlacedVolume _addNode(TGeoVolume* par, TGeoVolume* daughter, TGeoMatrix*
   TGeoVolume* parent = par;
   TObjArray* a = parent->GetNodes();
   Int_t id = a ? a->GetEntries() : 0;
+  if ( transform && transform != identityTransform() ) {
+    string nam = string(daughter->GetName())+"_placement";
+    transform->SetName(nam.c_str());
+  }
   parent->AddNode(daughter,id,transform);
   TGeoNodeMatrix* n = dynamic_cast<TGeoNodeMatrix*>(parent->GetNode(id));
   return PlacedVolume(n);
 }
 
+static TGeoTranslation* _translation(const Position& pos) {
+  return new TGeoTranslation("",pos.x,pos.y,pos.z);
+}
+
+static TGeoRotation* _rotation(const Rotation& rot) {
+  return new TGeoRotation("",rot.phi*RAD_2_DEGREE,rot.theta*RAD_2_DEGREE,rot.psi*RAD_2_DEGREE);
+}
+
 /// Place translated and rotated daughter volume
 PlacedVolume Volume::placeVolume(const Volume& volume, const Position& pos, const Rotation& rot)  const  {
   if ( volume.isValid() )   {
-    string nam = string(volume.name())+"_placement";
-    TGeoRotation rotation("",rot.phi*RAD_2_DEGREE,rot.theta*RAD_2_DEGREE,rot.psi*RAD_2_DEGREE);
-    TGeoCombiTrans* transform = new TGeoCombiTrans(nam.c_str(),pos.x,pos.y,pos.z,0);
-    transform->SetRotation(rotation);
+    TGeoCombiTrans* transform = new TGeoCombiTrans("",pos.x,pos.y,pos.z,_rotation(rot));
+    return _addNode(m_element,volume,transform);
+  }
+  throw runtime_error("Volume: Attempt to assign an invalid physical volume.");
+}
+
+/// Place translated and rotated daughter volume
+PlacedVolume Volume::placeVolumeEx(const Volume& volume, const Position& pos, const Rotation& rot)  const  {
+  if ( volume.isValid() )   {
+    TGeoHMatrix *transform = new TGeoHMatrix(TGeoTranslation(pos.x,pos.y,pos.z));
+    transform->RotateZ(rot.phi*RAD_2_DEGREE);
+    transform->RotateX(rot.theta*RAD_2_DEGREE);
+    transform->RotateY(rot.psi*RAD_2_DEGREE);
     return _addNode(m_element,volume,transform);
   }
   throw runtime_error("Volume: Attempt to assign an invalid physical volume.");
@@ -293,9 +314,7 @@ PlacedVolume Volume::placeVolume(const Volume& volume, const Position& pos, cons
 /// Place un-rotated daughter volume at the given position.
 PlacedVolume Volume::placeVolume(const Volume& volume, const Position& pos)  const  {
   if ( volume.isValid() )   {
-    string nam = string(volume.name())+"_placement";
-    TGeoTranslation* transform = new TGeoTranslation(nam.c_str(),pos.x,pos.y,pos.z);
-    return _addNode(m_element,volume,transform);
+    return _addNode(m_element,volume,_translation(pos));
   }
   throw runtime_error("Volume: Attempt to assign an invalid physical volume.");
 }
@@ -303,9 +322,7 @@ PlacedVolume Volume::placeVolume(const Volume& volume, const Position& pos)  con
 /// Place rotated daughter volume. The position is automatically the identity position
 PlacedVolume Volume::placeVolume(const Volume& volume, const Rotation& rot)  const  {
   if ( volume.isValid() )   {
-    string nam = string(volume.name())+"_placement";
-    TGeoRotation* transform = new TGeoRotation(nam.c_str(),rot.phi*RAD_2_DEGREE,rot.theta*RAD_2_DEGREE,rot.psi*RAD_2_DEGREE);
-    return _addNode(m_element,volume,transform);
+    return _addNode(m_element,volume,_rotation(rot));
   }
   throw runtime_error("Volume: Attempt to assign an invalid physical volume.");
 }
@@ -313,8 +330,7 @@ PlacedVolume Volume::placeVolume(const Volume& volume, const Rotation& rot)  con
 /// Place daughter volume. The position and rotation are the identity
 PlacedVolume Volume::placeVolume(const Volume& volume, const IdentityPos& /* pos */)  const  {
   if ( volume.isValid() )   {
-    string nam = string(volume.name())+"_placement";
-    return _addNode(m_element,volume,new TGeoIdentity(nam.c_str()));
+    return _addNode(m_element,volume,identityTransform());
   }
   throw runtime_error("Volume: Attempt to assign an invalid physical volume.");
 }
@@ -322,8 +338,7 @@ PlacedVolume Volume::placeVolume(const Volume& volume, const IdentityPos& /* pos
 /// Place daughter volume. The position and rotation are the identity
 PlacedVolume Volume::placeVolume(const Volume& volume, const IdentityRot& /* rot */)  const  {
   if ( volume.isValid() )   {
-    string nam = string(volume.name())+"_placement";
-    return _addNode(m_element,volume,new TGeoIdentity(nam.c_str()));
+    return _addNode(m_element,volume,identityTransform());
   }
   throw runtime_error("Volume: Attempt to assign an invalid physical volume.");
 }
-- 
GitLab