42 ClassImp(TGeoParaboloid);
47 TGeoParaboloid::TGeoParaboloid()
54 SetShapeBit(TGeoShape::kGeoParaboloid);
60 TGeoParaboloid::TGeoParaboloid(Double_t rlo, Double_t rhi, Double_t dz)
68 SetShapeBit(TGeoShape::kGeoParaboloid);
69 SetParaboloidDimensions(rlo, rhi, dz);
76 TGeoParaboloid::TGeoParaboloid(
const char *name, Double_t rlo, Double_t rhi, Double_t dz)
77 :TGeoBBox(name, 0, 0, 0)
84 SetShapeBit(TGeoShape::kGeoParaboloid);
85 SetParaboloidDimensions(rlo, rhi, dz);
95 TGeoParaboloid::TGeoParaboloid(Double_t *param)
97 SetShapeBit(TGeoShape::kGeoParaboloid);
105 TGeoParaboloid::~TGeoParaboloid()
112 Double_t TGeoParaboloid::Capacity()
const
114 Double_t capacity = TMath::Pi()*fDz*(fRlo*fRlo+fRhi*fRhi);
121 void TGeoParaboloid::ComputeBBox()
123 fDX = TMath::Max(fRlo, fRhi);
131 void TGeoParaboloid::ComputeNormal(
const Double_t *point,
const Double_t *dir, Double_t *norm)
133 norm[0] = norm[1] = 0.0;
134 if (TMath::Abs(point[2]) > fDz) {
135 norm[2] = TMath::Sign(1., dir[2]);
138 Double_t safz = fDz-TMath::Abs(point[2]);
139 Double_t r = TMath::Sqrt(point[0]*point[0]+point[1]*point[1]);
140 Double_t safr = TMath::Abs(r-TMath::Sqrt((point[2]-fB)/fA));
142 norm[2] = TMath::Sign(1., dir[2]);
145 Double_t talf = -2.*fA*r;
146 Double_t calf = 1./TMath::Sqrt(1.+talf*talf);
147 Double_t salf = talf * calf;
148 Double_t phi = TMath::ATan2(point[1], point[0]);
150 norm[0] = salf*TMath::Cos(phi);
151 norm[1] = salf*TMath::Sin(phi);
153 Double_t ndotd = norm[0]*dir[0]+norm[1]*dir[1]+norm[2]*dir[2];
164 Bool_t TGeoParaboloid::Contains(
const Double_t *point)
const
166 if (TMath::Abs(point[2])>fDz)
return kFALSE;
167 Double_t aa = fA*(point[2]-fB);
168 if (aa < 0)
return kFALSE;
169 Double_t rsq = point[0]*point[0]+point[1]*point[1];
170 if (aa < fA*fA*rsq)
return kFALSE;
177 Int_t TGeoParaboloid::DistancetoPrimitive(Int_t px, Int_t py)
179 Int_t n = gGeoManager->GetNsegments();
180 const Int_t numPoints=n*(n+1)+2;
181 return ShapeDistancetoPrimitive(numPoints, px, py);
188 Double_t TGeoParaboloid::DistToParaboloid(
const Double_t *point,
const Double_t *dir, Bool_t in)
const
190 Double_t rsq = point[0]*point[0]+point[1]*point[1];
191 Double_t a = fA * (dir[0]*dir[0] + dir[1]*dir[1]);
192 Double_t b = 2.*fA*(point[0]*dir[0]+point[1]*dir[1])-dir[2];
193 Double_t c = fA*rsq + fB - point[2];
194 Double_t dist = TGeoShape::Big();
195 if (TMath::Abs(a)<TGeoShape::Tolerance()) {
196 if (TMath::Abs(b)<TGeoShape::Tolerance())
return dist;
198 if (dist < 0)
return TGeoShape::Big();
201 Double_t ainv = 1./a;
202 Double_t sum = - b*ainv;
203 Double_t prod = c*ainv;
204 Double_t delta = sum*sum - 4.*prod;
205 if (delta<0)
return dist;
206 delta = TMath::Sqrt(delta);
207 Double_t sone = TMath::Sign(1.,ainv);
210 dist = 0.5*(sum+i*sone*delta);
212 if (dist<0)
continue;
214 Double_t talf = -2.*fA*TMath::Sqrt(rsq);
215 Double_t phi = TMath::ATan2(point[1], point[0]);
216 Double_t ndotd = talf*(TMath::Cos(phi)*dir[0]+TMath::Sin(phi)*dir[1])+dir[2];
217 if (!in) ndotd *= -1;
218 if (ndotd<0)
return dist;
221 return TGeoShape::Big();
227 Double_t TGeoParaboloid::DistFromInside(
const Double_t *point,
const Double_t *dir, Int_t iact, Double_t step, Double_t *safe)
const
229 if (iact<3 && safe) {
231 *safe = Safety(point, kTRUE);
232 if (iact==0)
return TGeoShape::Big();
233 if (iact==1 && step<*safe)
return TGeoShape::Big();
236 Double_t dz = TGeoShape::Big();
238 dz = -(point[2]+fDz)/dir[2];
239 }
else if (dir[2]>0) {
240 dz = (fDz-point[2])/dir[2];
242 Double_t dpara = DistToParaboloid(point, dir, kTRUE);
243 return TMath::Min(dz, dpara);
249 Double_t TGeoParaboloid::DistFromOutside(
const Double_t *point,
const Double_t *dir, Int_t iact, Double_t step, Double_t *safe)
const
251 Double_t snxt = TGeoShape::Big();
252 if (iact<3 && safe) {
254 *safe = Safety(point, kFALSE);
255 if (iact==0)
return TGeoShape::Big();
256 if (iact==1 && step<*safe)
return TGeoShape::Big();
258 Double_t xnew, ynew, znew;
259 if (point[2]<=-fDz) {
260 if (dir[2]<=0)
return TGeoShape::Big();
261 snxt = -(fDz+point[2])/dir[2];
263 xnew = point[0]+snxt*dir[0];
264 ynew = point[1]+snxt*dir[1];
265 if ((xnew*xnew+ynew*ynew) <= fRlo*fRlo)
return snxt;
266 }
else if (point[2]>=fDz) {
267 if (dir[2]>=0)
return TGeoShape::Big();
268 snxt = (fDz-point[2])/dir[2];
270 xnew = point[0]+snxt*dir[0];
271 ynew = point[1]+snxt*dir[1];
272 if ((xnew*xnew+ynew*ynew) <= fRhi*fRhi)
return snxt;
274 snxt = DistToParaboloid(point, dir, kFALSE);
275 if (snxt > 1E20)
return snxt;
276 znew = point[2]+snxt*dir[2];
277 if (TMath::Abs(znew) <= fDz)
return snxt;
278 return TGeoShape::Big();
284 TGeoVolume *TGeoParaboloid::Divide(TGeoVolume * ,
const char * , Int_t , Int_t ,
285 Double_t , Double_t )
287 Error(
"Divide",
"Paraboloid divisions not implemented");
295 void TGeoParaboloid::GetBoundingCylinder(Double_t *param)
const
299 param[1] *= param[1];
308 TGeoShape *TGeoParaboloid::GetMakeRuntimeShape(TGeoShape *, TGeoMatrix *)
const
316 void TGeoParaboloid::InspectShape()
const
318 printf(
"*** Shape %s: TGeoParaboloid ***\n", GetName());
319 printf(
" rlo = %11.5f\n", fRlo);
320 printf(
" rhi = %11.5f\n", fRhi);
321 printf(
" dz = %11.5f\n", fDz);
322 printf(
" Bounding box:\n");
323 TGeoBBox::InspectShape();
330 TBuffer3D *TGeoParaboloid::MakeBuffer3D()
const
332 Int_t n = gGeoManager->GetNsegments();
333 Int_t nbPnts = n*(n+1)+2;
334 Int_t nbSegs = n*(2*n+3);
335 Int_t nbPols = n*(n+2);
337 TBuffer3D* buff =
new TBuffer3D(TBuffer3DTypes::kGeneric,
338 nbPnts, 3*nbPnts, nbSegs, 3*nbSegs, nbPols, 2*n*5 + n*n*6);
342 SetPoints(buff->fPnts);
343 SetSegsAndPols(*buff);
352 void TGeoParaboloid::SetSegsAndPols(TBuffer3D &buff)
const
355 Int_t n = gGeoManager->GetNsegments();
357 Int_t c = GetBasicColor();
359 Int_t nn1 = (n+1)*n+1;
362 for (j=0; j<n; j++) {
363 buff.fSegs[indx++] = c+2;
364 buff.fSegs[indx++] = 0;
365 buff.fSegs[indx++] = j+1;
368 for (i=0; i<n+1; i++) {
370 for (j=0; j<n; j++) {
371 buff.fSegs[indx++] = c;
372 buff.fSegs[indx++] = n*i+1+j;
373 buff.fSegs[indx++] = n*i+1+((j+1)%n);
377 for (j=0; j<n; j++) {
378 buff.fSegs[indx++] = c;
379 buff.fSegs[indx++] = n*i+1+j;
380 buff.fSegs[indx++] = n*(i+1)+1+j;
384 for (j=0; j<n; j++) {
385 buff.fSegs[indx++] = c+1;
386 buff.fSegs[indx++] = n*n+1+j;
387 buff.fSegs[indx++] = nn1;
393 for (j=0; j<n; j++) {
394 buff.fPols[indx++] = c+2;
395 buff.fPols[indx++] = 3;
396 buff.fPols[indx++] = n+j;
397 buff.fPols[indx++] = (j+1)%n;
398 buff.fPols[indx++] = j;
401 for (i=0; i<n; i++) {
403 for (j=0; j<n; j++) {
404 buff.fPols[indx++] = c;
405 buff.fPols[indx++] = 4;
406 buff.fPols[indx++] = (2*i+1)*n+j;
407 buff.fPols[indx++] = 2*(i+1)*n+j;
408 buff.fPols[indx++] = (2*i+3)*n+j;
409 buff.fPols[indx++] = 2*(i+1)*n+((j+1)%n);
413 for (j=0; j<n; j++) {
414 buff.fPols[indx++] = c+1;
415 buff.fPols[indx++] = 3;
416 buff.fPols[indx++] = 2*n*(n+1)+j;
417 buff.fPols[indx++] = 2*n*(n+1)+((j+1)%n);
418 buff.fPols[indx++] = (2*n+1)*n+j;
425 Double_t TGeoParaboloid::Safety(
const Double_t *point, Bool_t in)
const
427 Double_t safz = fDz-TMath::Abs(point[2]);
428 if (!in) safz = -safz;
429 Double_t safr = TGeoShape::Big();
430 Double_t rsq = point[0]*point[0]+point[1]*point[1];
431 Double_t z0 = fA*rsq+fB;
432 Double_t r0sq = (point[2]-fB)/fA;
437 Double_t dr = TMath::Sqrt(rsq)-TMath::Sqrt(r0sq);
439 if (dr>-1.E-8)
return 0.;
440 Double_t dz = TMath::Abs(point[2]-z0);
441 safr = -dr*dz/TMath::Sqrt(dr*dr+dz*dz);
443 if (dr<1.E-8)
return safz;
444 Double_t talf = -2.*fA*TMath::Sqrt(r0sq);
445 Double_t salf = talf/TMath::Sqrt(1.+talf*talf);
446 safr = TMath::Abs(dr*salf);
448 if (in)
return TMath::Min(safr,safz);
449 return TMath::Max(safr,safz);
455 void TGeoParaboloid::SetParaboloidDimensions(Double_t rlo, Double_t rhi, Double_t dz)
457 if ((rlo<0) || (rhi<0) || (dz<=0) || TMath::Abs(rlo-rhi)<TGeoShape::Tolerance()) {
458 SetShapeBit(kGeoRunTimeShape);
459 Error(
"SetParaboloidDimensions",
"Dimensions of %s invalid: check (rlo>=0) (rhi>=0) (rlo!=rhi) dz>0",GetName());
465 Double_t dd = 1./(fRhi*fRhi - fRlo*fRlo);
467 fB = - fDz * (fRlo*fRlo + fRhi*fRhi)*dd;
473 void TGeoParaboloid::SetDimensions(Double_t *param)
475 Double_t rlo = param[0];
476 Double_t rhi = param[1];
477 Double_t dz = param[2];
478 SetParaboloidDimensions(rlo, rhi, dz);
500 void TGeoParaboloid::SetPoints(Double_t *points)
const
503 Double_t ttmin, ttmax;
504 ttmin = TMath::ATan2(-fDz, fRlo);
505 ttmax = TMath::ATan2(fDz, fRhi);
506 Int_t n = gGeoManager->GetNsegments();
507 Double_t dtt = (ttmax-ttmin)/n;
508 Double_t dphi = 360./n;
510 Double_t r, z, delta;
511 Double_t phi, sph, cph;
516 points[indx++] = -fDz;
517 for (Int_t i=0; i<n+1; i++) {
525 tt = TMath::Tan(ttmin + i*dtt);
526 delta = tt*tt - 4*fA*fB;
527 r = 0.5*(tt+TMath::Sqrt(delta))/fA;
530 for (Int_t j=0; j<n; j++) {
531 phi = j*dphi*TMath::DegToRad();
534 points[indx++] = r*cph;
535 points[indx++] = r*sph;
542 points[indx++] = fDz;
548 void TGeoParaboloid::GetMeshNumbers(Int_t &nvert, Int_t &nsegs, Int_t &npols)
const
550 Int_t n = gGeoManager->GetNsegments();
559 Int_t TGeoParaboloid::GetNmeshVertices()
const
561 Int_t n = gGeoManager->GetNsegments();
568 void TGeoParaboloid::SavePrimitive(std::ostream &out, Option_t * )
570 if (TObject::TestBit(kGeoSavePrimitive))
return;
571 out <<
" // Shape: " << GetName() <<
" type: " << ClassName() << std::endl;
572 out <<
" rlo = " << fRlo <<
";" << std::endl;
573 out <<
" rhi = " << fRhi <<
";" << std::endl;
574 out <<
" dz = " << fDZ <<
";" << std::endl;
575 out <<
" TGeoShape *" << GetPointerName() <<
" = new TGeoParaboloid(\"" << GetName() <<
"\", rlo,rhi,dz);" << std::endl;
576 TObject::SetBit(TGeoShape::kGeoSavePrimitive);
582 void TGeoParaboloid::SetPoints(Float_t *points)
const
585 Double_t ttmin, ttmax;
586 ttmin = TMath::ATan2(-fDz, fRlo);
587 ttmax = TMath::ATan2(fDz, fRhi);
588 Int_t n = gGeoManager->GetNsegments();
589 Double_t dtt = (ttmax-ttmin)/n;
590 Double_t dphi = 360./n;
592 Double_t r, z, delta;
593 Double_t phi, sph, cph;
598 points[indx++] = -fDz;
599 for (Int_t i=0; i<n+1; i++) {
607 tt = TMath::Tan(ttmin + i*dtt);
608 delta = tt*tt - 4*fA*fB;
609 r = 0.5*(tt+TMath::Sqrt(delta))/fA;
612 for (Int_t j=0; j<n; j++) {
613 phi = j*dphi*TMath::DegToRad();
616 points[indx++] = r*cph;
617 points[indx++] = r*sph;
624 points[indx++] = fDz;
628 void TGeoParaboloid::Sizeof3D()
const
635 const TBuffer3D & TGeoParaboloid::GetBuffer3D(Int_t reqSections, Bool_t localFrame)
const
637 static TBuffer3D buffer(TBuffer3DTypes::kGeneric);
638 TGeoBBox::FillBuffer3D(buffer, reqSections, localFrame);
640 if (reqSections & TBuffer3D::kRawSizes) {
641 Int_t n = gGeoManager->GetNsegments();
642 Int_t nbPnts = n*(n+1)+2;
643 Int_t nbSegs = n*(2*n+3);
644 Int_t nbPols = n*(n+2);
645 if (buffer.SetRawSizes(nbPnts, 3*nbPnts, nbSegs, 3*nbSegs, nbPols, 2*n*5 + n*n*6)) {
646 buffer.SetSectionsValid(TBuffer3D::kRawSizes);
649 if ((reqSections & TBuffer3D::kRaw) && buffer.SectionsValid(TBuffer3D::kRawSizes)) {
650 SetPoints(buffer.fPnts);
651 if (!buffer.fLocalFrame) {
652 TransformPoints(buffer.fPnts, buffer.NbPnts());
654 SetSegsAndPols(buffer);
655 buffer.SetSectionsValid(TBuffer3D::kRaw);
666 void TGeoParaboloid::Contains_v(
const Double_t *points, Bool_t *inside, Int_t vecsize)
const
668 for (Int_t i=0; i<vecsize; i++) inside[i] = Contains(&points[3*i]);
676 void TGeoParaboloid::ComputeNormal_v(
const Double_t *points,
const Double_t *dirs, Double_t *norms, Int_t vecsize)
678 for (Int_t i=0; i<vecsize; i++) ComputeNormal(&points[3*i], &dirs[3*i], &norms[3*i]);
684 void TGeoParaboloid::DistFromInside_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] = DistFromInside(&points[3*i], &dirs[3*i], 3, step[i]);
692 void TGeoParaboloid::DistFromOutside_v(
const Double_t *points,
const Double_t *dirs, Double_t *dists, Int_t vecsize, Double_t* step)
const
694 for (Int_t i=0; i<vecsize; i++) dists[i] = DistFromOutside(&points[3*i], &dirs[3*i], 3, step[i]);
702 void TGeoParaboloid::Safety_v(
const Double_t *points,
const Bool_t *inside, Double_t *safe, Int_t vecsize)
const
704 for (Int_t i=0; i<vecsize; i++) safe[i] = Safety(&points[3*i], inside[i]);