Geant4 11.4.0
Toolkit for the simulation of the passage of particles through matter
Loading...
Searching...
No Matches
G4TwistTubsSide.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// G4TwistTubsSide 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
33#include "G4TwistTubsSide.hh"
34
35//=====================================================================
36//* constructors ------------------------------------------------------
37
39 const G4RotationMatrix& rot,
40 const G4ThreeVector& tlate,
41 G4int handedness,
42 const G4double kappa,
43 const EAxis axis0,
44 const EAxis axis1,
45 G4double axis0min,
46 G4double axis1min,
47 G4double axis0max,
48 G4double axis1max)
49 : G4VTwistSurface(name, rot, tlate, handedness, axis0, axis1,
50 axis0min, axis1min, axis0max, axis1max),
51 fKappa(kappa)
52{
53 if (axis0 == kZAxis && axis1 == kXAxis)
54 {
55 G4Exception("G4TwistTubsSide::G4TwistTubsSide()", "GeomSolids0002",
56 FatalErrorInArgument, "Should swap axis0 and axis1!");
57 }
58 fIsValidNorm = false;
59 SetCorners();
60 SetBoundaries();
61}
62
64 G4double EndInnerRadius[2],
65 G4double EndOuterRadius[2],
66 G4double DPhi,
67 G4double EndPhi[2],
68 G4double EndZ[2],
69 G4double InnerRadius,
70 G4double OuterRadius,
71 G4double Kappa,
72 G4int handedness)
73 : G4VTwistSurface(name)
74{
75 fHandedness = handedness; // +z = +ve, -z = -ve
76 fAxis[0] = kXAxis; // in local coordinate system
77 fAxis[1] = kZAxis;
78 fAxisMin[0] = InnerRadius; // Inner-hype radius at z=0
79 fAxisMax[0] = OuterRadius; // Outer-hype radius at z=0
80 fAxisMin[1] = EndZ[0];
81 fAxisMax[1] = EndZ[1];
82
83 fKappa = Kappa;
84 fRot.rotateZ( fHandedness > 0
85 ? -0.5*DPhi
86 : 0.5*DPhi );
87 fTrans.set(0, 0, 0);
88 fIsValidNorm = false;
89
90 SetCorners( EndInnerRadius, EndOuterRadius, EndPhi, EndZ) ;
91 SetBoundaries();
92}
93
94//=====================================================================
95//* Fake default constructor ------------------------------------------
96
99{
100}
101
102//=====================================================================
103//* GetNormal ---------------------------------------------------------
104
106 G4bool isGlobal)
107{
108 // GetNormal returns a normal vector at a surface (or very close
109 // to surface) point at tmpxx.
110 // If isGlobal=true, it returns the normal in global coordinate.
111 //
112 G4ThreeVector xx;
113 if (isGlobal)
114 {
115 xx = ComputeLocalPoint(tmpxx);
116 if ((xx - fCurrentNormal.p).mag() < 0.5 * kCarTolerance)
117 {
119 }
120 }
121 else
122 {
123 xx = tmpxx;
124 if (xx == fCurrentNormal.p)
125 {
126 return fCurrentNormal.normal;
127 }
128 }
129
130 G4ThreeVector er(1, fKappa * xx.z(), 0);
131 G4ThreeVector ez(0, fKappa * xx.x(), 1);
132 G4ThreeVector normal = fHandedness*(er.cross(ez));
133
134 if (isGlobal)
135 {
136 fCurrentNormal.normal = ComputeGlobalDirection(normal.unit());
137 }
138 else
139 {
140 fCurrentNormal.normal = normal.unit();
141 }
142 return fCurrentNormal.normal;
143}
144
145//=====================================================================
146//* DistanceToSurface -------------------------------------------------
147
149 const G4ThreeVector& gv,
150 G4ThreeVector gxx[],
151 G4double distance[],
152 G4int areacode[],
153 G4bool isvalid[],
154 EValidate validate)
155{
156 // Coordinate system:
157 //
158 // The coordinate system is so chosen that the intersection of
159 // the twisted surface with the z=0 plane coincides with the
160 // x-axis.
161 // Rotation matrix from this coordinate system (local system)
162 // to global system is saved in fRot field.
163 // So the (global) particle position and (global) velocity vectors,
164 // p and v, should be rotated fRot.inverse() in order to convert
165 // to local vectors.
166 //
167 // Equation of a twisted surface:
168 //
169 // x(rho(z=0), z) = rho(z=0)
170 // y(rho(z=0), z) = rho(z=0)*K*z
171 // z(rho(z=0), z) = z
172 // with
173 // K = std::tan(fPhiTwist/2)/fZHalfLen
174 //
175 // Equation of a line:
176 //
177 // gxx = p + t*v
178 // with
179 // p = fRot.inverse()*gp
180 // v = fRot.inverse()*gv
181 //
182 // Solution for intersection:
183 //
184 // Required time for crossing is given by solving the
185 // following quadratic equation:
186 //
187 // a*t^2 + b*t + c = 0
188 //
189 // where
190 //
191 // a = K*v_x*v_z
192 // b = K*(v_x*p_z + v_z*p_x) - v_y
193 // c = K*p_x*p_z - p_y
194 //
195 // Out of the possible two solutions you must choose
196 // the one that gives a positive rho(z=0).
197 //
198 //
199
200 fCurStatWithV.ResetfDone(validate, &gp, &gv);
201
202 if (fCurStatWithV.IsDone())
203 {
204 for (G4int i=0; i<fCurStatWithV.GetNXX(); ++i)
205 {
206 gxx[i] = fCurStatWithV.GetXX(i);
207 distance[i] = fCurStatWithV.GetDistance(i);
208 areacode[i] = fCurStatWithV.GetAreacode(i);
209 isvalid[i] = fCurStatWithV.IsValid(i);
210 }
211 return fCurStatWithV.GetNXX();
212 }
213
214 // initialize
215 for (auto i=0; i<2; ++i)
216 {
217 distance[i] = kInfinity;
218 areacode[i] = sOutside;
219 isvalid[i] = false;
220 gxx[i].set(kInfinity, kInfinity, kInfinity);
221 }
222
225 G4ThreeVector xx[2];
226
227 //
228 // special case!
229 // p is origin or
230 //
231
232 G4double absvz = std::fabs(v.z());
233
234 if ((absvz<DBL_MIN) && (std::fabs(p.x() * v.y() - p.y() * v.x())<DBL_MIN))
235 {
236 // no intersection
237
238 isvalid[0] = false;
239 fCurStat.SetCurrentStatus(0, gxx[0], distance[0], areacode[0],
240 isvalid[0], 0, validate, &gp, &gv);
241 return 0;
242 }
243
244 //
245 // special case end
246 //
247
248 G4double a = fKappa * v.x() * v.z();
249 G4double b = fKappa * (v.x() * p.z() + v.z() * p.x()) - v.y();
250 G4double c = fKappa * p.x() * p.z() - p.y();
251 G4double D = b * b - 4 * a * c; // discriminant
252 G4int vout = 0;
253
254 if (std::fabs(a) < DBL_MIN)
255 {
256 if (std::fabs(b) > DBL_MIN)
257 {
258 // single solution
259
260 distance[0] = - c / b;
261 xx[0] = p + distance[0]*v;
262 gxx[0] = ComputeGlobalPoint(xx[0]);
263
264 if (validate == kValidateWithTol)
265 {
266 areacode[0] = GetAreaCode(xx[0]);
267 if (!IsOutside(areacode[0]))
268 {
269 if (distance[0] >= 0) { isvalid[0] = true; }
270 }
271 }
272 else if (validate == kValidateWithoutTol)
273 {
274 areacode[0] = GetAreaCode(xx[0], false);
275 if (IsInside(areacode[0]))
276 {
277 if (distance[0] >= 0) { isvalid[0] = true; }
278 }
279 }
280 else // kDontValidate
281 {
282 // we must omit x(rho,z) = rho(z=0) < 0
283 if (xx[0].x() > 0)
284 {
285 areacode[0] = sInside;
286 if (distance[0] >= 0) { isvalid[0] = true; }
287 }
288 else
289 {
290 distance[0] = kInfinity;
291 fCurStatWithV.SetCurrentStatus(0, gxx[0], distance[0],
292 areacode[0], isvalid[0],
293 0, validate, &gp, &gv);
294 return vout;
295 }
296 }
297
298 fCurStatWithV.SetCurrentStatus(0, gxx[0], distance[0], areacode[0],
299 isvalid[0], 1, validate, &gp, &gv);
300 vout = 1;
301 }
302 else
303 {
304 // if a=b=0 , v.y=0 and (v.x=0 && p.x=0) or (v.z=0 && p.z=0) .
305 // if v.x=0 && p.x=0, no intersection unless p is on z-axis
306 // (in that case, v is paralell to surface).
307 // if v.z=0 && p.z=0, no intersection unless p is on x-axis
308 // (in that case, v is paralell to surface).
309 // return distance = infinity.
310
311 fCurStatWithV.SetCurrentStatus(0, gxx[0], distance[0], areacode[0],
312 isvalid[0], 0, validate, &gp, &gv);
313 }
314 }
315 else if (D > DBL_MIN)
316 {
317 // double solutions
318
319 D = std::sqrt(D);
320 G4double factor = 0.5/a;
321 G4double tmpdist[2] = {kInfinity, kInfinity};
322 G4ThreeVector tmpxx[2];
323 G4int tmpareacode[2] = {sOutside, sOutside};
324 G4bool tmpisvalid[2] = {false, false};
325
326 for (auto i=0; i<2; ++i)
327 {
328 G4double bminusD = - b - D;
329
330 // protection against round off error
331 //G4double protection = 1.0e-6;
332 G4double protection = 0;
333 if ( b * D < 0 && std::fabs(bminusD / D) < protection )
334 {
335 G4double acovbb = (a*c)/(b*b);
336 tmpdist[i] = - c/b * ( 1 - acovbb * (1 + 2*acovbb));
337 }
338 else
339 {
340 tmpdist[i] = factor * bminusD;
341 }
342
343 D = -D;
344 tmpxx[i] = p + tmpdist[i]*v;
345
346 if (validate == kValidateWithTol)
347 {
348 tmpareacode[i] = GetAreaCode(tmpxx[i]);
349 if (!IsOutside(tmpareacode[i]))
350 {
351 if (tmpdist[i] >= 0) { tmpisvalid[i] = true; }
352 continue;
353 }
354 }
355 else if (validate == kValidateWithoutTol)
356 {
357 tmpareacode[i] = GetAreaCode(tmpxx[i], false);
358 if (IsInside(tmpareacode[i]))
359 {
360 if (tmpdist[i] >= 0) { tmpisvalid[i] = true; }
361 continue;
362 }
363 }
364 else // kDontValidate
365 {
366 // we must choose x(rho,z) = rho(z=0) > 0
367 if (tmpxx[i].x() > 0)
368 {
369 tmpareacode[i] = sInside;
370 if (tmpdist[i] >= 0) { tmpisvalid[i] = true; }
371 continue;
372 }
373
374 tmpdist[i] = kInfinity;
375 continue;
376 }
377 }
378
379 if (tmpdist[0] <= tmpdist[1])
380 {
381 distance[0] = tmpdist[0];
382 distance[1] = tmpdist[1];
383 xx[0] = tmpxx[0];
384 xx[1] = tmpxx[1];
385 gxx[0] = ComputeGlobalPoint(tmpxx[0]);
386 gxx[1] = ComputeGlobalPoint(tmpxx[1]);
387 areacode[0] = tmpareacode[0];
388 areacode[1] = tmpareacode[1];
389 isvalid[0] = tmpisvalid[0];
390 isvalid[1] = tmpisvalid[1];
391 }
392 else
393 {
394 distance[0] = tmpdist[1];
395 distance[1] = tmpdist[0];
396 xx[0] = tmpxx[1];
397 xx[1] = tmpxx[0];
398 gxx[0] = ComputeGlobalPoint(tmpxx[1]);
399 gxx[1] = ComputeGlobalPoint(tmpxx[0]);
400 areacode[0] = tmpareacode[1];
401 areacode[1] = tmpareacode[0];
402 isvalid[0] = tmpisvalid[1];
403 isvalid[1] = tmpisvalid[0];
404 }
405
406 fCurStatWithV.SetCurrentStatus(0, gxx[0], distance[0], areacode[0],
407 isvalid[0], 2, validate, &gp, &gv);
408 fCurStatWithV.SetCurrentStatus(1, gxx[1], distance[1], areacode[1],
409 isvalid[1], 2, validate, &gp, &gv);
410
411 // protection against roundoff error
412
413 for (G4int k=0; k<2; ++k)
414 {
415 if (!isvalid[k]) { continue; }
416
417 G4ThreeVector xxonsurface(xx[k].x(), fKappa * std::fabs(xx[k].x())
418 * xx[k].z() , xx[k].z());
419 G4double deltaY = (xx[k] - xxonsurface).mag();
420
421 if ( deltaY > 0.5*kCarTolerance )
422 {
423 G4int maxcount = 10;
424 G4int l;
425 G4double lastdeltaY = deltaY;
426 for (l=0; l<maxcount; ++l)
427 {
428 G4ThreeVector surfacenormal = GetNormal(xxonsurface);
429 distance[k] = DistanceToPlaneWithV(p, v, xxonsurface,
430 surfacenormal, xx[k]);
431 deltaY = (xx[k] - xxonsurface).mag();
432 if (deltaY > lastdeltaY) { } // ???
433 gxx[k] = ComputeGlobalPoint(xx[k]);
434
435 if (deltaY <= 0.5*kCarTolerance) { break; }
436 xxonsurface.set(xx[k].x(),
437 fKappa * std::fabs(xx[k].x()) * xx[k].z(),
438 xx[k].z());
439 }
440 if (l == maxcount)
441 {
442 std::ostringstream message;
443 message << "Exceeded maxloop count!" << G4endl
444 << " maxloop count " << maxcount;
445 G4Exception("G4TwistTubsFlatSide::DistanceToSurface(p,v)",
446 "GeomSolids0003", FatalException, message);
447 }
448 }
449 }
450 vout = 2;
451 }
452 else
453 {
454 // if D<0, no solution
455 // if D=0, just grazing the surfaces, return kInfinity
456
457 fCurStatWithV.SetCurrentStatus(0, gxx[0], distance[0], areacode[0],
458 isvalid[0], 0, validate, &gp, &gv);
459 }
460
461 return vout;
462}
463
464//=====================================================================
465//* DistanceToSurface -------------------------------------------------
466
468 G4ThreeVector gxx[],
469 G4double distance[],
470 G4int areacode[])
471{
472 fCurStat.ResetfDone(kDontValidate, &gp);
473 if (fCurStat.IsDone())
474 {
475 for (G4int i=0; i<fCurStat.GetNXX(); ++i)
476 {
477 gxx[i] = fCurStat.GetXX(i);
478 distance[i] = fCurStat.GetDistance(i);
479 areacode[i] = fCurStat.GetAreacode(i);
480 }
481 return fCurStat.GetNXX();
482 }
483
484 // initialize
485 for (auto i=0; i<2; ++i)
486 {
487 distance[i] = kInfinity;
488 areacode[i] = sOutside;
489 gxx[i].set(kInfinity, kInfinity, kInfinity);
490 }
491
492 const G4double halftol = 0.5 * kCarTolerance;
493
495 G4ThreeVector xx;
496 G4int parity = (fKappa >= 0 ? 1 : -1);
497
498 //
499 // special case!
500 // If p is on surface, or
501 // p is on z-axis,
502 // return here immediatery.
503 //
504
505 G4ThreeVector lastgxx[2];
506 for (auto i=0; i<2; ++i)
507 {
508 lastgxx[i] = fCurStatWithV.GetXX(i);
509 }
510
511 if ((gp - lastgxx[0]).mag() < halftol
512 || (gp - lastgxx[1]).mag() < halftol)
513 {
514 // last winner, or last poststep point is on the surface.
515 xx = p;
516 distance[0] = 0;
517 gxx[0] = gp;
518
519 G4bool isvalid = true;
520 fCurStat.SetCurrentStatus(0, gxx[0], distance[0], areacode[0],
521 isvalid, 1, kDontValidate, &gp);
522 return 1;
523 }
524
525 if (p.getRho() == 0)
526 {
527 // p is on z-axis. Namely, p is on twisted surface (invalid area).
528 // We must return here, however, returning distance to x-minimum
529 // boundary is better than return 0-distance.
530 //
531 G4bool isvalid = true;
532 if (fAxis[0] == kXAxis && fAxis[1] == kZAxis)
533 {
534 distance[0] = DistanceToBoundary(sAxis0 & sAxisMin, xx, p);
535 areacode[0] = sInside;
536 }
537 else
538 {
539 distance[0] = 0;
540 xx.set(0., 0., 0.);
541 }
542 gxx[0] = ComputeGlobalPoint(xx);
543 fCurStat.SetCurrentStatus(0, gxx[0], distance[0], areacode[0],
544 isvalid, 0, kDontValidate, &gp);
545 return 1;
546 }
547
548 //
549 // special case end
550 //
551
552 // set corner points of quadrangle try area ...
553
554 G4ThreeVector A; // foot of normal from p to boundary of sAxis0 & sAxisMin
555 G4ThreeVector C; // foot of normal from p to boundary of sAxis0 & sAxisMax
556 G4ThreeVector B; // point on boundary sAxis0 & sAxisMax at z = A.z()
557 G4ThreeVector D; // point on boundary sAxis0 & sAxisMin at z = C.z()
558
559 // G4double distToA; // distance from p to A
561 // G4double distToC; // distance from p to C
563
564 // is p.z between a.z and c.z?
565 // p.z must be bracketed a.z and c.z.
566 if (A.z() > C.z())
567 {
568 if (p.z() > A.z())
569 {
571 }
572 else if (p.z() < C.z())
573 {
575 }
576 }
577 else
578 {
579 if (p.z() > C.z())
580 {
582 }
583 else if (p.z() < A.z())
584 {
586 }
587 }
588
589 G4ThreeVector d[2]; // direction vectors of boundary
590 G4ThreeVector x0[2]; // foot of normal from line to p
591 G4int btype[2]; // boundary type
592
593 for (auto i=0; i<2; ++i)
594 {
595 if (i == 0)
596 {
597 GetBoundaryParameters((sAxis0 & sAxisMax), d[i], x0[i], btype[i]);
598 B = x0[i] + ((A.z() - x0[i].z()) / d[i].z()) * d[i];
599 // x0 + t*d , d is direction unit vector.
600 }
601 else
602 {
603 GetBoundaryParameters((sAxis0 & sAxisMin), d[i], x0[i], btype[i]);
604 D = x0[i] + ((C.z() - x0[i].z()) / d[i].z()) * d[i];
605 }
606 }
607
608 // In order to set correct diagonal, swap A and D, C and B if needed.
609 G4ThreeVector pt(p.x(), p.y(), 0.);
610 G4double rc = std::fabs(p.x());
611 G4ThreeVector surfacevector(rc, rc * fKappa * p.z(), 0.);
612 G4int pside = AmIOnLeftSide(pt, surfacevector);
613 G4double test = (A.z() - C.z()) * parity * pside;
614
615 if (test == 0)
616 {
617 if (pside == 0)
618 {
619 // p is on surface.
620 xx = p;
621 distance[0] = 0;
622 gxx[0] = gp;
623
624 G4bool isvalid = true;
625 fCurStat.SetCurrentStatus(0, gxx[0], distance[0], areacode[0],
626 isvalid, 1, kDontValidate, &gp);
627 return 1;
628 }
629
630 // A.z = C.z(). return distance to line.
631 d[0] = C - A;
632 distance[0] = DistanceToLine(p, A, d[0], xx);
633 areacode[0] = sInside;
634 gxx[0] = ComputeGlobalPoint(xx);
635 G4bool isvalid = true;
636 fCurStat.SetCurrentStatus(0, gxx[0], distance[0], areacode[0],
637 isvalid, 1, kDontValidate, &gp);
638 return 1;
639 }
640 if (test < 0) // wrong diagonal. vector AC is crossing the surface!
641 { // swap A and D, C and B
642 G4ThreeVector tmp;
643 tmp = A;
644 A = D;
645 D = tmp;
646 tmp = C;
647 C = B;
648 B = tmp;
649 }
650 // else, correct diagonal. nothing to do.
651
652 // Now, we chose correct diagonal.
653 // First try. divide quadrangle into double triangle by diagonal and
654 // calculate distance to both surfaces.
655
656 G4ThreeVector xxacb; // foot of normal from plane ACB to p
657 G4ThreeVector nacb; // normal of plane ACD
658 G4ThreeVector xxcad; // foot of normal from plane CAD to p
659 G4ThreeVector ncad; // normal of plane CAD
660 G4ThreeVector AB(A.x(), A.y(), 0);
661 G4ThreeVector DC(C.x(), C.y(), 0);
662
663 G4double distToACB = G4VTwistSurface::DistanceToPlane(p, A, C-A, AB,
664 xxacb, nacb) * parity;
665 G4double distToCAD = G4VTwistSurface::DistanceToPlane(p, C, C-A, DC,
666 xxcad, ncad) * parity;
667 // if calculated distance = 0, return
668
669 if (std::fabs(distToACB) <= halftol || std::fabs(distToCAD) <= halftol)
670 {
671 xx = (std::fabs(distToACB) < std::fabs(distToCAD) ? xxacb : xxcad);
672 areacode[0] = sInside;
673 gxx[0] = ComputeGlobalPoint(xx);
674 distance[0] = 0;
675 G4bool isvalid = true;
676 fCurStat.SetCurrentStatus(0, gxx[0], distance[0] , areacode[0],
677 isvalid, 1, kDontValidate, &gp);
678 return 1;
679 }
680
681 if (distToACB * distToCAD > 0 && distToACB < 0)
682 {
683 // both distToACB and distToCAD are negative.
684 // divide quadrangle into double triangle by diagonal
685 G4ThreeVector normal;
686 distance[0] = DistanceToPlane(p, A, B, C, D, parity, xx, normal);
687 }
688 else
689 {
690 if (distToACB * distToCAD > 0)
691 {
692 // both distToACB and distToCAD are positive.
693 // Take smaller one.
694 if (distToACB <= distToCAD)
695 {
696 distance[0] = distToACB;
697 xx = xxacb;
698 }
699 else
700 {
701 distance[0] = distToCAD;
702 xx = xxcad;
703 }
704 }
705 else
706 {
707 // distToACB * distToCAD is negative.
708 // take positive one
709 if (distToACB > 0)
710 {
711 distance[0] = distToACB;
712 xx = xxacb;
713 }
714 else
715 {
716 distance[0] = distToCAD;
717 xx = xxcad;
718 }
719 }
720 }
721 areacode[0] = sInside;
722 gxx[0] = ComputeGlobalPoint(xx);
723 G4bool isvalid = true;
724 fCurStat.SetCurrentStatus(0, gxx[0], distance[0], areacode[0],
725 isvalid, 1, kDontValidate, &gp);
726 return 1;
727}
728
729//=====================================================================
730//* DistanceToPlane ---------------------------------------------------
731
732G4double G4TwistTubsSide::DistanceToPlane(const G4ThreeVector& p,
733 const G4ThreeVector& A,
734 const G4ThreeVector& B,
735 const G4ThreeVector& C,
736 const G4ThreeVector& D,
737 const G4int parity,
738 G4ThreeVector& xx,
739 G4ThreeVector& n)
740{
741 const G4double halftol = 0.5 * kCarTolerance;
742
743 G4ThreeVector M = 0.5*(A + B);
744 G4ThreeVector N = 0.5*(C + D);
745 G4ThreeVector xxanm; // foot of normal from p to plane ANM
746 G4ThreeVector nanm; // normal of plane ANM
747 G4ThreeVector xxcmn; // foot of normal from p to plane CMN
748 G4ThreeVector ncmn; // normal of plane CMN
749
750 G4double distToanm = G4VTwistSurface::DistanceToPlane(p, A, (N - A), (M - A),
751 xxanm, nanm) * parity;
752 G4double distTocmn = G4VTwistSurface::DistanceToPlane(p, C, (M - C), (N - C),
753 xxcmn, ncmn) * parity;
754#ifdef G4SPECSDEBUG
755 // if p is behind of both surfaces, abort.
756 if (distToanm * distTocmn > 0 && distToanm < 0)
757 {
758 G4Exception("G4TwistTubsSide::DistanceToPlane()",
759 "GeomSolids0003", FatalException,
760 "Point p is behind the surfaces.");
761 }
762#endif
763 // if p is on surface, return 0.
764 if (std::fabs(distToanm) <= halftol)
765 {
766 xx = xxanm;
767 n = nanm * parity;
768 return 0;
769 }
770 if (std::fabs(distTocmn) <= halftol)
771 {
772 xx = xxcmn;
773 n = ncmn * parity;
774 return 0;
775 }
776
777 if (distToanm <= distTocmn)
778 {
779 if (distToanm > 0)
780 {
781 // both distanses are positive. take smaller one.
782 xx = xxanm;
783 n = nanm * parity;
784 return distToanm;
785 }
786 // take -ve distance and call the function recursively.
787 return DistanceToPlane(p, A, M, N, D, parity, xx, n);
788 }
789
790 if (distTocmn > 0)
791 {
792 // both distanses are positive. take smaller one.
793 xx = xxcmn;
794 n = ncmn * parity;
795 return distTocmn;
796 }
797 // take -ve distance and call the function recursively.
798 return DistanceToPlane(p, C, N, M, B, parity, xx, n);
799}
800
801//=====================================================================
802//* GetAreaCode -------------------------------------------------------
803
804G4int G4TwistTubsSide::GetAreaCode(const G4ThreeVector& xx,
805 G4bool withTol)
806{
807 // We must use the function in local coordinate system.
808 // See the description of DistanceToSurface(p,v).
809
810 const G4double ctol = 0.5 * kCarTolerance;
811 G4int areacode = sInside;
812
813 if (fAxis[0] == kXAxis && fAxis[1] == kZAxis)
814 {
815 G4int xaxis = 0;
816 G4int zaxis = 1;
817
818 if (withTol)
819 {
820 G4bool isoutside = false;
821
822 // test boundary of xaxis
823
824 if (xx.x() < fAxisMin[xaxis] + ctol)
825 {
826 areacode |= (sAxis0 & (sAxisX | sAxisMin)) | sBoundary;
827 if (xx.x() <= fAxisMin[xaxis] - ctol) { isoutside = true; }
828 }
829 else if (xx.x() > fAxisMax[xaxis] - ctol)
830 {
831 areacode |= (sAxis0 & (sAxisX | sAxisMax)) | sBoundary;
832 if (xx.x() >= fAxisMax[xaxis] + ctol) { isoutside = true; }
833 }
834
835 // test boundary of z-axis
836
837 if (xx.z() < fAxisMin[zaxis] + ctol)
838 {
839 areacode |= (sAxis1 & (sAxisZ | sAxisMin));
840
841 if ((areacode & sBoundary) != 0)
842 {
843 areacode |= sCorner; // xx is on corner
844 }
845 else
846 {
847 areacode |= sBoundary;
848 }
849 if (xx.z() <= fAxisMin[zaxis] - ctol) { isoutside = true; }
850 }
851 else if (xx.z() > fAxisMax[zaxis] - ctol)
852 {
853 areacode |= (sAxis1 & (sAxisZ | sAxisMax));
854
855 if ((areacode & sBoundary) != 0)
856 {
857 areacode |= sCorner; // xx is on corner
858 }
859 else
860 {
861 areacode |= sBoundary;
862 }
863 if (xx.z() >= fAxisMax[zaxis] + ctol)
864 {
865 isoutside = true;
866 }
867 }
868
869 // if isoutside = true, clear inside bit.
870 // if not on boundary, add axis information.
871
872 if (isoutside)
873 {
874 G4int tmpareacode = areacode & (~sInside);
875 areacode = tmpareacode;
876 }
877 else if ((areacode & sBoundary) != sBoundary)
878 {
879 areacode |= (sAxis0 & sAxisX) | (sAxis1 & sAxisZ);
880 }
881 }
882 else
883 {
884 // boundary of x-axis
885
886 if (xx.x() < fAxisMin[xaxis] )
887 {
888 areacode |= (sAxis0 & (sAxisX | sAxisMin)) | sBoundary;
889 }
890 else if (xx.x() > fAxisMax[xaxis])
891 {
892 areacode |= (sAxis0 & (sAxisX | sAxisMax)) | sBoundary;
893 }
894
895 // boundary of z-axis
896
897 if (xx.z() < fAxisMin[zaxis])
898 {
899 areacode |= (sAxis1 & (sAxisZ | sAxisMin));
900 if ((areacode & sBoundary) != 0)
901 {
902 areacode |= sCorner; // xx is oncorner
903 }
904 else
905 {
906 areacode |= sBoundary;
907 }
908 }
909 else if (xx.z() > fAxisMax[zaxis])
910 {
911 areacode |= (sAxis1 & (sAxisZ | sAxisMax)) ;
912 if ((areacode & sBoundary) != 0)
913 {
914 areacode |= sCorner; // xx is on corner
915 }
916 else
917 {
918 areacode |= sBoundary;
919 }
920 }
921
922 if ((areacode & sBoundary) != sBoundary)
923 {
924 areacode |= (sAxis0 & sAxisX) | (sAxis1 & sAxisZ);
925 }
926 }
927 return areacode;
928 }
929
930 G4Exception("G4TwistTubsSide::GetAreaCode()",
931 "GeomSolids0001", FatalException,
932 "Feature NOT implemented !");
933
934 return areacode;
935}
936
937//=====================================================================
938//* SetCorners( arglist ) -------------------------------------------------
939
940void G4TwistTubsSide::SetCorners( G4double endInnerRad[2],
941 G4double endOuterRad[2],
942 G4double endPhi[2],
943 G4double endZ[2] )
944{
945 // Set Corner points in local coodinate.
946
947 if (fAxis[0] == kXAxis && fAxis[1] == kZAxis)
948 {
949 G4int zmin = 0 ; // at -ve z
950 G4int zmax = 1 ; // at +ve z
951
952 G4double x, y, z;
953
954 // corner of Axis0min and Axis1min
955 x = endInnerRad[zmin]*std::cos(endPhi[zmin]);
956 y = endInnerRad[zmin]*std::sin(endPhi[zmin]);
957 z = endZ[zmin];
958 SetCorner(sC0Min1Min, x, y, z);
959
960 // corner of Axis0max and Axis1min
961 x = endOuterRad[zmin]*std::cos(endPhi[zmin]);
962 y = endOuterRad[zmin]*std::sin(endPhi[zmin]);
963 z = endZ[zmin];
964 SetCorner(sC0Max1Min, x, y, z);
965
966 // corner of Axis0max and Axis1max
967 x = endOuterRad[zmax]*std::cos(endPhi[zmax]);
968 y = endOuterRad[zmax]*std::sin(endPhi[zmax]);
969 z = endZ[zmax];
970 SetCorner(sC0Max1Max, x, y, z);
971
972 // corner of Axis0min and Axis1max
973 x = endInnerRad[zmax]*std::cos(endPhi[zmax]);
974 y = endInnerRad[zmax]*std::sin(endPhi[zmax]);
975 z = endZ[zmax];
976 SetCorner(sC0Min1Max, x, y, z);
977
978 }
979 else
980 {
981 std::ostringstream message;
982 message << "Feature NOT implemented !" << G4endl
983 << " fAxis[0] = " << fAxis[0] << G4endl
984 << " fAxis[1] = " << fAxis[1];
985 G4Exception("G4TwistTubsSide::SetCorners()",
986 "GeomSolids0001", FatalException, message);
987 }
988}
989
990//=====================================================================
991//* SetCorners() ------------------------------------------------------
992
993void G4TwistTubsSide::SetCorners()
994{
995 G4Exception("G4TwistTubsSide::SetCorners()",
996 "GeomSolids0001", FatalException,
997 "Method NOT implemented !");
998}
999
1000//=====================================================================
1001//* SetBoundaries() ---------------------------------------------------
1002
1003void G4TwistTubsSide::SetBoundaries()
1004{
1005 // Set direction-unit vector of boundary-lines in local coodinate.
1006 //
1007 G4ThreeVector direction;
1008
1009 if (fAxis[0] == kXAxis && fAxis[1] == kZAxis)
1010 {
1011 // sAxis0 & sAxisMin
1012 direction = GetCorner(sC0Min1Max) - GetCorner(sC0Min1Min);
1013 direction = direction.unit();
1014 SetBoundary(sAxis0 & (sAxisX | sAxisMin), direction,
1016
1017 // sAxis0 & sAxisMax
1018 direction = GetCorner(sC0Max1Max) - GetCorner(sC0Max1Min);
1019 direction = direction.unit();
1020 SetBoundary(sAxis0 & (sAxisX | sAxisMax), direction,
1022
1023 // sAxis1 & sAxisMin
1024 direction = GetCorner(sC0Max1Min) - GetCorner(sC0Min1Min);
1025 direction = direction.unit();
1026 SetBoundary(sAxis1 & (sAxisZ | sAxisMin), direction,
1028
1029 // sAxis1 & sAxisMax
1030 direction = GetCorner(sC0Max1Max) - GetCorner(sC0Min1Max);
1031 direction = direction.unit();
1032 SetBoundary(sAxis1 & (sAxisZ | sAxisMax), direction,
1034
1035 }
1036 else
1037 {
1038 std::ostringstream message;
1039 message << "Feature NOT implemented !" << G4endl
1040 << " fAxis[0] = " << fAxis[0] << G4endl
1041 << " fAxis[1] = " << fAxis[1];
1042 G4Exception("G4TwistTubsSide::SetCorners()",
1043 "GeomSolids0001", FatalException, message);
1044 }
1045}
1046
1047//=====================================================================
1048//* GetFacets() -------------------------------------------------------
1049
1050void G4TwistTubsSide::GetFacets( G4int k, G4int n, G4double xyz[][3],
1051 G4int faces[][4], G4int iside )
1052{
1053 G4double z ; // the two parameters for the surface equation
1054 G4double x,xmin,xmax ;
1055
1056 G4ThreeVector p ; // a point on the surface, given by (z,u)
1057
1058 G4int nnode ;
1059 G4int nface ;
1060
1061 // calculate the (n-1)*(k-1) vertices
1062
1063 for ( G4int i = 0 ; i<n ; ++i )
1064 {
1065 z = fAxisMin[1] + i*(fAxisMax[1]-fAxisMin[1])/(n-1) ;
1066
1067 for ( G4int j = 0 ; j<k ; ++j )
1068 {
1069 nnode = GetNode(i,j,k,n,iside) ;
1070
1071 xmin = GetBoundaryMin(z) ;
1072 xmax = GetBoundaryMax(z) ;
1073
1074 if (fHandedness < 0)
1075 {
1076 x = xmin + j*(xmax-xmin)/(k-1) ;
1077 }
1078 else
1079 {
1080 x = xmax - j*(xmax-xmin)/(k-1) ;
1081 }
1082
1083 p = SurfacePoint(x,z,true) ; // surface point in global coord.system
1084
1085 xyz[nnode][0] = p.x() ;
1086 xyz[nnode][1] = p.y() ;
1087 xyz[nnode][2] = p.z() ;
1088
1089 if ( i<n-1 && j<k-1 ) // clock wise filling
1090 {
1091 nface = GetFace(i,j,k,n,iside) ;
1092
1093 faces[nface][0] = GetEdgeVisibility(i,j,k,n,0,1)
1094 * ( GetNode(i ,j ,k,n,iside)+1) ;
1095 faces[nface][1] = GetEdgeVisibility(i,j,k,n,1,1)
1096 * ( GetNode(i+1,j ,k,n,iside)+1) ;
1097 faces[nface][2] = GetEdgeVisibility(i,j,k,n,2,1)
1098 * ( GetNode(i+1,j+1,k,n,iside)+1) ;
1099 faces[nface][3] = GetEdgeVisibility(i,j,k,n,3,1)
1100 * ( GetNode(i ,j+1,k,n,iside)+1) ;
1101 }
1102 }
1103 }
1104}
const G4double kCarTolerance
G4double C(G4double temp)
G4double B(G4double temperature)
G4double D(G4double temp)
@ FatalException
@ FatalErrorInArgument
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *description)
#define M(row, col)
CLHEP::HepRotation G4RotationMatrix
CLHEP::Hep3Vector G4ThreeVector
double G4double
Definition G4Types.hh:83
bool G4bool
Definition G4Types.hh:86
int G4int
Definition G4Types.hh:85
const G4double A[17]
#define G4endl
Definition G4ios.hh:67
double z() const
Hep3Vector unit() const
double x() const
double y() const
Hep3Vector cross(const Hep3Vector &) const
double getRho() const
void set(double x, double y, double z)
G4ThreeVector GetNormal(const G4ThreeVector &p, G4bool isGlobal=false) override
G4TwistTubsSide(const G4String &name, const G4RotationMatrix &rot, const G4ThreeVector &tlate, G4int handedness, const G4double kappa, const EAxis axis0=kXAxis, const EAxis axis1=kZAxis, G4double axis0min=-kInfinity, G4double axis1min=-kInfinity, G4double axis0max=kInfinity, G4double axis1max=kInfinity)
G4int DistanceToSurface(const G4ThreeVector &gp, const G4ThreeVector &gv, G4ThreeVector gxx[], G4double distance[], G4int areacode[], G4bool isvalid[], EValidate validate=kValidateWithTol) override
virtual G4int AmIOnLeftSide(const G4ThreeVector &me, const G4ThreeVector &vec, G4bool withTol=true)
static const G4int sC0Min1Min
static const G4int sC0Min1Max
G4VTwistSurface(const G4String &name)
G4double DistanceToPlane(const G4ThreeVector &p, const G4ThreeVector &x0, const G4ThreeVector &n0, G4ThreeVector &xx)
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)
G4RotationMatrix fRot
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 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
virtual G4double DistanceToBoundary(G4int areacode, G4ThreeVector &xx, const G4ThreeVector &p)
static const G4int sCorner
static const G4int sC0Max1Min
static const G4int sInside
CurrentStatus fCurStatWithV
static const G4int sAxisX
G4double DistanceToPlaneWithV(const G4ThreeVector &p, const G4ThreeVector &v, const G4ThreeVector &x0, const G4ThreeVector &n0, G4ThreeVector &xx)
G4ThreeVector ComputeGlobalPoint(const G4ThreeVector &lp) const
G4SurfCurNormal fCurrentNormal
virtual void GetBoundaryParameters(const G4int &areacode, G4ThreeVector &d, G4ThreeVector &x0, G4int &boundarytype) const
CurrentStatus fCurStat
#define N
Definition crc32.c:57
EAxis
Definition geomdefs.hh:54
@ kXAxis
Definition geomdefs.hh:55
@ kZAxis
Definition geomdefs.hh:57
#define DBL_MIN
Definition templates.hh:54