CMS 3D CMS Logo

DD4hep_volumeHandle.cc
Go to the documentation of this file.
1 /*
2  * See header file for a description of this class.
3  *
4  * \author N. Amapane - INFN Torino (original developer)
5  */
6 
7 #include "DD4hep_volumeHandle.h"
8 
16 
18 
20 
21 #include <string>
22 #include <iterator>
23 
24 using namespace SurfaceOrientation;
25 using namespace std;
26 using namespace magneticfield;
27 using namespace edm;
28 
29 volumeHandle::volumeHandle(const cms::DDFilteredView &fv, bool expand2Pi, bool debugVal)
30  : BaseVolumeHandle(expand2Pi, debugVal), theShape(fv.legacyShape(cms::dd::getCurrentShape(fv))), solid(fv) {
31  name = fv.name();
32  copyno = fv.copyNum();
33  const auto *const transArray = fv.trans();
34  center_ = GlobalPoint(transArray[0], transArray[1], transArray[2]);
35 
36  // ASSUMPTION: volume names ends with "_NUM" where NUM is the volume number
37  string volName = name;
38  volName.erase(0, volName.rfind('_') + 1);
39  volumeno = static_cast<unsigned short>(std::atoi(volName.c_str()));
40 
41  for (int i = 0; i < 6; ++i) {
42  isAssigned[i] = false;
43  }
44  referencePlane(fv);
45  switch (theShape) {
47  buildBox();
48  break;
50  buildTrap();
51  break;
53  buildCons();
54  break;
56  buildTubs();
57  break;
60  break;
61  default:
62  LogError("magneticfield::volumeHandle")
63  << "ctor: Unexpected shape # " << static_cast<int>(theShape) << " for vol " << name;
64  }
65 
66  // Get material for this volume
67  if (fv.materialName() == "Iron")
68  isIronFlag = true;
69 
70  if (debug) {
71  LogTrace("magneticfield::volumeHandle") << " RMin = " << theRMin << newln << " RMax = " << theRMax;
72 
73  if (theRMin < 0 || theRN < theRMin || theRMax < theRN)
74  LogTrace("magneticfield::volumeHandle") << "*** WARNING: wrong RMin/RN/RMax";
75 
76  LogTrace("magneticfield::volumeHandle")
77  << "Summary: " << name << " " << copyno << " shape = " << theShape << " trasl " << center() << " R "
78  << center().perp() << " phi " << center().phi() << " magFile " << magFile << " Material= " << fv.materialName()
79  << " isIron= " << isIronFlag << " masterSector= " << masterSector;
80 
81  LogTrace("magneticfield::volumeHandle") << " Orientation of surfaces:";
82  std::string sideName[3] = {"positiveSide", "negativeSide", "onSurface"};
83  for (int i = 0; i < 6; ++i) {
84  if (surfaces[i] != nullptr)
85  LogTrace("magneticfield::volumeHandle") << " " << i << ":" << sideName[surfaces[i]->side(center_, 0.3)];
86  }
87  }
88 }
89 
91  // The refPlane is the "main plane" for the solid. It corresponds to the
92  // x,y plane in the DDD local frame, and defines a frame where the local
93  // coordinates are the same as in DDD.
94  // In the geometry version 85l_030919, this plane is normal to the
95  // beam line for all volumes but pseudotraps, so that global R is along Y,
96  // global phi is along -X and global Z along Z:
97  //
98  // Global(for vol at pi/2) Local
99  // +R (+Y) +Y
100  // +phi(-X) -X
101  // +Z +Z
102  //
103  // For pseudotraps the refPlane is parallel to beam line and global R is
104  // along Z, global phi is along +-X and and global Z along Y:
105  //
106  // Global(for vol at pi/2) Local
107  // +R (+Y) +Z
108  // +phi(-X) +X
109  // +Z +Y
110  //
111  // Note that the frame is centered in the DDD volume center, which is
112  // inside the volume for DDD boxes and (pesudo)trapezoids, on the beam line
113  // for tubs, cons and trunctubs.
114 
115  // In geometry version 1103l, trapezoids have X and Z in the opposite direction
116  // than the above. Boxes are either oriented as described above or in some case
117  // have opposite direction for Y and X.
118 
119  // The global position
120  Surface::PositionType &posResult = center_;
121 
122  // The reference plane rotation
123  math::XYZVector x, y, z;
124  dd4hep::Rotation3D refRot;
125  fv.rot(refRot);
126  refRot.GetComponents(x, y, z);
127  if (debug) {
128  if (x.Cross(y).Dot(z) < 0.5) {
129  LogTrace("magneticfield::volumeHandle") << "*** WARNING: Rotation is not RH ";
130  }
131  }
132 
133  // The global rotation
134  Surface::RotationType rotResult(float(x.X()),
135  float(x.Y()),
136  float(x.Z()),
137  float(y.X()),
138  float(y.Y()),
139  float(y.Z()),
140  float(z.X()),
141  float(z.Y()),
142  float(z.Z()));
143 
144  refPlane = new GloballyPositioned<float>(posResult, rotResult);
145 
146  // Check correct orientation
147  if (debug) {
148  LogTrace("magneticfield::volumeHandle") << "Refplane pos " << refPlane->position();
149 
150  // See comments above for the conventions for orientation.
151  LocalVector globalZdir(0., 0., 1.); // Local direction of the axis along global Z
152 
153  /* Preserve in case pseudotrap is needed again
154  if (theShape == DDSolidShape::ddpseudotrap) {
155  globalZdir = LocalVector(0., 1., 0.);
156  }
157  */
158  if (refPlane->toGlobal(globalZdir).z() < 0.) {
159  globalZdir = -globalZdir;
160  }
161  float chk = refPlane->toGlobal(globalZdir).dot(GlobalVector(0, 0, 1));
162  if (chk < .999)
163  LogTrace("magneticfield::volumeHandle") << "*** WARNING RefPlane check failed!***" << chk;
164  }
165 }
166 
167 std::vector<VolumeSide> volumeHandle::sides() const {
168  std::vector<VolumeSide> result;
169  for (int i = 0; i < 6; ++i) {
170  // If this is just a master volume out of wich a 2pi volume
171  // should be built (e.g. central cylinder), skip the phi boundaries.
172  if (expand && (i == phiplus || i == phiminus))
173  continue;
174 
175  // FIXME: Skip null inner degenerate cylindrical surface
177  continue;
178 
179  ReferenceCountingPointer<Surface> s = const_cast<Surface *>(surfaces[i].get());
180  result.push_back(VolumeSide(s, GlobalFace(i), surfaces[i]->side(center_, 0.3)));
181  }
182  return result;
183 }
184 
185 // The files included below are used here and in the old DD version of this file.
186 // To allow them to be used in both places, they call a "convertUnits" function
187 // that is defined differently between old and new DD.
188 // For the old DD, another version of this function converts mm to cm.
189 
190 namespace {
191  template <class NumType>
192  inline constexpr NumType convertUnits(NumType centimeters) {
193  return (centimeters);
194  }
195 } // namespace
196 
197 using namespace cms::dd;
198 
199 #include "buildBox.icc"
200 #include "buildTrap.icc"
201 #include "buildTubs.icc"
202 #include "buildCons.icc"
203 #include "buildTruncTubs.icc"
MagGeoBuilderFromDDD::volumeHandle volumeHandle
DDSolidShape getCurrentShape(const cms::DDFilteredView &fview)
Definition: DDShapes.cc:19
T perp() const
Definition: PV3DBase.h:69
std::string_view materialName() const
Geom::Phi< T > phi() const
Definition: PV3DBase.h:66
unsigned short volumeno
volume number
const char *const newln
unsigned short copyno
copy number
unsigned short copyNum() const
GloballyPositioned< float > * refPlane
void referencePlane(const cms::DDFilteredView &fv)
Surface::GlobalPoint GlobalPoint
T z() const
Definition: PV3DBase.h:61
const Double_t * rot() const
The absolute rotation of the current node.
int masterSector
The sector for which an interpolator for this class of volumes should be built.
std::string_view name() const
#define LogTrace(id)
const GlobalPoint & center() const
Return the center of the volume.
Namespace of DDCMS conversion namespace.
GlobalPoint toGlobal(const LocalPoint &lp) const
const Double_t * trans() const
The absolute translation of the current node.
XYZVectorD XYZVector
spatial vector with cartesian internal representation
Definition: Vector3D.h:31
std::string name
Name of the volume.
HLT enums.
const PositionType & position() const
std::string magFile
Name of magnetic field table file.
#define constexpr
Global3DVector GlobalVector
Definition: GlobalVector.h:10
std::vector< VolumeSide > sides() const override
The surfaces and they orientation, as required to build a MagVolume.