Geant4 11.4.0
Toolkit for the simulation of the passage of particles through matter
Loading...
Searching...
No Matches
G4TwistTubsHypeSide.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// G4TwistTubsHypeSide implementation
27//
28// Author: Kotoyo Hoshina (Chiba University), 01.08.2002 - Created.
29// Oliver Link (CERN), 13.11.2003 - Integration in Geant4
30// from original version in Jupiter-2.5.02 application.
31// --------------------------------------------------------------------
32
36
37//=====================================================================
38//* constructors ------------------------------------------------------
39
41 const G4RotationMatrix& rot,
42 const G4ThreeVector& tlate,
43 const G4int handedness,
44 const G4double kappa,
45 const G4double tanstereo,
46 const G4double r0,
47 const EAxis axis0,
48 const EAxis axis1,
49 G4double axis0min,
50 G4double axis1min,
51 G4double axis0max,
52 G4double axis1max )
53 : G4VTwistSurface(name, rot, tlate, handedness, axis0, axis1,
54 axis0min, axis1min, axis0max, axis1max),
55 fKappa(kappa), fTanStereo(tanstereo),
56 fTan2Stereo(tanstereo*tanstereo), fR0(r0), fR02(r0*r0), fDPhi(twopi)
57{
58 if ( (axis0 == kZAxis) && (axis1 == kPhi) )
59 {
60 G4Exception("G4TwistTubsHypeSide::G4TwistTubsHypeSide()",
61 "GeomSolids0002", FatalErrorInArgument,
62 "Should swap axis0 and axis1!");
63 }
64 fInside.gp.set(kInfinity, kInfinity, kInfinity);
65 fInside.inside = kOutside;
66 fIsValidNorm = false;
67 SetCorners();
68 SetBoundaries();
69}
70
72 G4double EndInnerRadius[2],
73 G4double EndOuterRadius[2],
74 G4double DPhi,
75 G4double EndPhi[2],
76 G4double EndZ[2],
77 G4double InnerRadius,
78 G4double OuterRadius,
79 G4double Kappa,
80 G4double TanInnerStereo,
81 G4double TanOuterStereo,
82 G4int handedness)
83 : G4VTwistSurface(name)
84{
85
86 fHandedness = handedness; // +z = +ve, -z = -ve
87 fAxis[0] = kPhi;
88 fAxis[1] = kZAxis;
89 fAxisMin[0] = kInfinity; // we cannot fix boundary min of Phi,
90 fAxisMax[0] = kInfinity; // because it depends on z.
91 fAxisMin[1] = EndZ[0];
92 fAxisMax[1] = EndZ[1];
93 fKappa = Kappa;
94 fDPhi = DPhi ;
95
96 if (handedness < 0) // inner hyperbolic surface
97 {
98 fTanStereo = TanInnerStereo;
99 fR0 = InnerRadius;
100 }
101 else // outer hyperbolic surface
102 {
103 fTanStereo = TanOuterStereo;
104 fR0 = OuterRadius;
105 }
106 fTan2Stereo = fTanStereo * fTanStereo;
107 fR02 = fR0 * fR0;
108
109 fTrans.set(0, 0, 0);
110 fIsValidNorm = false;
111
112 fInside.gp.set(kInfinity, kInfinity, kInfinity);
113 fInside.inside = kOutside;
114
115 SetCorners(EndInnerRadius, EndOuterRadius, DPhi, EndPhi, EndZ) ;
116
117 SetBoundaries();
118}
119
120//=====================================================================
121//* Fake default constructor ------------------------------------------
122
127
128//=====================================================================
129//* GetNormal ---------------------------------------------------------
130
132 G4bool isGlobal)
133{
134 // GetNormal returns a normal vector at a surface (or very close
135 // to surface) point at tmpxx.
136 // If isGlobal=true, it returns the normal in global coordinate.
137
138 G4ThreeVector xx;
139 if (isGlobal)
140 {
141 xx = ComputeLocalPoint(tmpxx);
142 if ((xx - fCurrentNormal.p).mag() < 0.5 * kCarTolerance)
143 {
145 }
146 }
147 else
148 {
149 xx = tmpxx;
150 if (xx == fCurrentNormal.p)
151 {
152 return fCurrentNormal.normal;
153 }
154 }
155
156 fCurrentNormal.p = xx;
157
158 G4ThreeVector normal( xx.x(), xx.y(), -xx.z() * fTan2Stereo);
159 normal *= fHandedness;
160 normal = normal.unit();
161
162 if (isGlobal)
163 {
164 fCurrentNormal.normal = ComputeLocalDirection(normal);
165 }
166 else
167 {
168 fCurrentNormal.normal = normal;
169 }
170 return fCurrentNormal.normal;
171}
172
173//=====================================================================
174//* Inside() ----------------------------------------------------------
175
177{
178 // Inside returns
179 const G4double halftol
181
182 if (fInside.gp == gp)
183 {
184 return fInside.inside;
185 }
186 fInside.gp = gp;
187
189
190
191 if (p.mag() < DBL_MIN)
192 {
193 fInside.inside = kOutside;
194 return fInside.inside;
195 }
196
197 G4double rhohype = GetRhoAtPZ(p);
198 G4double distanceToOut = fHandedness * (rhohype - p.getRho());
199 // +ve : inside
200
201 if (distanceToOut < -halftol)
202 {
203 fInside.inside = kOutside;
204 }
205 else
206 {
207 G4int areacode = GetAreaCode(p);
208 if (IsOutside(areacode))
209 {
210 fInside.inside = kOutside;
211 }
212 else if (IsBoundary(areacode))
213 {
214 fInside.inside = kSurface;
215 }
216 else if (IsInside(areacode))
217 {
218 if (distanceToOut <= halftol)
219 {
220 fInside.inside = kSurface;
221 }
222 else
223 {
224 fInside.inside = kInside;
225 }
226 }
227 else
228 {
229 G4cout << "WARNING - G4TwistTubsHypeSide::Inside()" << G4endl
230 << " Invalid option !" << G4endl
231 << " name, areacode, distanceToOut = "
232 << GetName() << ", " << std::hex << areacode
233 << std::dec << ", " << distanceToOut << G4endl;
234 }
235 }
236
237 return fInside.inside;
238}
239
240//=====================================================================
241//* DistanceToSurface -------------------------------------------------
242
244 const G4ThreeVector& gv,
245 G4ThreeVector gxx[],
246 G4double distance[],
247 G4int areacode[],
248 G4bool isvalid[],
249 EValidate validate)
250{
251 // Decide if and where a line intersects with a hyperbolic
252 // surface (of infinite extent)
253 //
254 // Arguments:
255 // p - (in) Point on trajectory
256 // v - (in) Vector along trajectory
257 // r2 - (in) Square of radius at z = 0
258 // tan2phi - (in) std::tan(stereo)**2
259 // s - (out) Up to two points of intersection, where the
260 // intersection point is p + s*v, and if there are
261 // two intersections, s[0] < s[1]. May be negative.
262 // Returns:
263 // The number of intersections. If 0, the trajectory misses.
264 //
265 //
266 // Equation of a line:
267 //
268 // x = x0 + s*tx y = y0 + s*ty z = z0 + s*tz
269 //
270 // Equation of a hyperbolic surface:
271 //
272 // x**2 + y**2 = r**2 + (z*tanPhi)**2
273 //
274 // Solution is quadratic:
275 //
276 // a*s**2 + b*s + c = 0
277 //
278 // where:
279 //
280 // a = tx**2 + ty**2 - (tz*tanPhi)**2
281 //
282 // b = 2*( x0*tx + y0*ty - z0*tz*tanPhi**2 )
283 //
284 // c = x0**2 + y0**2 - r**2 - (z0*tanPhi)**2
285 //
286
287 fCurStatWithV.ResetfDone(validate, &gp, &gv);
288
289 if (fCurStatWithV.IsDone())
290 {
291 for (G4int i=0; i<fCurStatWithV.GetNXX(); ++i)
292 {
293 gxx[i] = fCurStatWithV.GetXX(i);
294 distance[i] = fCurStatWithV.GetDistance(i);
295 areacode[i] = fCurStatWithV.GetAreacode(i);
296 isvalid[i] = fCurStatWithV.IsValid(i);
297 }
298 return fCurStatWithV.GetNXX();
299 }
300
301 // initialize
302 for (auto i=0; i<2; ++i)
303 {
304 distance[i] = kInfinity;
305 areacode[i] = sOutside;
306 isvalid[i] = false;
307 gxx[i].set(kInfinity, kInfinity, kInfinity);
308 }
309
312 G4ThreeVector xx[2];
313
314 //
315 // special case! p is on origin.
316 //
317
318 if (p.mag() == 0)
319 {
320 // p is origin.
321 // unique solution of 2-dimension question in r-z plane
322 // Equations:
323 // r^2 = fR02 + z^2*fTan2Stere0
324 // r = beta*z
325 // where
326 // beta = vrho / vz
327 // Solution (z value of intersection point):
328 // xxz = +- std::sqrt (fR02 / (beta^2 - fTan2Stereo))
329 //
330
331 G4double vz = v.z();
332 G4double absvz = std::fabs(vz);
333 G4double vrho = v.getRho();
334 G4double vslope = vrho/vz;
335 G4double vslope2 = vslope * vslope;
336 if (vrho == 0 || (vrho/absvz) <= (absvz*std::fabs(fTanStereo)/absvz))
337 {
338 // vz/vrho is bigger than slope of asymptonic line
339 distance[0] = kInfinity;
340 fCurStatWithV.SetCurrentStatus(0, gxx[0], distance[0], areacode[0],
341 isvalid[0], 0, validate, &gp, &gv);
342 return 0;
343 }
344
345 if (vz != 0.0)
346 {
347 G4double xxz = std::sqrt(fR02 / (vslope2 - fTan2Stereo))
348 * (vz / std::fabs(vz)) ;
349 G4double t = xxz / vz;
350 xx[0].set(t*v.x(), t*v.y(), xxz);
351 }
352 else
353 {
354 // p.z = 0 && v.z =0
355 xx[0].set(v.x()*fR0, v.y()*fR0, 0); // v is a unit vector.
356 }
357 distance[0] = xx[0].mag();
358 gxx[0] = ComputeGlobalPoint(xx[0]);
359
360 if (validate == kValidateWithTol)
361 {
362 areacode[0] = GetAreaCode(xx[0]);
363 if (!IsOutside(areacode[0]))
364 {
365 if (distance[0] >= 0) { isvalid[0] = true; }
366 }
367 }
368 else if (validate == kValidateWithoutTol)
369 {
370 areacode[0] = GetAreaCode(xx[0], false);
371 if (IsInside(areacode[0]))
372 {
373 if (distance[0] >= 0) { isvalid[0] = true; }
374 }
375 }
376 else // kDontValidate
377 {
378 areacode[0] = sInside;
379 if (distance[0] >= 0) { isvalid[0] = true; }
380 }
381
382 fCurStatWithV.SetCurrentStatus(0, gxx[0], distance[0], areacode[0],
383 isvalid[0], 1, validate, &gp, &gv);
384 return 1;
385 }
386
387 //
388 // special case end.
389 //
390
391 G4double a = v.x()*v.x() + v.y()*v.y() - v.z()*v.z()*fTan2Stereo;
392 G4double b = 2.0
393 * ( p.x() * v.x() + p.y() * v.y() - p.z() * v.z() * fTan2Stereo );
394 G4double c = p.x()*p.x() + p.y()*p.y() - fR02 - p.z()*p.z()*fTan2Stereo;
395 G4double D = b*b - 4*a*c; //discriminant
396 G4int vout = 0;
397
398 if (std::fabs(a) < DBL_MIN)
399 {
400 if (std::fabs(b) > DBL_MIN) // single solution
401 {
402 distance[0] = -c/b;
403 xx[0] = p + distance[0]*v;
404 gxx[0] = ComputeGlobalPoint(xx[0]);
405
406 if (validate == kValidateWithTol)
407 {
408 areacode[0] = GetAreaCode(xx[0]);
409 if (!IsOutside(areacode[0]))
410 {
411 if (distance[0] >= 0) { isvalid[0] = true; }
412 }
413 }
414 else if (validate == kValidateWithoutTol)
415 {
416 areacode[0] = GetAreaCode(xx[0], false);
417 if (IsInside(areacode[0]))
418 {
419 if (distance[0] >= 0) { isvalid[0] = true; }
420 }
421 }
422 else // kDontValidate
423 {
424 areacode[0] = sInside;
425 if (distance[0] >= 0) { isvalid[0] = true; }
426 }
427
428 fCurStatWithV.SetCurrentStatus(0, gxx[0], distance[0], areacode[0],
429 isvalid[0], 1, validate, &gp, &gv);
430 vout = 1;
431 }
432 else
433 {
434 // if a=b=0 and c != 0, p is origin and v is parallel to asymptotic line
435 // if a=b=c=0, p is on surface and v is paralell to stereo wire.
436 // return distance = infinity
437
438 fCurStatWithV.SetCurrentStatus(0, gxx[0], distance[0], areacode[0],
439 isvalid[0], 0, validate, &gp, &gv);
440 vout = 0;
441 }
442 }
443 else if (D > DBL_MIN) // double solutions
444 {
445 D = std::sqrt(D);
446 G4double factor = 0.5/a;
447 G4double tmpdist[2] = {kInfinity, kInfinity};
448 G4ThreeVector tmpxx[2] ;
449 G4int tmpareacode[2] = {sOutside, sOutside};
450 G4bool tmpisvalid[2] = {false, false};
451
452 for (auto i=0; i<2; ++i)
453 {
454 tmpdist[i] = factor*(-b - D);
455 D = -D;
456 tmpxx[i] = p + tmpdist[i]*v;
457
458 if (validate == kValidateWithTol)
459 {
460 tmpareacode[i] = GetAreaCode(tmpxx[i]);
461 if (!IsOutside(tmpareacode[i]))
462 {
463 if (tmpdist[i] >= 0) { tmpisvalid[i] = true; }
464 continue;
465 }
466 }
467 else if (validate == kValidateWithoutTol)
468 {
469 tmpareacode[i] = GetAreaCode(tmpxx[i], false);
470 if (IsInside(tmpareacode[i]))
471 {
472 if (tmpdist[i] >= 0) { tmpisvalid[i] = true; }
473 continue;
474 }
475 }
476 else // kDontValidate
477 {
478 tmpareacode[i] = sInside;
479 if (tmpdist[i] >= 0) { tmpisvalid[i] = true; }
480 continue;
481 }
482 }
483
484 if (tmpdist[0] <= tmpdist[1])
485 {
486 distance[0] = tmpdist[0];
487 distance[1] = tmpdist[1];
488 xx[0] = tmpxx[0];
489 xx[1] = tmpxx[1];
490 gxx[0] = ComputeGlobalPoint(tmpxx[0]);
491 gxx[1] = ComputeGlobalPoint(tmpxx[1]);
492 areacode[0] = tmpareacode[0];
493 areacode[1] = tmpareacode[1];
494 isvalid[0] = tmpisvalid[0];
495 isvalid[1] = tmpisvalid[1];
496 }
497 else
498 {
499 distance[0] = tmpdist[1];
500 distance[1] = tmpdist[0];
501 xx[0] = tmpxx[1];
502 xx[1] = tmpxx[0];
503 gxx[0] = ComputeGlobalPoint(tmpxx[1]);
504 gxx[1] = ComputeGlobalPoint(tmpxx[0]);
505 areacode[0] = tmpareacode[1];
506 areacode[1] = tmpareacode[0];
507 isvalid[0] = tmpisvalid[1];
508 isvalid[1] = tmpisvalid[0];
509 }
510
511 fCurStatWithV.SetCurrentStatus(0, gxx[0], distance[0], areacode[0],
512 isvalid[0], 2, validate, &gp, &gv);
513 fCurStatWithV.SetCurrentStatus(1, gxx[1], distance[1], areacode[1],
514 isvalid[1], 2, validate, &gp, &gv);
515 vout = 2;
516 }
517 else
518 {
519 // if D<0, no solution
520 // if D=0, just grazing the surfaces, return kInfinity
521
522 fCurStatWithV.SetCurrentStatus(0, gxx[0], distance[0], areacode[0],
523 isvalid[0], 0, validate, &gp, &gv);
524 vout = 0;
525 }
526 return vout;
527}
528
529//=====================================================================
530//* DistanceToSurface -------------------------------------------------
531
533 G4ThreeVector gxx[],
534 G4double distance[],
535 G4int areacode[])
536{
537 // Find the approximate distance of a point of a hyperbolic surface.
538 // The distance must be an underestimate.
539 // It will also be nice (although not necessary) that the estimate is
540 // always finite no matter how close the point is.
541 //
542 // We arranged G4Hype::ApproxDistOutside and G4Hype::ApproxDistInside
543 // for this function. See these discriptions.
544
545 const G4double halftol
547
548 fCurStat.ResetfDone(kDontValidate, &gp);
549
550 if (fCurStat.IsDone())
551 {
552 for (G4int i=0; i<fCurStat.GetNXX(); ++i)
553 {
554 gxx[i] = fCurStat.GetXX(i);
555 distance[i] = fCurStat.GetDistance(i);
556 areacode[i] = fCurStat.GetAreacode(i);
557 }
558 return fCurStat.GetNXX();
559 }
560
561 // initialize
562 for (auto i=0; i<2; ++i)
563 {
564 distance[i] = kInfinity;
565 areacode[i] = sOutside;
566 gxx[i].set(kInfinity, kInfinity, kInfinity);
567 }
568
570 G4ThreeVector xx;
571
572 //
573 // special case!
574 // If p is on surface, return distance = 0 immediatery .
575 //
576 G4ThreeVector lastgxx[2];
577 for (auto i=0; i<2; ++i)
578 {
579 lastgxx[i] = fCurStatWithV.GetXX(i);
580 }
581
582 if ((gp - lastgxx[0]).mag() < halftol || (gp - lastgxx[1]).mag() < halftol)
583 {
584 // last winner, or last poststep point is on the surface.
585 xx = p;
586 gxx[0] = gp;
587 distance[0] = 0;
588
589 G4bool isvalid = true;
590 fCurStat.SetCurrentStatus(0, gxx[0], distance[0], areacode[0],
591 isvalid, 1, kDontValidate, &gp);
592
593 return 1;
594 }
595 //
596 // special case end
597 //
598
599 G4double prho = p.getRho();
600 G4double pz = std::fabs(p.z()); // use symmetry
601 G4double r1 = std::sqrt(fR02 + pz * pz * fTan2Stereo);
602
603 G4ThreeVector pabsz(p.x(), p.y(), pz);
604
605 if (prho > r1 + halftol) // p is outside of Hyperbolic surface
606 {
607 // First point xx1
608 G4double t = r1 / prho;
609 G4ThreeVector xx1(t * pabsz.x(), t * pabsz.y() , pz);
610
611 // Second point xx2
612 G4double z2 = (prho * fTanStereo + pz) / (1 + fTan2Stereo);
613 G4double r2 = std::sqrt(fR02 + z2 * z2 * fTan2Stereo);
614 t = r2 / prho;
615 G4ThreeVector xx2(t * pabsz.x(), t * pabsz.y() , z2);
616
617 G4double len = (xx2 - xx1).mag();
618 if (len < DBL_MIN)
619 {
620 // xx2 = xx1?? I guess we
621 // must have really bracketed the normal
622 distance[0] = (pabsz - xx1).mag();
623 xx = xx1;
624 }
625 else
626 {
627 distance[0] = DistanceToLine(pabsz, xx1, (xx2 - xx1) , xx);
628 }
629
630 }
631 else if (prho < r1 - halftol) // p is inside of Hyperbolic surface.
632 {
633 // First point xx1
634 G4double t;
635 G4ThreeVector xx1;
636 if (prho < DBL_MIN)
637 {
638 xx1.set(r1, 0. , pz);
639 }
640 else
641 {
642 t = r1 / prho;
643 xx1.set(t * pabsz.x(), t * pabsz.y() , pz);
644 }
645
646 // dr, dz is tangential vector of Hyparbolic surface at xx1
647 // dr = r, dz = z*tan2stereo
648 G4double dr = pz * fTan2Stereo;
649 G4double dz = r1;
650 G4double tanbeta = dr / dz;
651 G4double pztanbeta = pz * tanbeta;
652
653 // Second point xx2
654 // xx2 is intersection between x-axis and tangential vector
655 G4double r2 = r1 - pztanbeta;
656 G4ThreeVector xx2;
657 if (prho < DBL_MIN)
658 {
659 xx2.set(r2, 0. , 0.);
660 }
661 else
662 {
663 t = r2 / prho;
664 xx2.set(t * pabsz.x(), t * pabsz.y() , 0.);
665 }
666
667 G4ThreeVector d = xx2 - xx1;
668 distance[0] = DistanceToLine(pabsz, xx1, d, xx);
669
670 }
671 else // p is on Hyperbolic surface.
672 {
673 distance[0] = 0;
674 xx.set(p.x(), p.y(), pz);
675 }
676
677 if (p.z() < 0)
678 {
679 G4ThreeVector tmpxx(xx.x(), xx.y(), -xx.z());
680 xx = tmpxx;
681 }
682
683 gxx[0] = ComputeGlobalPoint(xx);
684 areacode[0] = sInside;
685 G4bool isvalid = true;
686 fCurStat.SetCurrentStatus(0, gxx[0], distance[0], areacode[0],
687 isvalid, 1, kDontValidate, &gp);
688 return 1;
689}
690
691//=====================================================================
692//* GetAreaCode -------------------------------------------------------
693
694G4int G4TwistTubsHypeSide::GetAreaCode(const G4ThreeVector& xx,
695 G4bool withTol)
696{
697 const G4double ctol = 0.5 * kCarTolerance;
698 G4int areacode = sInside;
699
700 if ((fAxis[0] == kPhi && fAxis[1] == kZAxis))
701 {
702 G4int zaxis = 1;
703
704 if (withTol)
705 {
706 G4bool isoutside = false;
707 G4int phiareacode = GetAreaCodeInPhi(xx);
708 G4bool isoutsideinphi = IsOutside(phiareacode);
709
710 // test boundary of phiaxis
711
712 if ((phiareacode & sAxisMin) == sAxisMin)
713 {
714 areacode |= (sAxis0 & (sAxisPhi | sAxisMin)) | sBoundary;
715 if (isoutsideinphi) { isoutside = true; }
716 }
717 else if ((phiareacode & sAxisMax) == sAxisMax)
718 {
719 areacode |= (sAxis0 & (sAxisPhi | sAxisMax)) | sBoundary;
720 if (isoutsideinphi) { isoutside = true; }
721 }
722
723 // test boundary of zaxis
724
725 if (xx.z() < fAxisMin[zaxis] + ctol)
726 {
727 areacode |= (sAxis1 & (sAxisZ | sAxisMin));
728 if ((areacode & sBoundary) != 0)
729 {
730 areacode |= sCorner; // xx is on corner.
731 }
732 else
733 {
734 areacode |= sBoundary;
735 }
736
737 if (xx.z() <= fAxisMin[zaxis] - ctol) { isoutside = true; }
738 }
739 else if (xx.z() > fAxisMax[zaxis] - ctol)
740 {
741 areacode |= (sAxis1 & (sAxisZ | sAxisMax));
742 if ((areacode & sBoundary) != 0)
743 {
744 areacode |= sCorner; // xx is on corner.
745 }
746 else
747 {
748 areacode |= sBoundary;
749 }
750
751 if (xx.z() >= fAxisMax[zaxis] + ctol) { isoutside = true; }
752 }
753
754 // if isoutside = true, clear sInside bit.
755 // if not on boundary, add boundary information.
756
757 if (isoutside)
758 {
759 G4int tmpareacode = areacode & (~sInside);
760 areacode = tmpareacode;
761 }
762 else if ((areacode & sBoundary) != sBoundary)
763 {
764 areacode |= (sAxis0 & sAxisPhi) | (sAxis1 & sAxisZ);
765 }
766
767 return areacode;
768 }
769
770 G4int phiareacode = GetAreaCodeInPhi(xx, false);
771
772 // test boundary of z-axis
773
774 if (xx.z() < fAxisMin[zaxis])
775 {
776 areacode |= (sAxis1 & (sAxisZ | sAxisMin)) | sBoundary;
777 }
778 else if (xx.z() > fAxisMax[zaxis])
779 {
780 areacode |= (sAxis1 & (sAxisZ | sAxisMax)) | sBoundary;
781 }
782
783 // boundary of phi-axis
784
785 if (phiareacode == sAxisMin)
786 {
787 areacode |= (sAxis0 & (sAxisPhi | sAxisMin));
788 if ((areacode & sBoundary) != 0)
789 {
790 areacode |= sCorner; // xx is on corner.
791 }
792 else
793 {
794 areacode |= sBoundary;
795 }
796 }
797 else if (phiareacode == sAxisMax)
798 {
799 areacode |= (sAxis0 & (sAxisPhi | sAxisMax));
800 if ((areacode & sBoundary) != 0)
801 {
802 areacode |= sCorner; // xx is on corner.
803 }
804 else
805 {
806 areacode |= sBoundary;
807 }
808 }
809
810 // if not on boundary, add boundary information.
811
812 if ((areacode & sBoundary) != sBoundary)
813 {
814 areacode |= (sAxis0 & sAxisPhi) | (sAxis1 & sAxisZ);
815 }
816 return areacode;
817 }
818 else
819 {
820 std::ostringstream message;
821 message << "Feature NOT implemented !" << G4endl
822 << " fAxis[0] = " << fAxis[0] << G4endl
823 << " fAxis[1] = " << fAxis[1];
824 G4Exception("G4TwistTubsHypeSide::GetAreaCode()",
825 "GeomSolids0001", FatalException, message);
826 }
827 return areacode;
828}
829
830//=====================================================================
831//* GetAreaCodeInPhi --------------------------------------------------
832
833G4int G4TwistTubsHypeSide::GetAreaCodeInPhi(const G4ThreeVector& xx,
834 G4bool withTol)
835{
836
837 G4ThreeVector lowerlimit; // lower phi-boundary limit at z = xx.z()
838 G4ThreeVector upperlimit; // upper phi-boundary limit at z = xx.z()
839 lowerlimit = GetBoundaryAtPZ(sAxis0 & sAxisMin, xx);
840 upperlimit = GetBoundaryAtPZ(sAxis0 & sAxisMax, xx);
841
842 G4int areacode = sInside;
843 G4bool isoutside = false;
844
845 if (withTol)
846 {
847 if (AmIOnLeftSide(xx, lowerlimit) >= 0) // xx is on lowerlimit
848 {
849 areacode |= (sAxisMin | sBoundary);
850 if (AmIOnLeftSide(xx, lowerlimit) > 0) { isoutside = true; }
851 }
852 else if (AmIOnLeftSide(xx, upperlimit) <= 0) // xx is on upperlimit
853 {
854 areacode |= (sAxisMax | sBoundary);
855 if (AmIOnLeftSide(xx, upperlimit) < 0) { isoutside = true; }
856 }
857
858 // if isoutside = true, clear inside bit.
859
860 if (isoutside)
861 {
862 G4int tmpareacode = areacode & (~sInside);
863 areacode = tmpareacode;
864 }
865 }
866 else
867 {
868 if (AmIOnLeftSide(xx, lowerlimit, false) >= 0)
869 {
870 areacode |= (sAxisMin | sBoundary);
871 }
872 else if (AmIOnLeftSide(xx, upperlimit, false) <= 0)
873 {
874 areacode |= (sAxisMax | sBoundary);
875 }
876 }
877
878 return areacode;
879}
880
881//=====================================================================
882//* SetCorners(EndInnerRadius, EndOuterRadius,DPhi,EndPhi,EndZ) -------
883
884void G4TwistTubsHypeSide::SetCorners( G4double EndInnerRadius[2],
885 G4double EndOuterRadius[2],
886 G4double DPhi,
887 G4double endPhi[2],
888 G4double endZ[2] )
889{
890 // Set Corner points in local coodinate.
891
892 if (fAxis[0] == kPhi && fAxis[1] == kZAxis) {
893
894 G4double endRad[2];
895 G4double halfdphi = 0.5*DPhi;
896
897 for (auto i=0; i<2; ++i) // i=0,1 : -ve z, +ve z
898 {
899 endRad[i] = (fHandedness == 1 ? EndOuterRadius[i] : EndInnerRadius[i]);
900 }
901
902 G4int zmin = 0 ; // at -ve z
903 G4int zmax = 1 ; // at +ve z
904
905 G4double x, y, z;
906
907 // corner of Axis0min and Axis1min
908 x = endRad[zmin]*std::cos(endPhi[zmin] - halfdphi);
909 y = endRad[zmin]*std::sin(endPhi[zmin] - halfdphi);
910 z = endZ[zmin];
911 SetCorner(sC0Min1Min, x, y, z);
912
913 // corner of Axis0max and Axis1min
914 x = endRad[zmin]*std::cos(endPhi[zmin] + halfdphi);
915 y = endRad[zmin]*std::sin(endPhi[zmin] + halfdphi);
916 z = endZ[zmin];
917 SetCorner(sC0Max1Min, x, y, z);
918
919 // corner of Axis0max and Axis1max
920 x = endRad[zmax]*std::cos(endPhi[zmax] + halfdphi);
921 y = endRad[zmax]*std::sin(endPhi[zmax] + halfdphi);
922 z = endZ[zmax];
923 SetCorner(sC0Max1Max, x, y, z);
924
925 // corner of Axis0min and Axis1max
926 x = endRad[zmax]*std::cos(endPhi[zmax] - halfdphi);
927 y = endRad[zmax]*std::sin(endPhi[zmax] - halfdphi);
928 z = endZ[zmax];
929 SetCorner(sC0Min1Max, x, y, z);
930
931 }
932 else
933 {
934 std::ostringstream message;
935 message << "Feature NOT implemented !" << G4endl
936 << " fAxis[0] = " << fAxis[0] << G4endl
937 << " fAxis[1] = " << fAxis[1];
938 G4Exception("G4TwistTubsHypeSide::SetCorners()",
939 "GeomSolids0001", FatalException, message);
940 }
941}
942
943//=====================================================================
944//* SetCorners() ------------------------------------------------------
945
946void G4TwistTubsHypeSide::SetCorners()
947{
948 G4Exception("G4TwistTubsHypeSide::SetCorners()",
949 "GeomSolids0001", FatalException,
950 "Method NOT implemented !");
951}
952
953//=====================================================================
954//* SetBoundaries() ---------------------------------------------------
955
956void G4TwistTubsHypeSide::SetBoundaries()
957{
958 // Set direction-unit vector of phi-boundary-lines in local coodinate.
959 // sAxis0 must be kPhi.
960 // This fanction set lower phi-boundary and upper phi-boundary.
961
962 if (fAxis[0] == kPhi && fAxis[1] == kZAxis)
963 {
964 G4ThreeVector direction;
965 // sAxis0 & sAxisMin
967 direction = direction.unit();
968 SetBoundary(sAxis0 & (sAxisPhi | sAxisMin), direction,
970
971 // sAxis0 & sAxisMax
973 direction = direction.unit();
974 SetBoundary(sAxis0 & (sAxisPhi | sAxisMax), direction,
976
977 // sAxis1 & sAxisMin
979 direction = direction.unit();
980 SetBoundary(sAxis1 & (sAxisZ | sAxisMin), direction,
982
983 // sAxis1 & sAxisMax
985 direction = direction.unit();
986 SetBoundary(sAxis1 & (sAxisZ | sAxisMax), direction,
988 }
989 else
990 {
991 std::ostringstream message;
992 message << "Feature NOT implemented !" << G4endl
993 << " fAxis[0] = " << fAxis[0] << G4endl
994 << " fAxis[1] = " << fAxis[1];
995 G4Exception("G4TwistTubsHypeSide::SetBoundaries()",
996 "GeomSolids0001", FatalException, message);
997 }
998}
999
1000//=====================================================================
1001//* GetFacets() -------------------------------------------------------
1002
1003void G4TwistTubsHypeSide::GetFacets( G4int k, G4int n, G4double xyz[][3],
1004 G4int faces[][4], G4int iside )
1005{
1006 G4double z ; // the two parameters for the surface equation
1007 G4double x,xmin,xmax ;
1008
1009 G4ThreeVector p ; // a point on the surface, given by (z,u)
1010
1011 G4int nnode ;
1012 G4int nface ;
1013
1014 // calculate the (n-1)*(k-1) vertices
1015
1016 for ( G4int i = 0 ; i<n ; ++i )
1017 {
1018 z = fAxisMin[1] + i*(fAxisMax[1]-fAxisMin[1])/(n-1) ;
1019
1020 for ( G4int j = 0 ; j<k ; ++j )
1021 {
1022 nnode = GetNode(i,j,k,n,iside) ;
1023
1024 xmin = GetBoundaryMin(z) ;
1025 xmax = GetBoundaryMax(z) ;
1026
1027 if (fHandedness < 0) // inner hyperbolic surface
1028 {
1029 x = xmin + j*(xmax-xmin)/(k-1) ;
1030 }
1031 else // outer hyperbolic surface
1032 {
1033 x = xmax - j*(xmax-xmin)/(k-1) ;
1034 }
1035
1036 p = SurfacePoint(x,z,true) ; // surface point in global coord.system
1037
1038 xyz[nnode][0] = p.x() ;
1039 xyz[nnode][1] = p.y() ;
1040 xyz[nnode][2] = p.z() ;
1041
1042 if ( i<n-1 && j<k-1 ) // clock wise filling
1043 {
1044 nface = GetFace(i,j,k,n,iside) ;
1045 faces[nface][0] = GetEdgeVisibility(i,j,k,n,0,1)
1046 * ( GetNode(i ,j ,k,n,iside)+1) ;
1047 faces[nface][1] = GetEdgeVisibility(i,j,k,n,1,1)
1048 * ( GetNode(i+1,j ,k,n,iside)+1) ;
1049 faces[nface][2] = GetEdgeVisibility(i,j,k,n,2,1)
1050 * ( GetNode(i+1,j+1,k,n,iside)+1) ;
1051 faces[nface][3] = GetEdgeVisibility(i,j,k,n,3,1)
1052 * ( GetNode(i ,j+1,k,n,iside)+1) ;
1053 }
1054 }
1055 }
1056}
const G4double kCarTolerance
G4double D(G4double temp)
@ FatalException
@ FatalErrorInArgument
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *description)
CLHEP::HepRotation G4RotationMatrix
CLHEP::Hep3Vector G4ThreeVector
double G4double
Definition G4Types.hh:83
bool G4bool
Definition G4Types.hh:86
int G4int
Definition G4Types.hh:85
#define G4endl
Definition G4ios.hh:67
G4GLOB_DLL std::ostream G4cout
double z() const
Hep3Vector unit() const
double x() const
double y() const
double mag() const
double getRho() const
void set(double x, double y, double z)
G4double GetRadialTolerance() const
static G4GeometryTolerance * GetInstance()
G4ThreeVector GetNormal(const G4ThreeVector &p, G4bool isGlobal=false) override
G4int DistanceToSurface(const G4ThreeVector &gp, const G4ThreeVector &gv, G4ThreeVector gxx[], G4double distance[], G4int areacode[], G4bool isvalid[], EValidate validate=kValidateWithTol) override
EInside Inside(const G4ThreeVector &gp)
G4TwistTubsHypeSide(const G4String &name, const G4RotationMatrix &rot, const G4ThreeVector &tlate, const G4int handedness, const G4double kappa, const G4double tanstereo, const G4double r0, const EAxis axis0=kPhi, const EAxis axis1=kZAxis, G4double axis0min=-kInfinity, G4double axis1min=-kInfinity, G4double axis0max=kInfinity, G4double axis1max=kInfinity)
G4double GetRhoAtPZ(const G4ThreeVector &p, G4bool isglobal=false) const
virtual G4int AmIOnLeftSide(const G4ThreeVector &me, const G4ThreeVector &vec, G4bool withTol=true)
static const G4int sC0Min1Min
static const G4int sC0Min1Max
G4VTwistSurface(const G4String &name)
G4int GetNode(G4int i, G4int j, G4int m, G4int n, G4int iside)
static const G4int sOutside
G4ThreeVector ComputeGlobalDirection(const G4ThreeVector &lp) const
static const G4int sAxisMax
static const G4int sAxis0
G4int GetFace(G4int i, G4int j, G4int m, G4int n, G4int iside)
const G4String & GetName() const
G4int GetEdgeVisibility(G4int i, G4int j, G4int m, G4int n, G4int number, G4int orientation)
G4double DistanceToLine(const G4ThreeVector &p, const G4ThreeVector &x0, const G4ThreeVector &d, G4ThreeVector &xx)
G4ThreeVector ComputeLocalDirection(const G4ThreeVector &gp) const
static const G4int sAxisPhi
static const G4int sAxisMin
static const G4int sC0Max1Max
static const G4int sAxis1
virtual G4ThreeVector GetBoundaryAtPZ(G4int areacode, const G4ThreeVector &p) const
G4bool IsInside(G4int areacode, G4bool testbitmode=false) const
G4ThreeVector fTrans
virtual void SetBoundary(const G4int &axiscode, const G4ThreeVector &direction, const G4ThreeVector &x0, const G4int &boundarytype)
G4ThreeVector ComputeLocalPoint(const G4ThreeVector &gp) const
void SetCorner(G4int areacode, G4double x, G4double y, G4double z)
G4ThreeVector GetCorner(G4int areacode) const
static const G4int sBoundary
static const G4int sAxisZ
G4bool IsOutside(G4int areacode) const
static const G4int sCorner
static const G4int sC0Max1Min
static const G4int sInside
CurrentStatus fCurStatWithV
G4bool IsBoundary(G4int areacode, G4bool testbitmode=false) const
G4ThreeVector ComputeGlobalPoint(const G4ThreeVector &lp) const
G4SurfCurNormal fCurrentNormal
CurrentStatus fCurStat
EAxis
Definition geomdefs.hh:54
@ kPhi
Definition geomdefs.hh:60
@ kZAxis
Definition geomdefs.hh:57
EInside
Definition geomdefs.hh:67
@ kInside
Definition geomdefs.hh:70
@ kOutside
Definition geomdefs.hh:68
@ kSurface
Definition geomdefs.hh:69
#define DBL_MIN
Definition templates.hh:54