From be73f44947157c7dc60aeca881fec05fef5045e4 Mon Sep 17 00:00:00 2001
From: Markus Frank <markus.frank@cern.ch>
Date: Mon, 7 May 2012 13:32:44 +0000
Subject: [PATCH] Fix bux with placements

---
 DDCore/include/DD4hep/Detector.h | 20 +++++--
 DDCore/src/Detector.cpp          | 49 ++++++++++++++----
 DDCore/src/Volumes.cpp           | 89 ++++++++++++++++++++++++++++++++
 3 files changed, 146 insertions(+), 12 deletions(-)

diff --git a/DDCore/include/DD4hep/Detector.h b/DDCore/include/DD4hep/Detector.h
index 3db7993c7..d6e60d618 100644
--- a/DDCore/include/DD4hep/Detector.h
+++ b/DDCore/include/DD4hep/Detector.h
@@ -93,7 +93,14 @@ namespace DD4hep {
       typedef Ref_t                            Parent;
       typedef std::map<std::string,DetElement> Children;
       typedef std::vector<PlacedVolume>        Placements;
-
+      
+      enum {
+	COPY_NONE      = 0,
+	COPY_PLACEMENT = 1<<0,
+	COPY_PARENT    = 1<<1,
+	COPY_ALIGNMENT = 1<<2,
+	LAST            
+      } CopyParameters;
       struct Object  {
         unsigned int      magic;
         int               id;
@@ -103,15 +110,16 @@ namespace DD4hep {
         Readout           readout;
         Alignment         alignment;
         Conditions        conditions;
+	PlacedVolume      placement;
         Placements        placements;
 	Parent            parent;
         Children          children;
 	/// Default constructor
         Object();
 	/// Construct new empty object
-	virtual Value<TNamed,Object>* construct(int new_id) const;
+	virtual Value<TNamed,Object>* construct(int new_id, int flag) const;
 	/// Deep object copy to replicate DetElement trees e.g. for reflection
-	virtual void deepCopy(const Object& source, int new_id);
+	virtual void deepCopy(const Object& source, int new_id, int flag);
       };
 
       /// Additional data accessor
@@ -166,10 +174,16 @@ namespace DD4hep {
       /// Assign readout definition
       DetElement&     setReadout(const Readout& readout);
       
+      /// Access to the physical volume of this detector element
+      PlacedVolume    placement() const;
+      /// Set the physical volumes of the detector element
+      DetElement&     setPlacement(const PlacedVolume& volume);
+
       /// Access the physical volumes of the detector element
       Placements      placements() const;
       /// Set the physical volumes of the detector element
       DetElement&     addPlacement(const PlacedVolume& volume);
+
       /// Access to the logical volume of the placements (all daughters have the same!)
       Volume          volume() const;
       
diff --git a/DDCore/src/Detector.cpp b/DDCore/src/Detector.cpp
index c6bba7bcd..bfe18cdb8 100644
--- a/DDCore/src/Detector.cpp
+++ b/DDCore/src/Detector.cpp
@@ -17,29 +17,33 @@ using namespace DD4hep::Geometry;
 /// Default constructor
 DetElement::Object::Object()  
   : magic(magic_word()), id(0), combine_hits(0), readout(), 
-    alignment(), placements(), parent(), children()
+    alignment(), placement(), placements(), parent(), children()
 {
 }
 
 /// Construct new empty object
-Value<TNamed,DetElement::Object>* DetElement::Object::construct(int new_id) const {
+Value<TNamed,DetElement::Object>* DetElement::Object::construct(int new_id, int flag) const {
   Value<TNamed,Object>* obj = new Value<TNamed,Object>();
-  obj->deepCopy(*this,new_id);
+  obj->deepCopy(*this,new_id,flag);
   return obj;
 }
 
 /// Deep object copy to replicate DetElement trees e.g. for reflection
-void DetElement::Object::deepCopy(const Object& source, int new_id)  {
+void DetElement::Object::deepCopy(const Object& source, int new_id, int flag)  {
   id           = new_id;
   combine_hits = source.combine_hits;
   readout      = source.readout;
   volume       = source.volume;
   alignment    = Alignment();
   conditions   = Conditions();
-  placements   = Placements();
-  parent       = DetElement();
+  parent       = ((flag&COPY_PARENT)    == COPY_PARENT) ? source.parent : DetElement();
+  placement    = ((flag&COPY_PLACEMENT) == COPY_PLACEMENT) ? source.placement : PlacedVolume();
+
+  placements   = ((flag&COPY_PLACEMENT) == COPY_PLACEMENT) ? source.placements : Placements();
   for(DetElement::Children::const_iterator i=source.children.begin(); i != source.children.end(); ++i) {
-    DetElement child = (*i).second.clone((*i).second->GetName());
+    const DetElement::Object& d = (*i).second._data();
+    const TNamed* pc = (*i).second.ptr();
+    DetElement child(d.construct(d.id,COPY_PLACEMENT|COPY_PARENT),pc->GetName(),pc->GetTitle());
     children.insert(make_pair((*i).first,child));
   }
 }
@@ -129,18 +133,45 @@ DetElement::Placements DetElement::placements() const    {
 
 DetElement DetElement::clone(const string& new_name)  const  {
   if ( isValid() ) {
-    return DetElement(_data().construct(_data().id), new_name, ptr()->GetTitle());
+    return DetElement(_data().construct(_data().id,COPY_NONE), new_name, ptr()->GetTitle());
   }
   throw runtime_error("DetElement::clone: Self is not defined - clone failed! [Invalid Handle]");
 }
 
 DetElement DetElement::clone(const string& new_name, int new_id)  const  {
   if ( isValid() ) {
-    return DetElement(_data().construct(new_id), new_name, ptr()->GetTitle());
+    return DetElement(_data().construct(new_id, COPY_NONE), new_name, ptr()->GetTitle());
   }
   throw runtime_error("DetElement::clone: Self is not defined - clone failed! [Invalid Handle]");
 }
 
+/// Access to the physical volume of this detector element
+PlacedVolume DetElement::placement() const {
+  if ( isValid() ) {
+    Object& o = _data();
+    if ( o.placement.isValid() )  {
+      return o.placement;
+    }
+  }
+  return PlacedVolume();
+}
+
+/// Set the physical volumes of the detector element
+DetElement& DetElement::setPlacement(const PlacedVolume& placement) {
+  if ( isValid() ) {
+    if ( placement.isValid() )  {
+      Object& o = _data();
+      o.placement = placement;
+      o.volume = placement.volume();
+      placement.setDetElement(*this);
+      return *this;
+    }
+    throw runtime_error("DetElement::addPlacement: Placement is not defined [Invalid Handle]");
+  }
+  throw runtime_error("DetElement::addPlacement: Self is not defined [Invalid Handle]");
+}
+
+
 DetElement& DetElement::addPlacement(const PlacedVolume& placement)  {
   if ( isValid() ) {
     if ( placement.isValid() )  {
diff --git a/DDCore/src/Volumes.cpp b/DDCore/src/Volumes.cpp
index de6da0f03..76aed0739 100644
--- a/DDCore/src/Volumes.cpp
+++ b/DDCore/src/Volumes.cpp
@@ -17,6 +17,9 @@
 #include "TGeoMatrix.h"
 #include "TGeoMedium.h"
 
+#include "TGeoVoxelFinder.h"
+#include "TGeoShapeAssembly.h"
+
 // C/C++ include files
 #include <climits>
 #include <iostream>
@@ -81,12 +84,98 @@ namespace DD4hep  { namespace Geometry  {
     : public _VolWrap<TGeoVolume>, public Volume::Object  {
     Value(const char* name, TGeoShape* s=0, TGeoMedium* m=0) : _VolWrap<TGeoVolume>(name,s,m) {magic = magic_word();}
     virtual ~Value() {}
+    virtual TGeoVolume* MakeCopyVolume(TGeoShape *newshape) {
+      // make a copy of this volume. build a volume with same name, shape and medium
+      TGeoVolume *vol = new Value<TGeoVolume,Volume::Object>(GetName(), newshape, fMedium);
+      vol->SetVisibility(IsVisible());
+      vol->SetLineColor(GetLineColor());
+      vol->SetLineStyle(GetLineStyle());
+      vol->SetLineWidth(GetLineWidth());
+      vol->SetFillColor(GetFillColor());
+      vol->SetFillStyle(GetFillStyle());
+      vol->SetField(fField);
+      if (fFinder) vol->SetFinder(fFinder);
+      CloneNodesAndConnect(vol);
+      ((TObject*)vol)->SetBit(kVolumeClone);
+      return vol;       
+    }
+    TGeoVolume* CloneVolume() const    {
+      TGeoVolume *vol = new Value<TGeoVolume,Volume::Object>(GetName(), fShape, fMedium);
+      Int_t i;
+      // copy volume attributes
+      vol->SetLineColor(GetLineColor());
+      vol->SetLineStyle(GetLineStyle());
+      vol->SetLineWidth(GetLineWidth());
+      vol->SetFillColor(GetFillColor());
+      vol->SetFillStyle(GetFillStyle());
+      // copy other attributes
+      Int_t nbits = 8*sizeof(UInt_t);
+      for (i=0; i<nbits; i++) 
+	vol->SetAttBit(1<<i, TGeoAtt::TestAttBit(1<<i));
+      for (i=14; i<24; i++)
+	vol->SetBit(1<<i, TestBit(1<<i));   
+   
+      // copy field
+      vol->SetField(fField);
+      // Set bits
+      for (i=0; i<nbits; i++) 
+	vol->SetBit(1<<i, TObject::TestBit(1<<i));
+      vol->SetBit(kVolumeClone);   
+      // copy nodes
+      //   CloneNodesAndConnect(vol);
+      vol->MakeCopyNodes(this);   
+      // if volume is divided, copy finder
+      vol->SetFinder(fFinder);
+      // copy voxels
+      TGeoVoxelFinder *voxels = 0;
+      if (fVoxels) {
+	voxels = new TGeoVoxelFinder(vol);
+	vol->SetVoxelFinder(voxels);
+      }   
+      // copy option, uid
+      vol->SetOption(fOption);
+      vol->SetNumber(fNumber);
+      vol->SetNtotal(fNtotal);
+      return vol;
+    }
   };
   
   template <> struct Value<TGeoVolumeAssembly,Assembly::Object> 
     : public _VolWrap<TGeoVolumeAssembly>, public Assembly::Object  {
     Value(const char* name) : _VolWrap<TGeoVolumeAssembly>(name,0,0) {  magic = magic_word(); }
     virtual ~Value() {}
+
+    TGeoVolume *CloneVolume() const    {
+      TGeoVolume *vol = new Value<TGeoVolumeAssembly,Assembly::Object>(GetName());
+      Int_t i;
+      // copy other attributes
+      Int_t nbits = 8*sizeof(UInt_t);
+      for (i=0; i<nbits; i++) 
+	vol->SetAttBit(1<<i, TGeoAtt::TestAttBit(1<<i));
+      for (i=14; i<24; i++)
+	vol->SetBit(1<<i, TestBit(1<<i));   
+   
+      // copy field
+      vol->SetField(fField);
+      // Set bits
+      for (i=0; i<nbits; i++) 
+	vol->SetBit(1<<i, TObject::TestBit(1<<i));
+      vol->SetBit(kVolumeClone);   
+      // make copy nodes
+      vol->MakeCopyNodes(this);
+      ((TGeoShapeAssembly*)vol->GetShape())->NeedsBBoxRecompute();
+      // copy voxels
+      TGeoVoxelFinder *voxels = 0;
+      if (fVoxels) {
+	voxels = new TGeoVoxelFinder(vol);
+	vol->SetVoxelFinder(voxels);
+      }   
+      // copy option, uid
+      vol->SetOption(fOption);
+      vol->SetNumber(fNumber);
+      vol->SetNtotal(fNtotal);
+      return vol;
+    }
   };
 }}
 
-- 
GitLab