DD4hep  1.30.0
Detector Description Toolkit for High Energy Physics
Beampipe_o1_v01_geo.cpp
Go to the documentation of this file.
1 //==========================================================================
2 // AIDA Detector description implementation
3 //--------------------------------------------------------------------------
4 // Copyright (C) Organisation europeenne pour la Recherche nucleaire (CERN)
5 // All rights reserved.
6 //
7 // For the licensing terms see $DD4hepINSTALL/LICENSE.
8 // For the list of contributors see $DD4hepINSTALL/doc/CREDITS.
9 //
10 //==========================================================================
11 
13 
15 #include "DD4hep/DD4hepUnits.h"
16 #include "DD4hep/DetType.h"
17 #include "DD4hep/Printout.h"
18 
19 #include "DDRec/DetectorData.h"
20 #include "DDRec/Surface.h"
21 
22 #include "XML/Utilities.h"
23 
24 #include <cmath>
25 #include <map>
26 #include <string>
27 
29 using dd4hep::Position;
30 using dd4hep::RotationY;
31 using dd4hep::RotateY;
34 using dd4hep::Material;
35 using dd4hep::Volume;
36 using dd4hep::Solid;
37 using dd4hep::Tube;
38 namespace units = dd4hep;
43 
46  double _half_length ;
47 public:
50  double thickness_inner ,double thickness_outer, Vector3D origin ) :
51  dd4hep::rec::VolCylinderImpl( vol, type, thickness_inner, thickness_outer, origin ),
52  _half_length(0){
53  }
54  void setHalfLength( double half_length){
55  _half_length = half_length ;
56  }
57  void setID( dd4hep::FieldID id ) { _id = id ;
58  }
59  // overwrite to include points inside the inner radius of the barrel
60  bool insideBounds(const Vector3D& point, double epsilon) const {
61  return ( std::abs( point.rho() - origin().rho() ) < epsilon && std::abs( point.z() ) < _half_length ) ;
62  }
63 
64  virtual std::vector< std::pair<Vector3D, Vector3D> > getLines(unsigned nMax=100){
65 
66  std::vector< std::pair<Vector3D, Vector3D> > lines ;
67 
68  lines.reserve( nMax ) ;
69 
70  Vector3D zv( 0. , 0. , _half_length ) ;
71  double r = _o.rho() ;
72 
73  unsigned n = nMax / 4 ;
74  double dPhi = 2.* ROOT::Math::Pi() / double( n ) ;
75 
76  for( unsigned i = 0 ; i < n ; ++i ) {
77 
78  Vector3D rv0( r*sin( i *dPhi ) , r*cos( i *dPhi ) , 0. ) ;
79  Vector3D rv1( r*sin( (i+1)*dPhi ) , r*cos( (i+1)*dPhi ) , 0. ) ;
80 
81  Vector3D pl0 = zv + rv0 ;
82  Vector3D pl1 = zv + rv1 ;
83  Vector3D pl2 = -zv + rv1 ;
84  Vector3D pl3 = -zv + rv0 ;
85 
86  lines.push_back( std::make_pair( pl0, pl1 ) ) ;
87  lines.push_back( std::make_pair( pl1, pl2 ) ) ;
88  lines.push_back( std::make_pair( pl2, pl3 ) ) ;
89  lines.push_back( std::make_pair( pl3, pl0 ) ) ;
90  }
91  return lines;
92  }
93 };
94 
96 public:
98  double thickness_outer, Vector3D origin ) :
99  dd4hep::rec::VolSurface( new SimpleCylinderImpl( vol, type, thickness_inner , thickness_outer, origin ) ) {
100  }
101  SimpleCylinderImpl* operator->() { return static_cast<SimpleCylinderImpl*>( _surf ) ; }
102 } ;
103 
104 
105 static dd4hep::Ref_t create_element(dd4hep::Detector& description,
106  xml_h element,
107  dd4hep::SensitiveDetector /*sens*/) {
108 
109  printout(dd4hep::DEBUG,"DD4hep_Beampipe", "Creating Beampipe" ) ;
110 
111  //Access to the XML File
112  xml_det_t xmlBeampipe = element;
113  const std::string name = xmlBeampipe.nameStr();
114  bool nocore = xmlBeampipe.nocore(false);
115 
116  dd4hep::DetElement tube( name, xmlBeampipe.id() ) ;
117 
118  // --- create an envelope volume and position it into the world ---------------------
119 
120  Volume envelope = dd4hep::xml::createPlacedEnvelope( description, element , tube ) ;
121 
122  dd4hep::xml::setDetectorTypeFlag( element, tube ) ;
123 
124  if( description.buildType() == dd4hep::BUILD_ENVELOPE ) return tube ;
125 
126  //-----------------------------------------------------------------------------------
127 
128 
130 
131  //DD4hep/TGeo seems to need rad (as opposed to the manual)
132  const double phi1 = 0 ;
133  const double phi2 = 360.0*units::degree;
134 
135  //Parameters we have to know about
136  dd4hep::xml::Component xmlParameter = xmlBeampipe.child(_Unicode(parameter));
137  const double crossingAngle = xmlParameter.attr< double >(_Unicode(crossingangle))*0.5; // only half the angle
138 
139 
140  double min_radius = 1.e99 ;
141 
142  for(xml_coll_t c( xmlBeampipe ,Unicode("section")); c; ++c) {
143 
144  xml_comp_t xmlSection( c );
145 
146  ODH::ECrossType crossType = ODH::getCrossType(xmlSection.attr< std::string >(_Unicode(type)));
147  const double zStart = xmlSection.attr< double > (_Unicode(start));
148  const double zEnd = xmlSection.attr< double > (_Unicode(end));
149  const double rInnerStart = xmlSection.attr< double > (_Unicode(rMin1));
150  const double rInnerEnd = xmlSection.attr< double > (_Unicode(rMin2));
151  const double rOuterStart = xmlSection.attr< double > (_Unicode(rMax1));
152  const double rOuterEnd = xmlSection.attr< double > (_Unicode(rMax2));
153  const double thickness = rOuterStart - rInnerStart;
154  Material sectionMat = description.material(xmlSection.materialStr());
155  const std::string volName = "tube_" + xmlSection.nameStr();
156 
157  std::stringstream pipeInfo;
158  pipeInfo << std::setw(8) << zStart /units::mm
159  << std::setw(8) << zEnd /units::mm
160  << std::setw(8) << rInnerStart /units::mm
161  << std::setw(8) << rInnerEnd /units::mm
162  << std::setw(8) << rOuterStart /units::mm
163  << std::setw(8) << rOuterEnd /units::mm
164  << std::setw(8) << thickness /units::mm
165  << std::setw(8) << crossType
166  << std::setw(35) << volName
167  << std::setw(15) << sectionMat.name();
168 
169  printout(dd4hep::INFO, "DD4hep_Beampipe", pipeInfo.str() );
170 
171  if( crossType == ODH::kCenter ) { // store only the central sections !
172  dd4hep::rec::ConicalSupportData::Section section ;
173  section.rInner = rInnerStart ;
174  section.rOuter = rOuterStart ;
175  section.zPos = zStart ;
176  beampipeData->sections.push_back( section ) ;
177  }
178 
179  // things which can be calculated immediately
180  const double zHalf = fabs(zEnd - zStart) * 0.5; // half z length of the cone
181  const double zPosition = fabs(zEnd + zStart) * 0.5; // middle z position
182  Material coreMaterial = description.material("beam"); // always the same
183  Material wallMaterial = sectionMat;
184 
185  // this could mess up your geometry, so better check it
186  if (not checkForSensibleGeometry(crossingAngle, crossType)){
187 
188  throw std::runtime_error( " Beampipe_o1_v01_geo.cpp : checkForSensibleGeometry() failed " ) ;
189  // return false;
190  }
191  const double rotateAngle = getCurrentAngle(crossingAngle, crossType); // for the placement at +z (better make it const now)
192  const double mirrorAngle = M_PI - rotateAngle; // for the "mirrored" placement at -z
193  // the "mirroring" in fact is done by a rotation of (almost) 180 degrees around the y-axis
194 
195  switch (crossType) {
196  case ODH::kCenter:
197  case ODH::kUpstream:
198  case ODH::kDnstream: {
199  // a volume on the z-axis, on the upstream branch, or on the downstream branch
200 
201  // absolute transformations for the placement in the world
202  Transform3D transformer(RotationY(rotateAngle), RotateY( Position(0, 0, zPosition), rotateAngle) );
203  Transform3D transmirror(RotationY(mirrorAngle), RotateY( Position(0, 0, zPosition), mirrorAngle) );
204 
205  // solid for the tube (including vacuum and wall): a solid cone
206  ConeSegment tubeSolid( zHalf, 0, rOuterStart, 0, rOuterEnd , phi1, phi2);
207 
208  // tube consists of vacuum
209  // place tube twice explicitely so we can attach surfaces to each one
210  Volume tubeLog( volName, tubeSolid, coreMaterial ) ;
211  Volume tubeLog2( volName, tubeSolid, coreMaterial ) ;
212 
213  // if inner and outer radii are equal, then omit the tube wall
214  if (rInnerStart != rOuterStart || rInnerEnd != rOuterEnd) {
215 
216  // the wall solid: a tubular cone
217  ConeSegment wallSolid( zHalf, rInnerStart, rOuterStart, rInnerEnd, rOuterEnd, phi1, phi2);
218 
219  // the wall consists of the material given in the XML
220  Volume wallLog ( volName + "_wall", wallSolid, wallMaterial);
221  Volume wallLog2( volName + "_wall2", wallSolid, wallMaterial);
222 
223  if( crossType == ODH::kCenter ) {
224 
225  // add surface for tracking ....
226  const bool isCylinder = ( rInnerStart == rInnerEnd );
227 
228 
229  if (isCylinder) { // cylinder
230 
231  Vector3D ocyl( rInnerStart + thickness/2. , 0. , 0. ) ;
232 
233  VolCylinder cylSurf1( wallLog , SurfaceType( SurfaceType::Helper ) , 0.5*thickness , 0.5*thickness , ocyl );
234  VolCylinder cylSurf2( wallLog2, SurfaceType( SurfaceType::Helper ) , 0.5*thickness , 0.5*thickness , ocyl );
235 
236  dd4hep::rec::volSurfaceList( tube )->push_back( cylSurf1 );
237  dd4hep::rec::volSurfaceList( tube )->push_back( cylSurf2 );
238 
239  }else{ // cone
240 
241  const double dr = rInnerEnd - rInnerStart ;
242  const double theta = atan2( dr , 2.* zHalf ) ;
243 
244  Vector3D ocon( rInnerStart + 0.5 * ( dr + thickness ), 0. , 0. );
245 
246  Vector3D v( 1. , 0. , theta, Vector3D::spherical ) ;
247 
248  VolCone conSurf1( wallLog , SurfaceType( SurfaceType::Helper ) , 0.5*thickness , 0.5*thickness , v, ocon );
249  VolCone conSurf2( wallLog2, SurfaceType( SurfaceType::Helper ) , 0.5*thickness , 0.5*thickness , v, ocon );
250 
251  dd4hep::rec::volSurfaceList( tube )->push_back( conSurf1 );
252  dd4hep::rec::volSurfaceList( tube )->push_back( conSurf2 );
253 
254  }
255 
256  if( rInnerStart < min_radius ) min_radius = rInnerStart ;
257  if( rOuterStart < min_radius ) min_radius = rOuterStart ;
258  }
259 
260  wallLog.setVisAttributes(description, "TubeVis");
261  wallLog2.setVisAttributes(description, "TubeVis");
262  tubeLog.setVisAttributes(description, "VacVis");
263  tubeLog2.setVisAttributes(description, "VacVis");
264 
265  if (nocore){
266 
267  //placement of the wall only
268  envelope.placeVolume( wallLog, transformer );
269  envelope.placeVolume( wallLog2, transmirror );
270 
271  }else{
272 
273  // placement of the tube in the world, both at +z and -z
274  envelope.placeVolume( tubeLog, transformer );
275  envelope.placeVolume( tubeLog2, transmirror );
276 
277  // placement as a daughter volume of the tube, will appear in both placements of the tube
278  tubeLog.placeVolume( wallLog, Transform3D() );
279  tubeLog2.placeVolume( wallLog2, Transform3D() );
280  }
281 
282  }
283  }
284  break;
285 
286  case ODH::kPunchedCenter: {
287  // a volume on the z-axis with one or two inner holes
288  // (implemented as a cone from which tubes are punched out)
289 
290  const double rUpstreamPunch = rInnerStart; // just alias names denoting what is meant here
291  const double rDnstreamPunch = rInnerEnd; // (the database entries are "abused" in this case)
292 
293  // relative transformations for the composition of the SubtractionVolumes
294  Transform3D upstreamTransformer(RotationY(-crossingAngle), Position(zPosition * tan(-crossingAngle), 0, 0));
295  Transform3D dnstreamTransformer(RotationY(+crossingAngle), Position(zPosition * tan(+crossingAngle), 0, 0));
296 
297  // absolute transformations for the final placement in the world (angles always equal zero and 180 deg)
298  Transform3D placementTransformer(RotationY(rotateAngle), RotateY( Position(0, 0, zPosition) , rotateAngle) );
299  Transform3D placementTransmirror(RotationY(mirrorAngle), RotateY( Position(0, 0, zPosition) , mirrorAngle) );
300 
301  // solid for the tube (including vacuum and wall): a solid cone
302  ConeSegment tubeSolid( zHalf, 0, rOuterStart, 0, rOuterEnd, phi1, phi2);
303 
304  // tube consists of vacuum (will later have two different daughters)
305  Volume tubeLog0( volName + "_0", tubeSolid, coreMaterial );
306  Volume tubeLog1( volName + "_1", tubeSolid, coreMaterial );
307 
308  // the wall solid and placeholders for possible SubtractionSolids
309  ConeSegment wholeSolid( zHalf, 0, rOuterStart, 0, rOuterEnd, phi1, phi2);
310 
311  Solid tmpSolid0, tmpSolid1, wallSolid0, wallSolid1;
312 
313  // the punched subtraction solids can be asymmetric and therefore have to be created twice:
314  // one time in the "right" way, another time in the "reverse" way, because the "mirroring"
315  // rotation around the y-axis will not only exchange +z and -z, but also +x and -x
316 
317  if ( rUpstreamPunch > 1e-6 ) { // do we need a hole on the upstream branch?
318  Tube upstreamPunch( 0, rUpstreamPunch, 5 * zHalf, phi1, phi2); // a bit longer
319  tmpSolid0 = SubtractionSolid( wholeSolid, upstreamPunch, upstreamTransformer);
320  tmpSolid1 = SubtractionSolid( wholeSolid, upstreamPunch, dnstreamTransformer); // [sic]
321  } else { // dont't do anything, just pass on the unmodified shape
322  tmpSolid0 = wholeSolid;
323  tmpSolid1 = wholeSolid;
324  }
325 
326  if (rDnstreamPunch > 1e-6 ) { // do we need a hole on the downstream branch?
327  Tube dnstreamPunch( 0, rDnstreamPunch, 5 * zHalf, phi1, phi2); // a bit longer
328  wallSolid0 = SubtractionSolid( tmpSolid0, dnstreamPunch, dnstreamTransformer);
329  wallSolid1 = SubtractionSolid( tmpSolid1, dnstreamPunch, upstreamTransformer); // [sic]
330  } else { // dont't do anything, just pass on the unmodified shape
331  wallSolid0 = tmpSolid0;
332  wallSolid1 = tmpSolid1;
333  }
334 
335  // the wall consists of the material given in the XML
336  Volume wallLog0( volName + "_wall_0", wallSolid0, wallMaterial );
337  Volume wallLog1( volName + "_wall_1", wallSolid1, wallMaterial );
338 
339  wallLog0.setVisAttributes(description, "TubeVis");
340  wallLog1.setVisAttributes(description, "TubeVis");
341  tubeLog0.setVisAttributes(description, "VacVis");
342  tubeLog1.setVisAttributes(description, "VacVis");
343 
344  if (nocore){
345 
346  // placement of the wall only
347  envelope.placeVolume( wallLog0, placementTransformer );
348  envelope.placeVolume( wallLog1, placementTransmirror );
349 
350  }else{
351 
352  // placement of the tube in the world, both at +z and -z
353  envelope.placeVolume( tubeLog0, placementTransformer );
354  envelope.placeVolume( tubeLog1, placementTransmirror );
355 
356  // placement as a daughter volumes of the tube
357  tubeLog0.placeVolume( wallLog0, Position() );
358  tubeLog1.placeVolume( wallLog1, Position() );
359  }
360 
361  break;
362  }
363 
365  case ODH::kPunchedDnstream: {
366  // a volume on the upstream or downstream branch with two inner holes
367  // (implemented as a cone from which another tube is punched out)
368 
369  const double rCenterPunch = (crossType == ODH::kPunchedUpstream) ? (rInnerStart) : (rInnerEnd); // just alias names denoting what is meant here
370  const double rOffsetPunch = (crossType == ODH::kPunchedDnstream) ? (rInnerStart) : (rInnerEnd); // (the database entries are "abused" in this case)
371 
372  // relative transformations for the composition of the SubtractionVolumes
373  Transform3D punchTransformer(RotationY(-2 * rotateAngle), Position(zPosition * tan(-2 * rotateAngle), 0, 0));
374  Transform3D punchTransmirror(RotationY(+2 * rotateAngle), Position(zPosition * tan(+2 * rotateAngle), 0, 0));
375 
376  // absolute transformations for the final placement in the world
377  Transform3D placementTransformer(RotationY(rotateAngle), RotateY( Position(0, 0, zPosition) , rotateAngle) );
378  Transform3D placementTransmirror(RotationY(mirrorAngle), RotateY( Position(0, 0, zPosition) , mirrorAngle) );
379 
380  // solid for the tube (including vacuum and wall): a solid cone
381  ConeSegment tubeSolid( zHalf, 0, rOuterStart, 0, rOuterEnd, phi1, phi2);
382 
383  // tube consists of vacuum (will later have two different daughters)
384  Volume tubeLog0( volName + "_0", tubeSolid, coreMaterial );
385  Volume tubeLog1( volName + "_1", tubeSolid, coreMaterial );
386 
387  // the wall solid and the piece (only a tube, for the moment) which will be punched out
388  ConeSegment wholeSolid( zHalf, rCenterPunch , rOuterStart, rCenterPunch, rOuterEnd, phi1, phi2);
389 
390  Tube punchSolid( 0, rOffsetPunch, 5 * zHalf, phi1, phi2); // a bit longer
391 
392  // the punched subtraction solids can be asymmetric and therefore have to be created twice:
393  // one time in the "right" way, another time in the "reverse" way, because the "mirroring"
394  // rotation around the y-axis will not only exchange +z and -z, but also +x and -x
395  SubtractionSolid wallSolid0( wholeSolid, punchSolid, punchTransformer);
396  SubtractionSolid wallSolid1( wholeSolid, punchSolid, punchTransmirror);
397 
398  // the wall consists of the material given in the database
399  Volume wallLog0( volName + "_wall_0", wallSolid0, wallMaterial );
400  Volume wallLog1( volName + "_wall_1", wallSolid1, wallMaterial );
401 
402  wallLog0.setVisAttributes(description, "TubeVis");
403  wallLog1.setVisAttributes(description, "TubeVis");
404 
405  tubeLog0.setVisAttributes(description, "VacVis");
406  tubeLog1.setVisAttributes(description, "VacVis");
407 
408 
409  if (nocore){
410 
411  // placement of the wall only
412  envelope.placeVolume( wallLog0, placementTransformer );
413  envelope.placeVolume( wallLog1, placementTransmirror );
414 
415  }else{
416 
417  // placement of the tube in the world, both at +z and -z
418  envelope.placeVolume( tubeLog0, placementTransformer );
419  envelope.placeVolume( tubeLog1, placementTransmirror );
420 
421  // placement as a daughter volumes of the tube
422  tubeLog0.placeVolume( wallLog0 , Position() );
423  tubeLog1.placeVolume( wallLog1 , Position() );
424  }
425 
426  break;
427  }
428 
433  // a volume on the upstream or donwstream branch, but with the front face parallel to the xy-plane
434  // or to a piece tilted in the other direction ("sliced" like a salami with 2 * rotateAngle)
435  // (implemented as a slightly longer cone from which the end is clipped off)
436 
437  // the volume which will be used for clipping: a solid tube
438  const double clipSize = rOuterStart; // the right order of magnitude for the clipping volume (alias name)
439  Tube clipSolid( 0, 2 * clipSize, clipSize, phi1, phi2); // should be large enough
440 
441  // relative transformations for the composition of the SubtractionVolumes
442  const double clipAngle = (crossType == ODH::kUpstreamClippedFront || crossType == ODH::kDnstreamClippedFront) ? (rotateAngle) : (2 * rotateAngle);
443  const double clipShift = (zStart - clipSize) / cos(clipAngle) - (zPosition - clipSize / 2); // question: why is this correct?
444  Transform3D clipTransformer(RotationY(-clipAngle), Position(0, 0, clipShift));
445  Transform3D clipTransmirror(RotationY(+clipAngle), Position(0, 0, clipShift));
446 
447  // absolute transformations for the final placement in the world
448  Transform3D placementTransformer(RotationY(rotateAngle), RotateY( Position(0, 0, zPosition - clipSize / 2) , rotateAngle) );
449  Transform3D placementTransmirror(RotationY(mirrorAngle), RotateY( Position(0, 0, zPosition - clipSize / 2) , mirrorAngle) );
450 
451  // solid for the tube (including vacuum and wall): a solid cone
452 
453  ConeSegment wholeSolid( zHalf + clipSize / 2, 0, rOuterStart, 0, rOuterEnd, phi1, phi2); // a bit longer
454 
455  // clip away the protruding end
456  SubtractionSolid tubeSolid0( wholeSolid, clipSolid, clipTransformer);
457  SubtractionSolid tubeSolid1( wholeSolid, clipSolid, clipTransmirror);
458 
459  // tube consists of vacuum (will later have two different daughters)
460  Volume tubeLog0( volName + "_0", tubeSolid0, coreMaterial );
461  Volume tubeLog1( volName + "_1", tubeSolid1, coreMaterial );
462 
463  if (nocore==false){
464  // placement of the tube in the world, both at +z and -z
465  envelope.placeVolume( tubeLog0, placementTransformer );
466  envelope.placeVolume( tubeLog1, placementTransmirror );
467  }
468 
469  if (rInnerStart != rOuterStart || rInnerEnd != rOuterEnd) {
470  // the wall solid: a tubular cone
471  ConeSegment wallWholeSolid( zHalf + clipSize / 2, rInnerStart, rOuterStart, rInnerEnd, rOuterEnd, phi1, phi2); // a bit longer
472 
473  // clip away the protruding end
474  SubtractionSolid wallSolid0( wallWholeSolid, clipSolid, clipTransformer);
475  SubtractionSolid wallSolid1( wallWholeSolid, clipSolid, clipTransmirror);
476 
477  // the wall consists of the material given in the database
478  Volume wallLog0( volName + "_wall_0", wallSolid0, wallMaterial );
479  Volume wallLog1( volName + "_wall_1", wallSolid1, wallMaterial );
480 
481  wallLog0.setVisAttributes(description, "TubeVis");
482  wallLog1.setVisAttributes(description, "TubeVis");
483 
484  tubeLog0.setVisAttributes(description, "VacVis");
485  tubeLog1.setVisAttributes(description, "VacVis");
486  if (nocore==false){
487  // placement as a daughter volumes of the tube
488  tubeLog0.placeVolume( wallLog0, Position() );
489  tubeLog1.placeVolume( wallLog1, Position() );
490  }else{ // placement of the wall only
491  envelope.placeVolume( wallLog0, placementTransformer );
492  envelope.placeVolume( wallLog1, placementTransmirror );
493  }
494  }
495  }
496  break;
497 
502  // a volume on the upstream or donwstream branch, but with the rear face parallel to the xy-plane
503  // or to a piece tilted in the other direction ("sliced" like a salami with 2 * rotateAngle)
504  // (implemented as a slightly longer cone from which the end is clipped off)
505 
506  // the volume which will be used for clipping: a solid tube
507  const double clipSize = rOuterEnd; // the right order of magnitude for the clipping volume (alias name)
508  Tube clipSolid( 0, 2 * clipSize, clipSize, phi1, phi2); // should be large enough
509 
510  // relative transformations for the composition of the SubtractionVolumes
511  const double clipAngle = (crossType == ODH::kUpstreamClippedRear || crossType == ODH::kDnstreamClippedRear) ? (rotateAngle) : (2 * rotateAngle);
512  const double clipShift = (zEnd + clipSize) / cos(clipAngle) - (zPosition + clipSize / 2); // question: why is this correct?
513  Transform3D clipTransformer(RotationY(-clipAngle), Position(0, 0, clipShift));
514  Transform3D clipTransmirror(RotationY(+clipAngle), Position(0, 0, clipShift));
515 
516  // absolute transformations for the final placement in the world
517  Transform3D placementTransformer(RotationY(rotateAngle), RotateY( Position(0, 0, zPosition + clipSize / 2) , rotateAngle) );
518  Transform3D placementTransmirror(RotationY(mirrorAngle), RotateY( Position(0, 0, zPosition + clipSize / 2) , mirrorAngle) );
519 
520  // solid for the tube (including vacuum and wall): a solid cone
521  ConeSegment wholeSolid( 0, rOuterStart, 0, rOuterEnd, zHalf + clipSize / 2, phi1, phi2); // a bit longer
522 
523  // clip away the protruding end
524  SubtractionSolid tubeSolid0( wholeSolid, clipSolid, clipTransformer);
525  SubtractionSolid tubeSolid1( wholeSolid, clipSolid, clipTransmirror);
526 
527  // tube consists of vacuum (will later have two different daughters)
528  Volume tubeLog0( volName + "_0", tubeSolid0, coreMaterial );
529  Volume tubeLog1( volName + "_1", tubeSolid1, coreMaterial );
530 
531  if (nocore==false){
532  // placement of the tube in the world, both at +z and -z
533  envelope.placeVolume( tubeLog0, placementTransformer );
534  envelope.placeVolume( tubeLog1, placementTransmirror );
535  }
536 
537  if (rInnerStart != rOuterStart || rInnerEnd != rOuterEnd) {
538  // the wall solid: a tubular cone
539  ConeSegment wallWholeSolid( rInnerStart, rOuterStart, rInnerEnd, rOuterEnd, zHalf + clipSize / 2, phi1, phi2); // a bit longer
540 
541  // clip away the protruding end
542  SubtractionSolid wallSolid0( wallWholeSolid, clipSolid, clipTransformer);
543  SubtractionSolid wallSolid1( wallWholeSolid, clipSolid, clipTransmirror);
544 
545  // the wall consists of the material given in the database
546  Volume wallLog0( volName + "_wall_0", wallSolid0, wallMaterial );
547  Volume wallLog1( volName + "_wall_1", wallSolid1, wallMaterial );
548 
549  wallLog0.setVisAttributes(description, "TubeVis");
550  wallLog1.setVisAttributes(description, "TubeVis");
551 
552  tubeLog0.setVisAttributes(description, "VacVis");
553  tubeLog1.setVisAttributes(description, "VacVis");
554 
555  if (nocore==false){
556  // placement as a daughter volumes of the tube
557  tubeLog0.placeVolume( wallLog0, Transform3D() );
558  tubeLog1.placeVolume( wallLog1, Transform3D() );
559  }else{ // placement of the wall only
560  envelope.placeVolume( wallLog0, placementTransformer );
561  envelope.placeVolume( wallLog1, placementTransmirror );
562  }
563  }
564  break;
565  }
566 
571  // a volume on the upstream or donwstream branch, but with both faces parallel to the xy-plane
572  // or to a piece tilted in the other direction ("sliced" like a salami with 2 * rotateAngle)
573  // (implemented as a slightly longer cone from which the end is clipped off)
574 
575  // the volume which will be used for clipping: a solid tube
576  const double clipSize = rOuterEnd; // the right order of magnitude for the clipping volume (alias name)
577  Tube clipSolid( 0, 2 * clipSize, clipSize, phi1, phi2); // should be large enough
578 
579  // relative transformations for the composition of the SubtractionVolumes
580  const double clipAngle = (crossType == ODH::kUpstreamClippedBoth || crossType == ODH::kDnstreamClippedBoth) ? (rotateAngle) : (2 * rotateAngle);
581  const double clipShiftFrnt = (zStart - clipSize) / cos(clipAngle) - zPosition;
582  const double clipShiftRear = (zEnd + clipSize) / cos(clipAngle) - zPosition;
583  Transform3D clipTransformerFrnt(RotationY(-clipAngle), Position(0, 0, clipShiftFrnt));
584  Transform3D clipTransformerRear(RotationY(-clipAngle), Position(0, 0, clipShiftRear));
585  Transform3D clipTransmirrorFrnt(RotationY(+clipAngle), Position(0, 0, clipShiftFrnt));
586  Transform3D clipTransmirrorRear(RotationY(+clipAngle), Position(0, 0, clipShiftRear));
587 
588  // absolute transformations for the final placement in the world
589  Transform3D placementTransformer(RotationY(rotateAngle), RotateY( Position(0, 0, zPosition) , rotateAngle) );
590  Transform3D placementTransmirror(RotationY(mirrorAngle), RotateY( Position(0, 0, zPosition) , mirrorAngle) );
591 
592  // solid for the tube (including vacuum and wall): a solid cone
593  ConeSegment wholeSolid( 0, rOuterStart, 0, rOuterEnd, zHalf + clipSize, phi1, phi2); // a bit longer
594 
595  // clip away the protruding ends
596  SubtractionSolid tmpSolid0 ( wholeSolid, clipSolid, clipTransformerFrnt);
597  SubtractionSolid tmpSolid1 ( wholeSolid, clipSolid, clipTransmirrorFrnt);
598  SubtractionSolid tubeSolid0( tmpSolid0, clipSolid, clipTransformerRear);
599  SubtractionSolid tubeSolid1( tmpSolid1, clipSolid, clipTransmirrorRear);
600 
601  // tube consists of vacuum (will later have two different daughters)
602  Volume tubeLog0( volName + "_0", tubeSolid0, coreMaterial );
603  Volume tubeLog1( volName + "_1", tubeSolid1, coreMaterial );
604 
605  if (nocore==false){
606  // placement of the tube in the world, both at +z and -z
607  envelope.placeVolume( tubeLog0, placementTransformer );
608  envelope.placeVolume( tubeLog1, placementTransmirror );
609  }
610 
611  if (rInnerStart != rOuterStart || rInnerEnd != rOuterEnd) {
612  // the wall solid: a tubular cone
613  ConeSegment wallWholeSolid( rInnerStart, rOuterStart, rInnerEnd, rOuterEnd, zHalf + clipSize, phi1, phi2); // a bit longer
614 
615  // clip away the protruding ends
616  SubtractionSolid wallTmpSolid0( wallWholeSolid, clipSolid, clipTransformerFrnt);
617  SubtractionSolid wallTmpSolid1( wallWholeSolid, clipSolid, clipTransmirrorFrnt);
618  SubtractionSolid wallSolid0 ( wallTmpSolid0, clipSolid, clipTransformerRear);
619  SubtractionSolid wallSolid1 ( wallTmpSolid1, clipSolid, clipTransmirrorRear);
620 
621  // the wall consists of the material given in the database
622  Volume wallLog0(volName + "_wall_0", wallSolid0, wallMaterial );
623  Volume wallLog1(volName + "_wall_1", wallSolid1, wallMaterial );
624 
625  wallLog0.setVisAttributes(description, "TubeVis");
626  wallLog1.setVisAttributes(description, "TubeVis");
627 
628  tubeLog0.setVisAttributes(description, "VacVis");
629  tubeLog1.setVisAttributes(description, "VacVis");
630 
631  if (nocore==false){
632  // placement as a daughter volumes of the tube
633  tubeLog0.placeVolume( wallLog0, Transform3D() );
634  tubeLog1.placeVolume( wallLog1, Transform3D() );
635  }else{ // placement of the wall only
636  envelope.placeVolume( wallLog0, placementTransformer );
637  envelope.placeVolume( wallLog1, placementTransmirror );
638  }
639  }
640  break;
641  }
642  default: {
643  throw std::runtime_error( " Beampipe_o1_v01_geo.cpp : fatal failure !! ?? " ) ;
644 
645  // return false; // fatal failure
646  }
647 
648  }//end switch
649  }//for all xmlSections
650 
651  //######################################################################################################################################################################
652 
653 
654  // add a surface just inside the beampipe for tracking:
655  if (nocore==false){
656  Vector3D oIPCyl( (min_radius-1.e-3) , 0. , 0. ) ;
657  SimpleCylinder ipCylSurf( envelope , SurfaceType( SurfaceType::Helper ) , 1.e-5 , 1e-5 , oIPCyl ) ;
658  // the length does not really matter here as long as it is long enough for all tracks ...
659  ipCylSurf->setHalfLength( 100*units::cm ) ;
660  dd4hep::rec::volSurfaceList( tube )->push_back( ipCylSurf ) ;
661  }
662 
663  tube.addExtension< dd4hep::rec::ConicalSupportData >( beampipeData ) ;
664 
665  //--------------------------------------
666 
667  tube.setVisAttributes( description, xmlBeampipe.visStr(), envelope );
668 
669  // // tube.setPlacement(pv);
670 
671  return tube;
672 }
673 DECLARE_DETELEMENT(DD4hep_Beampipe_o1_v01,create_element)
dd4hep::xml::Collection_t
Class to support the access to collections of XmlNodes (or XmlElements)
Definition: XMLElements.h:636
ODH::kCenter
@ kCenter
Definition: OtherDetectorHelpers.h:23
ODH::kUpstreamSlicedFront
@ kUpstreamSlicedFront
Definition: OtherDetectorHelpers.h:35
dd4hep::rec::VolSurfaceBase::_o
Vector3D _o
Definition: Surface.h:52
DetectorData.h
dd4hep::rec::Vector3D::rho
double rho() const
Definition: Vector3D.h:148
dd4hep::rec::Vector3D::z
double z() const
Definition: Vector3D.h:109
ODH::kUpstreamSlicedBoth
@ kUpstreamSlicedBoth
Definition: OtherDetectorHelpers.h:39
dd4hep::rec::VolSurface::type
virtual const SurfaceType & type() const
Definition: Surface.cpp:248
dd4hep::rec::VolCylinderImpl::VolCylinderImpl
VolCylinderImpl()
default c'tor
Definition: Surface.h:366
v
View * v
Definition: MultiView.cpp:28
dd4hep::rec::Vector3D
Definition: Vector3D.h:32
dd4hep::SensitiveDetector
Handle class to hold the information of a sensitive detector.
Definition: DetElement.h:44
DECLARE_DETELEMENT
#define DECLARE_DETELEMENT(name, func)
Definition: Factories.h:339
M_PI
#define M_PI
Definition: Handle.h:33
ODH::kPunchedUpstream
@ kPunchedUpstream
Definition: OtherDetectorHelpers.h:27
ODH::kUpstreamClippedFront
@ kUpstreamClippedFront
Definition: OtherDetectorHelpers.h:29
SimpleCylinderImpl::setHalfLength
void setHalfLength(double half_length)
Definition: Beampipe_o1_v01_geo.cpp:54
dd4hep::rec::VolSurface::_surf
VolSurfaceBase * _surf
Definition: Surface.h:185
SimpleCylinderImpl::_half_length
double _half_length
Definition: Beampipe_o1_v01_geo.cpp:46
dd4hep::rec::VolCylinderImpl
Definition: Surface.h:361
dd4hep::BUILD_ENVELOPE
@ BUILD_ENVELOPE
Definition: BuildType.h:40
dd4hep::Handle< NamedObject >
dd4hep::rec::VolSurfaceBase::id
virtual long64 id() const
The id of this surface.
Definition: Surface.cpp:42
dd4hep::xml::Handle_t
Class to easily access the properties of single XmlElements.
Definition: XMLElements.h:380
dd4hep::Handle::name
const char * name() const
Access the object name (or "" if not supported by the object)
DetType.h
ODH::kDnstreamClippedFront
@ kDnstreamClippedFront
Definition: OtherDetectorHelpers.h:30
ODH::kUpstreamSlicedRear
@ kUpstreamSlicedRear
Definition: OtherDetectorHelpers.h:37
dd4hep::Volume::placeVolume
PlacedVolume placeVolume(const Volume &volume) const
Place daughter volume. The position and rotation are the identity.
Definition: Volumes.cpp:830
dd4hep::DDSegmentation::FieldID
int64_t FieldID
Definition: BitFieldCoder.h:25
epsilon
const double epsilon
Definition: test_cellid_position_converter.cpp:41
dd4hep::RotateY
V RotateY(const V &v, double a)
Definition: Objects.h:88
dd4hep::rec::VolCylinder
Definition: Surface.h:477
dd4hep::ConeSegment
Class describing a cone segment shape.
Definition: Shapes.h:542
xml_comp_t
dd4hep::xml::Component xml_comp_t
Definition: XML.h:33
_Unicode
#define _Unicode(a)
Definition: Tags.h:24
dd4hep::Material
Handle class describing a material.
Definition: Objects.h:272
Surface.h
ODH::ECrossType
ECrossType
Definition: OtherDetectorHelpers.h:22
ODH::kDnstreamClippedRear
@ kDnstreamClippedRear
Definition: OtherDetectorHelpers.h:32
dd4hep::Detector::material
virtual Material material(const std::string &name) const =0
Retrieve a matrial by its name from the detector description.
dd4hep::rec::volSurfaceList
VolSurfaceList * volSurfaceList(DetElement &det)
Definition: Surface.cpp:528
SimpleCylinder::SimpleCylinder
SimpleCylinder(dd4hep::Volume vol, dd4hep::rec::SurfaceType type, double thickness_inner, double thickness_outer, Vector3D origin)
Definition: Beampipe_o1_v01_geo.cpp:97
dd4hep::DetElement
Handle class describing a detector element.
Definition: DetElement.h:188
dd4hep::Volume
Handle class holding a placed volume (also called physical volume)
Definition: Volumes.h:378
SimpleCylinderImpl::SimpleCylinderImpl
SimpleCylinderImpl(dd4hep::Volume vol, SurfaceType type, double thickness_inner, double thickness_outer, Vector3D origin)
standard c'tor with all necessary arguments - origin is (0,0,0) if not given.
Definition: Beampipe_o1_v01_geo.cpp:49
dd4hep::rec::VolSurface
Definition: Surface.h:181
dd4hep::rec::VolSurface::origin
virtual const Vector3D & origin() const
Definition: Surface.cpp:252
Unicode
dd4hep::xml::Strng_t Unicode
Definition: XML.h:24
xml_det_t
dd4hep::xml::DetElement xml_det_t
Definition: XML.h:32
ODH::kDnstreamSlicedBoth
@ kDnstreamSlicedBoth
Definition: OtherDetectorHelpers.h:40
ODH::kDnstreamSlicedFront
@ kDnstreamSlicedFront
Definition: OtherDetectorHelpers.h:36
dd4hep::rec::ConicalSupportData
StructExtension< ConicalSupportStruct > ConicalSupportData
Definition: DetectorData.h:345
SimpleCylinderImpl::getLines
virtual std::vector< std::pair< Vector3D, Vector3D > > getLines(unsigned nMax=100)
Definition: Beampipe_o1_v01_geo.cpp:64
dd4hep::rec::VolSurfaceBase::origin
virtual const Vector3D & origin() const
Definition: Surface.cpp:48
dd4hep::rec::VolSurfaceBase::type
virtual const SurfaceType & type() const
Definition: Surface.cpp:44
dd4hep::rec::SurfaceType
Definition: ISurface.h:140
dd4hep::rec::VolSurface::VolSurface
VolSurface()
default c'tor
Definition: Surface.h:196
dd4hep::xml::setDetectorTypeFlag
void setDetectorTypeFlag(dd4hep::xml::Handle_t e, dd4hep::DetElement sdet)
Definition: Utilities.cpp:284
ODH::kPunchedCenter
@ kPunchedCenter
Definition: OtherDetectorHelpers.h:26
dd4hep::Transform3D
ROOT::Math::Transform3D Transform3D
Definition: Objects.h:117
ODH::kUpstreamClippedRear
@ kUpstreamClippedRear
Definition: OtherDetectorHelpers.h:31
ODH::kPunchedDnstream
@ kPunchedDnstream
Definition: OtherDetectorHelpers.h:28
dd4hep::Position
ROOT::Math::XYZVector Position
Definition: Objects.h:81
dd4hep::RotationY
ROOT::Math::RotationY RotationY
Definition: Objects.h:109
DetFactoryHelper.h
dd4hep::rec::VolCone
Definition: Surface.h:483
SimpleCylinderImpl::insideBounds
bool insideBounds(const Vector3D &point, double epsilon) const
Checks if the given point lies within the surface.
Definition: Beampipe_o1_v01_geo.cpp:60
dd4hep::xml::createPlacedEnvelope
Volume createPlacedEnvelope(dd4hep::Detector &description, dd4hep::xml::Handle_t e, dd4hep::DetElement sdet)
Definition: Utilities.cpp:220
dd4hep::Detector::buildType
virtual DetectorBuildType buildType() const =0
Access flag to steer the detail of building of the geometry/detector description.
ODH::kUpstreamClippedBoth
@ kUpstreamClippedBoth
Definition: OtherDetectorHelpers.h:33
dd4hep::rec::StructExtension
Definition: DetectorData.h:37
SimpleCylinderImpl
helper class for a simple cylinder surface parallel to z with a given length - used as IP layer
Definition: Beampipe_o1_v01_geo.cpp:45
dd4hep
Namespace for the AIDA detector description toolkit.
Definition: AlignmentsCalib.h:28
dd4hep::Solid
Solid_type< TGeoShape > Solid
Definition: Shapes.h:197
ODH::kDnstream
@ kDnstream
Definition: OtherDetectorHelpers.h:25
dd4hep::Detector
The main interface to the dd4hep detector description package.
Definition: Detector.h:90
SimpleCylinder
Definition: Beampipe_o1_v01_geo.cpp:95
SimpleCylinderImpl::setID
void setID(dd4hep::FieldID id)
Definition: Beampipe_o1_v01_geo.cpp:57
ODH::kDnstreamClippedBoth
@ kDnstreamClippedBoth
Definition: OtherDetectorHelpers.h:34
SimpleCylinder::operator->
SimpleCylinderImpl * operator->()
Definition: Beampipe_o1_v01_geo.cpp:101
DD4hepUnits.h
dd4hep::Tube
Class describing a tube shape of a section of a tube.
Definition: Shapes.h:628
OtherDetectorHelpers.h
Printout.h
ODH::kDnstreamSlicedRear
@ kDnstreamSlicedRear
Definition: OtherDetectorHelpers.h:38
dd4hep::rec::VolSurfaceBase::_id
long64 _id
Definition: Surface.h:58
Utilities.h
dd4hep::SubtractionSolid
Class describing boolean subtraction solid.
Definition: Shapes.h:1878
ODH::kUpstream
@ kUpstream
Definition: OtherDetectorHelpers.h:24