14 #define _USE_MATH_DEFINES
31 #include <TGeoMatrix.h>
32 #include <TGeoBoolNode.h>
33 #include <TGeoScaledShape.h>
34 #include <TGeoCompositeShape.h>
40 auto p = this->access();
41 p->SetDimensions(param);
48 this->assign(n, nam, tit);
56 return this->ptr()->GetName();
58 return this->access()->GetName();
64 return this->ptr()->GetTitle();
66 return this->access()->GetTitle();
71 this->access()->SetName(value);
77 this->access()->SetName(value.c_str());
84 return this->ptr()->IsA()->GetName();
86 return this->access()->GetName();
101 template <
typename T> TGeoVolume*
103 int iaxis,
int ndiv,
double start,
double step)
const {
106 auto* pdiv = p->Divide(voldiv.
ptr(), divname.c_str(), iaxis, ndiv, start, step);
111 except(
"dd4hep",
"Volume: Failed to divide volume %s -> %s [Invalid result]",
112 voldiv.
name(), divname.c_str());
114 except(
"dd4hep",
"Volume: Attempt to divide an invalid logical volume to %s.", divname.c_str());
123 void Scale::make(
const std::string& nam,
Solid base,
double x_scale,
double y_scale,
double z_scale) {
124 auto scale = std::make_unique<TGeoScale>(x_scale, y_scale, z_scale);
130 return this->
access()->GetScale()->GetScale()[0];
135 return this->
access()->GetScale()->GetScale()[1];
140 return this->
access()->GetScale()->GetScale()[2];
143 void Box::make(
const std::string& nam,
double x_val,
double y_val,
double z_val) {
144 _assign(
new TGeoBBox(nam.c_str(), x_val, y_val, z_val),
"",
BOX_TAG,
true);
149 double params[] = { x_val, y_val, z_val};
156 return this->
ptr()->GetDX();
161 return this->
ptr()->GetDY();
166 return this->
ptr()->GetDZ();
170 void HalfSpace::make(
const std::string& nam,
const double*
const point,
const double*
const normal) {
181 const std::vector<double>& rmin,
const std::vector<double>& rmax,
const std::vector<double>& z) {
182 std::vector<double> params;
183 if (rmin.size() < 2) {
184 throw std::runtime_error(
"dd4hep: PolyCone Not enough Z planes. minimum is 2!");
186 if((
z.size()!=rmin.size()) || (
z.size()!=rmax.size()) ) {
187 throw std::runtime_error(
"dd4hep: Polycone: vectors z,rmin,rmax not of same length");
189 params.emplace_back(
startPhi/units::deg);
190 params.emplace_back(
deltaPhi/units::deg);
191 params.emplace_back(rmin.size());
192 for (std::size_t i = 0; i < rmin.size(); ++i) {
193 params.emplace_back(
z[i] );
194 params.emplace_back(rmin[i] );
195 params.emplace_back(rmax[i] );
201 Polycone::Polycone(
double startPhi,
double deltaPhi,
const std::vector<double>& r,
const std::vector<double>& z) {
202 std::vector<double> params;
204 throw std::runtime_error(
"dd4hep: PolyCone Not enough Z planes. minimum is 2!");
206 if((
z.size()!=r.size()) ) {
207 throw std::runtime_error(
"dd4hep: Polycone: vectors z,r not of same length");
209 params.emplace_back(
startPhi/units::deg);
210 params.emplace_back(
deltaPhi/units::deg);
211 params.emplace_back(r.size());
212 for (std::size_t i = 0; i < r.size(); ++i) {
213 params.emplace_back(
z[i] );
214 params.emplace_back(0.0 );
215 params.emplace_back(r[i] );
227 const std::vector<double>& rmin,
const std::vector<double>& rmax,
const std::vector<double>& z) {
228 std::vector<double> params;
229 if (rmin.size() < 2) {
230 throw std::runtime_error(
"dd4hep: PolyCone Not enough Z planes. minimum is 2!");
232 if((
z.size()!=rmin.size()) || (
z.size()!=rmax.size()) ) {
233 throw std::runtime_error(
"dd4hep: Polycone: vectors z,rmin,rmax not of same length");
235 params.emplace_back(
startPhi/units::deg);
236 params.emplace_back(
deltaPhi/units::deg);
237 params.emplace_back(rmin.size());
238 for (std::size_t i = 0; i < rmin.size(); ++i) {
239 params.emplace_back(
z[i] );
240 params.emplace_back(rmin[i] );
241 params.emplace_back(rmax[i] );
247 Polycone::Polycone(
const std::string& nam,
double startPhi,
double deltaPhi,
const std::vector<double>& r,
const std::vector<double>& z) {
248 std::vector<double> params;
250 throw std::runtime_error(
"dd4hep: PolyCone Not enough Z planes. minimum is 2!");
252 if((
z.size()!=r.size()) ) {
253 throw std::runtime_error(
"dd4hep: Polycone: vectors z,r not of same length");
255 params.emplace_back(
startPhi/units::deg);
256 params.emplace_back(
deltaPhi/units::deg);
257 params.emplace_back(r.size());
258 for (std::size_t i = 0; i < r.size(); ++i) {
259 params.emplace_back(
z[i] );
260 params.emplace_back(0.0 );
261 params.emplace_back(r[i] );
267 void Polycone::addZPlanes(
const std::vector<double>& rmin,
const std::vector<double>& rmax,
const std::vector<double>& z) {
268 TGeoPcon* sh = *
this;
269 std::vector<double> params;
270 std::size_t num = sh->GetNz();
271 if (num + rmin.size() < 2) {
272 except(
"PolyCone",
"++ addZPlanes: Not enough Z planes. minimum is 2!");
274 params.emplace_back(sh->GetPhi1());
275 params.emplace_back(sh->GetDphi());
276 params.emplace_back(num + rmin.size());
277 for (std::size_t i = 0; i < num; ++i) {
278 params.emplace_back(sh->GetZ(i));
279 params.emplace_back(sh->GetRmin(i));
280 params.emplace_back(sh->GetRmax(i));
282 for (std::size_t i = 0; i < rmin.size(); ++i) {
283 params.emplace_back(
z[i] );
284 params.emplace_back(rmin[i] );
285 params.emplace_back(rmax[i] );
293 double rmin1,
double rmax1,
294 double rmin2,
double rmax2,
295 double startPhi,
double endPhi)
303 double rmin1,
double rmax1,
304 double rmin2,
double rmax2,
305 double startPhi,
double endPhi) {
306 double params[] = { dz, rmin1, rmax1, rmin2, rmax2,
startPhi/units::deg,
endPhi/units::deg };
312 void Cone::make(
const std::string& nam,
double z,
double rmin1,
double rmax1,
double rmin2,
double rmax2) {
313 _assign(
new TGeoCone(nam.c_str(), z, rmin1, rmax1, rmin2, rmax2 ),
"",
CONE_TAG,
true);
318 double params[] = { z, rmin1, rmax1, rmin2, rmax2 };
324 void Tube::make(
const std::string& nam,
double rmin,
double rmax,
double z,
double start_phi,
double end_phi) {
326 if(fabs(end_phi-start_phi-2*
M_PI)<10e-6){
327 _assign(
new TGeoTubeSeg(nam.c_str(), rmin, rmax, z, start_phi/units::deg, start_phi/units::deg+360.),nam,
TUBE_TAG,
true);
329 _assign(
new TGeoTubeSeg(nam.c_str(), rmin, rmax, z, start_phi/units::deg, end_phi/units::deg),nam,
TUBE_TAG,
true);
335 double params[] = {rmin,rmax,z,start_phi/units::deg,end_phi/units::deg};
342 double lx,
double ly,
double lz,
double tx,
double ty,
double tz) {
343 make(
"", rmin,rmax,dz,start_phi/units::deg,end_phi/units::deg,lx,ly,lz,tx,ty,tz);
348 double rmin,
double rmax,
double dz,
double start_phi,
double end_phi,
349 double lx,
double ly,
double lz,
double tx,
double ty,
double tz) {
350 make(nam, rmin,rmax,dz,start_phi/units::deg,end_phi/units::deg,lx,ly,lz,tx,ty,tz);
354 void CutTube::make(
const std::string& nam,
double rmin,
double rmax,
double dz,
double start_phi,
double end_phi,
355 double lx,
double ly,
double lz,
double tx,
double ty,
double tz) {
356 _assign(
new TGeoCtub(nam.c_str(), rmin,rmax,dz,start_phi,end_phi,lx,ly,lz,tx,ty,tz),
"",
CUTTUBE_TAG,
true);
361 double cut_atStart,
double cut_atDelta,
bool cut_inside)
362 {
make(
"", dz, rmin, rmax, start_phi/units::deg, delta_phi/units::deg, cut_atStart, cut_atDelta, cut_inside); }
366 double dz,
double rmin,
double rmax,
double start_phi,
double delta_phi,
367 double cut_atStart,
double cut_atDelta,
bool cut_inside)
368 {
make(nam, dz, rmin, rmax, start_phi/units::deg, delta_phi/units::deg, cut_atStart, cut_atDelta, cut_inside); }
372 double dz,
double rmin,
double rmax,
double start_phi,
double delta_phi,
373 double cut_atStart,
double cut_atDelta,
bool cut_inside) {
375 if( rmin <= 0 || rmax <= 0 || cut_atStart <= 0 || cut_atDelta <= 0 )
376 except(
TRUNCATEDTUBE_TAG,
"++ 0 <= rIn,cut_atStart,rOut,cut_atDelta,rOut violated!");
377 else if( rmin >= rmax )
379 else if( start_phi != 0. )
382 double r = cut_atStart;
383 double R = cut_atDelta;
385 double cath = r - R * std::cos( delta_phi*units::deg );
386 double hypo = std::sqrt( r*r + R*R - 2.*r*R * std::cos( delta_phi*units::deg ));
387 double cos_alpha = cath / hypo;
388 double alpha = std::acos( cos_alpha );
389 double sin_alpha = std::sin( std::fabs(alpha) );
394 double boxX = 1.1*rmax + rmax/sin_alpha;
397 double boxZ = 1.1 * dz;
400 xBox = r - boxY / sin_alpha;
402 xBox = r + boxY / sin_alpha;
406 rot.RotateZ( -alpha/dd4hep::deg );
407 TGeoTranslation trans(xBox, 0., 0.);
408 TGeoBBox* box =
new TGeoBBox((nam+
"Box").c_str(), boxX, boxY, boxZ);
409 TGeoTubeSeg* tubs =
new TGeoTubeSeg((nam+
"Tubs").c_str(), rmin, rmax, dz, start_phi, delta_phi);
410 TGeoCombiTrans* combi =
new TGeoCombiTrans(trans, rot);
411 TGeoSubtraction* sub =
new TGeoSubtraction(tubs, box,
nullptr, combi);
413 std::stringstream params;
414 params << dz <<
" " << std::endl
415 << rmin <<
" " << std::endl
416 << rmax <<
" " << std::endl
417 << start_phi*units::deg <<
" " << std::endl
418 << delta_phi*units::deg <<
" " << std::endl
419 << cut_atStart <<
" " << std::endl
420 << cut_atDelta <<
" " << std::endl
421 << char(cut_inside ?
'1' :
'0') << std::endl;
422 combi->SetTitle(params.str().c_str());
426 <<
"\t dz: " << dz <<
" " << std::endl
427 <<
"\t rmin: " << rmin <<
" " << std::endl
428 <<
"\t rmax: " << rmax <<
" " << std::endl
429 <<
"\t startPhi: " << start_phi <<
" " << std::endl
430 <<
"\t deltaPhi: " << delta_phi <<
" " << std::endl
431 <<
"\t r/cutAtStart:" << cut_atStart <<
" " << std::endl
432 <<
"\t R/cutAtDelta:" << cut_atDelta <<
" " << std::endl
433 <<
"\t cutInside: " << char(cut_inside ?
'1' :
'0') << std::endl
434 <<
"\t\t alpha: " << alpha << std::endl
435 <<
"\t\t sin_alpha: " << sin_alpha << std::endl
436 <<
"\t\t boxY: " << boxY << std::endl
437 <<
"\t\t xBox: " << xBox << std::endl;
440 cout <<
"Trans:"; trans.Print(); cout << std::endl;
441 cout <<
"Rot: "; rot.Print(); cout << std::endl;
442 cout <<
" Dz: " << dz
445 <<
" r/cutAtStart: " << r
446 <<
" R/cutAtDelta: " << R
447 <<
" cutInside: " << (cut_inside ?
"YES" :
"NO ")
449 cout <<
" cath: " << cath
451 <<
" cos_alpha: " << cos_alpha
452 <<
" alpha: " << alpha
453 <<
" alpha(deg):" << alpha/dd4hep::deg
455 cout <<
" Deg: " << dd4hep::deg
456 <<
" cm: " << dd4hep::cm
459 cout <<
"Box:" <<
"x:" << box->GetDX() <<
" y:" << box->GetDY() <<
" z:" << box->GetDZ() << std::endl;
460 cout <<
"Tubs:" <<
" rmin:" << rmin <<
" rmax" << rmax <<
"dZ" <<
dZ
461 <<
" startPhi:" << start_phi <<
" deltaPhi:" << delta_phi << std::endl;
512 double zneg,
double zpos,
int nsegments,
double totphi) {
513 _assign(
new TwistedTubeObject(nam.c_str(), twist_angle/units::deg, rmin, rmax, zneg, zpos, nsegments, totphi/units::deg),
518 void Trd1::make(
const std::string& nam,
double x1,
double x2,
double y,
double z) {
524 double params[] = { x1, x2, y, z };
530 void Trd2::make(
const std::string& nam,
double x1,
double x2,
double y1,
double y2,
double z) {
531 _assign(
new TGeoTrd2(nam.c_str(), x1, x2, y1, y2, z ),
"",
TRD2_TAG,
true);
536 double params[] = { x1, x2, y1, y2, z };
542 void Paraboloid::make(
const std::string& nam,
double r_low,
double r_high,
double delta_z) {
548 double params[] = { r_low, r_high, delta_z };
554 void Hyperboloid::make(
const std::string& nam,
double rin,
double stin,
double rout,
double stout,
double dz) {
555 _assign(
new TGeoHype(nam.c_str(), rin, stin/units::deg, rout, stout/units::deg, dz),
"",
HYPERBOLOID_TAG,
true);
560 double params[] = { rin, stin/units::deg, rout, stout/units::deg, dz};
566 void Sphere::make(
const std::string& nam,
double rmin,
double rmax,
double startTheta,
double endTheta,
double startPhi,
double endPhi) {
567 _assign(
new TGeoSphere(nam.c_str(), rmin, rmax,
580 void Torus::make(
const std::string& nam,
double r,
double rmin,
double rmax,
double startPhi,
double deltaPhi) {
593 double h1,
double bl1,
double tl1,
double alpha1,
594 double h2,
double bl2,
double tl2,
double alpha2) {
596 h1, bl1, tl1,
alpha1/units::deg,
602 double z,
double theta,
double phi,
603 double h1,
double bl1,
double tl1,
double alpha1,
604 double h2,
double bl2,
double tl2,
double alpha2) {
606 h1, bl1, tl1,
alpha1/units::deg,
611 void Trap::make(
const std::string& nam,
double pZ,
double pY,
double pX,
double pLTX) {
615 double fDy1 = 0.5*pY;
616 double fDx1 = 0.5*pX;
617 double fDx2 = 0.5*pLTX;
618 double fAlpha1 = atan(0.5*(pLTX - pX)/pY);
622 double fAlpha2 = fAlpha1;
624 _assign(
new TGeoTrap(nam.c_str(),
626 fDy1, fDx1, fDx2, fAlpha1/units::deg,
627 fDy2, fDx3, fDx4, fAlpha2/units::deg),
"",
TRAP_TAG,
true);
632 double h1,
double bl1,
double tl1,
double alpha1,
633 double h2,
double bl2,
double tl2,
double alpha2) {
634 double params[] = { z,
theta/units::deg,
phi/units::deg,
635 h1, bl1, tl1,
alpha1/units::deg,
636 h2, bl2, tl2,
alpha2/units::deg };
642 void PseudoTrap::make(
const std::string& nam,
double x1,
double x2,
double y1,
double y2,
double z,
double r,
bool atMinusZ) {
643 double x = atMinusZ ? x1 : x2;
645 bool intersec =
false;
646 double displacement = 0;
649 double halfOpeningAngle = std::asin( x / std::abs( r ))/units::deg;
652 double delta = std::sqrt( r * r - x * x );
657 if( r < 0 && std::abs(r) >= x ) {
659 h = y1 < y2 ? y2 : y1;
662 displacement = -halfZ -
delta;
663 startPhi = 270.0 - halfOpeningAngle;
666 displacement = halfZ +
delta;
667 startPhi = 90.0 - halfOpeningAngle;
670 else if( r > 0 && std::abs(r) >= x ) {
672 displacement = -halfZ +
delta;
673 startPhi = 90.0 - halfOpeningAngle;
678 displacement = halfZ -
delta;
679 startPhi = 270.0 - halfOpeningAngle;
690 if( r < 0 && std::abs(r) >= x ) {
692 h = y1 < y2 ? y2 : y1;
695 displacement = - halfZ -
delta;
696 startPhi = 90.0 - halfOpeningAngle;
699 displacement = halfZ +
delta;
700 startPhi = -90.0 - halfOpeningAngle;
703 else if( r > 0 && std::abs(r) >= x ) {
705 displacement = - halfZ +
delta;
706 startPhi = 270.0 - halfOpeningAngle;
711 displacement = halfZ -
delta;
712 startPhi = 90.0 - halfOpeningAngle;
719 printout(DEBUG,
"PseudoTrap",
"++ Trd2(%s): x1=%.3g x2=%.3g y1=%.3g y2=%.3g halfZ=%.3g",
720 (nam+
"Trd2").c_str(), x1, x2, y1, y2, halfZ);
721 printout(DEBUG,
"PseudoTrap",
"++ Tubs(%s): r=%.3g h=%.3g startPhi=%.3g endPhi=%.3g",
722 (nam+
"Tubs").c_str(), std::abs(r),h,startPhi,startPhi + halfOpeningAngle*2.);
724 Solid trap(
new TGeoTrd2((nam+
"Trd2").c_str(), x1, x2, y1, y2, halfZ));
725 Solid tubs(
new TGeoTubeSeg((nam+
"Tubs").c_str(), 0.,std::abs(r),h,startPhi,startPhi + halfOpeningAngle*2.));
726 std::stringstream params;
727 params << x1 <<
" " << x2 <<
" " << y1 <<
" " << y2 <<
" " << z <<
" "
728 << r <<
" " << char(atMinusZ ?
'1' :
'0') <<
" ";
729 TGeoCompositeShape* solid = 0;
731 printout(DEBUG,
"PseudoTrap",
"++ Intersection displacement=%.3g", displacement);
735 printout(DEBUG,
"PseudoTrap",
"++ Union displacement=%.3g sqrt(r*r-x*x)=%.3g", displacement, std::sqrt(r*r-x*x));
739 solid->GetBoolNode()->GetRightMatrix()->SetTitle(params.str().c_str());
745 double zpos,
double zneg,
double start,
double delta) {
746 if (rmin < 0e0 || rmin > rmax)
747 throw std::runtime_error(
"dd4hep: PolyhedraRegular: Illegal argument rmin:<" +
_toString(rmin) +
"> is invalid!");
749 throw std::runtime_error(
"dd4hep: PolyhedraRegular: Illegal argument rmax:<" +
_toString(rmax) +
"> is invalid!");
750 double params[] = { start/units::deg,
delta/units::deg, double(nsides), 2e0, zpos, rmin, rmax, zneg, rmin, rmax };
757 const std::vector<double>& z,
const std::vector<double>& rmin,
const std::vector<double>& rmax) {
758 std::vector<double> temp;
759 if ( rmin.size() !=
z.size() || rmax.size() !=
z.size() ) {
761 "Number of values to define zplanes are incorrect: z:%ld rmin:%ld rmax:%ld",
762 z.size(), rmin.size(), rmax.size());
765 temp.reserve(4+
z.size()*2);
766 temp.emplace_back(start/units::deg);
767 temp.emplace_back(
delta/units::deg);
768 temp.emplace_back(
double(nsides));
769 temp.emplace_back(
double(
z.size()));
770 for(std::size_t i=0; i<
z.size(); ++i) {
771 temp.emplace_back(
z[i]);
772 temp.emplace_back(rmin[i]);
773 temp.emplace_back(rmax[i]);
780 const std::vector<double>& pt_x,
781 const std::vector<double>& pt_y,
782 const std::vector<double>& sec_z,
783 const std::vector<double>& sec_x,
784 const std::vector<double>& sec_y,
785 const std::vector<double>& sec_scale)
787 TGeoXtru* solid =
new TGeoXtru(sec_z.size());
790 solid->DefinePolygon(pt_x.size(), &(*pt_x.begin()), &(*pt_y.begin()));
791 for( std::size_t i = 0; i < sec_z.size(); ++i )
792 solid->DefineSection(i, sec_z[i], sec_x[i], sec_y[i], sec_scale[i]);
812 return access()->AddFacet(pt0, pt1, pt2);
817 return access()->AddFacet(pt0, pt1, pt2, pt3);
822 return access()->AddFacet(pt0, pt1, pt2);
827 return access()->AddFacet(pt0, pt1, pt2, pt3);
832 return access()->GetNvertices();
837 return ptr()->GetFacet(index);
842 return access()->GetNvertices();
847 return ptr()->GetVertex(index);
852 return access()->GetBoolNode()->GetRightShape();
857 return access()->GetBoolNode()->GetLeftShape();
862 return access()->GetBoolNode()->GetRightMatrix();
867 return access()->GetBoolNode()->GetLeftMatrix();
1051 #define INSTANTIATE(X) template class dd4hep::Solid_type<X>