Geant4 11.1.1
Toolkit for the simulation of the passage of particles through matter
Loading...
Searching...
No Matches
G4TwistedTubs.cc
Go to the documentation of this file.
1//
2// ********************************************************************
3// * License and Disclaimer *
4// * *
5// * The Geant4 software is copyright of the Copyright Holders of *
6// * the Geant4 Collaboration. It is provided under the terms and *
7// * conditions of the Geant4 Software License, included in the file *
8// * LICENSE and available at http://cern.ch/geant4/license . These *
9// * include a list of copyright holders. *
10// * *
11// * Neither the authors of this software system, nor their employing *
12// * institutes,nor the agencies providing financial support for this *
13// * work make any representation or warranty, express or implied, *
14// * regarding this software system or assume any liability for its *
15// * use. Please see the license in the file LICENSE and URL above *
16// * for the full disclaimer and the limitation of liability. *
17// * *
18// * This code implementation is the result of the scientific and *
19// * technical work of the GEANT4 collaboration. *
20// * By using, copying, modifying or distributing the software (or *
21// * any work based on the software) you agree to acknowledge its *
22// * use in resulting scientific publications, and indicate your *
23// * acceptance of all terms of the Geant4 Software license. *
24// ********************************************************************
25//
26// G4TwistedTubs implementation
27//
28// 01-Aug-2002 - Kotoyo Hoshina ([email protected]), created.
29// 13-Nov-2003 - O.Link ([email protected]), Integration in Geant4
30// from original version in Jupiter-2.5.02 application.
31// --------------------------------------------------------------------
32
33#include "G4TwistedTubs.hh"
34
35#include "G4GeomTools.hh"
37#include "G4SystemOfUnits.hh"
39#include "G4VoxelLimits.hh"
40#include "G4AffineTransform.hh"
41#include "G4BoundingEnvelope.hh"
42#include "G4ClippablePolygon.hh"
44#include "meshdefs.hh"
45
46#include "G4VGraphicsScene.hh"
47#include "G4Polyhedron.hh"
48#include "G4VisExtent.hh"
49
50#include "Randomize.hh"
51
52#include "G4AutoLock.hh"
53
54namespace
55{
56 G4Mutex polyhedronMutex = G4MUTEX_INITIALIZER;
57}
58
59//=====================================================================
60//* constructors ------------------------------------------------------
61
63 G4double twistedangle,
64 G4double endinnerrad,
65 G4double endouterrad,
66 G4double halfzlen,
67 G4double dphi)
68 : G4VSolid(pname), fDPhi(dphi),
69 fLowerEndcap(0), fUpperEndcap(0), fLatterTwisted(0),
70 fFormerTwisted(0), fInnerHype(0), fOuterHype(0)
71{
72 if (endinnerrad < DBL_MIN)
73 {
74 G4Exception("G4TwistedTubs::G4TwistedTubs()", "GeomSolids0002",
75 FatalErrorInArgument, "Invalid end-inner-radius!");
76 }
77
78 G4double sinhalftwist = std::sin(0.5 * twistedangle);
79
80 G4double endinnerradX = endinnerrad * sinhalftwist;
81 G4double innerrad = std::sqrt( endinnerrad * endinnerrad
82 - endinnerradX * endinnerradX );
83
84 G4double endouterradX = endouterrad * sinhalftwist;
85 G4double outerrad = std::sqrt( endouterrad * endouterrad
86 - endouterradX * endouterradX );
87
88 // temporary treatment!!
89 SetFields(twistedangle, innerrad, outerrad, -halfzlen, halfzlen);
90 CreateSurfaces();
91}
92
94 G4double twistedangle,
95 G4double endinnerrad,
96 G4double endouterrad,
97 G4double halfzlen,
98 G4int nseg,
99 G4double totphi)
100 : G4VSolid(pname),
101 fLowerEndcap(0), fUpperEndcap(0), fLatterTwisted(0),
102 fFormerTwisted(0), fInnerHype(0), fOuterHype(0)
103{
104
105 if (!nseg)
106 {
107 std::ostringstream message;
108 message << "Invalid number of segments." << G4endl
109 << " nseg = " << nseg;
110 G4Exception("G4TwistedTubs::G4TwistedTubs()", "GeomSolids0002",
111 FatalErrorInArgument, message);
112 }
113 if (totphi == DBL_MIN || endinnerrad < DBL_MIN)
114 {
115 G4Exception("G4TwistedTubs::G4TwistedTubs()", "GeomSolids0002",
116 FatalErrorInArgument, "Invalid total-phi or end-inner-radius!");
117 }
118
119 G4double sinhalftwist = std::sin(0.5 * twistedangle);
120
121 G4double endinnerradX = endinnerrad * sinhalftwist;
122 G4double innerrad = std::sqrt( endinnerrad * endinnerrad
123 - endinnerradX * endinnerradX );
124
125 G4double endouterradX = endouterrad * sinhalftwist;
126 G4double outerrad = std::sqrt( endouterrad * endouterrad
127 - endouterradX * endouterradX );
128
129 // temporary treatment!!
130 fDPhi = totphi / nseg;
131 SetFields(twistedangle, innerrad, outerrad, -halfzlen, halfzlen);
132 CreateSurfaces();
133}
134
136 G4double twistedangle,
137 G4double innerrad,
138 G4double outerrad,
139 G4double negativeEndz,
140 G4double positiveEndz,
141 G4double dphi)
142 : G4VSolid(pname), fDPhi(dphi),
143 fLowerEndcap(0), fUpperEndcap(0), fLatterTwisted(0),
144 fFormerTwisted(0), fInnerHype(0), fOuterHype(0)
145{
146 if (innerrad < DBL_MIN)
147 {
148 G4Exception("G4TwistedTubs::G4TwistedTubs()", "GeomSolids0002",
149 FatalErrorInArgument, "Invalid end-inner-radius!");
150 }
151
152 SetFields(twistedangle, innerrad, outerrad, negativeEndz, positiveEndz);
153 CreateSurfaces();
154}
155
157 G4double twistedangle,
158 G4double innerrad,
159 G4double outerrad,
160 G4double negativeEndz,
161 G4double positiveEndz,
162 G4int nseg,
163 G4double totphi)
164 : G4VSolid(pname),
165 fLowerEndcap(0), fUpperEndcap(0), fLatterTwisted(0),
166 fFormerTwisted(0), fInnerHype(0), fOuterHype(0)
167{
168 if (!nseg)
169 {
170 std::ostringstream message;
171 message << "Invalid number of segments." << G4endl
172 << " nseg = " << nseg;
173 G4Exception("G4TwistedTubs::G4TwistedTubs()", "GeomSolids0002",
174 FatalErrorInArgument, message);
175 }
176 if (totphi == DBL_MIN || innerrad < DBL_MIN)
177 {
178 G4Exception("G4TwistedTubs::G4TwistedTubs()", "GeomSolids0002",
179 FatalErrorInArgument, "Invalid total-phi or end-inner-radius!");
180 }
181
182 fDPhi = totphi / nseg;
183 SetFields(twistedangle, innerrad, outerrad, negativeEndz, positiveEndz);
184 CreateSurfaces();
185}
186
187//=====================================================================
188//* Fake default constructor ------------------------------------------
189
191 : G4VSolid(a), fPhiTwist(0.), fInnerRadius(0.), fOuterRadius(0.), fDPhi(0.),
192 fZHalfLength(0.), fInnerStereo(0.), fOuterStereo(0.), fTanInnerStereo(0.),
193 fTanOuterStereo(0.), fKappa(0.), fInnerRadius2(0.), fOuterRadius2(0.),
194 fTanInnerStereo2(0.), fTanOuterStereo2(0.), fLowerEndcap(0), fUpperEndcap(0),
195 fLatterTwisted(0), fFormerTwisted(0), fInnerHype(0), fOuterHype(0)
196{
197}
198
199//=====================================================================
200//* destructor --------------------------------------------------------
201
203{
204 if (fLowerEndcap) { delete fLowerEndcap; }
205 if (fUpperEndcap) { delete fUpperEndcap; }
206 if (fLatterTwisted) { delete fLatterTwisted; }
207 if (fFormerTwisted) { delete fFormerTwisted; }
208 if (fInnerHype) { delete fInnerHype; }
209 if (fOuterHype) { delete fOuterHype; }
210 if (fpPolyhedron) { delete fpPolyhedron; fpPolyhedron = nullptr; }
211}
212
213//=====================================================================
214//* Copy constructor --------------------------------------------------
215
217 : G4VSolid(rhs), fPhiTwist(rhs.fPhiTwist),
218 fInnerRadius(rhs.fInnerRadius), fOuterRadius(rhs.fOuterRadius),
219 fDPhi(rhs.fDPhi), fZHalfLength(rhs.fZHalfLength),
220 fInnerStereo(rhs.fInnerStereo), fOuterStereo(rhs.fOuterStereo),
221 fTanInnerStereo(rhs.fTanInnerStereo), fTanOuterStereo(rhs.fTanOuterStereo),
222 fKappa(rhs.fKappa), fInnerRadius2(rhs.fInnerRadius2),
223 fOuterRadius2(rhs.fOuterRadius2), fTanInnerStereo2(rhs.fTanInnerStereo2),
224 fTanOuterStereo2(rhs.fTanOuterStereo2),
225 fLowerEndcap(0), fUpperEndcap(0), fLatterTwisted(0), fFormerTwisted(0),
226 fInnerHype(0), fOuterHype(0),
227 fCubicVolume(rhs.fCubicVolume), fSurfaceArea(rhs.fSurfaceArea),
228 fLastInside(rhs.fLastInside), fLastNormal(rhs.fLastNormal),
229 fLastDistanceToIn(rhs.fLastDistanceToIn),
230 fLastDistanceToOut(rhs.fLastDistanceToOut),
231 fLastDistanceToInWithV(rhs.fLastDistanceToInWithV),
232 fLastDistanceToOutWithV(rhs.fLastDistanceToOutWithV)
233{
234 for (auto i=0; i<2; ++i)
235 {
236 fEndZ[i] = rhs.fEndZ[i];
237 fEndInnerRadius[i] = rhs.fEndInnerRadius[i];
238 fEndOuterRadius[i] = rhs.fEndOuterRadius[i];
239 fEndPhi[i] = rhs.fEndPhi[i];
240 fEndZ2[i] = rhs.fEndZ2[i];
241 }
242 CreateSurfaces();
243}
244
245
246//=====================================================================
247//* Assignment operator -----------------------------------------------
248
250{
251 // Check assignment to self
252 //
253 if (this == &rhs) { return *this; }
254
255 // Copy base class data
256 //
258
259 // Copy data
260 //
261 fPhiTwist= rhs.fPhiTwist;
262 fInnerRadius= rhs.fInnerRadius; fOuterRadius= rhs.fOuterRadius;
263 fDPhi= rhs.fDPhi; fZHalfLength= rhs.fZHalfLength;
264 fInnerStereo= rhs.fInnerStereo; fOuterStereo= rhs.fOuterStereo;
265 fTanInnerStereo= rhs.fTanInnerStereo; fTanOuterStereo= rhs.fTanOuterStereo;
266 fKappa= rhs.fKappa; fInnerRadius2= rhs.fInnerRadius2;
267 fOuterRadius2= rhs.fOuterRadius2; fTanInnerStereo2= rhs.fTanInnerStereo2;
268 fTanOuterStereo2= rhs.fTanOuterStereo2;
269 fLowerEndcap= fUpperEndcap= fLatterTwisted= fFormerTwisted= 0;
270 fInnerHype= fOuterHype= 0;
271 fCubicVolume= rhs.fCubicVolume; fSurfaceArea= rhs.fSurfaceArea;
272 fLastInside= rhs.fLastInside; fLastNormal= rhs.fLastNormal;
273 fLastDistanceToIn= rhs.fLastDistanceToIn;
274 fLastDistanceToOut= rhs.fLastDistanceToOut;
275 fLastDistanceToInWithV= rhs.fLastDistanceToInWithV;
276 fLastDistanceToOutWithV= rhs.fLastDistanceToOutWithV;
277
278 for (auto i=0; i<2; ++i)
279 {
280 fEndZ[i] = rhs.fEndZ[i];
281 fEndInnerRadius[i] = rhs.fEndInnerRadius[i];
282 fEndOuterRadius[i] = rhs.fEndOuterRadius[i];
283 fEndPhi[i] = rhs.fEndPhi[i];
284 fEndZ2[i] = rhs.fEndZ2[i];
285 }
286
287 CreateSurfaces();
288 fRebuildPolyhedron = false;
289 delete fpPolyhedron; fpPolyhedron = nullptr;
290
291 return *this;
292}
293
294//=====================================================================
295//* ComputeDimensions -------------------------------------------------
296
298 const G4int /* n */ ,
299 const G4VPhysicalVolume* /* pRep */ )
300{
301 G4Exception("G4TwistedTubs::ComputeDimensions()",
302 "GeomSolids0001", FatalException,
303 "G4TwistedTubs does not support Parameterisation.");
304}
305
306//=====================================================================
307//* BoundingLimits ----------------------------------------------------
308
310 G4ThreeVector& pMax) const
311{
312 // Find bounding tube
313 G4double rmin = GetInnerRadius();
315
316 G4double zmin = std::min(GetEndZ(0), GetEndZ(1));
317 G4double zmax = std::max(GetEndZ(0), GetEndZ(1));
318
319 G4double dphi = 0.5*GetDPhi();
320 G4double sphi = std::min(GetEndPhi(0), GetEndPhi(1)) - dphi;
321 G4double ephi = std::max(GetEndPhi(0), GetEndPhi(1)) + dphi;
322 G4double totalphi = ephi - sphi;
323
324 // Find bounding box
325 if (dphi <= 0 || totalphi >= CLHEP::twopi)
326 {
327 pMin.set(-rmax,-rmax, zmin);
328 pMax.set( rmax, rmax, zmax);
329 }
330 else
331 {
332 G4TwoVector vmin,vmax;
333 G4GeomTools::DiskExtent(rmin, rmax, sphi, totalphi, vmin, vmax);
334 pMin.set(vmin.x(), vmin.y(), zmin);
335 pMax.set(vmax.x(), vmax.y(), zmax);
336 }
337
338 // Check correctness of the bounding box
339 //
340 if (pMin.x() >= pMax.x() || pMin.y() >= pMax.y() || pMin.z() >= pMax.z())
341 {
342 std::ostringstream message;
343 message << "Bad bounding box (min >= max) for solid: "
344 << GetName() << " !"
345 << "\npMin = " << pMin
346 << "\npMax = " << pMax;
347 G4Exception("G4TwistedTubs::BoundingLimits()", "GeomMgt0001",
348 JustWarning, message);
349 DumpInfo();
350 }
351}
352
353//=====================================================================
354//* CalculateExtent ---------------------------------------------------
355
356G4bool
358 const G4VoxelLimits& pVoxelLimit,
359 const G4AffineTransform& pTransform,
360 G4double& pMin, G4double& pMax) const
361{
362 G4ThreeVector bmin, bmax;
363
364 // Get bounding box
365 BoundingLimits(bmin,bmax);
366
367 // Find extent
368 G4BoundingEnvelope bbox(bmin,bmax);
369 return bbox.CalculateExtent(pAxis,pVoxelLimit,pTransform,pMin,pMax);
370}
371
372
373//=====================================================================
374//* Inside ------------------------------------------------------------
375
377{
378
379 const G4double halftol
381 // static G4int timerid = -1;
382 // G4Timer timer(timerid, "G4TwistedTubs", "Inside");
383 // timer.Start();
384
385 G4ThreeVector *tmpp;
386 EInside *tmpinside;
387 if (fLastInside.p == p)
388 {
389 return fLastInside.inside;
390 }
391 else
392 {
393 tmpp = const_cast<G4ThreeVector*>(&(fLastInside.p));
394 tmpinside = const_cast<EInside*>(&(fLastInside.inside));
395 tmpp->set(p.x(), p.y(), p.z());
396 }
397
398 EInside outerhypearea = ((G4TwistTubsHypeSide *)fOuterHype)->Inside(p);
399 G4double innerhyperho = ((G4TwistTubsHypeSide *)fInnerHype)->GetRhoAtPZ(p);
400 G4double distanceToOut = p.getRho() - innerhyperho; // +ve: inside
401
402 if ((outerhypearea == kOutside) || (distanceToOut < -halftol))
403 {
404 *tmpinside = kOutside;
405 }
406 else if (outerhypearea == kSurface)
407 {
408 *tmpinside = kSurface;
409 }
410 else
411 {
412 if (distanceToOut <= halftol)
413 {
414 *tmpinside = kSurface;
415 }
416 else
417 {
418 *tmpinside = kInside;
419 }
420 }
421
422 return fLastInside.inside;
423}
424
425//=====================================================================
426//* SurfaceNormal -----------------------------------------------------
427
429{
430 //
431 // return the normal unit vector to the Hyperbolical Surface at a point
432 // p on (or nearly on) the surface
433 //
434 // Which of the three or four surfaces are we closest to?
435 //
436
437 if (fLastNormal.p == p)
438 {
439 return fLastNormal.vec;
440 }
441 G4ThreeVector *tmpp =
442 const_cast<G4ThreeVector*>(&(fLastNormal.p));
443 G4ThreeVector *tmpnormal =
444 const_cast<G4ThreeVector*>(&(fLastNormal.vec));
445 G4VTwistSurface **tmpsurface =
446 const_cast<G4VTwistSurface**>(fLastNormal.surface);
447 tmpp->set(p.x(), p.y(), p.z());
448
449 G4double distance = kInfinity;
450
451 G4VTwistSurface *surfaces[6];
452 surfaces[0] = fLatterTwisted;
453 surfaces[1] = fFormerTwisted;
454 surfaces[2] = fInnerHype;
455 surfaces[3] = fOuterHype;
456 surfaces[4] = fLowerEndcap;
457 surfaces[5] = fUpperEndcap;
458
459 G4ThreeVector xx;
460 G4ThreeVector bestxx;
461 G4int besti = -1;
462 for (auto i=0; i<6; ++i)
463 {
464 G4double tmpdistance = surfaces[i]->DistanceTo(p, xx);
465 if (tmpdistance < distance)
466 {
467 distance = tmpdistance;
468 bestxx = xx;
469 besti = i;
470 }
471 }
472
473 tmpsurface[0] = surfaces[besti];
474 *tmpnormal = tmpsurface[0]->GetNormal(bestxx, true);
475
476 return fLastNormal.vec;
477}
478
479//=====================================================================
480//* DistanceToIn (p, v) -----------------------------------------------
481
483 const G4ThreeVector& v ) const
484{
485
486 // DistanceToIn (p, v):
487 // Calculate distance to surface of shape from `outside'
488 // along with the v, allowing for tolerance.
489 // The function returns kInfinity if no intersection or
490 // just grazing within tolerance.
491
492 //
493 // checking last value
494 //
495
496 G4ThreeVector* tmpp;
497 G4ThreeVector* tmpv;
498 G4double* tmpdist;
499 if ((fLastDistanceToInWithV.p == p) && (fLastDistanceToInWithV.vec == v))
500 {
501 return fLastDistanceToIn.value;
502 }
503 else
504 {
505 tmpp = const_cast<G4ThreeVector*>(&(fLastDistanceToInWithV.p));
506 tmpv = const_cast<G4ThreeVector*>(&(fLastDistanceToInWithV.vec));
507 tmpdist = const_cast<G4double*>(&(fLastDistanceToInWithV.value));
508 tmpp->set(p.x(), p.y(), p.z());
509 tmpv->set(v.x(), v.y(), v.z());
510 }
511
512 //
513 // Calculate DistanceToIn(p,v)
514 //
515
516 EInside currentside = Inside(p);
517
518 if (currentside == kInside)
519 {
520 }
521 else
522 {
523 if (currentside == kSurface)
524 {
525 // particle is just on a boundary.
526 // If the particle is entering to the volume, return 0.
527 //
528 G4ThreeVector normal = SurfaceNormal(p);
529 if (normal*v < 0)
530 {
531 *tmpdist = 0.;
532 return fLastDistanceToInWithV.value;
533 }
534 }
535 }
536
537 // now, we can take smallest positive distance.
538
539 // Initialize
540 //
541 G4double distance = kInfinity;
542
543 // find intersections and choose nearest one.
544 //
545 G4VTwistSurface* surfaces[6];
546 surfaces[0] = fLowerEndcap;
547 surfaces[1] = fUpperEndcap;
548 surfaces[2] = fLatterTwisted;
549 surfaces[3] = fFormerTwisted;
550 surfaces[4] = fInnerHype;
551 surfaces[5] = fOuterHype;
552
553 G4ThreeVector xx;
554 G4ThreeVector bestxx;
555 for (auto i=0; i<6; ++i)
556 {
557 G4double tmpdistance = surfaces[i]->DistanceToIn(p, v, xx);
558 if (tmpdistance < distance)
559 {
560 distance = tmpdistance;
561 bestxx = xx;
562 }
563 }
564 *tmpdist = distance;
565
566 return fLastDistanceToInWithV.value;
567}
568
569//=====================================================================
570//* DistanceToIn (p) --------------------------------------------------
571
573{
574 // DistanceToIn(p):
575 // Calculate distance to surface of shape from `outside',
576 // allowing for tolerance
577
578 //
579 // checking last value
580 //
581
582 G4ThreeVector* tmpp;
583 G4double* tmpdist;
584 if (fLastDistanceToIn.p == p)
585 {
586 return fLastDistanceToIn.value;
587 }
588 else
589 {
590 tmpp = const_cast<G4ThreeVector*>(&(fLastDistanceToIn.p));
591 tmpdist = const_cast<G4double*>(&(fLastDistanceToIn.value));
592 tmpp->set(p.x(), p.y(), p.z());
593 }
594
595 //
596 // Calculate DistanceToIn(p)
597 //
598
599 EInside currentside = Inside(p);
600
601 switch (currentside)
602 {
603 case (kInside) :
604 {}
605 case (kSurface) :
606 {
607 *tmpdist = 0.;
608 return fLastDistanceToIn.value;
609 }
610 case (kOutside) :
611 {
612 // Initialize
613 G4double distance = kInfinity;
614
615 // find intersections and choose nearest one.
616 G4VTwistSurface *surfaces[6];
617 surfaces[0] = fLowerEndcap;
618 surfaces[1] = fUpperEndcap;
619 surfaces[2] = fLatterTwisted;
620 surfaces[3] = fFormerTwisted;
621 surfaces[4] = fInnerHype;
622 surfaces[5] = fOuterHype;
623
624 G4ThreeVector xx;
625 G4ThreeVector bestxx;
626 for (auto i=0; i<6; ++i)
627 {
628 G4double tmpdistance = surfaces[i]->DistanceTo(p, xx);
629 if (tmpdistance < distance)
630 {
631 distance = tmpdistance;
632 bestxx = xx;
633 }
634 }
635 *tmpdist = distance;
636 return fLastDistanceToIn.value;
637 }
638 default :
639 {
640 G4Exception("G4TwistedTubs::DistanceToIn(p)", "GeomSolids0003",
641 FatalException, "Unknown point location!");
642 }
643 } // switch end
644
645 return kInfinity;
646}
647
648//=====================================================================
649//* DistanceToOut (p, v) ----------------------------------------------
650
652 const G4ThreeVector& v,
653 const G4bool calcNorm,
654 G4bool *validNorm,
655 G4ThreeVector *norm ) const
656{
657 // DistanceToOut (p, v):
658 // Calculate distance to surface of shape from `inside'
659 // along with the v, allowing for tolerance.
660 // The function returns kInfinity if no intersection or
661 // just grazing within tolerance.
662
663 //
664 // checking last value
665 //
666
667 G4ThreeVector* tmpp;
668 G4ThreeVector* tmpv;
669 G4double* tmpdist;
670 if ((fLastDistanceToOutWithV.p == p) && (fLastDistanceToOutWithV.vec == v) )
671 {
672 return fLastDistanceToOutWithV.value;
673 }
674 else
675 {
676 tmpp = const_cast<G4ThreeVector*>(&(fLastDistanceToOutWithV.p));
677 tmpv = const_cast<G4ThreeVector*>(&(fLastDistanceToOutWithV.vec));
678 tmpdist = const_cast<G4double*>(&(fLastDistanceToOutWithV.value));
679 tmpp->set(p.x(), p.y(), p.z());
680 tmpv->set(v.x(), v.y(), v.z());
681 }
682
683 //
684 // Calculate DistanceToOut(p,v)
685 //
686
687 EInside currentside = Inside(p);
688
689 if (currentside == kOutside)
690 {
691 }
692 else
693 {
694 if (currentside == kSurface)
695 {
696 // particle is just on a boundary.
697 // If the particle is exiting from the volume, return 0.
698 //
699 G4ThreeVector normal = SurfaceNormal(p);
700 G4VTwistSurface *blockedsurface = fLastNormal.surface[0];
701 if (normal*v > 0)
702 {
703 if (calcNorm)
704 {
705 *norm = (blockedsurface->GetNormal(p, true));
706 *validNorm = blockedsurface->IsValidNorm();
707 }
708 *tmpdist = 0.;
709 return fLastDistanceToOutWithV.value;
710 }
711 }
712 }
713
714 // now, we can take smallest positive distance.
715
716 // Initialize
717 //
718 G4double distance = kInfinity;
719
720 // find intersections and choose nearest one.
721 //
722 G4VTwistSurface* surfaces[6];
723 surfaces[0] = fLatterTwisted;
724 surfaces[1] = fFormerTwisted;
725 surfaces[2] = fInnerHype;
726 surfaces[3] = fOuterHype;
727 surfaces[4] = fLowerEndcap;
728 surfaces[5] = fUpperEndcap;
729
730 G4int besti = -1;
731 G4ThreeVector xx;
732 G4ThreeVector bestxx;
733 for (auto i=0; i<6; ++i)
734 {
735 G4double tmpdistance = surfaces[i]->DistanceToOut(p, v, xx);
736 if (tmpdistance < distance)
737 {
738 distance = tmpdistance;
739 bestxx = xx;
740 besti = i;
741 }
742 }
743
744 if (calcNorm)
745 {
746 if (besti != -1)
747 {
748 *norm = (surfaces[besti]->GetNormal(p, true));
749 *validNorm = surfaces[besti]->IsValidNorm();
750 }
751 }
752
753 *tmpdist = distance;
754
755 return fLastDistanceToOutWithV.value;
756}
757
758
759//=====================================================================
760//* DistanceToOut (p) ----------------------------------------------
761
763{
764 // DistanceToOut(p):
765 // Calculate distance to surface of shape from `inside',
766 // allowing for tolerance
767
768 //
769 // checking last value
770 //
771
772 G4ThreeVector* tmpp;
773 G4double* tmpdist;
774 if (fLastDistanceToOut.p == p)
775 {
776 return fLastDistanceToOut.value;
777 }
778 else
779 {
780 tmpp = const_cast<G4ThreeVector*>(&(fLastDistanceToOut.p));
781 tmpdist = const_cast<G4double*>(&(fLastDistanceToOut.value));
782 tmpp->set(p.x(), p.y(), p.z());
783 }
784
785 //
786 // Calculate DistanceToOut(p)
787 //
788
789 EInside currentside = Inside(p);
790
791 switch (currentside)
792 {
793 case (kOutside) :
794 {
795 }
796 case (kSurface) :
797 {
798 *tmpdist = 0.;
799 return fLastDistanceToOut.value;
800 }
801 case (kInside) :
802 {
803 // Initialize
804 G4double distance = kInfinity;
805
806 // find intersections and choose nearest one.
807 G4VTwistSurface* surfaces[6];
808 surfaces[0] = fLatterTwisted;
809 surfaces[1] = fFormerTwisted;
810 surfaces[2] = fInnerHype;
811 surfaces[3] = fOuterHype;
812 surfaces[4] = fLowerEndcap;
813 surfaces[5] = fUpperEndcap;
814
815 G4ThreeVector xx;
816 G4ThreeVector bestxx;
817 for (auto i=0; i<6; ++i)
818 {
819 G4double tmpdistance = surfaces[i]->DistanceTo(p, xx);
820 if (tmpdistance < distance)
821 {
822 distance = tmpdistance;
823 bestxx = xx;
824 }
825 }
826 *tmpdist = distance;
827
828 return fLastDistanceToOut.value;
829 }
830 default :
831 {
832 G4Exception("G4TwistedTubs::DistanceToOut(p)", "GeomSolids0003",
833 FatalException, "Unknown point location!");
834 }
835 } // switch end
836
837 return 0.;
838}
839
840//=====================================================================
841//* StreamInfo --------------------------------------------------------
842
843std::ostream& G4TwistedTubs::StreamInfo(std::ostream& os) const
844{
845 //
846 // Stream object contents to an output stream
847 //
848 G4long oldprc = os.precision(16);
849 os << "-----------------------------------------------------------\n"
850 << " *** Dump for solid - " << GetName() << " ***\n"
851 << " ===================================================\n"
852 << " Solid type: G4TwistedTubs\n"
853 << " Parameters: \n"
854 << " -ve end Z : " << fEndZ[0]/mm << " mm \n"
855 << " +ve end Z : " << fEndZ[1]/mm << " mm \n"
856 << " inner end radius(-ve z): " << fEndInnerRadius[0]/mm << " mm \n"
857 << " inner end radius(+ve z): " << fEndInnerRadius[1]/mm << " mm \n"
858 << " outer end radius(-ve z): " << fEndOuterRadius[0]/mm << " mm \n"
859 << " outer end radius(+ve z): " << fEndOuterRadius[1]/mm << " mm \n"
860 << " inner radius (z=0) : " << fInnerRadius/mm << " mm \n"
861 << " outer radius (z=0) : " << fOuterRadius/mm << " mm \n"
862 << " twisted angle : " << fPhiTwist/degree << " degrees \n"
863 << " inner stereo angle : " << fInnerStereo/degree << " degrees \n"
864 << " outer stereo angle : " << fOuterStereo/degree << " degrees \n"
865 << " phi-width of a piece : " << fDPhi/degree << " degrees \n"
866 << "-----------------------------------------------------------\n";
867 os.precision(oldprc);
868
869 return os;
870}
871
872
873//=====================================================================
874//* DiscribeYourselfTo ------------------------------------------------
875
877{
878 scene.AddSolid (*this);
879}
880
881//=====================================================================
882//* GetExtent ---------------------------------------------------------
883
885{
886 // Define the sides of the box into which the G4Tubs instance would fit.
887 //
888 G4ThreeVector pmin,pmax;
889 BoundingLimits(pmin,pmax);
890 return G4VisExtent(pmin.x(),pmax.x(),
891 pmin.y(),pmax.y(),
892 pmin.z(),pmax.z());
893}
894
895//=====================================================================
896//* CreatePolyhedron --------------------------------------------------
897
899{
900 // number of meshes
901 //
902 G4double absPhiTwist = std::abs(fPhiTwist);
903 G4double dA = std::max(fDPhi,absPhiTwist);
904 const G4int k =
906 const G4int n =
907 G4int(G4Polyhedron::GetNumberOfRotationSteps() * absPhiTwist / twopi) + 2;
908
909 const G4int nnodes = 4*(k-1)*(n-2) + 2*k*k ;
910 const G4int nfaces = 4*(k-1)*(n-1) + 2*(k-1)*(k-1) ;
911
912 G4Polyhedron* ph = new G4Polyhedron;
913 typedef G4double G4double3[3];
914 typedef G4int G4int4[4];
915 G4double3* xyz = new G4double3[nnodes]; // number of nodes
916 G4int4* faces = new G4int4[nfaces] ; // number of faces
917 fLowerEndcap->GetFacets(k,k,xyz,faces,0) ;
918 fUpperEndcap->GetFacets(k,k,xyz,faces,1) ;
919 fInnerHype->GetFacets(k,n,xyz,faces,2) ;
920 fFormerTwisted->GetFacets(k,n,xyz,faces,3) ;
921 fOuterHype->GetFacets(k,n,xyz,faces,4) ;
922 fLatterTwisted->GetFacets(k,n,xyz,faces,5) ;
923
924 ph->createPolyhedron(nnodes,nfaces,xyz,faces);
925
926 delete[] xyz;
927 delete[] faces;
928
929 return ph;
930}
931
932//=====================================================================
933//* GetPolyhedron -----------------------------------------------------
934
936{
937 if (fpPolyhedron == nullptr ||
938 fRebuildPolyhedron ||
940 fpPolyhedron->GetNumberOfRotationSteps())
941 {
942 G4AutoLock l(&polyhedronMutex);
943 delete fpPolyhedron;
944 fpPolyhedron = CreatePolyhedron();
945 fRebuildPolyhedron = false;
946 l.unlock();
947 }
948 return fpPolyhedron;
949}
950
951//=====================================================================
952//* CreateSurfaces ----------------------------------------------------
953
954void G4TwistedTubs::CreateSurfaces()
955{
956 // create 6 surfaces of TwistedTub
957
958 G4ThreeVector x0(0, 0, fEndZ[0]);
959 G4ThreeVector n (0, 0, -1);
960
961 fLowerEndcap = new G4TwistTubsFlatSide("LowerEndcap",
962 fEndInnerRadius, fEndOuterRadius,
963 fDPhi, fEndPhi, fEndZ, -1) ;
964
965 fUpperEndcap = new G4TwistTubsFlatSide("UpperEndcap",
966 fEndInnerRadius, fEndOuterRadius,
967 fDPhi, fEndPhi, fEndZ, 1) ;
968
969 G4RotationMatrix rotHalfDPhi;
970 rotHalfDPhi.rotateZ(0.5*fDPhi);
971
972 fLatterTwisted = new G4TwistTubsSide("LatterTwisted",
973 fEndInnerRadius, fEndOuterRadius,
974 fDPhi, fEndPhi, fEndZ,
975 fInnerRadius, fOuterRadius, fKappa,
976 1 ) ;
977 fFormerTwisted = new G4TwistTubsSide("FormerTwisted",
978 fEndInnerRadius, fEndOuterRadius,
979 fDPhi, fEndPhi, fEndZ,
980 fInnerRadius, fOuterRadius, fKappa,
981 -1 ) ;
982
983 fInnerHype = new G4TwistTubsHypeSide("InnerHype",
984 fEndInnerRadius, fEndOuterRadius,
985 fDPhi, fEndPhi, fEndZ,
986 fInnerRadius, fOuterRadius,fKappa,
987 fTanInnerStereo, fTanOuterStereo, -1) ;
988 fOuterHype = new G4TwistTubsHypeSide("OuterHype",
989 fEndInnerRadius, fEndOuterRadius,
990 fDPhi, fEndPhi, fEndZ,
991 fInnerRadius, fOuterRadius,fKappa,
992 fTanInnerStereo, fTanOuterStereo, 1) ;
993
994
995 // set neighbour surfaces
996 //
997 fLowerEndcap->SetNeighbours(fInnerHype, fLatterTwisted,
998 fOuterHype, fFormerTwisted);
999 fUpperEndcap->SetNeighbours(fInnerHype, fLatterTwisted,
1000 fOuterHype, fFormerTwisted);
1001 fLatterTwisted->SetNeighbours(fInnerHype, fLowerEndcap,
1002 fOuterHype, fUpperEndcap);
1003 fFormerTwisted->SetNeighbours(fInnerHype, fLowerEndcap,
1004 fOuterHype, fUpperEndcap);
1005 fInnerHype->SetNeighbours(fLatterTwisted, fLowerEndcap,
1006 fFormerTwisted, fUpperEndcap);
1007 fOuterHype->SetNeighbours(fLatterTwisted, fLowerEndcap,
1008 fFormerTwisted, fUpperEndcap);
1009}
1010
1011
1012//=====================================================================
1013//* GetEntityType -----------------------------------------------------
1014
1016{
1017 return G4String("G4TwistedTubs");
1018}
1019
1020//=====================================================================
1021//* Clone -------------------------------------------------------------
1022
1024{
1025 return new G4TwistedTubs(*this);
1026}
1027
1028//=====================================================================
1029//* GetCubicVolume ----------------------------------------------------
1030
1032{
1033 if (fCubicVolume == 0.)
1034 {
1035 G4double DPhi = GetDPhi();
1036 G4double Z0 = GetEndZ(0);
1037 G4double Z1 = GetEndZ(1);
1038 G4double Ain = GetInnerRadius();
1039 G4double Aout = GetOuterRadius();
1040 G4double R0in = GetEndInnerRadius(0);
1041 G4double R1in = GetEndInnerRadius(1);
1042 G4double R0out = GetEndOuterRadius(0);
1043 G4double R1out = GetEndOuterRadius(1);
1044
1045 // V_hyperboloid = pi*h*(2*a*a + R*R)/3
1046 fCubicVolume = (2.*(Z1 - Z0)*(Aout + Ain)*(Aout - Ain)
1047 + Z1*(R1out + R1in)*(R1out - R1in)
1048 - Z0*(R0out + R0in)*(R0out - R0in))*DPhi/6.;
1049 }
1050 return fCubicVolume;
1051}
1052
1053//=====================================================================
1054//* GetLateralArea ----------------------------------------------------
1055
1057G4TwistedTubs::GetLateralArea(G4double a, G4double r, G4double z) const
1058{
1059 if (z == 0) return 0.;
1060 G4double h = std::abs(z);
1061 G4double area = h*a;
1062 if (std::abs(a - r) > kCarTolerance)
1063 {
1064 G4double aa = a*a;
1065 G4double hh = h*h;
1066 G4double rr = r*r;
1067 G4double cc = aa*hh/(rr - aa);
1068 G4double k = std::sqrt(aa + cc)/cc;
1069 G4double kh = k*h;
1070 area = 0.5*a*(h*std::sqrt(1. + kh*kh) + std::asinh(kh)/k);
1071 }
1072 return GetDPhi()*area;
1073}
1074
1075//=====================================================================
1076//* GetPhiCutArea -----------------------------------------------------
1077
1079G4TwistedTubs::GetPhiCutArea(G4double a, G4double r, G4double z) const
1080{
1081 if (GetDPhi() >= CLHEP::twopi || r <= 0 || z == 0) return 0.;
1082 G4double h = std::abs(z);
1083 G4double area = h*a;
1084 if (GetPhiTwist() > kCarTolerance)
1085 {
1086 G4double sinw = std::sin(0.5*GetPhiTwist())*h/GetZHalfLength();
1087 G4double p = sinw*r/h;
1088 G4double q = sinw*r/a;
1089 G4double pp = p*p;
1090 G4double qq = q*q;
1091 G4double pq = p*q;
1092 G4double sqroot = std::sqrt(pp + qq + 1);
1093 area = (pq*sqroot +
1094 0.5*p*(pp + 3.)*std::atanh(q/sqroot) +
1095 0.5*q*(qq + 3.)*std::atanh(p/sqroot) +
1096 std::atan(sqroot/(pq)) - CLHEP::halfpi)*h*a/(3.*pq);
1097 }
1098 return area;
1099}
1100
1101//=====================================================================
1102//* GetSurfaceArea ----------------------------------------------------
1103
1105{
1106 if (fSurfaceArea == 0.)
1107 {
1108 G4double dphi = GetDPhi();
1109 G4double Ainn = GetInnerRadius();
1110 G4double Aout = GetOuterRadius();
1111 G4double Rinn0 = GetEndInnerRadius(0);
1112 G4double Rout0 = GetEndOuterRadius(0);
1113 G4double Rinn1 = GetEndInnerRadius(1);
1114 G4double Rout1 = GetEndOuterRadius(1);
1115 G4double z0 = GetEndZ(0);
1116 G4double z1 = GetEndZ(1);
1117
1118 G4double base0 = 0.5*dphi*(Rout0*Rout0 - Rinn0*Rinn0); // lower base
1119 G4double inner0 = GetLateralArea(Ainn, Rinn0, z0); // lower inner surface
1120 G4double outer0 = GetLateralArea(Aout, Rout0, z0); // lower outer surface
1121 G4double cut0 = // lower phi cut
1122 GetPhiCutArea(Aout, Rout0, z0) - GetPhiCutArea(Ainn, Rinn0, z0);
1123
1124 G4double base1 = base0;
1125 G4double inner1 = inner0;
1126 G4double outer1 = outer0;
1127 G4double cut1 = cut0;
1128 if (std::abs(z0) != std::abs(z1))
1129 {
1130 base1 = 0.5*dphi*(Rout1*Rout1 - Rinn1*Rinn1); // upper base
1131 inner1 = GetLateralArea(Ainn, Rinn1, z1); // upper inner surface
1132 outer1 = GetLateralArea(Aout, Rout1, z1); // upper outer surface
1133 cut1 = // upper phi cut
1134 GetPhiCutArea(Aout, Rout1, z1) - GetPhiCutArea(Ainn, Rinn1, z1);
1135 }
1136 fSurfaceArea = base0 + base1 +
1137 ((z0*z1 < 0) ?
1138 (inner0 + inner1 + outer0 + outer1 + 2.*(cut0 + cut1)) :
1139 std::abs(inner0 - inner1 + outer0 - outer1 + 2.*(cut0 - cut1)));
1140 }
1141 return fSurfaceArea;
1142}
1143
1144//=====================================================================
1145//* GetPointOnSurface -------------------------------------------------
1146
1148{
1149
1150 G4double z = G4RandFlat::shoot(fEndZ[0],fEndZ[1]);
1151 G4double phi , phimin, phimax ;
1152 G4double x , xmin, xmax ;
1153 G4double r , rmin, rmax ;
1154
1155 G4double a1 = fOuterHype->GetSurfaceArea() ;
1156 G4double a2 = fInnerHype->GetSurfaceArea() ;
1157 G4double a3 = fLatterTwisted->GetSurfaceArea() ;
1158 G4double a4 = fFormerTwisted->GetSurfaceArea() ;
1159 G4double a5 = fLowerEndcap->GetSurfaceArea() ;
1160 G4double a6 = fUpperEndcap->GetSurfaceArea() ;
1161
1162 G4double chose = G4RandFlat::shoot(0.,a1 + a2 + a3 + a4 + a5 + a6) ;
1163
1164 if(chose < a1)
1165 {
1166
1167 phimin = fOuterHype->GetBoundaryMin(z) ;
1168 phimax = fOuterHype->GetBoundaryMax(z) ;
1169 phi = G4RandFlat::shoot(phimin,phimax) ;
1170
1171 return fOuterHype->SurfacePoint(phi,z,true) ;
1172
1173 }
1174 else if ( (chose >= a1) && (chose < a1 + a2 ) )
1175 {
1176
1177 phimin = fInnerHype->GetBoundaryMin(z) ;
1178 phimax = fInnerHype->GetBoundaryMax(z) ;
1179 phi = G4RandFlat::shoot(phimin,phimax) ;
1180
1181 return fInnerHype->SurfacePoint(phi,z,true) ;
1182
1183 }
1184 else if ( (chose >= a1 + a2 ) && (chose < a1 + a2 + a3 ) )
1185 {
1186
1187 xmin = fLatterTwisted->GetBoundaryMin(z) ;
1188 xmax = fLatterTwisted->GetBoundaryMax(z) ;
1189 x = G4RandFlat::shoot(xmin,xmax) ;
1190
1191 return fLatterTwisted->SurfacePoint(x,z,true) ;
1192
1193 }
1194 else if ( (chose >= a1 + a2 + a3 ) && (chose < a1 + a2 + a3 + a4 ) )
1195 {
1196
1197 xmin = fFormerTwisted->GetBoundaryMin(z) ;
1198 xmax = fFormerTwisted->GetBoundaryMax(z) ;
1199 x = G4RandFlat::shoot(xmin,xmax) ;
1200
1201 return fFormerTwisted->SurfacePoint(x,z,true) ;
1202 }
1203 else if( (chose >= a1 + a2 + a3 + a4 )&&(chose < a1 + a2 + a3 + a4 + a5 ) )
1204 {
1205 rmin = GetEndInnerRadius(0) ;
1206 rmax = GetEndOuterRadius(0) ;
1207 r = std::sqrt(G4RandFlat::shoot()*(sqr(rmax)-sqr(rmin))+sqr(rmin));
1208
1209 phimin = fLowerEndcap->GetBoundaryMin(r) ;
1210 phimax = fLowerEndcap->GetBoundaryMax(r) ;
1211 phi = G4RandFlat::shoot(phimin,phimax) ;
1212
1213 return fLowerEndcap->SurfacePoint(phi,r,true) ;
1214 }
1215 else
1216 {
1217 rmin = GetEndInnerRadius(1) ;
1218 rmax = GetEndOuterRadius(1) ;
1219 r = rmin + (rmax-rmin)*std::sqrt(G4RandFlat::shoot());
1220
1221 phimin = fUpperEndcap->GetBoundaryMin(r) ;
1222 phimax = fUpperEndcap->GetBoundaryMax(r) ;
1223 phi = G4RandFlat::shoot(phimin,phimax) ;
1224
1225 return fUpperEndcap->SurfacePoint(phi,r,true) ;
1226 }
1227}
@ JustWarning
@ FatalException
@ FatalErrorInArgument
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *description)
Definition: G4Exception.cc:59
#define G4MUTEX_INITIALIZER
Definition: G4Threading.hh:85
std::mutex G4Mutex
Definition: G4Threading.hh:81
double G4double
Definition: G4Types.hh:83
long G4long
Definition: G4Types.hh:87
bool G4bool
Definition: G4Types.hh:86
int G4int
Definition: G4Types.hh:85
#define G4endl
Definition: G4ios.hh:57
double x() const
double y() const
double z() const
double x() const
double y() const
double getRho() const
void set(double x, double y, double z)
HepRotation & rotateZ(double delta)
Definition: Rotation.cc:87
G4bool CalculateExtent(const EAxis pAxis, const G4VoxelLimits &pVoxelLimits, const G4Transform3D &pTransform3D, G4double &pMin, G4double &pMax) const
static G4bool DiskExtent(G4double rmin, G4double rmax, G4double startPhi, G4double delPhi, G4TwoVector &pmin, G4TwoVector &pmax)
Definition: G4GeomTools.cc:390
G4double GetRadialTolerance() const
static G4GeometryTolerance * GetInstance()
G4int GetNumberOfRotationStepsAtTimeOfCreation() const
G4double GetOuterRadius() const
G4double DistanceToIn(const G4ThreeVector &p, const G4ThreeVector &v) const
G4bool CalculateExtent(const EAxis pAxis, const G4VoxelLimits &pVoxelLimit, const G4AffineTransform &pTransform, G4double &pMin, G4double &pMax) const
G4ThreeVector GetPointOnSurface() const
G4double GetZHalfLength() const
G4double GetPhiTwist() const
G4double GetSurfaceArea()
void DescribeYourselfTo(G4VGraphicsScene &scene) const
G4Polyhedron * CreatePolyhedron() const
void ComputeDimensions(G4VPVParameterisation *, const G4int, const G4VPhysicalVolume *)
G4VSolid * Clone() const
G4TwistedTubs & operator=(const G4TwistedTubs &rhs)
G4double GetEndInnerRadius() const
G4double GetEndOuterRadius() const
G4double GetCubicVolume()
G4Polyhedron * GetPolyhedron() const
G4GeometryType GetEntityType() const
virtual ~G4TwistedTubs()
G4double GetEndPhi(G4int i) const
G4TwistedTubs(const G4String &pname, G4double twistedangle, G4double endinnerrad, G4double endouterrad, G4double halfzlen, G4double dphi)
EInside Inside(const G4ThreeVector &p) const
G4double DistanceToOut(const G4ThreeVector &p, const G4ThreeVector &v, const G4bool calcnorm=false, G4bool *validnorm=nullptr, G4ThreeVector *n=nullptr) const
G4VisExtent GetExtent() const
G4ThreeVector SurfaceNormal(const G4ThreeVector &p) const
G4double GetEndZ(G4int i) const
G4double GetInnerRadius() const
void BoundingLimits(G4ThreeVector &pMin, G4ThreeVector &pMax) const
std::ostream & StreamInfo(std::ostream &os) const
G4double GetDPhi() const
virtual void AddSolid(const G4Box &)=0
G4String GetName() const
void DumpInfo() const
G4double kCarTolerance
Definition: G4VSolid.hh:299
G4VSolid & operator=(const G4VSolid &rhs)
Definition: G4VSolid.cc:107
virtual void GetFacets(G4int m, G4int n, G4double xyz[][3], G4int faces[][4], G4int iside)=0
void SetNeighbours(G4VTwistSurface *ax0min, G4VTwistSurface *ax1min, G4VTwistSurface *ax0max, G4VTwistSurface *ax1max)
virtual G4double GetBoundaryMin(G4double)=0
G4bool IsValidNorm() const
virtual G4double DistanceTo(const G4ThreeVector &gp, G4ThreeVector &gxx)
virtual G4double DistanceToOut(const G4ThreeVector &gp, const G4ThreeVector &gv, G4ThreeVector &gxxbest)
virtual G4double DistanceToIn(const G4ThreeVector &gp, const G4ThreeVector &gv, G4ThreeVector &gxxbest)
virtual G4ThreeVector SurfacePoint(G4double, G4double, G4bool isGlobal=false)=0
virtual G4double GetBoundaryMax(G4double)=0
virtual G4ThreeVector GetNormal(const G4ThreeVector &xx, G4bool isGlobal)=0
virtual G4double GetSurfaceArea()=0
static G4int GetNumberOfRotationSteps()
G4int createPolyhedron(G4int Nnodes, G4int Nfaces, const G4double xyz[][3], const G4int faces[][4])
EAxis
Definition: geomdefs.hh:54
EInside
Definition: geomdefs.hh:67
@ kInside
Definition: geomdefs.hh:70
@ kOutside
Definition: geomdefs.hh:68
@ kSurface
Definition: geomdefs.hh:69
T sqr(const T &x)
Definition: templates.hh:128
#define DBL_MIN
Definition: templates.hh:54