54 fDz = fDx1 = fDx2 = fDy = 0;
55 SetShapeBit(kGeoTrd1);
61 TGeoTrd1::TGeoTrd1(Double_t dx1, Double_t dx2, Double_t dy, Double_t dz)
64 SetShapeBit(kGeoTrd1);
69 if ((dx1<0) || (dx2<0) || (dy<0) || (dz<0)) {
70 SetShapeBit(kGeoRunTimeShape);
71 printf(
"trd1 : dx1=%f, dx2=%f, dy=%f, dz=%f\n",
80 TGeoTrd1::TGeoTrd1(
const char *name, Double_t dx1, Double_t dx2, Double_t dy, Double_t dz)
81 :TGeoBBox(name, 0,0,0)
83 SetShapeBit(kGeoTrd1);
88 if ((dx1<0) || (dx2<0) || (dy<0) || (dz<0)) {
89 SetShapeBit(kGeoRunTimeShape);
90 printf(
"trd1 : dx1=%f, dx2=%f, dy=%f, dz=%f\n",
103 TGeoTrd1::TGeoTrd1(Double_t *param)
106 SetShapeBit(kGeoTrd1);
107 SetDimensions(param);
108 if ((fDx1<0) || (fDx2<0) || (fDy<=0) || (fDz<=0)) SetShapeBit(kGeoRunTimeShape);
115 TGeoTrd1::~TGeoTrd1()
122 Double_t TGeoTrd1::Capacity()
const
124 Double_t capacity = 4.*(fDx1+fDx2)*fDy*fDz;
131 void TGeoTrd1::ComputeBBox()
133 fDX = TMath::Max(fDx1, fDx2);
136 memset(fOrigin, 0, 3*
sizeof(Double_t));
142 void TGeoTrd1::ComputeNormal(
const Double_t *point,
const Double_t *dir, Double_t *norm)
144 Double_t safe, safemin;
146 Double_t fx = 0.5*(fDx1-fDx2)/fDz;
147 Double_t calf = 1./TMath::Sqrt(1.0+fx*fx);
149 safe = safemin = TMath::Abs(fDz-TMath::Abs(point[2]));
150 norm[0] = norm[1] = 0;
151 norm[2] = (dir[2]>=0)?1:-1;
152 if (safe<1E-6)
return;
154 Double_t distx = 0.5*(fDx1+fDx2)-fx*point[2];
156 safe=TMath::Abs(distx-TMath::Abs(point[0]))*calf;
159 norm[0] = (point[0]>0)?calf:(-calf);
162 Double_t dot = norm[0]*dir[0]+norm[1]*dir[1]+norm[2]*dir[2];
167 if (safe<1E-6)
return;
171 safe = TMath::Abs(fDy-TMath::Abs(point[1]));
173 norm[0] = norm[2] = 0;
174 norm[1] = (dir[1]>=0)?1:-1;
182 Bool_t TGeoTrd1::Contains(
const Double_t *point)
const
184 if (TMath::Abs(point[2]) > fDz)
return kFALSE;
186 if (TMath::Abs(point[1]) > fDy)
return kFALSE;
188 Double_t dx = 0.5*(fDx2*(point[2]+fDz)+fDx1*(fDz-point[2]))/fDz;
189 if (TMath::Abs(point[0]) > dx)
return kFALSE;
197 Double_t TGeoTrd1::DistFromInside(
const Double_t *point,
const Double_t *dir, Int_t iact, Double_t step, Double_t *safe)
const
199 Double_t snxt = TGeoShape::Big();
200 if (iact<3 && safe) {
202 *safe = Safety(point, kTRUE);
203 if (iact==0)
return TGeoShape::Big();
204 if (iact==1 && step<*safe)
return TGeoShape::Big();
208 Double_t fx = 0.5*(fDx1-fDx2)/fDz;
210 Double_t distx = 0.5*(fDx1+fDx2)-fx*point[2];
214 for (Int_t i=0; i<3; i++) dist[i]=TGeoShape::Big();
216 dist[0]=-(point[2]+fDz)/dir[2];
217 }
else if (dir[2]>0) {
218 dist[0]=(fDz-point[2])/dir[2];
220 if (dist[0]<=0)
return 0.0;
222 cn = -dir[0]+fx*dir[2];
224 dist[1] = point[0]+distx;
225 if (dist[1]<=0)
return 0.0;
228 cn = dir[0]+fx*dir[2];
230 Double_t s = distx-point[0];
231 if (s<=0)
return 0.0;
233 if (s<dist[1]) dist[1] = s;
237 dist[2]=-(point[1]+fDy)/dir[1];
238 }
else if (dir[1]>0) {
239 dist[2]=(fDy-point[1])/dir[1];
241 if (dist[2]<=0)
return 0.0;
242 snxt = dist[TMath::LocMin(3,dist)];
249 void TGeoTrd1::GetVisibleCorner(
const Double_t *point, Double_t *vertex, Double_t *normals)
const
251 Double_t fx = 0.5*(fDx1-fDx2)/fDz;
252 Double_t calf = 1./TMath::Sqrt(1.0+fx*fx);
253 Double_t salf = calf*fx;
255 Double_t distx = 0.5*(fDx1+fDx2)-fx*point[2];
256 memset(normals, 0, 9*
sizeof(Double_t));
257 TGeoTrd1 *trd1 = (TGeoTrd1*)
this;
258 if (point[0]>distx) {
260 trd1->SetShapeBit(kGeoVisX);
264 trd1->SetShapeBit(kGeoVisX, kFALSE);
270 trd1->SetShapeBit(kGeoVisY);
273 trd1->SetShapeBit(kGeoVisY, kFALSE);
278 trd1->SetShapeBit(kGeoVisZ);
281 trd1->SetShapeBit(kGeoVisZ, kFALSE);
290 void TGeoTrd1::GetOppositeCorner(
const Double_t * , Int_t inorm, Double_t *vertex, Double_t *normals)
const
292 TGeoTrd1 *trd1 = (TGeoTrd1*)
this;
295 trd1->SetShapeBit(kGeoVisX, !TestShapeBit(kGeoVisX));
296 normals[0]=-normals[0];
300 trd1->SetShapeBit(kGeoVisY, !TestShapeBit(kGeoVisY));
301 normals[4]=-normals[4];
305 trd1->SetShapeBit(kGeoVisZ, !TestShapeBit(kGeoVisZ));
306 normals[8]=-normals[8];
315 Double_t TGeoTrd1::DistFromOutside(
const Double_t *point,
const Double_t *dir, Int_t iact, Double_t step, Double_t *safe)
const
317 Double_t snxt = TGeoShape::Big();
318 if (iact<3 && safe) {
320 *safe = Safety(point, kFALSE);
321 if (iact==0)
return TGeoShape::Big();
322 if (iact==1 && step<*safe)
return TGeoShape::Big();
325 Double_t xnew,ynew,znew;
326 Double_t fx = 0.5*(fDx1-fDx2)/fDz;
328 Double_t distx = 0.5*(fDx1+fDx2)-fx*point[2];
330 Double_t safx = distx-TMath::Abs(point[0]);
331 Double_t safy = fDy-TMath::Abs(point[1]);
332 Double_t safz = fDz-TMath::Abs(point[2]);
336 if (point[2]<=-fDz) {
337 if (dir[2]<=0)
return TGeoShape::Big();
339 snxt = -(fDz+point[2])/dir[2];
341 xnew = point[0]+snxt*dir[0];
342 if (TMath::Abs(xnew) <= fDx1) {
343 ynew = point[1]+snxt*dir[1];
344 if (TMath::Abs(ynew) <= fDy)
return snxt;
346 }
else if (point[2]>=fDz) {
347 if (dir[2]>=0)
return TGeoShape::Big();
349 snxt = (fDz-point[2])/dir[2];
351 xnew = point[0]+snxt*dir[0];
352 if (TMath::Abs(xnew) <= fDx2) {
353 ynew = point[1]+snxt*dir[1];
354 if (TMath::Abs(ynew) <= fDy)
return snxt;
358 if (point[0]<=-distx) {
359 cn = -dir[0]+fx*dir[2];
360 if (cn>=0)
return TGeoShape::Big();
362 snxt = (point[0]+distx)/cn;
364 ynew = point[1]+snxt*dir[1];
365 if (TMath::Abs(ynew) <= fDy) {
366 znew = point[2]+snxt*dir[2];
367 if (TMath::Abs(znew) <= fDz)
return snxt;
370 if (point[0]>=distx) {
371 cn = dir[0]+fx*dir[2];
372 if (cn>=0)
return TGeoShape::Big();
374 snxt = (distx-point[0])/cn;
376 ynew = point[1]+snxt*dir[1];
377 if (TMath::Abs(ynew) < fDy) {
378 znew = point[2]+snxt*dir[2];
379 if (TMath::Abs(znew) < fDz)
return snxt;
383 if (point[1]<=-fDy) {
385 if (cn>=0)
return TGeoShape::Big();
387 snxt = (point[1]+fDy)/cn;
389 znew = point[2]+snxt*dir[2];
390 if (TMath::Abs(znew) < fDz) {
391 xnew = point[0]+snxt*dir[0];
392 Double_t dx = 0.5*(fDx1+fDx2)-fx*znew;
393 if (TMath::Abs(xnew) < dx)
return snxt;
395 }
else if (point[1]>=fDy) {
397 if (cn>=0)
return TGeoShape::Big();
399 snxt = (fDy-point[1])/cn;
401 znew = point[2]+snxt*dir[2];
402 if (TMath::Abs(znew) < fDz) {
403 xnew = point[0]+snxt*dir[0];
404 Double_t dx = 0.5*(fDx1+fDx2)-fx*znew;
405 if (TMath::Abs(xnew) < dx)
return snxt;
408 if (!in)
return TGeoShape::Big();
410 if (safz<safx && safz<safy) {
411 if (point[2]*dir[2]>=0)
return TGeoShape::Big();
415 if (point[1]*dir[1]>=0)
return TGeoShape::Big();
418 cn = TMath::Sign(1.0,point[0])*dir[0]+fx*dir[2];
419 if (cn>=0)
return TGeoShape::Big();
430 TGeoVolume *TGeoTrd1::Divide(TGeoVolume *voldiv,
const char *divname, Int_t iaxis, Int_t ndiv,
431 Double_t start, Double_t step)
435 TGeoVolumeMulti *vmulti;
436 TGeoPatternFinder *finder;
438 Double_t zmin, zmax, dx1n, dx2n;
440 Double_t end = start+ndiv*step;
443 Warning(
"Divide",
"dividing a Trd1 on X not implemented");
446 finder =
new TGeoPatternY(voldiv, ndiv, start, end);
447 voldiv->SetFinder(finder);
448 finder->SetDivIndex(voldiv->GetNdaughters());
449 shape =
new TGeoTrd1(fDx1, fDx2, step/2, fDz);
450 vol =
new TGeoVolume(divname, shape, voldiv->GetMedium());
451 vmulti = gGeoManager->MakeVolumeMulti(divname, voldiv->GetMedium());
452 vmulti->AddVolume(vol);
454 for (
id=0;
id<ndiv;
id++) {
455 voldiv->AddNodeOffset(vol,
id, start+step/2+
id*step, opt.Data());
456 ((TGeoNodeOffset*)voldiv->GetNodes()->At(voldiv->GetNdaughters()-1))->SetFinder(finder);
460 finder =
new TGeoPatternZ(voldiv, ndiv, start, end);
461 voldiv->SetFinder(finder);
462 finder->SetDivIndex(voldiv->GetNdaughters());
463 vmulti = gGeoManager->MakeVolumeMulti(divname, voldiv->GetMedium());
464 for (
id=0;
id<ndiv;
id++) {
465 zmin = start+
id*step;
466 zmax = start+(
id+1)*step;
467 dx1n = 0.5*(fDx1*(fDz-zmin)+fDx2*(fDz+zmin))/fDz;
468 dx2n = 0.5*(fDx1*(fDz-zmax)+fDx2*(fDz+zmax))/fDz;
469 shape =
new TGeoTrd1(dx1n, dx2n, fDy, step/2.);
470 vol =
new TGeoVolume(divname, shape, voldiv->GetMedium());
471 vmulti->AddVolume(vol);
473 voldiv->AddNodeOffset(vol,
id, start+step/2+
id*step, opt.Data());
474 ((TGeoNodeOffset*)voldiv->GetNodes()->At(voldiv->GetNdaughters()-1))->SetFinder(finder);
478 Error(
"Divide",
"Wrong axis type for division");
486 Double_t TGeoTrd1::GetAxisRange(Int_t iaxis, Double_t &xlo, Double_t &xhi)
const
510 void TGeoTrd1::GetBoundingCylinder(Double_t *param)
const
512 TGeoBBox::GetBoundingCylinder(param);
518 Int_t TGeoTrd1::GetFittingBox(
const TGeoBBox *parambox, TGeoMatrix *mat, Double_t &dx, Double_t &dy, Double_t &dz)
const
521 if (mat->IsRotation()) {
522 Error(
"GetFittingBox",
"cannot handle parametrized rotated volumes");
527 mat->LocalToMaster(parambox->GetOrigin(), origin);
528 if (!Contains(origin)) {
529 Error(
"GetFittingBox",
"wrong matrix - parametrized box is outside this");
534 dd[0] = parambox->GetDX();
535 dd[1] = parambox->GetDY();
536 dd[2] = parambox->GetDZ();
539 dd[2] = TMath::Min(origin[2]+fDz, fDz-origin[2]);
541 Error(
"GetFittingBox",
"wrong matrix");
547 dd[1] = TMath::Min(origin[1]+fDy, fDy-origin[1]);
549 Error(
"GetFittingBox",
"wrong matrix");
560 Double_t fx = 0.5*(fDx1-fDx2)/fDz;
561 Double_t dx0 = 0.5*(fDx1+fDx2);
562 Double_t z=origin[2]-dd[2];
563 dd[0] = dx0-fx*z-origin[0];
565 dd[0] = TMath::Min(dd[0], dx0-fx*z-origin[0]);
567 Error(
"GetFittingBox",
"wrong matrix");
580 TGeoShape *TGeoTrd1::GetMakeRuntimeShape(TGeoShape *mother, TGeoMatrix * )
const
582 if (!TestShapeBit(kGeoRunTimeShape))
return 0;
583 if (!mother->TestShapeBit(kGeoTrd1)) {
584 Error(
"GetMakeRuntimeShape",
"invalid mother");
587 Double_t dx1, dx2, dy, dz;
588 if (fDx1<0) dx1=((TGeoTrd1*)mother)->GetDx1();
590 if (fDx2<0) dx2=((TGeoTrd1*)mother)->GetDx2();
592 if (fDy<0) dy=((TGeoTrd1*)mother)->GetDy();
594 if (fDz<0) dz=((TGeoTrd1*)mother)->GetDz();
597 return (
new TGeoTrd1(dx1, dx2, dy, dz));
603 void TGeoTrd1::InspectShape()
const
605 printf(
"*** Shape %s: TGeoTrd1 ***\n", GetName());
606 printf(
" dx1 = %11.5f\n", fDx1);
607 printf(
" dx2 = %11.5f\n", fDx2);
608 printf(
" dy = %11.5f\n", fDy);
609 printf(
" dz = %11.5f\n", fDz);
610 printf(
" Bounding box:\n");
611 TGeoBBox::InspectShape();
618 Double_t TGeoTrd1::Safety(
const Double_t *point, Bool_t in)
const
623 saf[0] = fDz-TMath::Abs(point[2]);
624 Double_t fx = 0.5*(fDx1-fDx2)/fDz;
625 Double_t calf = 1./TMath::Sqrt(1.0+fx*fx);
627 Double_t distx = 0.5*(fDx1+fDx2)-fx*point[2];
628 if (distx<0) saf[1]=TGeoShape::Big();
629 else saf[1]=(distx-TMath::Abs(point[0]))*calf;
631 saf[2] = fDy-TMath::Abs(point[1]);
632 if (in)
return saf[TMath::LocMin(3,saf)];
633 for (Int_t i=0; i<3; i++) saf[i]=-saf[i];
634 return saf[TMath::LocMax(3,saf)];
640 void TGeoTrd1::SavePrimitive(std::ostream &out, Option_t * )
642 if (TObject::TestBit(kGeoSavePrimitive))
return;
643 out <<
" // Shape: " << GetName() <<
" type: " << ClassName() << std::endl;
644 out <<
" dx1 = " << fDx1 <<
";" << std::endl;
645 out <<
" dx2 = " << fDx2 <<
";" << std::endl;
646 out <<
" dy = " << fDy <<
";" << std::endl;
647 out <<
" dz = " << fDZ <<
";" << std::endl;
648 out <<
" TGeoShape *" << GetPointerName() <<
" = new TGeoTrd1(\"" << GetName() <<
"\", dx1,dx2,dy,dz);" << std::endl;
649 TObject::SetBit(TGeoShape::kGeoSavePrimitive);
655 void TGeoTrd1::SetDimensions(Double_t *param)
667 void TGeoTrd1::SetVertex(Double_t *vertex)
const
669 if (TestShapeBit(kGeoVisX)) {
670 if (TestShapeBit(kGeoVisZ)) {
673 vertex[1] = (TestShapeBit(kGeoVisY))?fDy:-fDy;
677 vertex[1] = (TestShapeBit(kGeoVisY))?fDy:-fDy;
680 if (TestShapeBit(kGeoVisZ)) {
683 vertex[1] = (TestShapeBit(kGeoVisY))?fDy:-fDy;
687 vertex[1] = (TestShapeBit(kGeoVisY))?fDy:-fDy;
695 void TGeoTrd1::SetPoints(Double_t *points)
const
698 points[ 0] = -fDx1; points[ 1] = -fDy; points[ 2] = -fDz;
699 points[ 3] = -fDx1; points[ 4] = fDy; points[ 5] = -fDz;
700 points[ 6] = fDx1; points[ 7] = fDy; points[ 8] = -fDz;
701 points[ 9] = fDx1; points[10] = -fDy; points[11] = -fDz;
702 points[12] = -fDx2; points[13] = -fDy; points[14] = fDz;
703 points[15] = -fDx2; points[16] = fDy; points[17] = fDz;
704 points[18] = fDx2; points[19] = fDy; points[20] = fDz;
705 points[21] = fDx2; points[22] = -fDy; points[23] = fDz;
711 void TGeoTrd1::SetPoints(Float_t *points)
const
714 points[ 0] = -fDx1; points[ 1] = -fDy; points[ 2] = -fDz;
715 points[ 3] = -fDx1; points[ 4] = fDy; points[ 5] = -fDz;
716 points[ 6] = fDx1; points[ 7] = fDy; points[ 8] = -fDz;
717 points[ 9] = fDx1; points[10] = -fDy; points[11] = -fDz;
718 points[12] = -fDx2; points[13] = -fDy; points[14] = fDz;
719 points[15] = -fDx2; points[16] = fDy; points[17] = fDz;
720 points[18] = fDx2; points[19] = fDy; points[20] = fDz;
721 points[21] = fDx2; points[22] = -fDy; points[23] = fDz;
727 void TGeoTrd1::Sizeof3D()
const
729 TGeoBBox::Sizeof3D();
737 void TGeoTrd1::Contains_v(
const Double_t *points, Bool_t *inside, Int_t vecsize)
const
739 for (Int_t i=0; i<vecsize; i++) inside[i] = Contains(&points[3*i]);
747 void TGeoTrd1::ComputeNormal_v(
const Double_t *points,
const Double_t *dirs, Double_t *norms, Int_t vecsize)
749 for (Int_t i=0; i<vecsize; i++) ComputeNormal(&points[3*i], &dirs[3*i], &norms[3*i]);
755 void TGeoTrd1::DistFromInside_v(
const Double_t *points,
const Double_t *dirs, Double_t *dists, Int_t vecsize, Double_t* step)
const
757 for (Int_t i=0; i<vecsize; i++) dists[i] = DistFromInside(&points[3*i], &dirs[3*i], 3, step[i]);
763 void TGeoTrd1::DistFromOutside_v(
const Double_t *points,
const Double_t *dirs, Double_t *dists, Int_t vecsize, Double_t* step)
const
765 for (Int_t i=0; i<vecsize; i++) dists[i] = DistFromOutside(&points[3*i], &dirs[3*i], 3, step[i]);
773 void TGeoTrd1::Safety_v(
const Double_t *points,
const Bool_t *inside, Double_t *safe, Int_t vecsize)
const
775 for (Int_t i=0; i<vecsize; i++) safe[i] = Safety(&points[3*i], inside[i]);