56 SetShapeBit(TGeoShape::kGeoEltu);
62 TGeoEltu::TGeoEltu(Double_t a, Double_t b, Double_t dz)
65 SetShapeBit(TGeoShape::kGeoEltu);
66 SetEltuDimensions(a, b, dz);
73 TGeoEltu::TGeoEltu(
const char *name, Double_t a, Double_t b, Double_t dz)
74 :TGeoTube(name,0.,b,dz)
77 SetShapeBit(TGeoShape::kGeoEltu);
78 SetEltuDimensions(a, b, dz);
88 TGeoEltu::TGeoEltu(Double_t *param)
90 SetShapeBit(TGeoShape::kGeoEltu);
105 Double_t TGeoEltu::Capacity()
const
107 Double_t capacity = 2.*TMath::Pi()*fDz*fRmin*fRmax;
114 void TGeoEltu::ComputeBBox()
124 void TGeoEltu::ComputeNormal(
const Double_t *point,
const Double_t *dir, Double_t *norm)
128 Double_t safr = TMath::Abs(TMath::Sqrt(point[0]*point[0]/(a*a)+point[1]*point[1]/(b*b))-1.);
129 safr *= TMath::Min(a,b);
130 Double_t safz = TMath::Abs(fDz-TMath::Abs(point[2]));
132 norm[0] = norm[1] = 0;
133 norm[2] = TMath::Sign(1.,dir[2]);
137 norm[0] = point[0]*b*b;
138 norm[1] = point[1]*a*a;
139 TMath::Normalize(norm);
145 Bool_t TGeoEltu::Contains(
const Double_t *point)
const
147 if (TMath::Abs(point[2]) > fDz)
return kFALSE;
148 Double_t r2 = (point[0]*point[0])/(fRmin*fRmin)+(point[1]*point[1])/(fRmax*fRmax);
149 if (r2>1.)
return kFALSE;
156 Int_t TGeoEltu::DistancetoPrimitive(Int_t px, Int_t py)
158 Int_t n = gGeoManager->GetNsegments();
159 const Int_t numPoints=4*n;
160 return ShapeDistancetoPrimitive(numPoints, px, py);
166 Double_t TGeoEltu::DistFromInside(
const Double_t *point,
const Double_t *dir, Int_t iact, Double_t step, Double_t *safe)
const
168 Double_t a2=fRmin*fRmin;
169 Double_t b2=fRmax*fRmax;
170 Double_t safz1=fDz-point[2];
171 Double_t safz2=fDz+point[2];
173 if (iact<3 && safe) {
174 Double_t x0=TMath::Abs(point[0]);
175 Double_t y0=TMath::Abs(point[1]);
177 Double_t y1=TMath::Sqrt((fRmin-x0)*(fRmin+x0))*fRmax/fRmin;
179 Double_t x2=TMath::Sqrt((fRmax-y0)*(fRmax+y0))*fRmin/fRmax;
180 Double_t d1=(x1-x0)*(x1-x0)+(y1-y0)*(y1-y0);
181 Double_t d2=(x2-x0)*(x2-x0)+(y2-y0)*(y2-y0);
184 Double_t safr=TGeoShape::Big();
185 Double_t safz = TMath::Min(safz1,safz2);
186 for (Int_t i=0; i<8; i++) {
189 y3=TMath::Sqrt((fRmin-x3)*(fRmin+x3))*fRmax/fRmin;;
192 x3=TMath::Sqrt((fRmax-y3)*(fRmax+y3))*fRmin/fRmax;
197 d2=(x2-x0)*(x2-x0)+(y2-y0)*(y2-y0);
201 d1=(x1-x0)*(x1-x0)+(y1-y0)*(y1-y0);
204 safr=TMath::Sqrt(d1)-1.0E-3;
205 *safe = TMath::Min(safz, safr);
206 if (iact==0)
return TGeoShape::Big();
207 if ((iact==1) && (*safe>step))
return TGeoShape::Big();
211 Double_t snxt = TGeoShape::Big();
215 if (dir[2]<0) snxt=-safz2/dir[2];
218 Double_t xz=point[0]+dir[0]*sz;
219 Double_t yz=point[1]+dir[1]*sz;
220 if ((xz*xz/a2+yz*yz/b2)<=1)
return snxt;
222 Double_t tolerance = TGeoShape::Tolerance();
223 Double_t u=dir[0]*dir[0]*b2+dir[1]*dir[1]*a2;
224 Double_t v=point[0]*dir[0]*b2+point[1]*dir[1]*a2;
225 Double_t w=point[0]*point[0]*b2+point[1]*point[1]*a2-a2*b2;
227 if (d<0 || TGeoShape::IsSameWithinTolerance(u,0))
return tolerance;
228 Double_t sd=TMath::Sqrt(d);
231 if (snxt<0)
return tolerance;
238 Double_t TGeoEltu::DistFromOutside(
const Double_t *point,
const Double_t *dir, Int_t iact, Double_t step, Double_t *safe)
const
240 Double_t safz=TMath::Abs(point[2])-fDz;
241 Double_t a2=fRmin*fRmin;
242 Double_t b2=fRmax*fRmax;
243 if (iact<3 && safe) {
244 Double_t x0=TMath::Abs(point[0]);
245 Double_t y0=TMath::Abs(point[1]);
247 if ((x0*x0/a2+y0*y0/b2)>=1) {
249 Double_t phi2=0.5*TMath::Pi();
251 Double_t x3=0.,y3=0.,d;
252 for (Int_t i=0; i<10; i++) {
253 phi3=(phi1+phi2)*0.5;
254 x3=fRmin*TMath::Cos(phi3);
255 y3=fRmax*TMath::Sin(phi3);
256 d=y3*a2*(x0-x3)-x3*b2*(y0-y3);
260 *safe=TMath::Sqrt((x0-x3)*(x0-x3)+(y0-y3)*(y0-y3));
263 *safe=TMath::Sqrt((*safe)*(*safe)+safz*safz);
265 if (iact==0)
return TGeoShape::Big();
266 if ((iact==1) && (step<*safe))
return TGeoShape::Big();
270 Double_t epsil = 10.*TGeoShape::Tolerance();
274 if (point[2]*dir[2]>0)
return TGeoShape::Big();
276 if (TGeoShape::IsSameWithinTolerance(dir[2],0))
return TGeoShape::Big();
278 zi = (point[2] > 0) ? fDz : -fDz;
280 tau = (zi-point[2])/dir[2];
282 Double_t xz=point[0]+dir[0]*tau;
283 Double_t yz=point[1]+dir[1]*tau;
284 if ((xz*xz/a2+yz*yz/b2)<1)
return tau;
288 Double_t sdist = TGeoBBox::DistFromOutside(point,dir, fDX, fDY, fDZ, fOrigin, step);
289 if (sdist>=step)
return TGeoShape::Big();
290 Double_t u=dir[0]*dir[0]*b2+dir[1]*dir[1]*a2;
291 if (TGeoShape::IsSameWithinTolerance(u,0))
return TGeoShape::Big();
292 Double_t v=point[0]*dir[0]*b2+point[1]*dir[1]*a2;
293 Double_t w=point[0]*point[0]*b2+point[1]*point[1]*a2-a2*b2;
295 if (d<0)
return TGeoShape::Big();
296 Double_t dsq=TMath::Sqrt(d);
300 if (tau < epsil)
return TGeoShape::Big();
303 zi=point[2]+tau*dir[2];
305 if ((TMath::Abs(zi)-fDz)>0)
return TGeoShape::Big();
307 if (tau < 0)
return 0.;
315 TGeoVolume *TGeoEltu::Divide(TGeoVolume * ,
const char * , Int_t , Int_t ,
316 Double_t , Double_t )
318 Error(
"Divide",
"Elliptical tubes divisions not implemented");
326 void TGeoEltu::GetBoundingCylinder(Double_t *param)
const
329 param[1] = TMath::Max(fRmin, fRmax);
330 param[1] *= param[1];
339 TGeoShape *TGeoEltu::GetMakeRuntimeShape(TGeoShape *mother, TGeoMatrix * )
const
341 if (!TestShapeBit(kGeoRunTimeShape))
return 0;
342 if (!mother->TestShapeBit(kGeoEltu)) {
343 Error(
"GetMakeRuntimeShape",
"invalid mother");
350 if (fDz<0) dz=((TGeoEltu*)mother)->GetDz();
352 a = ((TGeoEltu*)mother)->GetA();
354 a = ((TGeoEltu*)mother)->GetB();
356 return (
new TGeoEltu(a, b, dz));
362 void TGeoEltu::InspectShape()
const
364 printf(
"*** Shape %s: TGeoEltu ***\n", GetName());
365 printf(
" A = %11.5f\n", fRmin);
366 printf(
" B = %11.5f\n", fRmax);
367 printf(
" dz = %11.5f\n", fDz);
368 printf(
" Bounding box:\n");
369 TGeoBBox::InspectShape();
376 Double_t TGeoEltu::Safety(
const Double_t *point, Bool_t )
const
378 Double_t x0 = TMath::Abs(point[0]);
379 Double_t y0 = TMath::Abs(point[1]);
380 Double_t x1, y1, dx, dy;
382 safr = safz = TGeoShape::Big();
383 Double_t onepls = 1.+TGeoShape::Tolerance();
384 Double_t onemin = 1.-TGeoShape::Tolerance();
385 Double_t sqdist = x0*x0/(fRmin*fRmin)+y0*y0/(fRmax*fRmax);
387 if (sqdist>onepls) in = kFALSE;
388 else if (sqdist<onemin) in = kTRUE;
392 x1 = fRmin*TMath::Sqrt(1.-(y0*y0)/(fRmax*fRmax));
393 y1 = fRmax*TMath::Sqrt(1.-(x0*x0)/(fRmin*fRmin));
396 if (TMath::Abs(dx)<TGeoShape::Tolerance())
return 0;
397 safr = dx*dy/TMath::Sqrt(dx*dx+dy*dy);
398 safz = fDz - TMath::Abs(point[2]);
399 return TMath::Min(safr,safz);
402 if (TMath::Abs(x0)<TGeoShape::Tolerance()) {
405 if (TMath::Abs(y0)<TGeoShape::Tolerance()) {
408 Double_t f = fRmin*fRmax/TMath::Sqrt(x0*x0*fRmax*fRmax+y0*y0*fRmin*fRmin);
413 Double_t ast = fRmin*y1/fRmax;
414 Double_t bct = fRmax*x1/fRmin;
415 Double_t d = TMath::Sqrt(bct*bct+ast*ast);
416 safr = (dx*bct+dy*ast)/d;
419 safz = TMath::Abs(point[2])-fDz;
420 return TMath::Max(safr, safz);
426 void TGeoEltu::SavePrimitive(std::ostream &out, Option_t * )
428 if (TObject::TestBit(kGeoSavePrimitive))
return;
429 out <<
" // Shape: " << GetName() <<
" type: " << ClassName() << std::endl;
430 out <<
" a = " << fRmin <<
";" << std::endl;
431 out <<
" b = " << fRmax <<
";" << std::endl;
432 out <<
" dz = " << fDz <<
";" << std::endl;
433 out <<
" TGeoShape *" << GetPointerName() <<
" = new TGeoEltu(\"" << GetName() <<
"\",a,b,dz);" << std::endl;
434 TObject::SetBit(TGeoShape::kGeoSavePrimitive);
440 void TGeoEltu::SetEltuDimensions(Double_t a, Double_t b, Double_t dz)
442 if ((a<=0) || (b<0) || (dz<0)) {
443 SetShapeBit(kGeoRunTimeShape);
453 void TGeoEltu::SetDimensions(Double_t *param)
455 Double_t a = param[0];
456 Double_t b = param[1];
457 Double_t dz = param[2];
458 SetEltuDimensions(a, b, dz);
464 void TGeoEltu::SetPoints(Double_t *points)
const
469 n = gGeoManager->GetNsegments();
470 Double_t dphi = 360./n;
477 Double_t a2=fRmin*fRmin;
478 Double_t b2=fRmax*fRmax;
481 for (j = 0; j < n; j++) {
482 points[indx+6*n] = points[indx] = 0;
484 points[indx+6*n] = points[indx] = 0;
486 points[indx+6*n] = dz;
490 for (j = 0; j < n; j++) {
491 phi = j*dphi*TMath::DegToRad();
494 r2=(a2*b2)/(b2+(a2-b2)*sph*sph);
496 points[indx+6*n] = points[indx] = r*cph;
498 points[indx+6*n] = points[indx] = r*sph;
500 points[indx+6*n]= dz;
510 void TGeoEltu::GetMeshNumbers(Int_t &nvert, Int_t &nsegs, Int_t &npols)
const
512 TGeoTube::GetMeshNumbers(nvert,nsegs,npols);
518 Int_t TGeoEltu::GetNmeshVertices()
const
520 return TGeoTube::GetNmeshVertices();
526 void TGeoEltu::SetPoints(Float_t *points)
const
531 n = gGeoManager->GetNsegments();
532 Double_t dphi = 360./n;
539 Double_t a2=fRmin*fRmin;
540 Double_t b2=fRmax*fRmax;
543 for (j = 0; j < n; j++) {
544 points[indx+6*n] = points[indx] = 0;
546 points[indx+6*n] = points[indx] = 0;
548 points[indx+6*n] = dz;
552 for (j = 0; j < n; j++) {
553 phi = j*dphi*TMath::DegToRad();
556 r2=(a2*b2)/(b2+(a2-b2)*sph*sph);
558 points[indx+6*n] = points[indx] = r*cph;
560 points[indx+6*n] = points[indx] = r*sph;
562 points[indx+6*n]= dz;
572 const TBuffer3D & TGeoEltu::GetBuffer3D(Int_t reqSections, Bool_t localFrame)
const
574 static TBuffer3D buffer(TBuffer3DTypes::kGeneric);
575 TGeoBBox::FillBuffer3D(buffer, reqSections, localFrame);
577 if (reqSections & TBuffer3D::kRawSizes) {
578 Int_t n = gGeoManager->GetNsegments();
582 if (buffer.SetRawSizes(nbPnts, 3*nbPnts, nbSegs, 3*nbSegs, nbPols, 6*nbPols)) {
583 buffer.SetSectionsValid(TBuffer3D::kRawSizes);
586 if ((reqSections & TBuffer3D::kRaw) && buffer.SectionsValid(TBuffer3D::kRawSizes)) {
587 SetPoints(buffer.fPnts);
588 if (!buffer.fLocalFrame) {
589 TransformPoints(buffer.fPnts, buffer.NbPnts());
591 SetSegsAndPols(buffer);
592 buffer.SetSectionsValid(TBuffer3D::kRaw);
603 void TGeoEltu::Contains_v(
const Double_t *points, Bool_t *inside, Int_t vecsize)
const
605 for (Int_t i=0; i<vecsize; i++) inside[i] = Contains(&points[3*i]);
613 void TGeoEltu::ComputeNormal_v(
const Double_t *points,
const Double_t *dirs, Double_t *norms, Int_t vecsize)
615 for (Int_t i=0; i<vecsize; i++) ComputeNormal(&points[3*i], &dirs[3*i], &norms[3*i]);
621 void TGeoEltu::DistFromInside_v(
const Double_t *points,
const Double_t *dirs, Double_t *dists, Int_t vecsize, Double_t* step)
const
623 for (Int_t i=0; i<vecsize; i++) dists[i] = DistFromInside(&points[3*i], &dirs[3*i], 3, step[i]);
629 void TGeoEltu::DistFromOutside_v(
const Double_t *points,
const Double_t *dirs, Double_t *dists, Int_t vecsize, Double_t* step)
const
631 for (Int_t i=0; i<vecsize; i++) dists[i] = DistFromOutside(&points[3*i], &dirs[3*i], 3, step[i]);
639 void TGeoEltu::Safety_v(
const Double_t *points,
const Bool_t *inside, Double_t *safe, Int_t vecsize)
const
641 for (Int_t i=0; i<vecsize; i++) safe[i] = Safety(&points[3*i], inside[i]);