Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
TGeoCone.cxx
Go to the documentation of this file.
1// @(#)root/geom:$Id$
2// Author: Andrei Gheata 31/01/02
3// TGeoCone::Contains() and DistFromInside() implemented by Mihaela Gheata
4
5/*************************************************************************
6 * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. *
7 * All rights reserved. *
8 * *
9 * For the licensing terms see $ROOTSYS/LICENSE. *
10 * For the list of contributors see $ROOTSYS/README/CREDITS. *
11 *************************************************************************/
12
13/** \class TGeoCone
14\ingroup Cones
15
16The cones are defined by 5 parameters:
17
18~~~{.cpp}
19TGeoCone(Double_t dz,Double_t rmin1,Double_t rmax1,
20Double_t rmin2,Double_t rmax2);
21~~~
22
23 - `rmin1:` internal radius at Z is `-dz`
24 - `rmax1:` external radius at Z is `-dz`
25 - `rmin2:` internal radius at Z is `+dz`
26 - `rmax2:` external radius at Z is `+dz`
27 - `dz:` half length in Z (a cone ranges from `-dz` to +`dz`)
28
29A cone has Z-axis as its symmetry axis.
30
31Begin_Macro
32{
33 TCanvas *c = new TCanvas("c", "c",0,0,600,600);
34 new TGeoManager("cone", "poza4");
35 TGeoMaterial *mat = new TGeoMaterial("Al", 26.98,13,2.7);
36 TGeoMedium *med = new TGeoMedium("MED",1,mat);
37 TGeoVolume *top = gGeoManager->MakeBox("TOP",med,100,100,100);
38 gGeoManager->SetTopVolume(top);
39 TGeoVolume *vol = gGeoManager->MakeCone("CONE",med, 40,10,20,35,45);
40 vol->SetLineWidth(2);
41 top->AddNode(vol,1);
42 gGeoManager->CloseGeometry();
43 gGeoManager->SetNsegments(30);
44 top->Draw();
45 TView *view = gPad->GetView();
46 if (view) view->ShowAxis();
47}
48End_Macro
49*/
50
51/** \class TGeoConeSeg
52\ingroup Cones
53
54A cone segment is a cone having a range in `phi`. The cone segment class
55derives from **`TGeoCone`**, having two extra parameters: `phi1` and
56`phi2`.
57
58~~~{.cpp}
59TGeoConeSeg(Double_t dz,Double_t rmin1,Double_t rmax1,
60Double_t rmin2,Double_t rmax2,Double_t phi1,Double_t phi2);
61~~~
62
63Parameters `phi1` and `phi2` have the same meaning and convention as for
64tube segments.
65
66Begin_Macro
67{
68 TCanvas *c = new TCanvas("c", "c",0,0,600,600);
69 new TGeoManager("coneseg", "poza5");
70 TGeoMaterial *mat = new TGeoMaterial("Al", 26.98,13,2.7);
71 TGeoMedium *med = new TGeoMedium("MED",1,mat);
72 TGeoVolume *top = gGeoManager->MakeBox("TOP",med,100,100,100);
73 gGeoManager->SetTopVolume(top);
74 TGeoVolume *vol = gGeoManager->MakeCons("CONESEG",med, 40,30,40,10,20,-30,250);
75 top->AddNode(vol,1);
76 gGeoManager->CloseGeometry();
77 gGeoManager->SetNsegments(30);
78 top->Draw();
79 TView *view = gPad->GetView();
80 if (view) view->ShowAxis();
81}
82End_Macro
83*/
84
85#include <iostream>
86
87#include "TGeoManager.h"
88#include "TGeoVolume.h"
89#include "TVirtualGeoPainter.h"
90#include "TGeoCone.h"
91#include "TBuffer3D.h"
92#include "TBuffer3DTypes.h"
93#include "TMath.h"
94
95////////////////////////////////////////////////////////////////////////////////
96/// Default constructor
97
99{
101 fDz = 0.0;
102 fRmin1 = 0.0;
103 fRmax1 = 0.0;
104 fRmin2 = 0.0;
105 fRmax2 = 0.0;
106}
107
108////////////////////////////////////////////////////////////////////////////////
109/// Default constructor specifying minimum and maximum radius
110
120
121////////////////////////////////////////////////////////////////////////////////
122/// Default constructor specifying minimum and maximum radius
123
125 : TGeoBBox(name, 0, 0, 0)
126{
129 if ((dz < 0) || (rmin1 < 0) || (rmax1 < 0) || (rmin2 < 0) || (rmax2 < 0)) {
131 } else
132 ComputeBBox();
133}
134
135////////////////////////////////////////////////////////////////////////////////
136/// Default constructor specifying minimum and maximum radius
137/// - param[0] = dz
138/// - param[1] = Rmin1
139/// - param[2] = Rmax1
140/// - param[3] = Rmin2
141/// - param[4] = Rmax2
142
144{
146 SetDimensions(param);
147 if ((fDz < 0) || (fRmin1 < 0) || (fRmax1 < 0) || (fRmin2 < 0) || (fRmax2 < 0))
149 else
150 ComputeBBox();
151}
152
153////////////////////////////////////////////////////////////////////////////////
154/// Computes capacity of the shape in [length^3]
155
160
161////////////////////////////////////////////////////////////////////////////////
162/// Computes capacity of the shape in [length^3]
163
165{
166 Double_t capacity = (2. * dz * TMath::Pi() / 3.) *
167 (rmax1 * rmax1 + rmax2 * rmax2 + rmax1 * rmax2 - rmin1 * rmin1 - rmin2 * rmin2 - rmin1 * rmin2);
168 return capacity;
169}
170
171////////////////////////////////////////////////////////////////////////////////
172/// destructor
173
175
176////////////////////////////////////////////////////////////////////////////////
177/// compute bounding box of the sphere
178
180{
181 TGeoBBox *box = (TGeoBBox *)this;
182 box->SetBoxDimensions(TMath::Max(fRmax1, fRmax2), TMath::Max(fRmax1, fRmax2), fDz);
183 memset(fOrigin, 0, 3 * sizeof(Double_t));
184}
185
186////////////////////////////////////////////////////////////////////////////////
187/// Compute normal to closest surface from POINT.
188
189void TGeoCone::ComputeNormal(const Double_t *point, const Double_t *dir, Double_t *norm) const
190{
191 Double_t safr, safe, phi;
192 memset(norm, 0, 3 * sizeof(Double_t));
193 phi = TMath::ATan2(point[1], point[0]);
194 Double_t cphi = TMath::Cos(phi);
195 Double_t sphi = TMath::Sin(phi);
196 Double_t ro1 = 0.5 * (fRmin1 + fRmin2);
197 Double_t tg1 = 0.5 * (fRmin2 - fRmin1) / fDz;
198 Double_t cr1 = 1. / TMath::Sqrt(1. + tg1 * tg1);
199 Double_t ro2 = 0.5 * (fRmax1 + fRmax2);
200 Double_t tg2 = 0.5 * (fRmax2 - fRmax1) / fDz;
201 Double_t cr2 = 1. / TMath::Sqrt(1. + tg2 * tg2);
202
203 Double_t r = TMath::Sqrt(point[0] * point[0] + point[1] * point[1]);
204 Double_t rin = tg1 * point[2] + ro1;
205 Double_t rout = tg2 * point[2] + ro2;
206 safe = TMath::Abs(fDz - TMath::Abs(point[2]));
207 norm[2] = 1;
208
209 safr = (ro1 > 0) ? (TMath::Abs((r - rin) * cr1)) : TGeoShape::Big();
210 if (safr < safe) {
211 safe = safr;
212 norm[0] = cr1 * cphi;
213 norm[1] = cr1 * sphi;
214 norm[2] = -tg1 * cr1;
215 }
216 safr = TMath::Abs((rout - r) * cr2);
217 if (safr < safe) {
218 norm[0] = cr2 * cphi;
219 norm[1] = cr2 * sphi;
220 norm[2] = -tg2 * cr2;
221 }
222 if (norm[0] * dir[0] + norm[1] * dir[1] + norm[2] * dir[2] < 0) {
223 norm[0] = -norm[0];
224 norm[1] = -norm[1];
225 norm[2] = -norm[2];
226 }
227}
228
229////////////////////////////////////////////////////////////////////////////////
230/// Compute normal to closest surface from POINT.
231
234{
235 Double_t safe, phi;
236 memset(norm, 0, 3 * sizeof(Double_t));
237 phi = TMath::ATan2(point[1], point[0]);
238 Double_t cphi = TMath::Cos(phi);
239 Double_t sphi = TMath::Sin(phi);
240 Double_t ro1 = 0.5 * (rmin1 + rmin2);
241 Double_t tg1 = 0.5 * (rmin2 - rmin1) / dz;
242 Double_t cr1 = 1. / TMath::Sqrt(1. + tg1 * tg1);
243 Double_t ro2 = 0.5 * (rmax1 + rmax2);
244 Double_t tg2 = 0.5 * (rmax2 - rmax1) / dz;
245 Double_t cr2 = 1. / TMath::Sqrt(1. + tg2 * tg2);
246
247 Double_t r = TMath::Sqrt(point[0] * point[0] + point[1] * point[1]);
248 Double_t rin = tg1 * point[2] + ro1;
249 Double_t rout = tg2 * point[2] + ro2;
250 safe = (ro1 > 0) ? (TMath::Abs((r - rin) * cr1)) : TGeoShape::Big();
251 norm[0] = cr1 * cphi;
252 norm[1] = cr1 * sphi;
253 norm[2] = -tg1 * cr1;
254 if (TMath::Abs((rout - r) * cr2) < safe) {
255 norm[0] = cr2 * cphi;
256 norm[1] = cr2 * sphi;
257 norm[2] = -tg2 * cr2;
258 }
259 if (norm[0] * dir[0] + norm[1] * dir[1] + norm[2] * dir[2] < 0) {
260 norm[0] = -norm[0];
261 norm[1] = -norm[1];
262 norm[2] = -norm[2];
263 }
264}
265
266////////////////////////////////////////////////////////////////////////////////
267/// test if point is inside this cone
268
270{
271 if (TMath::Abs(point[2]) > fDz)
272 return kFALSE;
273 Double_t r2 = point[0] * point[0] + point[1] * point[1];
274 Double_t rl = 0.5 * (fRmin2 * (point[2] + fDz) + fRmin1 * (fDz - point[2])) / fDz;
275 Double_t rh = 0.5 * (fRmax2 * (point[2] + fDz) + fRmax1 * (fDz - point[2])) / fDz;
276 if ((r2 < rl * rl) || (r2 > rh * rh))
277 return kFALSE;
278 return kTRUE;
279}
280
281////////////////////////////////////////////////////////////////////////////////
282/// Compute distance from inside point to surface of the cone (static)
283/// Boundary safe algorithm.
284
287{
288 if (dz <= 0)
289 return TGeoShape::Big();
290 // compute distance to surface
291 // Do Z
293 if (dir[2]) {
294 sz = (TMath::Sign(dz, dir[2]) - point[2]) / dir[2];
295 if (sz <= 0)
296 return 0.0;
297 }
298 Double_t rsq = point[0] * point[0] + point[1] * point[1];
299 Double_t zinv = 1. / dz;
300 Double_t rin = 0.5 * (rmin1 + rmin2 + (rmin2 - rmin1) * point[2] * zinv);
301 // Do Rmin
302 Double_t b, delta, zi;
303 if (rin > 0) {
304 // Protection in case point is actually outside the cone
305 if (rsq < rin * (rin + TGeoShape::Tolerance())) {
307 point[0] * dir[0] + point[1] * dir[1] + 0.5 * (rmin1 - rmin2) * dir[2] * zinv * TMath::Sqrt(rsq);
308 if (ddotn <= 0)
309 return 0.0;
310 } else {
311 TGeoCone::DistToCone(point, dir, dz, rmin1, rmin2, b, delta);
312 if (delta > 0) {
313 Double_t sr = -b - delta;
314 if (sr > 0) {
315 zi = point[2] + sr * dir[2];
316 if (TMath::Abs(zi) <= dz)
317 return TMath::Min(sz, sr);
318 }
319 sr = -b + delta;
320 if (sr > 0) {
321 zi = point[2] + sr * dir[2];
322 if (TMath::Abs(zi) <= dz)
323 return TMath::Min(sz, sr);
324 }
325 }
326 }
327 }
328 // Do Rmax
329 Double_t rout = 0.5 * (rmax1 + rmax2 + (rmax2 - rmax1) * point[2] * zinv);
330 if (rsq > rout * (rout - TGeoShape::Tolerance())) {
331 Double_t ddotn = point[0] * dir[0] + point[1] * dir[1] + 0.5 * (rmax1 - rmax2) * dir[2] * zinv * TMath::Sqrt(rsq);
332 if (ddotn >= 0)
333 return 0.0;
334 TGeoCone::DistToCone(point, dir, dz, rmax1, rmax2, b, delta);
335 if (delta < 0)
336 return 0.0;
337 Double_t sr = -b + delta;
338 if (sr < 0)
339 return sz;
340 if (TMath::Abs(-b - delta) > sr)
341 return sz;
342 zi = point[2] + sr * dir[2];
343 if (TMath::Abs(zi) <= dz)
344 return TMath::Min(sz, sr);
345 return sz;
346 }
347 TGeoCone::DistToCone(point, dir, dz, rmax1, rmax2, b, delta);
348 if (delta > 0) {
349 Double_t sr = -b - delta;
350 if (sr > 0) {
351 zi = point[2] + sr * dir[2];
352 if (TMath::Abs(zi) <= dz)
353 return TMath::Min(sz, sr);
354 }
355 sr = -b + delta;
356 if (sr > TGeoShape::Tolerance()) {
357 zi = point[2] + sr * dir[2];
358 if (TMath::Abs(zi) <= dz)
359 return TMath::Min(sz, sr);
360 }
361 }
362 return sz;
363}
364
365////////////////////////////////////////////////////////////////////////////////
366/// Compute distance from inside point to surface of the cone
367/// Boundary safe algorithm.
368
371{
372 if (iact < 3 && safe) {
373 *safe = Safety(point, kTRUE);
374 if (iact == 0)
375 return TGeoShape::Big();
376 if ((iact == 1) && (*safe > step))
377 return TGeoShape::Big();
378 }
379 // compute distance to surface
380 return TGeoCone::DistFromInsideS(point, dir, fDz, fRmin1, fRmax1, fRmin2, fRmax2);
381}
382
383////////////////////////////////////////////////////////////////////////////////
384/// Compute distance from outside point to surface of the tube
385/// Boundary safe algorithm.
386
389{
390 // compute distance to Z planes
391 if (dz <= 0)
392 return TGeoShape::Big();
394 Double_t xp, yp, zp;
395 Bool_t inz = kTRUE;
396
397 if (point[2] <= -dz) {
398 if (dir[2] <= 0)
399 return TGeoShape::Big();
400 snxt = (-dz - point[2]) / dir[2];
401 xp = point[0] + snxt * dir[0];
402 yp = point[1] + snxt * dir[1];
403 Double_t r2 = xp * xp + yp * yp;
404 if ((r2 >= rmin1 * rmin1) && (r2 <= rmax1 * rmax1))
405 return snxt;
406 inz = kFALSE;
407 } else {
408 if (point[2] >= dz) {
409 if (dir[2] >= 0)
410 return TGeoShape::Big();
411 snxt = (dz - point[2]) / dir[2];
412 xp = point[0] + snxt * dir[0];
413 yp = point[1] + snxt * dir[1];
414 Double_t r2 = xp * xp + yp * yp;
415 if ((r2 >= rmin2 * rmin2) && (r2 <= rmax2 * rmax2))
416 return snxt;
417 inz = kFALSE;
418 }
419 }
420
421 Double_t rsq = point[0] * point[0] + point[1] * point[1];
422 Double_t dzinv = 1. / dz;
423 Double_t ro1 = 0.5 * (rmin1 + rmin2);
424 Bool_t hasrmin = (ro1 > 0) ? kTRUE : kFALSE;
425 Double_t tg1 = 0.;
426 Double_t rin = 0.;
427 Bool_t inrmin = kTRUE; // r>=rmin
428 if (hasrmin) {
429 tg1 = 0.5 * (rmin2 - rmin1) * dzinv;
430 rin = ro1 + tg1 * point[2];
431 if (rin > 0 && rsq < rin * (rin - TGeoShape::Tolerance()))
432 inrmin = kFALSE;
433 }
434 Double_t ro2 = 0.5 * (rmax1 + rmax2);
435 Double_t tg2 = 0.5 * (rmax2 - rmax1) * dzinv;
436 Double_t rout = tg2 * point[2] + ro2;
438 if (rout > 0 && rsq < rout * (rout + TGeoShape::Tolerance()))
439 inrmax = kTRUE;
440 Bool_t in = inz & inrmin & inrmax;
441 Double_t b, delta;
442 // If inside cone, we are most likely on a boundary within machine precision.
443 if (in) {
445 Double_t safz = dz - TMath::Abs(point[2]); // positive
448 if (safz <= safrmin && safz <= safrmax) {
449 // on Z boundary
450 if (point[2] * dir[2] < 0)
451 return 0.0;
452 return TGeoShape::Big();
453 }
454 if (safrmax < safrmin) {
455 // on rmax boundary
456 Double_t ddotn = point[0] * dir[0] + point[1] * dir[1] - tg2 * dir[2] * r;
457 if (ddotn <= 0)
458 return 0.0;
459 return TGeoShape::Big();
460 }
461 // on rmin boundary
462 Double_t ddotn = point[0] * dir[0] + point[1] * dir[1] - tg1 * dir[2] * r;
463 if (ddotn >= 0)
464 return 0.0;
465 // we can cross (+) solution of rmin
466 TGeoCone::DistToCone(point, dir, dz, rmin1, rmin2, b, delta);
467
468 if (delta < 0)
469 return 0.0;
470 snxt = -b + delta;
471 if (snxt < 0)
472 return TGeoShape::Big();
473 if (TMath::Abs(-b - delta) > snxt)
474 return TGeoShape::Big();
475 zp = point[2] + snxt * dir[2];
476 if (TMath::Abs(zp) <= dz)
477 return snxt;
478 return TGeoShape::Big();
479 }
480
481 // compute distance to inner cone
483 if (!inrmin) {
484 // ray can cross inner cone (but not only!)
485 TGeoCone::DistToCone(point, dir, dz, rmin1, rmin2, b, delta);
486 if (delta < 0)
487 return TGeoShape::Big();
488 snxt = -b + delta;
489 if (snxt > 0) {
490 zp = point[2] + snxt * dir[2];
491 if (TMath::Abs(zp) <= dz)
492 return snxt;
493 }
494 snxt = -b - delta;
495 if (snxt > 0) {
496 zp = point[2] + snxt * dir[2];
497 if (TMath::Abs(zp) <= dz)
498 return snxt;
499 }
501 } else {
502 if (hasrmin) {
503 TGeoCone::DistToCone(point, dir, dz, rmin1, rmin2, b, delta);
504 if (delta > 0) {
505 Double_t din = -b + delta;
506 if (din > 0) {
507 zp = point[2] + din * dir[2];
508 if (TMath::Abs(zp) <= dz)
509 snxt = din;
510 }
511 }
512 }
513 }
514
515 if (inrmax)
516 return snxt;
517 // We can cross outer cone, both solutions possible
518 // compute distance to outer cone
519 TGeoCone::DistToCone(point, dir, dz, rmax1, rmax2, b, delta);
520 if (delta < 0)
521 return snxt;
522 Double_t dout = -b - delta;
523 if (dout > 0 && dout < snxt) {
524 zp = point[2] + dout * dir[2];
525 if (TMath::Abs(zp) <= dz)
526 return dout;
527 }
528 dout = -b + delta;
530 return snxt;
531 zp = point[2] + dout * dir[2];
532 if (TMath::Abs(zp) <= dz)
533 return dout;
534 return snxt;
535}
536
537////////////////////////////////////////////////////////////////////////////////
538/// compute distance from outside point to surface of the tube
539
542{
543 // compute safe radius
544 if (iact < 3 && safe) {
545 *safe = Safety(point, kFALSE);
546 if (iact == 0)
547 return TGeoShape::Big();
548 if ((iact == 1) && (*safe > step))
549 return TGeoShape::Big();
550 }
551 // Check if the bounding box is crossed within the requested distance
552 Double_t sdist = TGeoBBox::DistFromOutside(point, dir, fDX, fDY, fDZ, fOrigin, step);
553 if (sdist >= step)
554 return TGeoShape::Big();
555 // compute distance to Z planes
557}
558
559////////////////////////////////////////////////////////////////////////////////
560/// Static method to compute distance to a conical surface with :
561/// - r1, z1 - radius and Z position of lower base
562/// - r2, z2 - radius and Z position of upper base
563
565 Double_t &b, Double_t &delta)
566{
567 b = 0;
568 delta = -1.;
569 if (dz < 0)
570 return;
571 Double_t ro0 = 0.5 * (r1 + r2);
572 Double_t tz = 0.5 * (r2 - r1) / dz;
573 Double_t rsq = point[0] * point[0] + point[1] * point[1];
574 Double_t rc = ro0 + point[2] * tz;
575
576 Double_t a = dir[0] * dir[0] + dir[1] * dir[1] - tz * tz * dir[2] * dir[2];
577 b = point[0] * dir[0] + point[1] * dir[1] - tz * rc * dir[2];
578 Double_t c = rsq - rc * rc;
579
582 return;
583 b = 0.5 * c / b;
584 delta = 0.;
585 return;
586 }
587 a = 1. / a;
588 b *= a;
589 c *= a;
590 delta = b * b - c;
591 if (delta > 0) {
592 delta = TMath::Sqrt(delta);
593 } else {
594 delta = -1.;
595 }
596}
597
598////////////////////////////////////////////////////////////////////////////////
599/// compute closest distance from point px,py to each corner
600
602{
604 const Int_t numPoints = 4 * n;
605 return ShapeDistancetoPrimitive(numPoints, px, py);
606}
607
608////////////////////////////////////////////////////////////////////////////////
609/// Divide this cone shape belonging to volume "voldiv" into ndiv volumes
610/// called divname, from start position with the given step. Returns pointer
611/// to created division cell volume in case of Z divisions. For Z division
612/// creates all volumes with different shapes and returns pointer to volume that
613/// was divided. In case a wrong division axis is supplied, returns pointer to
614/// volume that was divided.
615
618{
619 TGeoShape *shape; //--- shape to be created
620 TGeoVolume *vol; //--- division volume to be created
621 TGeoVolumeMulti *vmulti; //--- generic divided volume
622 TGeoPatternFinder *finder; //--- finder to be attached
623 TString opt = ""; //--- option to be attached
624 Int_t id;
625 Double_t end = start + ndiv * step;
626 switch (iaxis) {
627 case 1: //--- R division
628 Error("Divide", "division of a cone on R not implemented");
629 return nullptr;
630 case 2: // --- Phi division
631 finder = new TGeoPatternCylPhi(voldiv, ndiv, start, end);
632 voldiv->SetFinder(finder);
633 finder->SetDivIndex(voldiv->GetNdaughters());
634 shape = new TGeoConeSeg(fDz, fRmin1, fRmax1, fRmin2, fRmax2, -step / 2, step / 2);
635 vol = new TGeoVolume(divname, shape, voldiv->GetMedium());
637 vmulti->AddVolume(vol);
638 opt = "Phi";
639 for (id = 0; id < ndiv; id++) {
640 voldiv->AddNodeOffset(vol, id, start + id * step + step / 2, opt.Data());
641 ((TGeoNodeOffset *)voldiv->GetNodes()->At(voldiv->GetNdaughters() - 1))->SetFinder(finder);
642 }
643 return vmulti;
644 case 3: //--- Z division
646 finder = new TGeoPatternZ(voldiv, ndiv, start, end);
647 voldiv->SetFinder(finder);
648 finder->SetDivIndex(voldiv->GetNdaughters());
649 for (id = 0; id < ndiv; id++) {
650 Double_t z1 = start + id * step;
651 Double_t z2 = start + (id + 1) * step;
652 Double_t rmin1n = 0.5 * (fRmin1 * (fDz - z1) + fRmin2 * (fDz + z1)) / fDz;
653 Double_t rmax1n = 0.5 * (fRmax1 * (fDz - z1) + fRmax2 * (fDz + z1)) / fDz;
654 Double_t rmin2n = 0.5 * (fRmin1 * (fDz - z2) + fRmin2 * (fDz + z2)) / fDz;
655 Double_t rmax2n = 0.5 * (fRmax1 * (fDz - z2) + fRmax2 * (fDz + z2)) / fDz;
656 shape = new TGeoCone(0.5 * step, rmin1n, rmax1n, rmin2n, rmax2n);
657 vol = new TGeoVolume(divname, shape, voldiv->GetMedium());
658 vmulti->AddVolume(vol);
659 opt = "Z";
660 voldiv->AddNodeOffset(vol, id, start + id * step + step / 2, opt.Data());
661 ((TGeoNodeOffset *)voldiv->GetNodes()->At(voldiv->GetNdaughters() - 1))->SetFinder(finder);
662 }
663 return vmulti;
664 default: Error("Divide", "Wrong axis type for division"); return nullptr;
665 }
666}
667
668////////////////////////////////////////////////////////////////////////////////
669/// Returns name of axis IAXIS.
670
672{
673 switch (iaxis) {
674 case 1: return "R";
675 case 2: return "PHI";
676 case 3: return "Z";
677 default: return "undefined";
678 }
679}
680
681////////////////////////////////////////////////////////////////////////////////
682/// Get range of shape for a given axis.
683
685{
686 xlo = 0;
687 xhi = 0;
688 Double_t dx = 0;
689 switch (iaxis) {
690 case 2:
691 xlo = 0.;
692 xhi = 360.;
693 return 360.;
694 case 3:
695 xlo = -fDz;
696 xhi = fDz;
697 dx = xhi - xlo;
698 return dx;
699 }
700 return dx;
701}
702
703////////////////////////////////////////////////////////////////////////////////
704/// Fill vector param[4] with the bounding cylinder parameters. The order
705/// is the following : Rmin, Rmax, Phi1, Phi2, dZ
706
708{
709 param[0] = TMath::Min(fRmin1, fRmin2); // Rmin
710 param[0] *= param[0];
711 param[1] = TMath::Max(fRmax1, fRmax2); // Rmax
712 param[1] *= param[1];
713 param[2] = 0.; // Phi1
714 param[3] = 360.; // Phi2
715}
716
717////////////////////////////////////////////////////////////////////////////////
718/// in case shape has some negative parameters, these has to be computed
719/// in order to fit the mother
720
722{
724 return nullptr;
725 if (!mother->TestShapeBit(kGeoCone)) {
726 Error("GetMakeRuntimeShape", "invalid mother");
727 return nullptr;
728 }
730 rmin1 = fRmin1;
731 rmax1 = fRmax1;
732 rmin2 = fRmin2;
733 rmax2 = fRmax2;
734 dz = fDz;
735 if (fDz < 0)
736 dz = ((TGeoCone *)mother)->GetDz();
737 if (fRmin1 < 0)
738 rmin1 = ((TGeoCone *)mother)->GetRmin1();
739 if (fRmax1 < 0)
740 rmax1 = ((TGeoCone *)mother)->GetRmax1();
741 if (fRmin2 < 0)
742 rmin2 = ((TGeoCone *)mother)->GetRmin2();
743 if (fRmax2 < 0)
744 rmax2 = ((TGeoCone *)mother)->GetRmax2();
745
746 return (new TGeoCone(GetName(), dz, rmin1, rmax1, rmin2, rmax2));
747}
748
749////////////////////////////////////////////////////////////////////////////////
750/// Fills array with n random points located on the line segments of the shape mesh.
751/// The output array must be provided with a length of minimum 3*npoints. Returns
752/// true if operation is implemented.
753
755{
756 if (!array || npoints <= 0)
757 return kFALSE;
758
759 const Bool_t hasInner = (fRmin1 > 0.0) || (fRmin2 > 0.0);
760 const Double_t z1 = -fDz;
761 const Double_t z2 = +fDz;
762 const Double_t dzTot = z2 - z1;
763
764 // Degenerate: if dzTot == 0, the "cone" collapses to a disk/ring; this routine
765 // is about generators, so just refuse.
766 if (dzTot == 0.0)
767 return kFALSE;
768
770 Int_t inPoints = 0;
771 if (hasInner) {
772 outPoints = (npoints + 1) / 2; // outer gets the extra point if odd
774 }
775
777 if (nSurfPoints <= 0)
778 return kTRUE;
779
780 // Choose number of generators ~ sqrt(n), clamped to [1, nSurfPoints]
782 if (nGen < 1)
783 nGen = 1;
784 if (nGen > nSurfPoints)
786
788
789 // Distribute points across generators as evenly as possible
790 const Int_t q = nSurfPoints / nGen;
791 const Int_t r = nSurfPoints % nGen;
792
793 for (Int_t ig = 0; ig < nGen; ++ig) {
794 const Int_t m = q + (ig < r ? 1 : 0); // points on this generator
795 if (m <= 0)
796 continue;
797
798 const Double_t phi = ig * dphi;
799 const Double_t c = TMath::Cos(phi);
800 const Double_t s = TMath::Sin(phi);
801
802 // Place m points along the generator (avoid exact endpoints to reduce duplicates)
803 // t in (0,1): (j+1)/(m+1)
804 for (Int_t j = 0; j < m; ++j) {
805 if (iCrt >= 3 * npoints)
806 return kFALSE; // overflow guard
807
808 const Double_t t = (Double_t)(j + 1) / (Double_t)(m + 1);
809 const Double_t z = z1 + t * dzTot;
810
811 // Linear radius interpolation along z (same formula you used; stable)
812 const Double_t rz = 0.5 * (r1 + r2) + 0.5 * (r2 - r1) * (z / fDz);
813
814 array[iCrt++] = rz * c;
815 array[iCrt++] = rz * s;
816 array[iCrt++] = z;
817 }
818 }
819
820 return kTRUE;
821 };
822
823 Int_t icrt = 0;
824
825 // Outer surface
827 return kFALSE;
828
829 // Inner surface (if hollow)
830 if (hasInner) {
832 return kFALSE;
833 }
834
835 // Contract: must fill exactly npoints
836 if (icrt != 3 * npoints)
837 return kFALSE;
838
839 return kTRUE;
840}
841
842////////////////////////////////////////////////////////////////////////////////
843/// print shape parameters
844
846{
847 printf("*** Shape %s TGeoCone ***\n", GetName());
848 printf(" dz =: %11.5f\n", fDz);
849 printf(" Rmin1 = %11.5f\n", fRmin1);
850 printf(" Rmax1 = %11.5f\n", fRmax1);
851 printf(" Rmin2 = %11.5f\n", fRmin2);
852 printf(" Rmax2 = %11.5f\n", fRmax2);
853 printf(" Bounding box:\n");
855}
856
857////////////////////////////////////////////////////////////////////////////////
858/// Fill TBuffer3D structure for segments and polygons.
859
861{
862 Int_t i, j;
865
866 for (i = 0; i < 4; i++) {
867 for (j = 0; j < n; j++) {
868 buffer.fSegs[(i * n + j) * 3] = c;
869 buffer.fSegs[(i * n + j) * 3 + 1] = i * n + j;
870 buffer.fSegs[(i * n + j) * 3 + 2] = i * n + j + 1;
871 }
872 buffer.fSegs[(i * n + j - 1) * 3 + 2] = i * n;
873 }
874 for (i = 4; i < 6; i++) {
875 for (j = 0; j < n; j++) {
876 buffer.fSegs[(i * n + j) * 3] = c + 1;
877 buffer.fSegs[(i * n + j) * 3 + 1] = (i - 4) * n + j;
878 buffer.fSegs[(i * n + j) * 3 + 2] = (i - 2) * n + j;
879 }
880 }
881 for (i = 6; i < 8; i++) {
882 for (j = 0; j < n; j++) {
883 buffer.fSegs[(i * n + j) * 3] = c;
884 buffer.fSegs[(i * n + j) * 3 + 1] = 2 * (i - 6) * n + j;
885 buffer.fSegs[(i * n + j) * 3 + 2] = (2 * (i - 6) + 1) * n + j;
886 }
887 }
888
889 Int_t indx = 0;
890 i = 0;
891 for (j = 0; j < n; j++) {
892 indx = 6 * (i * n + j);
893 buffer.fPols[indx] = c;
894 buffer.fPols[indx + 1] = 4;
895 buffer.fPols[indx + 5] = i * n + j;
896 buffer.fPols[indx + 4] = (4 + i) * n + j;
897 buffer.fPols[indx + 3] = (2 + i) * n + j;
898 buffer.fPols[indx + 2] = (4 + i) * n + j + 1;
899 }
900 buffer.fPols[indx + 2] = (4 + i) * n;
901 i = 1;
902 for (j = 0; j < n; j++) {
903 indx = 6 * (i * n + j);
904 buffer.fPols[indx] = c;
905 buffer.fPols[indx + 1] = 4;
906 buffer.fPols[indx + 2] = i * n + j;
907 buffer.fPols[indx + 3] = (4 + i) * n + j;
908 buffer.fPols[indx + 4] = (2 + i) * n + j;
909 buffer.fPols[indx + 5] = (4 + i) * n + j + 1;
910 }
911 buffer.fPols[indx + 5] = (4 + i) * n;
912 i = 2;
913 for (j = 0; j < n; j++) {
914 indx = 6 * (i * n + j);
915 buffer.fPols[indx] = c + i;
916 buffer.fPols[indx + 1] = 4;
917 buffer.fPols[indx + 2] = (i - 2) * 2 * n + j;
918 buffer.fPols[indx + 3] = (4 + i) * n + j;
919 buffer.fPols[indx + 4] = ((i - 2) * 2 + 1) * n + j;
920 buffer.fPols[indx + 5] = (4 + i) * n + j + 1;
921 }
922 buffer.fPols[indx + 5] = (4 + i) * n;
923 i = 3;
924 for (j = 0; j < n; j++) {
925 indx = 6 * (i * n + j);
926 buffer.fPols[indx] = c + i;
927 buffer.fPols[indx + 1] = 4;
928 buffer.fPols[indx + 5] = (i - 2) * 2 * n + j;
929 buffer.fPols[indx + 4] = (4 + i) * n + j;
930 buffer.fPols[indx + 3] = ((i - 2) * 2 + 1) * n + j;
931 buffer.fPols[indx + 2] = (4 + i) * n + j + 1;
932 }
933 buffer.fPols[indx + 2] = (4 + i) * n;
934}
935
936////////////////////////////////////////////////////////////////////////////////
937/// computes the closest distance from given point to this shape, according
938/// to option. The matching point on the shape is stored in spoint.
939
941{
942 Double_t saf[4];
943 Double_t r = TMath::Sqrt(point[0] * point[0] + point[1] * point[1]);
944 saf[0] = TGeoShape::SafetySeg(r, point[2], fRmin1, -fDz, fRmax1, -fDz, !in);
945 saf[1] = TGeoShape::SafetySeg(r, point[2], fRmax2, fDz, fRmin2, fDz, !in);
946 saf[2] = TGeoShape::SafetySeg(r, point[2], fRmin2, fDz, fRmin1, -fDz, !in);
947 saf[3] = TGeoShape::SafetySeg(r, point[2], fRmax1, -fDz, fRmax2, fDz, !in);
949 if (safety > 1.E20)
950 safety = 0.;
951 return safety;
952}
953
954////////////////////////////////////////////////////////////////////////////////
955/// computes the closest distance from given point to this shape, according
956/// to option. The matching point on the shape is stored in spoint.
957
960{
961 Double_t saf[4];
962 Double_t r = TMath::Sqrt(point[0] * point[0] + point[1] * point[1]);
963 // Double_t rin = tg1*point[2]+ro1;
964 // Double_t rout = tg2*point[2]+ro2;
965 switch (skipz) {
966 case 1: // skip lower Z plane
967 saf[0] = TGeoShape::Big();
968 saf[1] = TGeoShape::SafetySeg(r, point[2], rmax2, dz, rmin2, dz, !in);
969 break;
970 case 2: // skip upper Z plane
971 saf[0] = TGeoShape::SafetySeg(r, point[2], rmin1, -dz, rmax1, -dz, !in);
972 saf[1] = TGeoShape::Big();
973 break;
974 case 3: // skip both
975 saf[0] = saf[1] = TGeoShape::Big();
976 break;
977 default:
978 saf[0] = TGeoShape::SafetySeg(r, point[2], rmin1, -dz, rmax1, -dz, !in);
979 saf[1] = TGeoShape::SafetySeg(r, point[2], rmax2, dz, rmin2, dz, !in);
980 }
981 // Safety to inner part
982 if (rmin1 > 0 || rmin2 > 0)
983 saf[2] = TGeoShape::SafetySeg(r, point[2], rmin2, dz, rmin1, -dz, !in);
984 else
985 saf[2] = TGeoShape::Big();
986 saf[3] = TGeoShape::SafetySeg(r, point[2], rmax1, -dz, rmax2, dz, !in);
987 return saf[TMath::LocMin(4, saf)];
988}
989
990////////////////////////////////////////////////////////////////////////////////
991/// Save a primitive as a C++ statement(s) on output stream "out".
992
993void TGeoCone::SavePrimitive(std::ostream &out, Option_t * /*option*/ /*= ""*/)
994{
996 return;
997 out << " // Shape: " << GetName() << " type: " << ClassName() << std::endl;
998 out << " dz = " << fDz << ";" << std::endl;
999 out << " rmin1 = " << fRmin1 << ";" << std::endl;
1000 out << " rmax1 = " << fRmax1 << ";" << std::endl;
1001 out << " rmin2 = " << fRmin2 << ";" << std::endl;
1002 out << " rmax2 = " << fRmax2 << ";" << std::endl;
1003 out << " TGeoShape *" << GetPointerName() << " = new TGeoCone(\"" << GetName()
1004 << "\", dz,rmin1,rmax1,rmin2,rmax2);" << std::endl;
1006}
1007
1008////////////////////////////////////////////////////////////////////////////////
1009/// Set cone dimensions.
1010
1012{
1013 if (rmin1 >= 0) {
1014 if (rmax1 > 0) {
1015 if (rmin1 <= rmax1) {
1016 // normal rmin/rmax
1017 fRmin1 = rmin1;
1018 fRmax1 = rmax1;
1019 } else {
1020 fRmin1 = rmax1;
1021 fRmax1 = rmin1;
1022 Warning("SetConeDimensions", "rmin1>rmax1 Switch rmin1<->rmax1");
1024 }
1025 } else {
1026 // run-time
1027 fRmin1 = rmin1;
1028 fRmax1 = rmax1;
1029 }
1030 } else {
1031 // run-time
1032 fRmin1 = rmin1;
1033 fRmax1 = rmax1;
1034 }
1035 if (rmin2 >= 0) {
1036 if (rmax2 > 0) {
1037 if (rmin2 <= rmax2) {
1038 // normal rmin/rmax
1039 fRmin2 = rmin2;
1040 fRmax2 = rmax2;
1041 } else {
1042 fRmin2 = rmax2;
1043 fRmax2 = rmin2;
1044 Warning("SetConeDimensions", "rmin2>rmax2 Switch rmin2<->rmax2");
1046 }
1047 } else {
1048 // run-time
1049 fRmin2 = rmin2;
1050 fRmax2 = rmax2;
1051 }
1052 } else {
1053 // run-time
1054 fRmin2 = rmin2;
1055 fRmax2 = rmax2;
1056 }
1057
1058 fDz = dz;
1059}
1060
1061////////////////////////////////////////////////////////////////////////////////
1062/// Set cone dimensions from an array.
1063
1065{
1066 Double_t dz = param[0];
1067 Double_t rmin1 = param[1];
1068 Double_t rmax1 = param[2];
1069 Double_t rmin2 = param[3];
1070 Double_t rmax2 = param[4];
1072}
1073
1074////////////////////////////////////////////////////////////////////////////////
1075/// Create cone mesh points.
1076
1078{
1079 Double_t dz, phi, dphi;
1080 Int_t j, n;
1081
1083 dphi = 360. / n;
1084 dz = fDz;
1085 Int_t indx = 0;
1086
1087 if (points) {
1088 for (j = 0; j < n; j++) {
1089 phi = j * dphi * TMath::DegToRad();
1090 points[indx++] = fRmin1 * TMath::Cos(phi);
1091 points[indx++] = fRmin1 * TMath::Sin(phi);
1092 points[indx++] = -dz;
1093 }
1094
1095 for (j = 0; j < n; j++) {
1096 phi = j * dphi * TMath::DegToRad();
1097 points[indx++] = fRmax1 * TMath::Cos(phi);
1098 points[indx++] = fRmax1 * TMath::Sin(phi);
1099 points[indx++] = -dz;
1100 }
1101
1102 for (j = 0; j < n; j++) {
1103 phi = j * dphi * TMath::DegToRad();
1104 points[indx++] = fRmin2 * TMath::Cos(phi);
1105 points[indx++] = fRmin2 * TMath::Sin(phi);
1106 points[indx++] = dz;
1107 }
1108
1109 for (j = 0; j < n; j++) {
1110 phi = j * dphi * TMath::DegToRad();
1111 points[indx++] = fRmax2 * TMath::Cos(phi);
1112 points[indx++] = fRmax2 * TMath::Sin(phi);
1113 points[indx++] = dz;
1114 }
1115 }
1116}
1117
1118////////////////////////////////////////////////////////////////////////////////
1119/// Create cone mesh points.
1120
1122{
1123 Double_t dz, phi, dphi;
1124 Int_t j, n;
1125
1127 dphi = 360. / n;
1128 dz = fDz;
1129 Int_t indx = 0;
1130
1131 if (points) {
1132 for (j = 0; j < n; j++) {
1133 phi = j * dphi * TMath::DegToRad();
1134 points[indx++] = fRmin1 * TMath::Cos(phi);
1135 points[indx++] = fRmin1 * TMath::Sin(phi);
1136 points[indx++] = -dz;
1137 }
1138
1139 for (j = 0; j < n; j++) {
1140 phi = j * dphi * TMath::DegToRad();
1141 points[indx++] = fRmax1 * TMath::Cos(phi);
1142 points[indx++] = fRmax1 * TMath::Sin(phi);
1143 points[indx++] = -dz;
1144 }
1145
1146 for (j = 0; j < n; j++) {
1147 phi = j * dphi * TMath::DegToRad();
1148 points[indx++] = fRmin2 * TMath::Cos(phi);
1149 points[indx++] = fRmin2 * TMath::Sin(phi);
1150 points[indx++] = dz;
1151 }
1152
1153 for (j = 0; j < n; j++) {
1154 phi = j * dphi * TMath::DegToRad();
1155 points[indx++] = fRmax2 * TMath::Cos(phi);
1156 points[indx++] = fRmax2 * TMath::Sin(phi);
1157 points[indx++] = dz;
1158 }
1159 }
1160}
1161
1162////////////////////////////////////////////////////////////////////////////////
1163/// Returns numbers of vertices, segments and polygons composing the shape mesh.
1164
1166{
1168 nvert = n * 4;
1169 nsegs = n * 8;
1170 npols = n * 4;
1171}
1172
1173////////////////////////////////////////////////////////////////////////////////
1174/// Return number of vertices of the mesh representation
1175
1177{
1179 Int_t numPoints = n * 4;
1180 return numPoints;
1181}
1182
1183////////////////////////////////////////////////////////////////////////////////
1184/// Fill size of this 3-D object
1185
1186void TGeoCone::Sizeof3D() const {}
1187
1188////////////////////////////////////////////////////////////////////////////////
1189/// Fills a static 3D buffer and returns a reference.
1190
1192{
1193 static TBuffer3D buffer(TBuffer3DTypes::kGeneric);
1194
1196
1199 Int_t nbPnts = 4 * n;
1200 Int_t nbSegs = 8 * n;
1201 Int_t nbPols = 4 * n;
1202 if (buffer.SetRawSizes(nbPnts, 3 * nbPnts, nbSegs, 3 * nbSegs, nbPols, 6 * nbPols)) {
1204 }
1205 }
1206
1207 // TODO: Can we push this as common down to TGeoShape?
1209 SetPoints(buffer.fPnts);
1210 if (!buffer.fLocalFrame) {
1211 TransformPoints(buffer.fPnts, buffer.NbPnts());
1212 }
1213
1214 SetSegsAndPols(buffer);
1216 }
1217
1218 return buffer;
1219}
1220
1221////////////////////////////////////////////////////////////////////////////////
1222/// Check the inside status for each of the points in the array.
1223/// Input: Array of point coordinates + vector size
1224/// Output: Array of Booleans for the inside of each point
1225
1227{
1228 for (Int_t i = 0; i < vecsize; i++)
1229 inside[i] = Contains(&points[3 * i]);
1230}
1231
1232////////////////////////////////////////////////////////////////////////////////
1233/// Compute the normal for an array o points so that norm.dot.dir is positive
1234/// Input: Arrays of point coordinates and directions + vector size
1235/// Output: Array of normal directions
1236
1238{
1239 for (Int_t i = 0; i < vecsize; i++)
1240 ComputeNormal(&points[3 * i], &dirs[3 * i], &norms[3 * i]);
1241}
1242
1243////////////////////////////////////////////////////////////////////////////////
1244/// Compute distance from array of input points having directions specified by dirs. Store output in dists
1245
1247 Double_t *step) const
1248{
1249 for (Int_t i = 0; i < vecsize; i++)
1250 dists[i] = DistFromInside(&points[3 * i], &dirs[3 * i], 3, step[i]);
1251}
1252
1253////////////////////////////////////////////////////////////////////////////////
1254/// Compute distance from array of input points having directions specified by dirs. Store output in dists
1255
1257 Double_t *step) const
1258{
1259 for (Int_t i = 0; i < vecsize; i++)
1260 dists[i] = DistFromOutside(&points[3 * i], &dirs[3 * i], 3, step[i]);
1261}
1262
1263////////////////////////////////////////////////////////////////////////////////
1264/// Compute safe distance from each of the points in the input array.
1265/// Input: Array of point coordinates, array of statuses for these points, size of the arrays
1266/// Output: Safety values
1267
1269{
1270 for (Int_t i = 0; i < vecsize; i++)
1271 safe[i] = Safety(&points[3 * i], inside[i]);
1272}
1273
1274////////////////////////////////////////////////////////////////////////////////
1275/// Default constructor
1276
1278 : TGeoCone(), fPhi1(0.), fPhi2(0.), fS1(0.), fC1(0.), fS2(0.), fC2(0.), fSm(0.), fCm(0.), fCdfi(0.)
1279{
1281 fPhi1 = fPhi2 = 0.0;
1282}
1283
1284////////////////////////////////////////////////////////////////////////////////
1285/// Default constructor specifying minimum and maximum radius
1286
1288 Double_t phi2)
1290 fPhi1(0.),
1291 fPhi2(0.),
1292 fS1(0.),
1293 fC1(0.),
1294 fS2(0.),
1295 fC2(0.),
1296 fSm(0.),
1297 fCm(0.),
1298 fCdfi(0.)
1299
1300{
1303 ComputeBBox();
1304}
1305
1306////////////////////////////////////////////////////////////////////////////////
1307/// Default constructor specifying minimum and maximum radius
1308
1312 fPhi1(0.),
1313 fPhi2(0.),
1314 fS1(0.),
1315 fC1(0.),
1316 fS2(0.),
1317 fC2(0.),
1318 fSm(0.),
1319 fCm(0.),
1320 fCdfi(0.)
1321{
1324 ComputeBBox();
1325}
1326
1327////////////////////////////////////////////////////////////////////////////////
1328/// Default constructor specifying minimum and maximum radius
1329/// - param[0] = dz
1330/// - param[1] = Rmin1
1331/// - param[2] = Rmax1
1332/// - param[3] = Rmin2
1333/// - param[4] = Rmax2
1334/// - param[5] = phi1
1335/// - param[6] = phi2
1336
1338 : TGeoCone(0, 0, 0, 0, 0), fPhi1(0.), fPhi2(0.), fS1(0.), fC1(0.), fS2(0.), fC2(0.), fSm(0.), fCm(0.), fCdfi(0.)
1339{
1341 SetDimensions(param);
1342 ComputeBBox();
1343}
1344
1345////////////////////////////////////////////////////////////////////////////////
1346/// destructor
1347
1349
1350////////////////////////////////////////////////////////////////////////////////
1351/// Function called after streaming an object of this class.
1352
1357
1358////////////////////////////////////////////////////////////////////////////////
1359/// Init frequently used trigonometric values
1360
1362{
1365 fC1 = TMath::Cos(phi1);
1366 fS1 = TMath::Sin(phi1);
1367 fC2 = TMath::Cos(phi2);
1368 fS2 = TMath::Sin(phi2);
1369 Double_t fio = 0.5 * (phi1 + phi2);
1370 fCm = TMath::Cos(fio);
1371 fSm = TMath::Sin(fio);
1372 Double_t dfi = 0.5 * (phi2 - phi1);
1373 fCdfi = TMath::Cos(dfi);
1374}
1375
1376////////////////////////////////////////////////////////////////////////////////
1377/// Computes capacity of the shape in [length^3]
1378
1383
1384////////////////////////////////////////////////////////////////////////////////
1385/// Computes capacity of the shape in [length^3]
1386
1394
1395////////////////////////////////////////////////////////////////////////////////
1396/// compute bounding box of the tube segment
1397
1399{
1403
1404 Double_t xc[4];
1405 Double_t yc[4];
1406 xc[0] = rmax * fC1;
1407 yc[0] = rmax * fS1;
1408 xc[1] = rmax * fC2;
1409 yc[1] = rmax * fS2;
1410 xc[2] = rmin * fC1;
1411 yc[2] = rmin * fS1;
1412 xc[3] = rmin * fC2;
1413 yc[3] = rmin * fS2;
1414
1415 Double_t xmin = xc[TMath::LocMin(4, &xc[0])];
1416 Double_t xmax = xc[TMath::LocMax(4, &xc[0])];
1417 Double_t ymin = yc[TMath::LocMin(4, &yc[0])];
1418 Double_t ymax = yc[TMath::LocMax(4, &yc[0])];
1419
1420 Double_t dp = fPhi2 - fPhi1;
1421 Double_t ddp = -fPhi1;
1422 if (ddp < 0)
1423 ddp += 360;
1424 if (ddp <= dp)
1425 xmax = rmax;
1426 ddp = 90 - fPhi1;
1427 if (ddp < 0)
1428 ddp += 360;
1429 if (ddp <= dp)
1430 ymax = rmax;
1431 ddp = 180 - fPhi1;
1432 if (ddp < 0)
1433 ddp += 360;
1434 if (ddp <= dp)
1435 xmin = -rmax;
1436 ddp = 270 - fPhi1;
1437 if (ddp < 0)
1438 ddp += 360;
1439 if (ddp <= dp)
1440 ymin = -rmax;
1441 fOrigin[0] = (xmax + xmin) / 2;
1442 fOrigin[1] = (ymax + ymin) / 2;
1443 fOrigin[2] = 0;
1444 fDX = (xmax - xmin) / 2;
1445 fDY = (ymax - ymin) / 2;
1446 fDZ = fDz;
1447}
1448
1449////////////////////////////////////////////////////////////////////////////////
1450/// Compute normal to closest surface from POINT.
1451
1452void TGeoConeSeg::ComputeNormal(const Double_t *point, const Double_t *dir, Double_t *norm) const
1453{
1454 Double_t saf[3];
1455 Double_t ro1 = 0.5 * (fRmin1 + fRmin2);
1456 Double_t tg1 = 0.5 * (fRmin2 - fRmin1) / fDz;
1457 Double_t cr1 = 1. / TMath::Sqrt(1. + tg1 * tg1);
1458 Double_t ro2 = 0.5 * (fRmax1 + fRmax2);
1459 Double_t tg2 = 0.5 * (fRmax2 - fRmax1) / fDz;
1460 Double_t cr2 = 1. / TMath::Sqrt(1. + tg2 * tg2);
1461
1462 Double_t r = TMath::Sqrt(point[0] * point[0] + point[1] * point[1]);
1463 Double_t rin = tg1 * point[2] + ro1;
1464 Double_t rout = tg2 * point[2] + ro2;
1465 saf[0] = TMath::Abs(fDz - TMath::Abs(point[2]));
1466 saf[1] = (ro1 > 0) ? (TMath::Abs((r - rin) * cr1)) : TGeoShape::Big();
1467 saf[2] = TMath::Abs((rout - r) * cr2);
1468 Int_t i = TMath::LocMin(3, saf);
1469 if (((fPhi2 - fPhi1) < 360.) && TGeoShape::IsCloseToPhi(saf[i], point, fC1, fS1, fC2, fS2)) {
1470 TGeoShape::NormalPhi(point, dir, norm, fC1, fS1, fC2, fS2);
1471 return;
1472 }
1473 if (i == 0) {
1474 norm[0] = norm[1] = 0.;
1475 norm[2] = TMath::Sign(1., dir[2]);
1476 return;
1477 }
1478
1479 Double_t phi = TMath::ATan2(point[1], point[0]);
1480 Double_t cphi = TMath::Cos(phi);
1481 Double_t sphi = TMath::Sin(phi);
1482
1483 if (i == 1) {
1484 norm[0] = cr1 * cphi;
1485 norm[1] = cr1 * sphi;
1486 norm[2] = -tg1 * cr1;
1487 } else {
1488 norm[0] = cr2 * cphi;
1489 norm[1] = cr2 * sphi;
1490 norm[2] = -tg2 * cr2;
1491 }
1492
1493 if (norm[0] * dir[0] + norm[1] * dir[1] + norm[2] * dir[2] < 0) {
1494 norm[0] = -norm[0];
1495 norm[1] = -norm[1];
1496 norm[2] = -norm[2];
1497 }
1498}
1499
1500////////////////////////////////////////////////////////////////////////////////
1501/// Compute normal to closest surface from POINT.
1502
1506{
1507 Double_t saf[2];
1508 Double_t ro1 = 0.5 * (rmin1 + rmin2);
1509 Double_t tg1 = 0.5 * (rmin2 - rmin1) / dz;
1510 Double_t cr1 = 1. / TMath::Sqrt(1. + tg1 * tg1);
1511 Double_t ro2 = 0.5 * (rmax1 + rmax2);
1512 Double_t tg2 = 0.5 * (rmax2 - rmax1) / dz;
1513 Double_t cr2 = 1. / TMath::Sqrt(1. + tg2 * tg2);
1514
1515 Double_t r = TMath::Sqrt(point[0] * point[0] + point[1] * point[1]);
1516 Double_t rin = tg1 * point[2] + ro1;
1517 Double_t rout = tg2 * point[2] + ro2;
1518 saf[0] = (ro1 > 0) ? (TMath::Abs((r - rin) * cr1)) : TGeoShape::Big();
1519 saf[1] = TMath::Abs((rout - r) * cr2);
1520 Int_t i = TMath::LocMin(2, saf);
1521 if (TGeoShape::IsCloseToPhi(saf[i], point, c1, s1, c2, s2)) {
1522 TGeoShape::NormalPhi(point, dir, norm, c1, s1, c2, s2);
1523 return;
1524 }
1525
1526 Double_t phi = TMath::ATan2(point[1], point[0]);
1527 Double_t cphi = TMath::Cos(phi);
1528 Double_t sphi = TMath::Sin(phi);
1529
1530 if (i == 0) {
1531 norm[0] = cr1 * cphi;
1532 norm[1] = cr1 * sphi;
1533 norm[2] = -tg1 * cr1;
1534 } else {
1535 norm[0] = cr2 * cphi;
1536 norm[1] = cr2 * sphi;
1537 norm[2] = -tg2 * cr2;
1538 }
1539
1540 if (norm[0] * dir[0] + norm[1] * dir[1] + norm[2] * dir[2] < 0) {
1541 norm[0] = -norm[0];
1542 norm[1] = -norm[1];
1543 norm[2] = -norm[2];
1544 }
1545}
1546
1547////////////////////////////////////////////////////////////////////////////////
1548/// test if point is inside this sphere
1549
1551{
1552 if (!TGeoCone::Contains(point))
1553 return kFALSE;
1555 if (dphi >= 360.)
1556 return kTRUE;
1557 Double_t phi = TMath::ATan2(point[1], point[0]) * TMath::RadToDeg();
1558 if (phi < 0)
1559 phi += 360.;
1560 Double_t ddp = phi - fPhi1;
1561 if (ddp < 0)
1562 ddp += 360.;
1563 // if (ddp > 360) ddp-=360;
1564 if (ddp > dphi)
1565 return kFALSE;
1566 return kTRUE;
1567}
1568
1569////////////////////////////////////////////////////////////////////////////////
1570/// Static method to compute distance to a conical surface with :
1571/// - r1, z1 - radius and Z position of lower base
1572/// - r2, z2 - radius and Z position of upper base
1573/// - phi1, phi2 - phi limits
1574
1577{
1578 Double_t dz = z2 - z1;
1579 if (dz <= 0) {
1580 return TGeoShape::Big();
1581 }
1582
1583 Double_t dphi = phi2 - phi1;
1585 if (dphi >= 360.)
1586 hasphi = kFALSE;
1587 if (dphi < 0)
1588 dphi += 360.;
1589 // printf("phi1=%f phi2=%f dphi=%f\n", phi1, phi2, dphi);
1590
1591 Double_t ro0 = 0.5 * (r1 + r2);
1592 Double_t fz = (r2 - r1) / dz;
1593 Double_t r0sq = point[0] * point[0] + point[1] * point[1];
1594 Double_t rc = ro0 + fz * (point[2] - 0.5 * (z1 + z2));
1595
1596 Double_t a = dir[0] * dir[0] + dir[1] * dir[1] - fz * fz * dir[2] * dir[2];
1597 Double_t b = point[0] * dir[0] + point[1] * dir[1] - fz * rc * dir[2];
1598 Double_t c = r0sq - rc * rc;
1599
1600 if (a == 0)
1601 return TGeoShape::Big();
1602 a = 1. / a;
1603 b *= a;
1604 c *= a;
1605 Double_t delta = b * b - c;
1606 if (delta < 0)
1607 return TGeoShape::Big();
1608 delta = TMath::Sqrt(delta);
1609
1610 Double_t snxt = -b - delta;
1611 Double_t ptnew[3];
1612 Double_t ddp, phi;
1613 if (snxt > 0) {
1614 // check Z range
1615 ptnew[2] = point[2] + snxt * dir[2];
1616 if (((ptnew[2] - z1) * (ptnew[2] - z2)) < 0) {
1617 // check phi range
1618 if (!hasphi)
1619 return snxt;
1620 ptnew[0] = point[0] + snxt * dir[0];
1621 ptnew[1] = point[1] + snxt * dir[1];
1622 phi = TMath::ATan2(ptnew[1], ptnew[0]) * TMath::RadToDeg();
1623 if (phi < 0)
1624 phi += 360.;
1625 ddp = phi - phi1;
1626 if (ddp < 0)
1627 ddp += 360.;
1628 // printf("snxt1=%f phi=%f ddp=%f\n", snxt, phi, ddp);
1629 if (ddp <= dphi)
1630 return snxt;
1631 }
1632 }
1633 snxt = -b + delta;
1634 if (snxt > 0) {
1635 // check Z range
1636 ptnew[2] = point[2] + snxt * dir[2];
1637 if (((ptnew[2] - z1) * (ptnew[2] - z2)) < 0) {
1638 // check phi range
1639 if (!hasphi)
1640 return snxt;
1641 ptnew[0] = point[0] + snxt * dir[0];
1642 ptnew[1] = point[1] + snxt * dir[1];
1643 phi = TMath::ATan2(ptnew[1], ptnew[0]) * TMath::RadToDeg();
1644 if (phi < 0)
1645 phi += 360.;
1646 ddp = phi - phi1;
1647 if (ddp < 0)
1648 ddp += 360.;
1649 // printf("snxt2=%f phi=%f ddp=%f\n", snxt, phi, ddp);
1650 if (ddp <= dphi)
1651 return snxt;
1652 }
1653 }
1654 return TGeoShape::Big();
1655}
1656
1657////////////////////////////////////////////////////////////////////////////////
1658/// compute distance from inside point to surface of the tube segment
1659
1663{
1664 if (dz <= 0)
1665 return TGeoShape::Big();
1666 // Do Z
1668 if (scone <= 0)
1669 return 0.0;
1671 Double_t rsq = point[0] * point[0] + point[1] * point[1];
1673 Double_t cpsi = point[0] * cm + point[1] * sm;
1674 if (cpsi > r * cdfi + TGeoShape::Tolerance()) {
1675 sfmin = TGeoShape::DistToPhiMin(point, dir, s1, c1, s2, c2, sm, cm);
1676 return TMath::Min(scone, sfmin);
1677 }
1678 // Point on the phi boundary or outside
1679 // which one: phi1 or phi2
1680 Double_t ddotn, xi, yi;
1681 if (TMath::Abs(point[1] - s1 * r) < TMath::Abs(point[1] - s2 * r)) {
1682 ddotn = s1 * dir[0] - c1 * dir[1];
1683 if (ddotn >= 0)
1684 return 0.0;
1685 ddotn = -s2 * dir[0] + c2 * dir[1];
1686 if (ddotn <= 0)
1687 return scone;
1688 sfmin = s2 * point[0] - c2 * point[1];
1689 if (sfmin <= 0)
1690 return scone;
1691 sfmin /= ddotn;
1692 if (sfmin >= scone)
1693 return scone;
1694 xi = point[0] + sfmin * dir[0];
1695 yi = point[1] + sfmin * dir[1];
1696 if (yi * cm - xi * sm < 0)
1697 return scone;
1698 return sfmin;
1699 }
1700 ddotn = -s2 * dir[0] + c2 * dir[1];
1701 if (ddotn >= 0)
1702 return 0.0;
1703 ddotn = s1 * dir[0] - c1 * dir[1];
1704 if (ddotn <= 0)
1705 return scone;
1706 sfmin = -s1 * point[0] + c1 * point[1];
1707 if (sfmin <= 0)
1708 return scone;
1709 sfmin /= ddotn;
1710 if (sfmin >= scone)
1711 return scone;
1712 xi = point[0] + sfmin * dir[0];
1713 yi = point[1] + sfmin * dir[1];
1714 if (yi * cm - xi * sm > 0)
1715 return scone;
1716 return sfmin;
1717}
1718
1719////////////////////////////////////////////////////////////////////////////////
1720/// compute distance from inside point to surface of the tube segment
1721
1724{
1725 if (iact < 3 && safe) {
1727 if (iact == 0)
1728 return TGeoShape::Big();
1729 if ((iact == 1) && (*safe > step))
1730 return TGeoShape::Big();
1731 }
1732 if ((fPhi2 - fPhi1) >= 360.)
1733 return TGeoCone::DistFromInsideS(point, dir, fDz, fRmin1, fRmax1, fRmin2, fRmax2);
1734
1735 // compute distance to surface
1737 fCdfi);
1738}
1739
1740////////////////////////////////////////////////////////////////////////////////
1741/// compute distance from outside point to surface of arbitrary tube
1742
1746{
1747 if (dz <= 0)
1748 return TGeoShape::Big();
1749 Double_t r2, cpsi;
1750 // check Z planes
1751 Double_t xi, yi, zi;
1752 Double_t b, delta;
1753 zi = dz - TMath::Abs(point[2]);
1754 Double_t rin, rout;
1757 Bool_t in = kFALSE;
1758 Bool_t inz = (zi < 0) ? kFALSE : kTRUE;
1759 if (!inz) {
1760 if (point[2] * dir[2] >= 0)
1761 return TGeoShape::Big();
1762 s = -zi / TMath::Abs(dir[2]);
1763 xi = point[0] + s * dir[0];
1764 yi = point[1] + s * dir[1];
1765 r2 = xi * xi + yi * yi;
1766 if (dir[2] > 0) {
1767 rin = rmin1;
1768 rout = rmax1;
1769 } else {
1770 rin = rmin2;
1771 rout = rmax2;
1772 }
1773 if ((rin * rin <= r2) && (r2 <= rout * rout)) {
1774 cpsi = xi * cm + yi * sm;
1775 if (cpsi >= (cdfi * TMath::Sqrt(r2)))
1776 return s;
1777 }
1778 }
1779 Double_t zinv = 1. / dz;
1780 Double_t rsq = point[0] * point[0] + point[1] * point[1];
1782 Double_t ro1 = 0.5 * (rmin1 + rmin2);
1783 Bool_t hasrmin = (ro1 > 0) ? kTRUE : kFALSE;
1784 Double_t tg1 = 0.0;
1786 rin = 0.0;
1787 if (hasrmin) {
1788 tg1 = 0.5 * (rmin2 - rmin1) * zinv;
1789 rin = ro1 + tg1 * point[2];
1790 if (rsq > rin * (rin - TGeoShape::Tolerance()))
1791 inrmin = kTRUE;
1792 } else {
1793 inrmin = kTRUE;
1794 }
1795 Double_t ro2 = 0.5 * (rmax1 + rmax2);
1796 Double_t tg2 = 0.5 * (rmax2 - rmax1) * zinv;
1797 rout = ro2 + tg2 * point[2];
1799 if (r < rout + TGeoShape::Tolerance())
1800 inrmax = kTRUE;
1802 cpsi = point[0] * cm + point[1] * sm;
1803 if (cpsi > r * cdfi - TGeoShape::Tolerance())
1804 inphi = kTRUE;
1805 in = inz & inrmin & inrmax & inphi;
1806 // If inside, we are most likely on a boundary within machine precision.
1807 if (in) {
1808 Double_t safphi = (cpsi - r * cdfi) * TMath::Sqrt(1. - cdfi * cdfi);
1811 // check if on Z boundaries
1812 if (zi < safrmax && zi < safrmin && zi < safphi) {
1813 if (point[2] * dir[2] < 0)
1814 return 0.0;
1815 return TGeoShape::Big();
1816 }
1817 // check if on Rmax boundary
1818 if (safrmax < safrmin && safrmax < safphi) {
1819 Double_t ddotn = point[0] * dir[0] + point[1] * dir[1] - tg2 * dir[2] * r;
1820 if (ddotn <= 0)
1821 return 0.0;
1822 return TGeoShape::Big();
1823 }
1824 // check if on phi boundary
1825 if (safphi < safrmin) {
1826 // We may cross again a phi of rmin boundary
1827 // check first if we are on phi1 or phi2
1828 Double_t un;
1829 if (point[0] * c1 + point[1] * s1 > point[0] * c2 + point[1] * s2) {
1830 un = dir[0] * s1 - dir[1] * c1;
1831 if (un < 0)
1832 return 0.0;
1833 if (cdfi >= 0)
1834 return TGeoShape::Big();
1835 un = -dir[0] * s2 + dir[1] * c2;
1836 if (un < 0) {
1837 s = -point[0] * s2 + point[1] * c2;
1838 if (s > 0) {
1839 s /= (-un);
1840 zi = point[2] + s * dir[2];
1841 if (TMath::Abs(zi) <= dz) {
1842 xi = point[0] + s * dir[0];
1843 yi = point[1] + s * dir[1];
1844 if ((yi * cm - xi * sm) > 0) {
1845 r2 = xi * xi + yi * yi;
1846 rin = ro1 + tg1 * zi;
1847 rout = ro2 + tg2 * zi;
1848 if ((rin * rin <= r2) && (rout * rout >= r2))
1849 return s;
1850 }
1851 }
1852 }
1853 }
1854 } else {
1855 un = -dir[0] * s2 + dir[1] * c2;
1856 if (un < 0)
1857 return 0.0;
1858 if (cdfi >= 0)
1859 return TGeoShape::Big();
1860 un = dir[0] * s1 - dir[1] * c1;
1861 if (un < 0) {
1862 s = point[0] * s1 - point[1] * c1;
1863 if (s > 0) {
1864 s /= (-un);
1865 zi = point[2] + s * dir[2];
1866 if (TMath::Abs(zi) <= dz) {
1867 xi = point[0] + s * dir[0];
1868 yi = point[1] + s * dir[1];
1869 if ((yi * cm - xi * sm) < 0) {
1870 r2 = xi * xi + yi * yi;
1871 rin = ro1 + tg1 * zi;
1872 rout = ro2 + tg2 * zi;
1873 if ((rin * rin <= r2) && (rout * rout >= r2))
1874 return s;
1875 }
1876 }
1877 }
1878 }
1879 }
1880 // We may also cross rmin, second solution coming from outside
1881 Double_t ddotn = point[0] * dir[0] + point[1] * dir[1] - tg1 * dir[2] * r;
1882 if (ddotn >= 0)
1883 return TGeoShape::Big();
1884 if (cdfi >= 0)
1885 return TGeoShape::Big();
1886 TGeoCone::DistToCone(point, dir, dz, rmin1, rmin2, b, delta);
1887 if (delta < 0)
1888 return TGeoShape::Big();
1889 snxt = -b - delta;
1890 if (snxt < 0)
1891 return TGeoShape::Big();
1892 snxt = -b + delta;
1893 zi = point[2] + snxt * dir[2];
1894 if (TMath::Abs(zi) > dz)
1895 return TGeoShape::Big();
1896 xi = point[0] + snxt * dir[0];
1897 yi = point[1] + snxt * dir[1];
1898 r2 = xi * xi + yi * yi;
1899 cpsi = xi * cm + yi * sm;
1900 if (cpsi >= (cdfi * TMath::Sqrt(r2)))
1901 return snxt;
1902 return TGeoShape::Big();
1903 }
1904 // We are on rmin boundary: we may cross again rmin or a phi facette
1905 Double_t ddotn = point[0] * dir[0] + point[1] * dir[1] - tg1 * dir[2] * r;
1906 if (ddotn >= 0)
1907 return 0.0;
1908 TGeoCone::DistToCone(point, dir, dz, rmin1, rmin2, b, delta);
1909 if (delta < 0)
1910 return 0.0;
1911 snxt = -b + delta;
1912 if (snxt < 0)
1913 return TGeoShape::Big();
1914 if (TMath::Abs(-b - delta) > snxt)
1915 return TGeoShape::Big();
1916 zi = point[2] + snxt * dir[2];
1917 if (TMath::Abs(zi) > dz)
1918 return TGeoShape::Big();
1919 // OK, we cross rmin at snxt - check if within phi range
1920 xi = point[0] + snxt * dir[0];
1921 yi = point[1] + snxt * dir[1];
1922 r2 = xi * xi + yi * yi;
1923 cpsi = xi * cm + yi * sm;
1924 if (cpsi >= (cdfi * TMath::Sqrt(r2)))
1925 return snxt;
1926 // we cross rmin in the phi gap - we may cross a phi facette
1927 if (cdfi >= 0)
1928 return TGeoShape::Big();
1929 Double_t un = -dir[0] * s1 + dir[1] * c1;
1930 if (un > 0) {
1931 s = point[0] * s1 - point[1] * c1;
1932 if (s >= 0) {
1933 s /= un;
1934 zi = point[2] + s * dir[2];
1935 if (TMath::Abs(zi) <= dz) {
1936 xi = point[0] + s * dir[0];
1937 yi = point[1] + s * dir[1];
1938 if ((yi * cm - xi * sm) <= 0) {
1939 r2 = xi * xi + yi * yi;
1940 rin = ro1 + tg1 * zi;
1941 rout = ro2 + tg2 * zi;
1942 if ((rin * rin <= r2) && (rout * rout >= r2))
1943 return s;
1944 }
1945 }
1946 }
1947 }
1948 un = dir[0] * s2 - dir[1] * c2;
1949 if (un > 0) {
1950 s = (point[1] * c2 - point[0] * s2) / un;
1951 if (s >= 0) {
1952 zi = point[2] + s * dir[2];
1953 if (TMath::Abs(zi) <= dz) {
1954 xi = point[0] + s * dir[0];
1955 yi = point[1] + s * dir[1];
1956 if ((yi * cm - xi * sm) >= 0) {
1957 r2 = xi * xi + yi * yi;
1958 rin = ro1 + tg1 * zi;
1959 rout = ro2 + tg2 * zi;
1960 if ((rin * rin <= r2) && (rout * rout >= r2))
1961 return s;
1962 }
1963 }
1964 }
1965 }
1966 return TGeoShape::Big();
1967 }
1968
1969 // The point is really outside
1971 if (!inrmax) {
1972 // check crossing with outer cone
1973 TGeoCone::DistToCone(point, dir, dz, rmax1, rmax2, b, delta);
1974 if (delta >= 0) {
1975 s = -b - delta;
1976 if (s > 0) {
1977 zi = point[2] + s * dir[2];
1978 if (TMath::Abs(zi) <= dz) {
1979 xi = point[0] + s * dir[0];
1980 yi = point[1] + s * dir[1];
1981 r2 = xi * xi + yi * yi;
1982 cpsi = xi * cm + yi * sm;
1983 if (cpsi >= (cdfi * TMath::Sqrt(r2)))
1984 return s; // rmax crossing
1985 }
1986 }
1987 s = -b + delta;
1988 if (s > 0) {
1989 zi = point[2] + s * dir[2];
1990 if (TMath::Abs(zi) <= dz) {
1991 xi = point[0] + s * dir[0];
1992 yi = point[1] + s * dir[1];
1993 r2 = xi * xi + yi * yi;
1994 cpsi = xi * cm + yi * sm;
1995 if (cpsi >= (cdfi * TMath::Sqrt(r2)))
1996 sr1 = s;
1997 }
1998 }
1999 }
2000 }
2001 // check crossing with inner cone
2003 TGeoCone::DistToCone(point, dir, dz, rmin1, rmin2, b, delta);
2004 if (delta >= 0) {
2005 s = -b - delta;
2006 if (s > 0) {
2007 zi = point[2] + s * dir[2];
2008 if (TMath::Abs(zi) <= dz) {
2009 xi = point[0] + s * dir[0];
2010 yi = point[1] + s * dir[1];
2011 r2 = xi * xi + yi * yi;
2012 cpsi = xi * cm + yi * sm;
2013 if (cpsi >= (cdfi * TMath::Sqrt(r2)))
2014 sr2 = s;
2015 }
2016 }
2017 if (sr2 > 1E10) {
2018 s = -b + delta;
2019 if (s > 0) {
2020 zi = point[2] + s * dir[2];
2021 if (TMath::Abs(zi) <= dz) {
2022 xi = point[0] + s * dir[0];
2023 yi = point[1] + s * dir[1];
2024 r2 = xi * xi + yi * yi;
2025 cpsi = xi * cm + yi * sm;
2026 if (cpsi >= (cdfi * TMath::Sqrt(r2)))
2027 sr2 = s;
2028 }
2029 }
2030 }
2031 }
2032 snxt = TMath::Min(sr1, sr2);
2033 // Check phi crossing
2034 s = TGeoShape::DistToPhiMin(point, dir, s1, c1, s2, c2, sm, cm, kFALSE);
2035 if (s > snxt)
2036 return snxt;
2037 zi = point[2] + s * dir[2];
2038 if (TMath::Abs(zi) > dz)
2039 return snxt;
2040 xi = point[0] + s * dir[0];
2041 yi = point[1] + s * dir[1];
2042 r2 = xi * xi + yi * yi;
2043 rout = ro2 + tg2 * zi;
2044 if (r2 > rout * rout)
2045 return snxt;
2046 rin = ro1 + tg1 * zi;
2047 if (r2 >= rin * rin)
2048 return s; // phi crossing
2049 return snxt;
2050}
2051
2052////////////////////////////////////////////////////////////////////////////////
2053/// compute distance from outside point to surface of the tube
2054
2056 Double_t *safe) const
2057{
2058 // compute safe radius
2059 if (iact < 3 && safe) {
2060 *safe = Safety(point, kFALSE);
2061 if (iact == 0)
2062 return TGeoShape::Big();
2063 if ((iact == 1) && (*safe > step))
2064 return TGeoShape::Big();
2065 }
2066 // Check if the bounding box is crossed within the requested distance
2067 Double_t sdist = TGeoBBox::DistFromOutside(point, dir, fDX, fDY, fDZ, fOrigin, step);
2068 if (sdist >= step)
2069 return TGeoShape::Big();
2070 if ((fPhi2 - fPhi1) >= 360.)
2071 return TGeoCone::DistFromOutsideS(point, dir, fDz, fRmin1, fRmax1, fRmin2, fRmax2);
2073 fCdfi);
2074}
2075
2076////////////////////////////////////////////////////////////////////////////////
2077/// compute closest distance from point px,py to each corner
2078
2080{
2082 const Int_t numPoints = 4 * n;
2083 return ShapeDistancetoPrimitive(numPoints, px, py);
2084}
2085
2086////////////////////////////////////////////////////////////////////////////////
2087/// Divide this cone segment shape belonging to volume "voldiv" into ndiv volumes
2088/// called divname, from start position with the given step. Returns pointer
2089/// to created division cell volume in case of Z divisions. For Z division
2090/// creates all volumes with different shapes and returns pointer to volume that
2091/// was divided. In case a wrong division axis is supplied, returns pointer to
2092/// volume that was divided.
2093
2094TGeoVolume *
2096{
2097 TGeoShape *shape; //--- shape to be created
2098 TGeoVolume *vol; //--- division volume to be created
2099 TGeoVolumeMulti *vmulti; //--- generic divided volume
2100 TGeoPatternFinder *finder; //--- finder to be attached
2101 TString opt = ""; //--- option to be attached
2102 Double_t dphi;
2103 Int_t id;
2104 Double_t end = start + ndiv * step;
2105 switch (iaxis) {
2106 case 1: //--- R division
2107 Error("Divide", "division of a cone segment on R not implemented");
2108 return nullptr;
2109 case 2: //--- Phi division
2110 dphi = fPhi2 - fPhi1;
2111 if (dphi < 0)
2112 dphi += 360.;
2113 finder = new TGeoPatternCylPhi(voldiv, ndiv, start, end);
2114 voldiv->SetFinder(finder);
2115 finder->SetDivIndex(voldiv->GetNdaughters());
2116 shape = new TGeoConeSeg(fDz, fRmin1, fRmax1, fRmin2, fRmax2, -step / 2, step / 2);
2117 vol = new TGeoVolume(divname, shape, voldiv->GetMedium());
2119 vmulti->AddVolume(vol);
2120 opt = "Phi";
2121 for (id = 0; id < ndiv; id++) {
2122 voldiv->AddNodeOffset(vol, id, start + id * step + step / 2, opt.Data());
2123 ((TGeoNodeOffset *)voldiv->GetNodes()->At(voldiv->GetNdaughters() - 1))->SetFinder(finder);
2124 }
2125 return vmulti;
2126 case 3: //--- Z division
2127 finder = new TGeoPatternZ(voldiv, ndiv, start, end);
2129 voldiv->SetFinder(finder);
2130 finder->SetDivIndex(voldiv->GetNdaughters());
2131 for (id = 0; id < ndiv; id++) {
2132 Double_t z1 = start + id * step;
2133 Double_t z2 = start + (id + 1) * step;
2134 Double_t rmin1n = 0.5 * (fRmin1 * (fDz - z1) + fRmin2 * (fDz + z1)) / fDz;
2135 Double_t rmax1n = 0.5 * (fRmax1 * (fDz - z1) + fRmax2 * (fDz + z1)) / fDz;
2136 Double_t rmin2n = 0.5 * (fRmin1 * (fDz - z2) + fRmin2 * (fDz + z2)) / fDz;
2137 Double_t rmax2n = 0.5 * (fRmax1 * (fDz - z2) + fRmax2 * (fDz + z2)) / fDz;
2138 shape = new TGeoConeSeg(step / 2, rmin1n, rmax1n, rmin2n, rmax2n, fPhi1, fPhi2);
2139 vol = new TGeoVolume(divname, shape, voldiv->GetMedium());
2140 vmulti->AddVolume(vol);
2141 opt = "Z";
2142 voldiv->AddNodeOffset(vol, id, start + id * step + step / 2, opt.Data());
2143 ((TGeoNodeOffset *)voldiv->GetNodes()->At(voldiv->GetNdaughters() - 1))->SetFinder(finder);
2144 }
2145 return vmulti;
2146 default: Error("Divide", "Wrong axis type for division"); return nullptr;
2147 }
2148}
2149
2150////////////////////////////////////////////////////////////////////////////////
2151/// Get range of shape for a given axis.
2152
2154{
2155 xlo = 0;
2156 xhi = 0;
2157 Double_t dx = 0;
2158 switch (iaxis) {
2159 case 2:
2160 xlo = fPhi1;
2161 xhi = fPhi2;
2162 dx = xhi - xlo;
2163 return dx;
2164 case 3:
2165 xlo = -fDz;
2166 xhi = fDz;
2167 dx = xhi - xlo;
2168 return dx;
2169 }
2170 return dx;
2171}
2172
2173////////////////////////////////////////////////////////////////////////////////
2174/// Fill vector param[4] with the bounding cylinder parameters. The order
2175/// is the following : Rmin, Rmax, Phi1, Phi2
2176
2178{
2179 param[0] = TMath::Min(fRmin1, fRmin2); // Rmin
2180 param[0] *= param[0];
2181 param[1] = TMath::Max(fRmax1, fRmax2); // Rmax
2182 param[1] *= param[1];
2183 param[2] = (fPhi1 < 0) ? (fPhi1 + 360.) : fPhi1; // Phi1
2184 param[3] = fPhi2; // Phi2
2185 while (param[3] < param[2])
2186 param[3] += 360.;
2187}
2188
2189////////////////////////////////////////////////////////////////////////////////
2190/// in case shape has some negative parameters, these has to be computed
2191/// in order to fit the mother
2192
2194{
2196 return nullptr;
2197 if (!mother->TestShapeBit(kGeoConeSeg)) {
2198 Error("GetMakeRuntimeShape", "invalid mother");
2199 return nullptr;
2200 }
2202 rmin1 = fRmin1;
2203 rmax1 = fRmax1;
2204 rmin2 = fRmin2;
2205 rmax2 = fRmax2;
2206 dz = fDz;
2207 if (fDz < 0)
2208 dz = ((TGeoCone *)mother)->GetDz();
2209 if (fRmin1 < 0)
2210 rmin1 = ((TGeoCone *)mother)->GetRmin1();
2211 if ((fRmax1 < 0) || (fRmax1 < fRmin1))
2212 rmax1 = ((TGeoCone *)mother)->GetRmax1();
2213 if (fRmin2 < 0)
2214 rmin2 = ((TGeoCone *)mother)->GetRmin2();
2215 if ((fRmax2 < 0) || (fRmax2 < fRmin2))
2216 rmax2 = ((TGeoCone *)mother)->GetRmax2();
2217
2218 return (new TGeoConeSeg(GetName(), dz, rmin1, rmax1, rmin2, rmax2, fPhi1, fPhi2));
2219}
2220
2221////////////////////////////////////////////////////////////////////////////////
2222/// print shape parameters
2223
2225{
2226 printf("*** Shape %s: TGeoConeSeg ***\n", GetName());
2227 printf(" dz = %11.5f\n", fDz);
2228 printf(" Rmin1 = %11.5f\n", fRmin1);
2229 printf(" Rmax1 = %11.5f\n", fRmax1);
2230 printf(" Rmin2 = %11.5f\n", fRmin2);
2231 printf(" Rmax2 = %11.5f\n", fRmax2);
2232 printf(" phi1 = %11.5f\n", fPhi1);
2233 printf(" phi2 = %11.5f\n", fPhi2);
2234 printf(" Bounding box:\n");
2236}
2237
2238////////////////////////////////////////////////////////////////////////////////
2239/// Fill TBuffer3D structure for segments and polygons.
2240
2242{
2243 Int_t i, j;
2245 Int_t c = GetBasicColor();
2246
2247 memset(buffer.fSegs, 0, buffer.NbSegs() * 3 * sizeof(Int_t));
2248 for (i = 0; i < 4; i++) {
2249 for (j = 1; j < n; j++) {
2250 buffer.fSegs[(i * n + j - 1) * 3] = c;
2251 buffer.fSegs[(i * n + j - 1) * 3 + 1] = i * n + j - 1;
2252 buffer.fSegs[(i * n + j - 1) * 3 + 2] = i * n + j;
2253 }
2254 }
2255 for (i = 4; i < 6; i++) {
2256 for (j = 0; j < n; j++) {
2257 buffer.fSegs[(i * n + j) * 3] = c + 1;
2258 buffer.fSegs[(i * n + j) * 3 + 1] = (i - 4) * n + j;
2259 buffer.fSegs[(i * n + j) * 3 + 2] = (i - 2) * n + j;
2260 }
2261 }
2262 for (i = 6; i < 8; i++) {
2263 for (j = 0; j < n; j++) {
2264 buffer.fSegs[(i * n + j) * 3] = c;
2265 buffer.fSegs[(i * n + j) * 3 + 1] = 2 * (i - 6) * n + j;
2266 buffer.fSegs[(i * n + j) * 3 + 2] = (2 * (i - 6) + 1) * n + j;
2267 }
2268 }
2269
2270 Int_t indx = 0;
2271 memset(buffer.fPols, 0, buffer.NbPols() * 6 * sizeof(Int_t));
2272 i = 0;
2273 for (j = 0; j < n - 1; j++) {
2274 buffer.fPols[indx++] = c;
2275 buffer.fPols[indx++] = 4;
2276 buffer.fPols[indx++] = (4 + i) * n + j + 1;
2277 buffer.fPols[indx++] = (2 + i) * n + j;
2278 buffer.fPols[indx++] = (4 + i) * n + j;
2279 buffer.fPols[indx++] = i * n + j;
2280 }
2281 i = 1;
2282 for (j = 0; j < n - 1; j++) {
2283 buffer.fPols[indx++] = c;
2284 buffer.fPols[indx++] = 4;
2285 buffer.fPols[indx++] = i * n + j;
2286 buffer.fPols[indx++] = (4 + i) * n + j;
2287 buffer.fPols[indx++] = (2 + i) * n + j;
2288 buffer.fPols[indx++] = (4 + i) * n + j + 1;
2289 }
2290 i = 2;
2291 for (j = 0; j < n - 1; j++) {
2292 buffer.fPols[indx++] = c + i;
2293 buffer.fPols[indx++] = 4;
2294 buffer.fPols[indx++] = (i - 2) * 2 * n + j;
2295 buffer.fPols[indx++] = (4 + i) * n + j;
2296 buffer.fPols[indx++] = ((i - 2) * 2 + 1) * n + j;
2297 buffer.fPols[indx++] = (4 + i) * n + j + 1;
2298 }
2299 i = 3;
2300 for (j = 0; j < n - 1; j++) {
2301 buffer.fPols[indx++] = c + i;
2302 buffer.fPols[indx++] = 4;
2303 buffer.fPols[indx++] = (4 + i) * n + j + 1;
2304 buffer.fPols[indx++] = ((i - 2) * 2 + 1) * n + j;
2305 buffer.fPols[indx++] = (4 + i) * n + j;
2306 buffer.fPols[indx++] = (i - 2) * 2 * n + j;
2307 }
2308 buffer.fPols[indx++] = c + 2;
2309 buffer.fPols[indx++] = 4;
2310 buffer.fPols[indx++] = 6 * n;
2311 buffer.fPols[indx++] = 4 * n;
2312 buffer.fPols[indx++] = 7 * n;
2313 buffer.fPols[indx++] = 5 * n;
2314 buffer.fPols[indx++] = c + 2;
2315 buffer.fPols[indx++] = 4;
2316 buffer.fPols[indx++] = 6 * n - 1;
2317 buffer.fPols[indx++] = 8 * n - 1;
2318 buffer.fPols[indx++] = 5 * n - 1;
2319 buffer.fPols[indx++] = 7 * n - 1;
2320}
2321
2322////////////////////////////////////////////////////////////////////////////////
2323/// computes the closest distance from given point to this shape, according
2324/// to option. The matching point on the shape is stored in spoint.
2325
2327{
2328 Double_t safe = TGeoCone::Safety(point, in);
2329 if ((fPhi2 - fPhi1) >= 360.)
2330 return safe;
2332 if (in)
2333 return TMath::Min(safe, safphi);
2334 if (safe > 1.E10)
2335 return safphi;
2336 return TMath::Max(safe, safphi);
2337}
2338
2339////////////////////////////////////////////////////////////////////////////////
2340/// Static method to compute the closest distance from given point to this shape.
2341
2344{
2346 if ((phi2 - phi1) >= 360.)
2347 return safe;
2349 if (in)
2350 return TMath::Min(safe, safphi);
2351 if (safe > 1.E10)
2352 return safphi;
2353 return TMath::Max(safe, safphi);
2354}
2355
2356////////////////////////////////////////////////////////////////////////////////
2357/// Save a primitive as a C++ statement(s) on output stream "out".
2358
2359void TGeoConeSeg::SavePrimitive(std::ostream &out, Option_t * /*option*/ /*= ""*/)
2360{
2362 return;
2363 out << " // Shape: " << GetName() << " type: " << ClassName() << std::endl;
2364 out << " dz = " << fDz << ";" << std::endl;
2365 out << " rmin1 = " << fRmin1 << ";" << std::endl;
2366 out << " rmax1 = " << fRmax1 << ";" << std::endl;
2367 out << " rmin2 = " << fRmin2 << ";" << std::endl;
2368 out << " rmax2 = " << fRmax2 << ";" << std::endl;
2369 out << " phi1 = " << fPhi1 << ";" << std::endl;
2370 out << " phi2 = " << fPhi2 << ";" << std::endl;
2371 out << " TGeoShape *" << GetPointerName() << " = new TGeoConeSeg(\"" << GetName()
2372 << "\", dz,rmin1,rmax1,rmin2,rmax2,phi1,phi2);" << std::endl;
2374}
2375
2376////////////////////////////////////////////////////////////////////////////////
2377/// Set dimensions of the cone segment.
2378
2381{
2382 fDz = dz;
2383 fRmin1 = rmin1;
2384 fRmax1 = rmax1;
2385 fRmin2 = rmin2;
2386 fRmax2 = rmax2;
2387 fPhi1 = phi1;
2388 while (fPhi1 < 0)
2389 fPhi1 += 360.;
2390 fPhi2 = phi2;
2391 while (fPhi2 <= fPhi1)
2392 fPhi2 += 360.;
2394 Fatal("SetConsDimensions", "In shape %s invalid phi1=%g, phi2=%g\n", GetName(), fPhi1, fPhi2);
2396}
2397
2398////////////////////////////////////////////////////////////////////////////////
2399/// Set dimensions of the cone segment from an array.
2400
2402{
2403 Double_t dz = param[0];
2404 Double_t rmin1 = param[1];
2405 Double_t rmax1 = param[2];
2406 Double_t rmin2 = param[3];
2407 Double_t rmax2 = param[4];
2408 Double_t phi1 = param[5];
2409 Double_t phi2 = param[6];
2411}
2412
2413////////////////////////////////////////////////////////////////////////////////
2414/// Create cone segment mesh points.
2415
2417{
2418 Int_t j, n;
2419 Float_t dphi, phi, phi1, phi2, dz;
2420
2421 n = gGeoManager->GetNsegments() + 1;
2422 dz = fDz;
2423 phi1 = fPhi1;
2424 phi2 = fPhi2;
2425
2426 dphi = (phi2 - phi1) / (n - 1);
2427
2428 Int_t indx = 0;
2429
2430 if (points) {
2431 for (j = 0; j < n; j++) {
2432 phi = (fPhi1 + j * dphi) * TMath::DegToRad();
2433 points[indx++] = fRmin1 * TMath::Cos(phi);
2434 points[indx++] = fRmin1 * TMath::Sin(phi);
2435 points[indx++] = -dz;
2436 }
2437 for (j = 0; j < n; j++) {
2438 phi = (fPhi1 + j * dphi) * TMath::DegToRad();
2439 points[indx++] = fRmax1 * TMath::Cos(phi);
2440 points[indx++] = fRmax1 * TMath::Sin(phi);
2441 points[indx++] = -dz;
2442 }
2443 for (j = 0; j < n; j++) {
2444 phi = (fPhi1 + j * dphi) * TMath::DegToRad();
2445 points[indx++] = fRmin2 * TMath::Cos(phi);
2446 points[indx++] = fRmin2 * TMath::Sin(phi);
2447 points[indx++] = dz;
2448 }
2449 for (j = 0; j < n; j++) {
2450 phi = (fPhi1 + j * dphi) * TMath::DegToRad();
2451 points[indx++] = fRmax2 * TMath::Cos(phi);
2452 points[indx++] = fRmax2 * TMath::Sin(phi);
2453 points[indx++] = dz;
2454 }
2455 }
2456}
2457
2458////////////////////////////////////////////////////////////////////////////////
2459/// Create cone segment mesh points.
2460
2462{
2463 Int_t j, n;
2464 Float_t dphi, phi, phi1, phi2, dz;
2465
2466 n = gGeoManager->GetNsegments() + 1;
2467 dz = fDz;
2468 phi1 = fPhi1;
2469 phi2 = fPhi2;
2470
2471 dphi = (phi2 - phi1) / (n - 1);
2472
2473 Int_t indx = 0;
2474
2475 if (points) {
2476 for (j = 0; j < n; j++) {
2477 phi = (fPhi1 + j * dphi) * TMath::DegToRad();
2478 points[indx++] = fRmin1 * TMath::Cos(phi);
2479 points[indx++] = fRmin1 * TMath::Sin(phi);
2480 points[indx++] = -dz;
2481 }
2482 for (j = 0; j < n; j++) {
2483 phi = (fPhi1 + j * dphi) * TMath::DegToRad();
2484 points[indx++] = fRmax1 * TMath::Cos(phi);
2485 points[indx++] = fRmax1 * TMath::Sin(phi);
2486 points[indx++] = -dz;
2487 }
2488 for (j = 0; j < n; j++) {
2489 phi = (fPhi1 + j * dphi) * TMath::DegToRad();
2490 points[indx++] = fRmin2 * TMath::Cos(phi);
2491 points[indx++] = fRmin2 * TMath::Sin(phi);
2492 points[indx++] = dz;
2493 }
2494 for (j = 0; j < n; j++) {
2495 phi = (fPhi1 + j * dphi) * TMath::DegToRad();
2496 points[indx++] = fRmax2 * TMath::Cos(phi);
2497 points[indx++] = fRmax2 * TMath::Sin(phi);
2498 points[indx++] = dz;
2499 }
2500 }
2501}
2502
2503////////////////////////////////////////////////////////////////////////////////
2504/// Returns numbers of vertices, segments and polygons composing the shape mesh.
2505
2507{
2509 nvert = n * 4;
2510 nsegs = n * 8;
2511 npols = n * 4 - 2;
2512}
2513
2514////////////////////////////////////////////////////////////////////////////////
2515/// Return number of vertices of the mesh representation
2516
2518{
2520 Int_t numPoints = n * 4;
2521 return numPoints;
2522}
2523
2524////////////////////////////////////////////////////////////////////////////////
2525/// Fill size of this 3-D object
2526
2528
2529////////////////////////////////////////////////////////////////////////////////
2530/// Fills a static 3D buffer and returns a reference.
2531
2533{
2534 static TBuffer3D buffer(TBuffer3DTypes::kGeneric);
2535
2537
2540 Int_t nbPnts = 4 * n;
2541 Int_t nbSegs = 2 * nbPnts;
2542 Int_t nbPols = nbPnts - 2;
2543 if (buffer.SetRawSizes(nbPnts, 3 * nbPnts, nbSegs, 3 * nbSegs, nbPols, 6 * nbPols)) {
2545 }
2546 }
2548 SetPoints(buffer.fPnts);
2549 if (!buffer.fLocalFrame) {
2550 TransformPoints(buffer.fPnts, buffer.NbPnts());
2551 }
2552
2553 SetSegsAndPols(buffer);
2555 }
2556
2557 return buffer;
2558}
2559
2560////////////////////////////////////////////////////////////////////////////////
2561/// Fills array with n random points located on the line segments of the shape mesh.
2562/// The output array must be provided with a length of minimum 3*npoints. Returns
2563/// true if operation is implemented.
2564
2566{
2567 if (!array || npoints <= 0)
2568 return kFALSE;
2569
2570 // Basic geometric sanity
2571 if (fDz <= 0.0)
2572 return kFALSE;
2573
2574 // Phi span (in radians), normalized to a positive value
2575 const Double_t phi1 = fPhi1 * TMath::DegToRad();
2576 const Double_t phi2 = fPhi2 * TMath::DegToRad();
2578
2579 // ROOT conesegs typically have phi2 > phi1, but be robust
2580 if (dphiSpan <= 0.0) {
2581 // try to wrap once
2583 if (dphiSpan <= 0.0)
2584 return kFALSE;
2585 }
2586
2587 const Bool_t hasInner = (fRmin1 > 0.0) || (fRmin2 > 0.0);
2588
2589 // Split budget: outer gets the extra point if odd
2591 Int_t inPoints = 0;
2592 if (hasInner) {
2593 outPoints = (npoints + 1) / 2;
2595 }
2596
2597 auto radiusAtZ = [&](Double_t r1, Double_t r2, Double_t z) -> Double_t {
2598 // linear interpolation in z, same form as legacy code
2599 return 0.5 * (r1 + r2) + 0.5 * (r2 - r1) * (z / fDz);
2600 };
2601
2603 if (nSurfPoints <= 0)
2604 return kTRUE;
2605
2606 // Choose number of generators ~ sqrt(n), clamp to [1, nSurfPoints]
2608 if (nGen < 1)
2609 nGen = 1;
2610 if (nGen > nSurfPoints)
2611 nGen = nSurfPoints;
2612
2613 // Distribute points across generators evenly
2614 const Int_t q = nSurfPoints / nGen;
2615 const Int_t r = nSurfPoints % nGen;
2616
2617 // Use interior φ values (avoid φ endpoints; those are already covered by SetPoints)
2618 const Double_t dphi = dphiSpan / (Double_t)nGen;
2619
2620 for (Int_t ig = 0; ig < nGen; ++ig) {
2621 const Int_t m = q + (ig < r ? 1 : 0); // points on this generator
2622 if (m <= 0)
2623 continue;
2624
2625 // Center of the φ bin => never exactly on the cut planes
2626 const Double_t phi = phi1 + (ig + 0.5) * dphi;
2627 const Double_t c = TMath::Cos(phi);
2628 const Double_t s = TMath::Sin(phi);
2629
2630 // Place points interior in z as well: t in (0,1)
2631 for (Int_t j = 0; j < m; ++j) {
2632 if (icrt + 3 > 3 * npoints)
2633 return kFALSE; // overflow guard
2634
2635 const Double_t t = (Double_t)(j + 1) / (Double_t)(m + 1); // avoids endpoints
2636 const Double_t z = -fDz + t * (2.0 * fDz);
2637
2638 const Double_t rz = radiusAtZ(r1, r2, z);
2639
2640 array[icrt++] = rz * c;
2641 array[icrt++] = rz * s;
2642 array[icrt++] = z;
2643 }
2644 }
2645
2646 return kTRUE;
2647 };
2648
2649 Int_t icrt = 0;
2650
2651 // Outer conical surface
2653 return kFALSE;
2654
2655 // Inner conical surface (if hollow)
2656 if (hasInner) {
2658 return kFALSE;
2659 }
2660
2661 // Contract: must fill exactly npoints
2662 if (icrt != 3 * npoints)
2663 return kFALSE;
2664
2665 return kTRUE;
2666}
2667
2668////////////////////////////////////////////////////////////////////////////////
2669/// Check the inside status for each of the points in the array.
2670/// Input: Array of point coordinates + vector size
2671/// Output: Array of Booleans for the inside of each point
2672
2674{
2675 for (Int_t i = 0; i < vecsize; i++)
2676 inside[i] = Contains(&points[3 * i]);
2677}
2678
2679////////////////////////////////////////////////////////////////////////////////
2680/// Compute the normal for an array o points so that norm.dot.dir is positive
2681/// Input: Arrays of point coordinates and directions + vector size
2682/// Output: Array of normal directions
2683
2685{
2686 for (Int_t i = 0; i < vecsize; i++)
2687 ComputeNormal(&points[3 * i], &dirs[3 * i], &norms[3 * i]);
2688}
2689
2690////////////////////////////////////////////////////////////////////////////////
2691/// Compute distance from array of input points having directions specified by dirs. Store output in dists
2692
2694 Double_t *step) const
2695{
2696 for (Int_t i = 0; i < vecsize; i++)
2697 dists[i] = DistFromInside(&points[3 * i], &dirs[3 * i], 3, step[i]);
2698}
2699
2700////////////////////////////////////////////////////////////////////////////////
2701/// Compute distance from array of input points having directions specified by dirs. Store output in dists
2702
2704 Double_t *step) const
2705{
2706 for (Int_t i = 0; i < vecsize; i++)
2707 dists[i] = DistFromOutside(&points[3 * i], &dirs[3 * i], 3, step[i]);
2708}
2709
2710////////////////////////////////////////////////////////////////////////////////
2711/// Compute safe distance from each of the points in the input array.
2712/// Input: Array of point coordinates, array of statuses for these points, size of the arrays
2713/// Output: Safety values
2714
2716{
2717 for (Int_t i = 0; i < vecsize; i++)
2718 safe[i] = Safety(&points[3 * i], inside[i]);
2719}
#define b(i)
Definition RSha256.hxx:100
#define c(i)
Definition RSha256.hxx:101
#define a(i)
Definition RSha256.hxx:99
#define s1(x)
Definition RSha256.hxx:91
int Int_t
Signed integer 4 bytes (int)
Definition RtypesCore.h:59
float Float_t
Float 4 bytes (float)
Definition RtypesCore.h:71
constexpr Bool_t kFALSE
Definition RtypesCore.h:108
double Double_t
Double 8 bytes.
Definition RtypesCore.h:73
constexpr Bool_t kTRUE
Definition RtypesCore.h:107
const char Option_t
Option string (const char)
Definition RtypesCore.h:80
ROOT::Detail::TRangeCast< T, true > TRangeDynCast
TRangeDynCast is an adapter class that allows the typed iteration through a TCollection.
void Error(const char *location, const char *msgfmt,...)
Use this function in case an error occurred.
Definition TError.cxx:208
void Fatal(const char *location, const char *msgfmt,...)
Use this function in case of a fatal error. It will abort the program.
Definition TError.cxx:267
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t r
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize id
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t points
char name[80]
Definition TGX11.cxx:110
R__EXTERN TGeoManager * gGeoManager
float xmin
float * q
float ymin
float xmax
float ymax
Generic 3D primitive description class.
Definition TBuffer3D.h:18
Int_t * fPols
Definition TBuffer3D.h:115
UInt_t NbPols() const
Definition TBuffer3D.h:82
UInt_t NbPnts() const
Definition TBuffer3D.h:80
UInt_t NbSegs() const
Definition TBuffer3D.h:81
Bool_t SectionsValid(UInt_t mask) const
Definition TBuffer3D.h:67
void SetSectionsValid(UInt_t mask)
Definition TBuffer3D.h:65
Int_t * fSegs
Definition TBuffer3D.h:114
Bool_t fLocalFrame
Definition TBuffer3D.h:90
Bool_t SetRawSizes(UInt_t reqPnts, UInt_t reqPntsCapacity, UInt_t reqSegs, UInt_t reqSegsCapacity, UInt_t reqPols, UInt_t reqPolsCapacity)
Set kRaw tessellation section of buffer with supplied sizes.
Double_t * fPnts
Definition TBuffer3D.h:113
Box class.
Definition TGeoBBox.h:18
void FillBuffer3D(TBuffer3D &buffer, Int_t reqSections, Bool_t localFrame) const override
Fills the supplied buffer, with sections in desired frame See TBuffer3D.h for explanation of sections...
Double_t fDX
Definition TGeoBBox.h:21
Double_t DistFromOutside(const Double_t *point, const Double_t *dir, Int_t iact=1, Double_t step=TGeoShape::Big(), Double_t *safe=nullptr) const override
Compute distance from outside point to surface of the box.
Definition TGeoBBox.cxx:431
Double_t fOrigin[3]
Definition TGeoBBox.h:24
void InspectShape() const override
Prints shape parameters.
Definition TGeoBBox.cxx:845
Double_t fDY
Definition TGeoBBox.h:22
Double_t fDZ
Definition TGeoBBox.h:23
A cone segment is a cone having a range in phi.
Definition TGeoCone.h:99
Double_t DistFromInside(const Double_t *point, const Double_t *dir, Int_t iact=1, Double_t step=TGeoShape::Big(), Double_t *safe=nullptr) const override
compute distance from inside point to surface of the tube segment
void InspectShape() const override
print shape parameters
TGeoShape * GetMakeRuntimeShape(TGeoShape *mother, TGeoMatrix *mat) const override
in case shape has some negative parameters, these has to be computed in order to fit the mother
static void ComputeNormalS(const Double_t *point, const Double_t *dir, Double_t *norm, Double_t dz, Double_t rmin1, Double_t rmax1, Double_t rmin2, Double_t rmax2, Double_t c1, Double_t s1, Double_t c2, Double_t s2)
Compute normal to closest surface from POINT.
Double_t fCdfi
Definition TGeoCone.h:111
Double_t Capacity() const override
Computes capacity of the shape in [length^3].
void Sizeof3D() const override
Fill size of this 3-D object.
Double_t fCm
Definition TGeoCone.h:110
static Double_t DistFromOutsideS(const Double_t *point, const Double_t *dir, Double_t dz, Double_t rmin1, Double_t rmax1, Double_t rmin2, Double_t rmax2, Double_t c1, Double_t s1, Double_t c2, Double_t s2, Double_t cm, Double_t sm, Double_t cdfi)
compute distance from outside point to surface of arbitrary tube
void SavePrimitive(std::ostream &out, Option_t *option="") override
Save a primitive as a C++ statement(s) on output stream "out".
TGeoConeSeg()
Default constructor.
Double_t GetAxisRange(Int_t iaxis, Double_t &xlo, Double_t &xhi) const override
Get range of shape for a given axis.
TGeoVolume * Divide(TGeoVolume *voldiv, const char *divname, Int_t iaxis, Int_t ndiv, Double_t start, Double_t step) override
Divide this cone segment shape belonging to volume "voldiv" into ndiv volumes called divname,...
void ComputeNormal(const Double_t *point, const Double_t *dir, Double_t *norm) const override
Compute normal to closest surface from POINT.
void ComputeBBox() override
compute bounding box of the tube segment
Bool_t Contains(const Double_t *point) const override
test if point is inside this sphere
Double_t fC1
Definition TGeoCone.h:106
void DistFromInside_v(const Double_t *points, const Double_t *dirs, Double_t *dists, Int_t vecsize, Double_t *step) const override
Compute distance from array of input points having directions specified by dirs. Store output in dist...
void SetSegsAndPols(TBuffer3D &buffer) const override
Fill TBuffer3D structure for segments and polygons.
void InitTrigonometry()
Init frequently used trigonometric values.
Int_t DistancetoPrimitive(Int_t px, Int_t py) override
compute closest distance from point px,py to each corner
void Contains_v(const Double_t *points, Bool_t *inside, Int_t vecsize) const override
Check the inside status for each of the points in the array.
void GetMeshNumbers(Int_t &nvert, Int_t &nsegs, Int_t &npols) const override
Returns numbers of vertices, segments and polygons composing the shape mesh.
static Double_t SafetyS(const Double_t *point, Bool_t in, Double_t dz, Double_t rmin1, Double_t rmax1, Double_t rmin2, Double_t rmax2, Double_t phi1, Double_t phi2, Int_t skipz=0)
Static method to compute the closest distance from given point to this shape.
Int_t GetNmeshVertices() const override
Return number of vertices of the mesh representation.
const TBuffer3D & GetBuffer3D(Int_t reqSections, Bool_t localFrame) const override
Fills a static 3D buffer and returns a reference.
void ComputeNormal_v(const Double_t *points, const Double_t *dirs, Double_t *norms, Int_t vecsize) override
Compute the normal for an array o points so that norm.dot.dir is positive Input: Arrays of point coor...
Double_t fPhi1
Definition TGeoCone.h:102
void SetConsDimensions(Double_t dz, Double_t rmin1, Double_t rmax1, Double_t rmin2, Double_t rmax2, Double_t phi1, Double_t phi2)
Set dimensions of the cone segment.
Double_t fS2
Definition TGeoCone.h:107
void AfterStreamer() override
Function called after streaming an object of this class.
void DistFromOutside_v(const Double_t *points, const Double_t *dirs, Double_t *dists, Int_t vecsize, Double_t *step) const override
Compute distance from array of input points having directions specified by dirs. Store output in dist...
~TGeoConeSeg() override
destructor
Double_t DistFromOutside(const Double_t *point, const Double_t *dir, Int_t iact=1, Double_t step=TGeoShape::Big(), Double_t *safe=nullptr) const override
compute distance from outside point to surface of the tube
Double_t fS1
Definition TGeoCone.h:105
static Double_t DistFromInsideS(const Double_t *point, const Double_t *dir, Double_t dz, Double_t rmin1, Double_t rmax1, Double_t rmin2, Double_t rmax2, Double_t c1, Double_t s1, Double_t c2, Double_t s2, Double_t cm, Double_t sm, Double_t cdfi)
compute distance from inside point to surface of the tube segment
static Double_t DistToCons(const Double_t *point, const Double_t *dir, Double_t r1, Double_t z1, Double_t r2, Double_t z2, Double_t phi1, Double_t phi2)
Static method to compute distance to a conical surface with :
Double_t Safety(const Double_t *point, Bool_t in=kTRUE) const override
computes the closest distance from given point to this shape, according to option.
Double_t fSm
Definition TGeoCone.h:109
Double_t fPhi2
Definition TGeoCone.h:103
void Safety_v(const Double_t *points, const Bool_t *inside, Double_t *safe, Int_t vecsize) const override
Compute safe distance from each of the points in the input array.
Double_t fC2
Definition TGeoCone.h:108
Bool_t GetPointsOnSegments(Int_t npoints, Double_t *array) const override
Fills array with n random points located on the line segments of the shape mesh.
void SetPoints(Double_t *points) const override
Create cone segment mesh points.
void SetDimensions(Double_t *param) override
Set dimensions of the cone segment from an array.
void GetBoundingCylinder(Double_t *param) const override
Fill vector param[4] with the bounding cylinder parameters.
The cones are defined by 5 parameters:
Definition TGeoCone.h:17
void SetDimensions(Double_t *param) override
Set cone dimensions from an array.
Double_t Capacity() const override
Computes capacity of the shape in [length^3].
Definition TGeoCone.cxx:156
const char * GetAxisName(Int_t iaxis) const override
Returns name of axis IAXIS.
Definition TGeoCone.cxx:671
Double_t GetAxisRange(Int_t iaxis, Double_t &xlo, Double_t &xhi) const override
Get range of shape for a given axis.
Definition TGeoCone.cxx:684
static void ComputeNormalS(const Double_t *point, const Double_t *dir, Double_t *norm, Double_t dz, Double_t rmin1, Double_t rmax1, Double_t rmin2, Double_t rmax2)
Compute normal to closest surface from POINT.
Definition TGeoCone.cxx:232
void SetConeDimensions(Double_t dz, Double_t rmin1, Double_t rmax1, Double_t rmin2, Double_t rmax2)
Set cone dimensions.
static Double_t DistFromInsideS(const Double_t *point, const Double_t *dir, Double_t dz, Double_t rmin1, Double_t rmax1, Double_t rmin2, Double_t rmax2)
Compute distance from inside point to surface of the cone (static) Boundary safe algorithm.
Definition TGeoCone.cxx:285
~TGeoCone() override
destructor
Definition TGeoCone.cxx:174
void DistFromOutside_v(const Double_t *points, const Double_t *dirs, Double_t *dists, Int_t vecsize, Double_t *step) const override
Compute distance from array of input points having directions specified by dirs. Store output in dist...
Double_t fRmax1
Definition TGeoCone.h:22
Double_t fRmax2
Definition TGeoCone.h:24
void SetPoints(Double_t *points) const override
Create cone mesh points.
Int_t DistancetoPrimitive(Int_t px, Int_t py) override
compute closest distance from point px,py to each corner
Definition TGeoCone.cxx:601
Double_t Safety(const Double_t *point, Bool_t in=kTRUE) const override
computes the closest distance from given point to this shape, according to option.
Definition TGeoCone.cxx:940
Double_t DistFromOutside(const Double_t *point, const Double_t *dir, Int_t iact=1, Double_t step=TGeoShape::Big(), Double_t *safe=nullptr) const override
compute distance from outside point to surface of the tube
Definition TGeoCone.cxx:541
void DistFromInside_v(const Double_t *points, const Double_t *dirs, Double_t *dists, Int_t vecsize, Double_t *step) const override
Compute distance from array of input points having directions specified by dirs. Store output in dist...
void ComputeBBox() override
compute bounding box of the sphere
Definition TGeoCone.cxx:179
TGeoVolume * Divide(TGeoVolume *voldiv, const char *divname, Int_t iaxis, Int_t ndiv, Double_t start, Double_t step) override
Divide this cone shape belonging to volume "voldiv" into ndiv volumes called divname,...
Definition TGeoCone.cxx:617
static Double_t DistFromOutsideS(const Double_t *point, const Double_t *dir, Double_t dz, Double_t rmin1, Double_t rmax1, Double_t rmin2, Double_t rmax2)
Compute distance from outside point to surface of the tube Boundary safe algorithm.
Definition TGeoCone.cxx:387
Double_t fDz
Definition TGeoCone.h:20
void Contains_v(const Double_t *points, Bool_t *inside, Int_t vecsize) const override
Check the inside status for each of the points in the array.
TGeoCone()
Default constructor.
Definition TGeoCone.cxx:98
TGeoShape * GetMakeRuntimeShape(TGeoShape *mother, TGeoMatrix *mat) const override
in case shape has some negative parameters, these has to be computed in order to fit the mother
Definition TGeoCone.cxx:721
void GetMeshNumbers(Int_t &nvert, Int_t &nsegs, Int_t &npols) const override
Returns numbers of vertices, segments and polygons composing the shape mesh.
Bool_t GetPointsOnSegments(Int_t npoints, Double_t *array) const override
Fills array with n random points located on the line segments of the shape mesh.
Definition TGeoCone.cxx:754
Bool_t Contains(const Double_t *point) const override
test if point is inside this cone
Definition TGeoCone.cxx:269
static void DistToCone(const Double_t *point, const Double_t *dir, Double_t dz, Double_t r1, Double_t r2, Double_t &b, Double_t &delta)
Static method to compute distance to a conical surface with :
Definition TGeoCone.cxx:564
static Double_t SafetyS(const Double_t *point, Bool_t in, Double_t dz, Double_t rmin1, Double_t rmax1, Double_t rmin2, Double_t rmax2, Int_t skipz=0)
computes the closest distance from given point to this shape, according to option.
Definition TGeoCone.cxx:958
void Sizeof3D() const override
Fill size of this 3-D object.
void Safety_v(const Double_t *points, const Bool_t *inside, Double_t *safe, Int_t vecsize) const override
Compute safe distance from each of the points in the input array.
void InspectShape() const override
print shape parameters
Definition TGeoCone.cxx:845
void ComputeNormal_v(const Double_t *points, const Double_t *dirs, Double_t *norms, Int_t vecsize) override
Compute the normal for an array o points so that norm.dot.dir is positive Input: Arrays of point coor...
void ComputeNormal(const Double_t *point, const Double_t *dir, Double_t *norm) const override
Compute normal to closest surface from POINT.
Definition TGeoCone.cxx:189
const TBuffer3D & GetBuffer3D(Int_t reqSections, Bool_t localFrame) const override
Fills a static 3D buffer and returns a reference.
Int_t GetNmeshVertices() const override
Return number of vertices of the mesh representation.
Double_t DistFromInside(const Double_t *point, const Double_t *dir, Int_t iact=1, Double_t step=TGeoShape::Big(), Double_t *safe=nullptr) const override
Compute distance from inside point to surface of the cone Boundary safe algorithm.
Definition TGeoCone.cxx:370
Double_t fRmin1
Definition TGeoCone.h:21
Double_t fRmin2
Definition TGeoCone.h:23
void SavePrimitive(std::ostream &out, Option_t *option="") override
Save a primitive as a C++ statement(s) on output stream "out".
Definition TGeoCone.cxx:993
void GetBoundingCylinder(Double_t *param) const override
Fill vector param[4] with the bounding cylinder parameters.
Definition TGeoCone.cxx:707
void SetSegsAndPols(TBuffer3D &buffer) const override
Fill TBuffer3D structure for segments and polygons.
Definition TGeoCone.cxx:860
TGeoVolumeMulti * MakeVolumeMulti(const char *name, TGeoMedium *medium)
Make a TGeoVolumeMulti handling a list of volumes.
Int_t GetNsegments() const
Get number of segments approximating circles.
Geometrical transformation package.
Definition TGeoMatrix.h:39
Node containing an offset.
Definition TGeoNode.h:185
a cylindrical phi divison pattern
base finder class for patterns. A pattern is specifying a division type
a Z axis divison pattern
Base abstract class for all shapes.
Definition TGeoShape.h:25
static Double_t Big()
Definition TGeoShape.h:95
Int_t GetBasicColor() const
Get the basic color (0-7).
void TransformPoints(Double_t *points, UInt_t NbPoints) const
Tranform a set of points (LocalToMaster)
void SetShapeBit(UInt_t f, Bool_t set)
Equivalent of TObject::SetBit.
static Double_t DistToPhiMin(const Double_t *point, const Double_t *dir, Double_t s1, Double_t c1, Double_t s2, Double_t c2, Double_t sm, Double_t cm, Bool_t in=kTRUE)
compute distance from point (inside phi) to both phi planes. Return minimum.
static Double_t SafetyPhi(const Double_t *point, Bool_t in, Double_t phi1, Double_t phi2)
Static method to compute safety w.r.t a phi corner defined by cosines/sines of the angles phi1,...
static Bool_t IsSameWithinTolerance(Double_t a, Double_t b)
Check if two numbers differ with less than a tolerance.
const char * GetPointerName() const
Provide a pointer name containing uid.
Int_t ShapeDistancetoPrimitive(Int_t numpoints, Int_t px, Int_t py) const
Returns distance to shape primitive mesh.
static void NormalPhi(const Double_t *point, const Double_t *dir, Double_t *norm, Double_t c1, Double_t s1, Double_t c2, Double_t s2)
Static method to compute normal to phi planes.
static Double_t SafetySeg(Double_t r, Double_t z, Double_t r1, Double_t z1, Double_t r2, Double_t z2, Bool_t outer)
Compute distance from point of coordinates (r,z) to segment (r1,z1):(r2,z2)
const char * GetName() const override
Get the shape name.
@ kGeoSavePrimitive
Definition TGeoShape.h:65
@ kGeoRunTimeShape
Definition TGeoShape.h:40
@ kGeoConeSeg
Definition TGeoShape.h:49
static Double_t Tolerance()
Definition TGeoShape.h:98
static Bool_t IsCloseToPhi(Double_t epsil, const Double_t *point, Double_t c1, Double_t s1, Double_t c2, Double_t s2)
True if point is closer than epsil to one of the phi planes defined by c1,s1 or c2,...
Bool_t TestShapeBit(UInt_t f) const
Definition TGeoShape.h:177
Volume families.
Definition TGeoVolume.h:267
TGeoVolume, TGeoVolumeMulti, TGeoVolumeAssembly are the volume classes.
Definition TGeoVolume.h:43
R__ALWAYS_INLINE Bool_t TestBit(UInt_t f) const
Definition TObject.h:202
virtual const char * ClassName() const
Returns name of class to which the object belongs.
Definition TObject.cxx:226
virtual void Warning(const char *method, const char *msgfmt,...) const
Issue warning message.
Definition TObject.cxx:1074
void SetBit(UInt_t f, Bool_t set)
Set or unset the user status bits as specified in f.
Definition TObject.cxx:881
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition TObject.cxx:1088
Basic string class.
Definition TString.h:138
const char * Data() const
Definition TString.h:384
void box(Int_t pat, Double_t x1, Double_t y1, Double_t x2, Double_t y2)
Definition fillpatterns.C:1
return c1
Definition legend1.C:41
const Int_t n
Definition legend1.C:16
return c2
Definition legend2.C:14
Long64_t LocMin(Long64_t n, const T *a)
Returns index of array with the minimum element.
Definition TMath.h:993
Short_t Max(Short_t a, Short_t b)
Returns the largest of a and b.
Definition TMathBase.h:249
T1 Sign(T1 a, T2 b)
Returns a value with the magnitude of a and the sign of b.
Definition TMathBase.h:174
Double_t ATan2(Double_t y, Double_t x)
Returns the principal value of the arc tangent of y/x, expressed in radians.
Definition TMath.h:657
Long64_t LocMax(Long64_t n, const T *a)
Returns index of array with the maximum element.
Definition TMath.h:1099
constexpr Double_t DegToRad()
Conversion from degree to radian: .
Definition TMath.h:82
Double_t Sqrt(Double_t x)
Returns the square root of x.
Definition TMath.h:673
Short_t Min(Short_t a, Short_t b)
Returns the smallest of a and b.
Definition TMathBase.h:197
Double_t Cos(Double_t)
Returns the cosine of an angle of x radians.
Definition TMath.h:605
constexpr Double_t Pi()
Definition TMath.h:40
Double_t Sin(Double_t)
Returns the sine of an angle of x radians.
Definition TMath.h:599
constexpr Double_t RadToDeg()
Conversion from radian to degree: .
Definition TMath.h:75
Short_t Abs(Short_t d)
Returns the absolute value of parameter Short_t d.
Definition TMathBase.h:122
constexpr Double_t TwoPi()
Definition TMath.h:47
TMarker m
Definition textangle.C:8