59 SetShapeBit(TGeoShape::kGeoPara);
72 TGeoPara::TGeoPara(Double_t dx, Double_t dy, Double_t dz, Double_t alpha,
73 Double_t theta, Double_t phi)
76 SetShapeBit(TGeoShape::kGeoPara);
83 fTxy = TMath::Tan(alpha*TMath::DegToRad());
84 Double_t tth = TMath::Tan(theta*TMath::DegToRad());
85 Double_t ph = phi*TMath::DegToRad();
86 fTxz = tth*TMath::Cos(ph);
87 fTyz = tth*TMath::Sin(ph);
88 if ((fX<0) || (fY<0) || (fZ<0)) {
90 SetShapeBit(kGeoRunTimeShape);
98 TGeoPara::TGeoPara(
const char *name, Double_t dx, Double_t dy, Double_t dz, Double_t alpha,
99 Double_t theta, Double_t phi)
100 :TGeoBBox(name, 0, 0, 0)
102 SetShapeBit(TGeoShape::kGeoPara);
109 fTxy = TMath::Tan(alpha*TMath::DegToRad());
110 Double_t tth = TMath::Tan(theta*TMath::DegToRad());
111 Double_t ph = phi*TMath::DegToRad();
112 fTxz = tth*TMath::Cos(ph);
113 fTyz = tth*TMath::Sin(ph);
114 if ((fX<0) || (fY<0) || (fZ<0)) {
116 SetShapeBit(kGeoRunTimeShape);
130 TGeoPara::TGeoPara(Double_t *param)
133 SetShapeBit(TGeoShape::kGeoPara);
134 SetDimensions(param);
135 if ((fX<0) || (fY<0) || (fZ<0)) SetShapeBit(kGeoRunTimeShape);
142 TGeoPara::~TGeoPara()
149 Double_t TGeoPara::Capacity()
const
151 Double_t capacity = 8.*fX*fY*fZ;
158 void TGeoPara::ComputeBBox()
160 Double_t dx = fX+fY*TMath::Abs(fTxy)+fZ*TMath::Abs(fTxz);
161 Double_t dy = fY+fZ*TMath::Abs(fTyz);
163 TGeoBBox::SetBoxDimensions(dx, dy, dz);
164 memset(fOrigin, 0, 3*
sizeof(Double_t));
170 void TGeoPara::ComputeNormal(
const Double_t *point,
const Double_t *dir, Double_t *norm)
174 saf[0] = TMath::Abs(fZ-TMath::Abs(point[2]));
176 Double_t yt = point[1]-fTyz*point[2];
177 saf[1] = TMath::Abs(fY-TMath::Abs(yt));
179 Double_t cty = 1.0/TMath::Sqrt(1.0+fTyz*fTyz);
181 Double_t xt = point[0]-fTxz*point[2]-fTxy*yt;
182 saf[2] = TMath::Abs(fX-TMath::Abs(xt));
184 Double_t ctx = 1.0/TMath::Sqrt(1.0+fTxy*fTxy+fTxz*fTxz);
187 Int_t i = TMath::LocMin(3,saf);
190 norm[0] = norm[1] = 0;
191 norm[2] = TMath::Sign(1.,dir[2]);
196 norm[2] = - fTyz*cty;
199 norm[0] = TMath::Cos(fTheta*TMath::DegToRad())*TMath::Cos(fAlpha*TMath::DegToRad());
200 norm[1] = - TMath::Cos(fTheta*TMath::DegToRad())*TMath::Sin(fAlpha*TMath::DegToRad());
201 norm[2] = -TMath::Sin(fTheta*TMath::DegToRad());
203 if (norm[0]*dir[0]+norm[1]*dir[1]+norm[2]*dir[2]<0) {
214 Bool_t TGeoPara::Contains(
const Double_t *point)
const
216 if (TMath::Abs(point[2]) > fZ)
return kFALSE;
218 Double_t yt=point[1]-fTyz*point[2];
219 if (TMath::Abs(yt) > fY)
return kFALSE;
220 Double_t xt=point[0]-fTxz*point[2]-fTxy*yt;
221 if (TMath::Abs(xt) > fX)
return kFALSE;
229 Double_t TGeoPara::DistFromInside(
const Double_t *point,
const Double_t *dir, Int_t iact, Double_t step, Double_t *safe)
const
231 if (iact<3 && safe) {
233 *safe = Safety(point, kTRUE);
234 if (iact==0)
return TGeoShape::Big();
235 if (iact==1 && step<*safe)
return TGeoShape::Big();
238 Double_t snxt = TGeoShape::Big();
240 saf[0] = fZ+point[2];
241 saf[1] = fZ-point[2];
242 if (!TGeoShape::IsSameWithinTolerance(dir[2],0)) {
243 s = (dir[2]>0)?(saf[1]/dir[2]):(-saf[0]/dir[2]);
245 if (s<snxt) snxt = s;
248 Double_t yt = point[1]-fTyz*point[2];
251 Double_t dy = dir[1]-fTyz*dir[2];
252 if (!TGeoShape::IsSameWithinTolerance(dy,0)) {
253 s = (dy>0)?(saf[1]/dy):(-saf[0]/dy);
255 if (s<snxt) snxt = s;
258 Double_t xt = point[0]-fTxz*point[2]-fTxy*yt;
261 Double_t dx = dir[0]-fTxz*dir[2]-fTxy*dy;
262 if (!TGeoShape::IsSameWithinTolerance(dx,0)) {
263 s = (dx>0)?(saf[1]/dx):(-saf[0]/dx);
265 if (s<snxt) snxt = s;
273 Double_t TGeoPara::DistFromOutside(
const Double_t *point,
const Double_t *dir, Int_t iact, Double_t step, Double_t *safe)
const
275 Double_t snxt=TGeoShape::Big();
276 if (iact<3 && safe) {
278 *safe = Safety(point, kFALSE);
279 if (iact==0)
return TGeoShape::Big();
280 if (iact==1 && step<*safe)
return TGeoShape::Big();
284 safz = TMath::Abs(point[2])-fZ;
287 if (point[2]*dir[2]>=0)
return TGeoShape::Big();
290 Double_t yt=point[1]-fTyz*point[2];
291 Double_t safy = TMath::Abs(yt)-fY;
292 Double_t dy=dir[1]-fTyz*dir[2];
294 if (yt*dy>=0)
return TGeoShape::Big();
297 Double_t xt=point[0]-fTxy*yt-fTxz*point[2];
298 Double_t safx = TMath::Abs(xt)-fX;
299 Double_t dx=dir[0]-fTxy*dy-fTxz*dir[2];
301 if (xt*dx>=0)
return TGeoShape::Big();
306 if (safz>safx && safz>safy) {
307 if (point[2]*dir[2]>0)
return TGeoShape::Big();
311 if (xt*dx>0)
return TGeoShape::Big();
314 if (yt*dy>0)
return TGeoShape::Big();
317 Double_t xnew,ynew,znew;
319 snxt = safz/TMath::Abs(dir[2]);
320 xnew = point[0]+snxt*dir[0];
321 ynew = point[1]+snxt*dir[1];
322 znew = (point[2]>0)?fZ:(-fZ);
323 Double_t ytn = ynew-fTyz*znew;
324 if (TMath::Abs(ytn)<=fY) {
325 Double_t xtn = xnew-fTxy*ytn-fTxz*znew;
326 if (TMath::Abs(xtn)<=fX)
return snxt;
330 snxt = safy/TMath::Abs(dy);
331 znew = point[2]+snxt*dir[2];
332 if (TMath::Abs(znew)<=fZ) {
333 Double_t ytn = (yt>0)?fY:(-fY);
334 xnew = point[0]+snxt*dir[0];
335 Double_t xtn = xnew-fTxy*ytn-fTxz*znew;
336 if (TMath::Abs(xtn)<=fX)
return snxt;
340 snxt = safx/TMath::Abs(dx);
341 znew = point[2]+snxt*dir[2];
342 if (TMath::Abs(znew)<=fZ) {
343 ynew = point[1]+snxt*dir[1];
344 Double_t ytn = ynew-fTyz*znew;
345 if (TMath::Abs(ytn)<=fY)
return snxt;
348 return TGeoShape::Big();
357 TGeoVolume *TGeoPara::Divide(TGeoVolume *voldiv,
const char *divname, Int_t iaxis, Int_t ndiv,
358 Double_t start, Double_t step)
362 TGeoVolumeMulti *vmulti;
363 TGeoPatternFinder *finder;
365 Double_t end=start+ndiv*step;
368 shape =
new TGeoPara(step/2, fY, fZ,fAlpha,fTheta, fPhi);
369 finder =
new TGeoPatternParaX(voldiv, ndiv, start, end);
373 shape =
new TGeoPara(fX, step/2, fZ, fAlpha, fTheta, fPhi);
374 finder =
new TGeoPatternParaY(voldiv, ndiv, start, end);
378 shape =
new TGeoPara(fX, fY, step/2, fAlpha, fTheta, fPhi);
379 finder =
new TGeoPatternParaZ(voldiv, ndiv, start, end);
383 Error(
"Divide",
"Wrong axis type for division");
386 vol =
new TGeoVolume(divname, shape, voldiv->GetMedium());
387 vmulti = gGeoManager->MakeVolumeMulti(divname, voldiv->GetMedium());
388 vmulti->AddVolume(vol);
389 voldiv->SetFinder(finder);
390 finder->SetDivIndex(voldiv->GetNdaughters());
391 for (Int_t ic=0; ic<ndiv; ic++) {
392 voldiv->AddNodeOffset(vol, ic, start+step/2.+ic*step, opt.Data());
393 ((TGeoNodeOffset*)voldiv->GetNodes()->At(voldiv->GetNdaughters()-1))->SetFinder(finder);
401 Double_t TGeoPara::GetAxisRange(Int_t iaxis, Double_t &xlo, Double_t &xhi)
const
430 void TGeoPara::GetBoundingCylinder(Double_t *param)
const
432 TGeoBBox::GetBoundingCylinder(param);
438 Int_t TGeoPara::GetFittingBox(
const TGeoBBox *parambox, TGeoMatrix *mat, Double_t &dx, Double_t &dy, Double_t &dz)
const
441 if (mat->IsRotation()) {
442 Error(
"GetFittingBox",
"cannot handle parametrized rotated volumes");
447 mat->LocalToMaster(parambox->GetOrigin(), origin);
448 if (!Contains(origin)) {
449 Error(
"GetFittingBox",
"wrong matrix - parametrized box is outside this");
454 dd[0] = parambox->GetDX();
455 dd[1] = parambox->GetDY();
456 dd[2] = parambox->GetDZ();
459 dd[2] = TMath::Min(origin[2]+fZ, fZ-origin[2]);
461 Error(
"GetFittingBox",
"wrong matrix");
465 if (dd[0]>=0 && dd[1]>=0) {
474 Double_t z=origin[2]-dd[2];
475 lower[0]=z*fTxz-fTxy*fY-fX;
477 lower[2]=z*fTxz+fTxy*fY-fX;
479 lower[4]=z*fTxz+fTxy*fY+fX;
481 lower[6]=z*fTxz-fTxy*fY+fX;
484 upper[0]=z*fTxz-fTxy*fY-fX;
486 upper[2]=z*fTxz+fTxy*fY-fX;
488 upper[4]=z*fTxz+fTxy*fY+fX;
490 upper[6]=z*fTxz-fTxy*fY+fX;
493 Double_t ddmin=TGeoShape::Big();
494 for (Int_t iaxis=0; iaxis<2; iaxis++) {
495 if (dd[iaxis]>=0)
continue;
496 ddmin=TGeoShape::Big();
497 for (Int_t ivert=0; ivert<4; ivert++) {
498 ddmin = TMath::Min(ddmin, TMath::Abs(origin[iaxis]-lower[2*ivert+iaxis]));
499 ddmin = TMath::Min(ddmin, TMath::Abs(origin[iaxis]-upper[2*ivert+iaxis]));
513 TGeoShape *TGeoPara::GetMakeRuntimeShape(TGeoShape *mother, TGeoMatrix * )
const
515 if (!TestShapeBit(kGeoRunTimeShape))
return 0;
516 if (!mother->TestShapeBit(kGeoPara)) {
517 Error(
"GetMakeRuntimeShape",
"invalid mother");
521 if (fX<0) dx=((TGeoPara*)mother)->GetX();
523 if (fY<0) dy=((TGeoPara*)mother)->GetY();
525 if (fZ<0) dz=((TGeoPara*)mother)->GetZ();
527 return (
new TGeoPara(dx, dy, dz, fAlpha, fTheta, fPhi));
533 void TGeoPara::InspectShape()
const
535 printf(
"*** Shape %s: TGeoPara ***\n", GetName());
536 printf(
" dX = %11.5f\n", fX);
537 printf(
" dY = %11.5f\n", fY);
538 printf(
" dZ = %11.5f\n", fZ);
539 printf(
" alpha = %11.5f\n", fAlpha);
540 printf(
" theta = %11.5f\n", fTheta);
541 printf(
" phi = %11.5f\n", fPhi);
542 printf(
" Bounding box:\n");
543 TGeoBBox::InspectShape();
550 Double_t TGeoPara::Safety(
const Double_t *point, Bool_t in)
const
554 saf[0] = fZ-TMath::Abs(point[2]);
556 Double_t yt = point[1]-fTyz*point[2];
557 saf[1] = fY-TMath::Abs(yt);
559 Double_t cty = 1.0/TMath::Sqrt(1.0+fTyz*fTyz);
561 Double_t xt = point[0]-fTxz*point[2]-fTxy*yt;
562 saf[2] = fX-TMath::Abs(xt);
564 Double_t ctx = 1.0/TMath::Sqrt(1.0+fTxy*fTxy+fTxz*fTxz);
567 if (in)
return saf[TMath::LocMin(3,saf)];
568 for (Int_t i=0; i<3; i++) saf[i]=-saf[i];
569 return saf[TMath::LocMax(3,saf)];
575 void TGeoPara::SavePrimitive(std::ostream &out, Option_t * )
577 if (TObject::TestBit(kGeoSavePrimitive))
return;
578 out <<
" // Shape: " << GetName() <<
" type: " << ClassName() << std::endl;
579 out <<
" dx = " << fX <<
";" << std::endl;
580 out <<
" dy = " << fY <<
";" << std::endl;
581 out <<
" dz = " << fZ <<
";" << std::endl;
582 out <<
" alpha = " << fAlpha<<
";" << std::endl;
583 out <<
" theta = " << fTheta <<
";" << std::endl;
584 out <<
" phi = " << fPhi <<
";" << std::endl;
585 out <<
" TGeoShape *" << GetPointerName() <<
" = new TGeoPara(\"" << GetName() <<
"\",dx,dy,dz,alpha,theta,phi);" << std::endl;
586 TObject::SetBit(TGeoShape::kGeoSavePrimitive);
592 void TGeoPara::SetDimensions(Double_t *param)
600 fTxy = TMath::Tan(param[3]*TMath::DegToRad());
601 Double_t tth = TMath::Tan(param[4]*TMath::DegToRad());
602 Double_t ph = param[5]*TMath::DegToRad();
603 fTxz = tth*TMath::Cos(ph);
604 fTyz = tth*TMath::Sin(ph);
610 void TGeoPara::SetPoints(Double_t *points)
const
616 *points++ = -fZ*txz-txy*fY-fX; *points++ = -fY-fZ*tyz; *points++ = -fZ;
617 *points++ = -fZ*txz+txy*fY-fX; *points++ = +fY-fZ*tyz; *points++ = -fZ;
618 *points++ = -fZ*txz+txy*fY+fX; *points++ = +fY-fZ*tyz; *points++ = -fZ;
619 *points++ = -fZ*txz-txy*fY+fX; *points++ = -fY-fZ*tyz; *points++ = -fZ;
620 *points++ = +fZ*txz-txy*fY-fX; *points++ = -fY+fZ*tyz; *points++ = +fZ;
621 *points++ = +fZ*txz+txy*fY-fX; *points++ = +fY+fZ*tyz; *points++ = +fZ;
622 *points++ = +fZ*txz+txy*fY+fX; *points++ = +fY+fZ*tyz; *points++ = +fZ;
623 *points++ = +fZ*txz-txy*fY+fX; *points++ = -fY+fZ*tyz; *points++ = +fZ;
629 void TGeoPara::SetPoints(Float_t *points)
const
635 *points++ = -fZ*txz-txy*fY-fX; *points++ = -fY-fZ*tyz; *points++ = -fZ;
636 *points++ = -fZ*txz+txy*fY-fX; *points++ = +fY-fZ*tyz; *points++ = -fZ;
637 *points++ = -fZ*txz+txy*fY+fX; *points++ = +fY-fZ*tyz; *points++ = -fZ;
638 *points++ = -fZ*txz-txy*fY+fX; *points++ = -fY-fZ*tyz; *points++ = -fZ;
639 *points++ = +fZ*txz-txy*fY-fX; *points++ = -fY+fZ*tyz; *points++ = +fZ;
640 *points++ = +fZ*txz+txy*fY-fX; *points++ = +fY+fZ*tyz; *points++ = +fZ;
641 *points++ = +fZ*txz+txy*fY+fX; *points++ = +fY+fZ*tyz; *points++ = +fZ;
642 *points++ = +fZ*txz-txy*fY+fX; *points++ = -fY+fZ*tyz; *points++ = +fZ;
648 void TGeoPara::Sizeof3D()
const
650 TGeoBBox::Sizeof3D();
658 void TGeoPara::Contains_v(
const Double_t *points, Bool_t *inside, Int_t vecsize)
const
660 for (Int_t i=0; i<vecsize; i++) inside[i] = Contains(&points[3*i]);
668 void TGeoPara::ComputeNormal_v(
const Double_t *points,
const Double_t *dirs, Double_t *norms, Int_t vecsize)
670 for (Int_t i=0; i<vecsize; i++) ComputeNormal(&points[3*i], &dirs[3*i], &norms[3*i]);
676 void TGeoPara::DistFromInside_v(
const Double_t *points,
const Double_t *dirs, Double_t *dists, Int_t vecsize, Double_t* step)
const
678 for (Int_t i=0; i<vecsize; i++) dists[i] = DistFromInside(&points[3*i], &dirs[3*i], 3, step[i]);
684 void TGeoPara::DistFromOutside_v(
const Double_t *points,
const Double_t *dirs, Double_t *dists, Int_t vecsize, Double_t* step)
const
686 for (Int_t i=0; i<vecsize; i++) dists[i] = DistFromOutside(&points[3*i], &dirs[3*i], 3, step[i]);
694 void TGeoPara::Safety_v(
const Double_t *points,
const Bool_t *inside, Double_t *safe, Int_t vecsize)
const
696 for (Int_t i=0; i<vecsize; i++) safe[i] = Safety(&points[3*i], inside[i]);