Belle II Software development
BelleLathe Class Reference

BelleLathe class. More...

#include <BelleLathe.h>

Inheritance diagram for BelleLathe:

Public Member Functions

 BelleLathe (const G4String &pName)
 Constructor for "nominal" BelleLathe whose parameters are to be set by a G4VPVParamaterisation later.
 
 BelleLathe (const G4String &pName, double phi0, double dphi, int n, double *z, double *rin, double *rout)
 explicit constructor
 
 BelleLathe (const G4String &pName, double, double, const std::vector< zr_t > &)
 explicit constructor
 
virtual ~BelleLathe ()
 Destructor.
 
void ComputeDimensions (G4VPVParameterisation *p, const G4int n, const G4VPhysicalVolume *pRep)
 compute the dimensions
 
G4bool CalculateExtent (const EAxis pAxis, const G4VoxelLimits &pVoxelLimit, const G4AffineTransform &pTransform, G4double &pMin, G4double &pMax) const
 calculate the extent of the volume
 
EInside Inside (const G4ThreeVector &p) const
 Return whether point inside/outside/on surface, using tolerance.
 
G4ThreeVector SurfaceNormal (const G4ThreeVector &p) const
 Calculate side nearest to p, and return normal.
 
G4double DistanceToIn (const G4ThreeVector &p, const G4ThreeVector &v) const
 Calculate distance to shape from outside - return kInfinity if no intersection.
 
G4double DistanceToIn (const G4ThreeVector &p) const
 Calculate exact shortest distance to any boundary from outside.
 
G4double DistanceToOut (const G4ThreeVector &p, const G4ThreeVector &v, const G4bool calcNorm=false, G4bool *validNorm=0, G4ThreeVector *n=0) const
 Calculate distance to surface of shape from inside.
 
G4double DistanceToOut (const G4ThreeVector &p) const
 Calculate exact shortest distance to any boundary from inside.
 
G4GeometryType GetEntityType () const
 Get entity type.
 
G4ThreeVector GetPointOnSurface () const
 Get point on surface.
 
G4double GetCubicVolume ()
 Get cubic volume.
 
G4double GetSurfaceArea ()
 Get surface area.
 
G4VSolid * Clone () const
 Make a clone of the object.
 
void BoundingLimits (G4ThreeVector &pMin, G4ThreeVector &pMax) const
 Two vectors define an axis-parallel bounding box for the shape.
 
std::ostream & StreamInfo (std::ostream &os) const
 Stream object contents to an output stream.
 
void DescribeYourselfTo (G4VGraphicsScene &scene) const
 Visualisation function.
 
G4Polyhedron * CreatePolyhedron () const
 create polyhedron
 
 BelleLathe (__void__ &)
 Fake default constructor for usage restricted to direct object persistency for clients requiring preallocation of memory for persistifiable objects.
 
 BelleLathe (const BelleLathe &rhs)
 copy constructor
 
BelleLatheoperator= (const BelleLathe &rhs)
 assignment operator
 

Protected Member Functions

bool insector (double, double) const
 True if (x,y) is within the shape rotation.
 
int wn_poly (const zr_t &) const
 wn_poly
 
double mindist (const zr_t &) const
 minimal distance
 
std::vector< double > linecross (const G4ThreeVector &, const G4ThreeVector &) const
 calculate all ray solid's surface intersection return ordered vector
 
void eartrim () const
 ear trim
 
zr_t normal (const zr_t &, double &) const
 return normal
 
void getvolarea ()
 get volume area
 
void Init (const std::vector< zr_t > &, double, double)
 initialize
 

Private Attributes

std::vector< zr_tfcontour
 vector of zr structs
 
std::vector< cachezr_tfcache
 vector of cached zr structs
 
std::vector< double > fz
 vector of z values
 
std::vector< int > findx
 vector of indices
 
std::vector< int > fseg
 vector of segments
 
std::vector< double > farea
 vector of area values
 
std::vector< triangle_tftlist
 vector of triangle structs
 
double fphi = 0.0
 starting angle
 
double fdphi = 0.0
 finishing angle
 
double fs0 = 0.0
 fs0
 
double fc0 = 0.0
 fc0
 
double fs1 = 0.0
 fs1
 
double fc1 = 0.0
 fc1
 
double fn0x = 0.0
 fn0x
 
double fn0y = 0.0
 fn0y
 
double fn1x = 0.0
 fn1x
 
double fn1y = 0.0
 fn1y
 
double frmin = 0.0
 minimal r value
 
double frmax = 0.0
 maximal r value
 
double fzmin = 0.0
 minimal z value
 
double fzmax = 0.0
 maximal z value
 
bool fgtpi
 greater than pi?
 
bool ftwopi
 bound within +- 2pi?
 
G4VSolid * fshape = nullptr
 shape
 
std::vector< G4ThreeVector > fsurf
 vector of surfaces
 

Detailed Description

BelleLathe class.

Definition at line 67 of file BelleLathe.h.

Constructor & Destructor Documentation

◆ BelleLathe() [1/5]

BelleLathe ( const G4String & pName)
explicit

Constructor for "nominal" BelleLathe whose parameters are to be set by a G4VPVParamaterisation later.

Definition at line 269 of file BelleLathe.cc.

270 : G4CSGSolid(pName)
271{
272 vector<zr_t> a;
273 Init(a, 0, 2 * M_PI);
274}
void Init(const std::vector< zr_t > &, double, double)
initialize

◆ BelleLathe() [2/5]

BelleLathe ( const G4String & pName,
double phi0,
double dphi,
int n,
double * z,
double * rin,
double * rout )

explicit constructor

Definition at line 85 of file BelleLathe.cc.

86 : G4CSGSolid(pName)
87{
88 vector<zr_t> contour;
89 for (int i = 0; i < n; i++) {
90 zr_t t = {z[i], rin[i]};
91 contour.push_back(t);
92 }
93 for (int i = n - 1; i >= 0; i--) {
94 zr_t t = {z[i], rout[i]};
95 contour.push_back(t);
96 }
97
98 Init(contour, phi0, dphi);
99}

◆ BelleLathe() [3/5]

BelleLathe ( const G4String & pName,
double phi0,
double dphi,
const std::vector< zr_t > & c )

explicit constructor

Definition at line 79 of file BelleLathe.cc.

80 : G4CSGSolid(pName)
81{
82 Init(c, phi0, dphi);
83}

◆ ~BelleLathe()

~BelleLathe ( )
virtual

Destructor.

Definition at line 286 of file BelleLathe.cc.

287{
288#if PERFCOUNTER==1
289 cout << GetName() << " ";
290 for (int i = 0; i < 6; i++) cout << counterl[GetName()][i] << " "; cout << endl;
291#endif
292}

◆ BelleLathe() [4/5]

BelleLathe ( __void__ & a)
explicit

Fake default constructor for usage restricted to direct object persistency for clients requiring preallocation of memory for persistifiable objects.

Definition at line 278 of file BelleLathe.cc.

279 : G4CSGSolid(a)
280{
281 vector<zr_t> b;
282 Init(b, 0, 2 * M_PI);
283}

◆ BelleLathe() [5/5]

BelleLathe ( const BelleLathe & rhs)

copy constructor

Definition at line 295 of file BelleLathe.cc.

296 : G4CSGSolid(rhs), fcontour(rhs.fcontour), fcache(rhs.fcache), fz(rhs.fz),
297 findx(rhs.findx), fseg(rhs.fseg), farea(rhs.farea), ftlist(rhs.ftlist),
298 fphi(rhs.fphi), fdphi(rhs.fdphi), fs0(rhs.fs0), fc0(rhs.fc0), fs1(rhs.fs1),
299 fc1(rhs.fc1), fn0x(rhs.fn0x), fn0y(rhs.fn0y), fn1x(rhs.fn1x), fn1y(rhs.fn1y),
300 frmin(rhs.frmin), frmax(rhs.frmax), fzmin(rhs.fzmin), fzmax(rhs.fzmax),
301 fgtpi(rhs.fgtpi), ftwopi(rhs.ftwopi), fshape(rhs.fshape), fsurf(rhs.fsurf)
302{
303}
double fzmax
maximal z value
Definition BelleLathe.h:192
double fphi
starting angle
Definition BelleLathe.h:179
std::vector< double > fz
vector of z values
Definition BelleLathe.h:173
std::vector< int > findx
vector of indices
Definition BelleLathe.h:174
std::vector< triangle_t > ftlist
vector of triangle structs
Definition BelleLathe.h:177
bool ftwopi
bound within +- 2pi?
Definition BelleLathe.h:194
std::vector< double > farea
vector of area values
Definition BelleLathe.h:176
std::vector< int > fseg
vector of segments
Definition BelleLathe.h:175
G4VSolid * fshape
shape
Definition BelleLathe.h:196
double fdphi
finishing angle
Definition BelleLathe.h:180
std::vector< zr_t > fcontour
vector of zr structs
Definition BelleLathe.h:171
bool fgtpi
greater than pi?
Definition BelleLathe.h:193
std::vector< cachezr_t > fcache
vector of cached zr structs
Definition BelleLathe.h:172
double fzmin
minimal z value
Definition BelleLathe.h:191
double frmax
maximal r value
Definition BelleLathe.h:190
double frmin
minimal r value
Definition BelleLathe.h:189
std::vector< G4ThreeVector > fsurf
vector of surfaces
Definition BelleLathe.h:197

Member Function Documentation

◆ BoundingLimits()

void BoundingLimits ( G4ThreeVector & pMin,
G4ThreeVector & pMax ) const

Two vectors define an axis-parallel bounding box for the shape.

Definition at line 1857 of file BelleLathe.cc.

1858{
1859 std::vector<vector_t> points;
1860 vector_t point{};
1861
1862 // Placeholder vectors
1863 const double inf = std::numeric_limits<double>::infinity();
1864 G4ThreeVector minimum(inf, inf, inf), maximum(-inf, -inf, -inf);
1865
1866 // Outer vertices
1867 if (fdphi < 2 * M_PI) { // Only axis-crossings are relevant if the shape is a full circle
1868 point.x = frmax * cos(fphi); point.y = frmax * sin(fphi);
1869 points.push_back(point);
1870 point.x = frmax * cos(fphi + fdphi); point.y = frmax * sin(fphi + fdphi);
1871 points.push_back(point);
1872 }
1873
1874 // Inner vertices
1875 point.x = frmin * cos(fphi); point.y = frmin * sin(fphi);
1876 points.push_back(point);
1877 if (frmin != 0) { // Avoid duplicate (0,0)
1878 point.x = frmin * cos(fphi + fdphi); point.y = frmin * sin(fphi + fdphi);
1879 points.push_back(point);
1880 }
1881
1882 // Check if shape crosses an axis
1883 // Because the inside is concave, extremums will always be at vertices
1884 // Because the outside is convex, extremums may be at an axis-crossing
1885 if (insector(0, 1)) {
1886 point.x = 0; point.y = frmax;
1887 points.push_back(point);
1888 }
1889 if (insector(-1, 0)) {
1890 point.x = -frmax; point.y = 0;
1891 points.push_back(point);
1892 }
1893 if (insector(0, -1)) {
1894 point.x = 0; point.y = -frmax;
1895 points.push_back(point);
1896 }
1897 if (insector(1, 0)) {
1898 point.x = frmax; point.y = 0;
1899 points.push_back(point);
1900 }
1901
1902 for (std::vector<vector_t>::size_type i = 0; i != points.size(); i++) {
1903 // global min in x
1904 if (points[i].x < minimum.x())
1905 minimum.setX(points[i].x);
1906
1907 // global min in y
1908 if (points[i].y < minimum.y())
1909 minimum.setY(points[i].y);
1910
1911 // global max in x
1912 if (points[i].x > maximum.x())
1913 maximum.setX(points[i].x);
1914
1915 // global max in y
1916 if (points[i].y > maximum.y())
1917 maximum.setY(points[i].y);
1918 }
1919
1920 // Set z extremum values
1921 minimum.setZ(fzmin);
1922 maximum.setZ(fzmax);
1923
1924 // Assign
1925 pMin = minimum;
1926 pMax = maximum;
1927}
bool insector(double, double) const
True if (x,y) is within the shape rotation.

◆ CalculateExtent()

G4bool CalculateExtent ( const EAxis pAxis,
const G4VoxelLimits & pVoxelLimit,
const G4AffineTransform & pTransform,
G4double & pMin,
G4double & pMax ) const

calculate the extent of the volume

Definition at line 515 of file BelleLathe.cc.

519{
520 auto maxdist = [this](const G4ThreeVector & n) -> G4ThreeVector {
521 G4ThreeVector r;
522 int i = 0, nsize = fcache.size();
523 if (ftwopi || insector(n.x(), n.y())) // n in sector
524 {
525 double nr = hypot(n.x(), n.y()), nz = n.z();
526 double dmax = -kInfinity, R = 0, Z = 0;
527 do {
528 const cachezr_t& s = fcache[i];
529 double d1 = nz * s.z + nr * s.r;
530 if (dmax < d1) { R = s.r; Z = s.z; dmax = d1;}
531 } while (++i < nsize);
532 if (nr > 0) {
533 R /= nr;
534 r.set(R * n.x(), R * n.y(), Z);
535 } else {
536 double phi = fphi + 0.5 * fdphi;
537 r.set(R * cos(phi), R * sin(phi), Z);
538 }
539 } else
540 {
541 double dmax = -kInfinity;
542 do {
543 const cachezr_t& s = fcache[i];
544 // check both sides
545 G4ThreeVector rf(-fn0y * s.r, fn0x * s.r, s.z), rl(fn1y * s.r, -fn1x * s.r, s.z);
546 double d0 = rf * n, d1 = rl * n;
547 // cout<<rf<<" "<<rl<<endl;
548 if (dmax < d0) { r = rf; dmax = d0;}
549 if (dmax < d1) { r = rl; dmax = d1;}
550 } while (++i < nsize);
551 }
552 return r;
553 };
554
555 struct seg_t {int i0, i1;};
556 auto clip = [](vector<G4ThreeVector>& vlist, vector<seg_t>& slist, const G4ThreeVector & n, double dist) {
557 vector<seg_t> snew;
558 vector<int> lone;
559
560 vector<double> d;
561 for (const G4ThreeVector& v : vlist) d.push_back(v * n + dist);
562
563 for (seg_t s : slist) {
564 double prod = d[s.i0] * d[s.i1];
565 // cout<<d[s.i0]<<" "<<d[s.i1]<<endl;
566 if (prod < 0) { // segment crosses plane - break it
567 G4ThreeVector rn = (vlist[s.i0] * d[s.i1] - vlist[s.i1] * d[s.i0]) * (1 / (d[s.i1] - d[s.i0]));
568 lone.push_back(vlist.size()); vlist.push_back(rn);
569 if (d[s.i0] < 0) {
570 s = {lone.back(), s.i1};
571 } else {
572 s = {s.i0, lone.back()};
573 }
574 } else if (prod == 0) { // segment end on plane
575 if (d[s.i0] == 0 && d[s.i1] > 0) {
576 lone.push_back(s.i0);
577 } else if (d[s.i0] > 0 && d[s.i1] == 0) {
578 lone.push_back(s.i1);
579 } else continue;
580 } else {
581 if (d[s.i0] < 0) continue; // segment below plane
582 }
583 snew.push_back(s);
584 }
585
586 double dmax = -1e99;
587 int imax = -1, jmax = -1;
588 // search for the most distant points on the clipping plane
589 for (unsigned int i = 0; i < lone.size(); i++) {
590 for (unsigned int j = i + 1; j < lone.size(); j++) {
591 double d2 = (vlist[lone[i]] - vlist[lone[j]]).mag2();
592 if (d2 > dmax) { imax = lone[i]; jmax = lone[j];}
593 }
594 }
595
596 // close the new polygon by creating new segments
597 if (imax >= 0) {
598 G4ThreeVector k = vlist[jmax] - vlist[imax];
599 sort(lone.begin(), lone.end(), [&k, &vlist, &imax](int i, int j) {return k * (vlist[i] - vlist[imax]) < k * (vlist[j] - vlist[imax]);});
600
601 for (unsigned int i = 0; i < lone.size(); i += 2) {
602 seg_t t = {lone[i], lone[i + 1]};
603 for (const seg_t& s : snew) {
604 if (t.i1 == s.i0) { snew.push_back(t); break;}
605 if (t.i0 == s.i0) { swap(t.i0, t.i1); snew.push_back(t); break;}
606 }
607 }
608 }
609 swap(slist, snew);
610 };
611
612 auto PhiCrossN = [this, clip](const vector<Plane_t>& planes) {
613 // unordered clipped phi-sides vertices within
614 // limiting planes
615 vector<G4ThreeVector> vlist; // vertex list
616 vector<seg_t> slist; // segment list
617 vector<G4ThreeVector> res;
618
619 int nsize = fcache.size();
620 vlist.reserve(nsize);
621 slist.reserve(nsize);
622 for (int iphi = 0; iphi < 2; iphi++) {
623 vlist.clear();
624 slist.clear();
625 // phi-side directional vector is (kx,ky)
626 double kx = iphi ? -fn0y : fn1y, ky = iphi ? fn0x : -fn1x;
627 do {
628 int i = 0;
629 do {
630 const cachezr_t& s = fcache[i];
631 G4ThreeVector r(kx * s.r, ky * s.r, s.z);
632 vlist.push_back(r);
633 seg_t t = {i, i + 1};
634 slist.push_back(t);
635 } while (++i < nsize - 1);
636 const cachezr_t& s = fcache[nsize - 1];
637 G4ThreeVector r(kx * s.r, ky * s.r, s.z);
638 vlist.push_back(r);
639 seg_t t = {nsize - 1, 0};
640 slist.push_back(t);
641 } while (0);
642
643 // clip phi-side polygon by limiting planes
644 for (const Plane_t& p : planes) {
645 // cout<<p.n<<" "<<p.d<<endl;
646 clip(vlist, slist, p.n, p.d);
647 // for(auto t:vlist) cout<<t<<" "; cout<<endl;
648 }
649 vector<bool> bv(vlist.size(), false);
650
651 for (vector<seg_t>::const_iterator it = slist.begin(); it != slist.end(); ++it) {
652 bv[(*it).i0] = true;
653 bv[(*it).i1] = true;
654 }
655
656 for (unsigned int i = 0; i < vlist.size(); i++) {
657 if (!bv[i]) continue;
658 res.push_back(vlist[i]);
659 }
660 }
661 return res;
662 };
663
664 auto RCross = [this](const G4ThreeVector & op, const G4ThreeVector & k, const G4ThreeVector & u) {
665 // plane with origin at op and normal vector n = [k x u], k and u are orthogonal k*u = 0
666 // plane equation r = t*k + s*u + op
667 vector<solution_t> ts;
668 int nsize = fcache.size();
669 int i = 0;
670 do {
671 const cachezr_t& seg = fcache[i];
672 // r0 -- cone radius at z0, c -- cone axis
673 // cone equation is (r0 + tg * ((r-c0)*c))^2 = (r-c0)^2 - ((r-c0)*c)^2
674 double r0 = seg.r, z0 = seg.z, tg = seg.ta;
675 double rtg = r0 * tg;
676
677 G4ThreeVector o(op.x(), op.y(), op.z() - z0);
678
679 double ko = k * o, uo = u * o, ck = k.z(), cu = u.z(), co = o.z();
680 double k2 = 1, u2 = 1, o2 = o * o;
681 double ck2 = ck * ck, cu2 = cu * cu;
682 double dr2 = r0 * r0 - o2;
683 if (seg.dz != 0.0) {
684 double tg2 = tg * tg, co2 = co * co;
685 double q0 = 1 + tg2;
686 double q1 = co * q0 + rtg;
687
688 double F00 = co2 * q0 + 2 * co * rtg + dr2;
689 double F10 = 2 * (ck * q1 - ko);
690 double F20 = ck2 * q0 - k2;
691 double F01 = 2 * (cu * q1 - uo);
692 double F11 = 2 * ck * cu * q0;
693 double F02 = cu2 * q0 - u2;
694
695 vector<solution_t> res = extremum(F02, F11, F20, F01, F10, F00);
696 for (const solution_t& r : res) {
697 double t = r.s, s = r.t;
698 G4ThreeVector p = t * k + s * u + op;
699 if (seg.zmin < p.z() && p.z() < seg.zmax) {
700 solution_t e = {t, s};
701 if (ftwopi || insector(p.x(), p.y()))
702 ts.push_back(e);
703 }
704 }
705 }
706 double a = -(ck2 * u2 + cu2 * k2);
707 if (a != 0) {
708 if (abs(cu) > abs(ck)) {
709 double b = 2 * (ck * (cu * uo - co * u2) - cu2 * ko);
710 double c = co * (2 * cu * uo - co * u2) + cu2 * dr2;
711 vector<double> tv = quadsolve(a, b, c);
712 for (double t : tv) {
713 double s = -(co + ck * t) / cu;
714 G4ThreeVector p = t * k + s * u + op;
715 if (ftwopi || insector(p.x(), p.y())) {
716 solution_t e = {t, s};
717 ts.push_back(e);
718 }
719 }
720 } else {
721 double b = 2 * (cu * (ck * ko - co * k2) - ck2 * uo);
722 double c = co * (2 * ck * ko - co * k2) + ck2 * dr2;
723 vector<double> sv = quadsolve(a, b, c);
724 for (double s : sv) {
725 double t = -(co + cu * s) / ck;
726 G4ThreeVector p = t * k + s * u + op;
727 if (ftwopi || insector(p.x(), p.y())) {
728 solution_t e = {t, s};
729 ts.push_back(e);
730 }
731 }
732 }
733 }
734 } while (++i < nsize);
735 return ts;
736 };
737
738 bool b1 = false, b2 = false;
739 G4ThreeVector n0, n1, n2;
740 switch (A) {
741 case kXAxis: n0.set(1, 0, 0); n1.set(0, 1, 0); n2.set(0, 0, 1); b1 = bb.IsYLimited(); b2 = bb.IsZLimited(); break;
742 case kYAxis: n0.set(0, 1, 0); n1.set(1, 0, 0); n2.set(0, 0, 1); b1 = bb.IsXLimited(); b2 = bb.IsZLimited(); break;
743 case kZAxis: n0.set(0, 0, 1); n1.set(1, 0, 0); n2.set(0, 1, 0); b1 = bb.IsXLimited(); b2 = bb.IsYLimited(); break;
744 default: break;
745 }
746
747 double dmin1 = -kInfinity, dmax1 = kInfinity;
748 if (b1) {
749 switch (A) {
750 case kXAxis: dmin1 = bb.GetMinYExtent(); dmax1 = bb.GetMaxYExtent(); break;
751 case kYAxis: dmin1 = bb.GetMinXExtent(); dmax1 = bb.GetMaxXExtent(); break;
752 case kZAxis: dmin1 = bb.GetMinXExtent(); dmax1 = bb.GetMaxXExtent(); break;
753 default: break;
754 }
755 }
756
757 double dmin2 = -kInfinity, dmax2 = kInfinity;
758 if (b2) {
759 switch (A) {
760 case kXAxis: dmin2 = bb.GetMinZExtent(); dmax2 = bb.GetMaxZExtent(); break;
761 case kYAxis: dmin2 = bb.GetMinZExtent(); dmax2 = bb.GetMaxZExtent(); break;
762 case kZAxis: dmin2 = bb.GetMinYExtent(); dmax2 = bb.GetMaxYExtent(); break;
763 default: break;
764 }
765 }
766
767 G4AffineTransform iT = T.Inverse();
768 // axis to solid coordinates
769 G4ThreeVector n0t = iT.TransformAxis(n0);
770 G4ThreeVector smin = n0t * kInfinity, smax = (-kInfinity) * n0t; // extremum points in solid coordinate system
771 double pmin = kInfinity, pmax = -pmin;
772 if (b1 && b2) {
773 G4ThreeVector corners[] = {n1* dmin1 + n2 * dmin2, n1* dmax1 + n2 * dmin2, n1* dmax1 + n2 * dmax2, n1* dmin1 + n2 * dmax2};
774 for (G4ThreeVector& c : corners) iT.ApplyPointTransform(c); // to solid coordinates
775
776 vector<Plane_t> planes;
777 for (int i = 0; i < 4; i++) {
778 const G4ThreeVector& c0 = corners[i], &c1 = corners[(i + 1) % 4];
779 vector<double> dists = linecross(c0, n0t);
780 // cout<<"c0 "<<c0<<endl;
781 for (double t : dists) {
782 G4ThreeVector p = n0t * t + c0;
783 double tt = t + c0 * n0t;
784 // cout<<p<<" "<<tt<<endl;
785 if (pmax < tt) { pmax = tt; smax = p;}
786 if (pmin > tt) { pmin = tt; smin = p;}
787 }
788
789 G4ThreeVector u = c1 - c0, un = u.unit();
790 vector<solution_t> ts = RCross(c0, n0t, un);
791 double umax = u.mag();
792 for (solution_t r : ts) {
793 if (0 < r.s && r.s < umax) {
794 double tt = r.t + c0 * n0t;
795 G4ThreeVector p = n0t * r.t + un * r.s + c0;
796 // cout<<r.t<<" "<<r.s<<" "<<smax<<endl;
797 if (pmax < tt) { pmax = tt; smax = p;}
798 if (pmin > tt) { pmin = tt; smin = p;}
799 }
800 }
801 planes.push_back({ -un, un * c1});
802 }
803
804 vector<G4ThreeVector> vside = PhiCrossN(planes);
805 for (const G4ThreeVector& p : vside) {
806 // cout<<p<<endl;
807 double tt = n0t * p;
808 if (pmax < tt) { pmax = tt; smax = p;}
809 if (pmin > tt) { pmin = tt; smin = p;}
810 }
811
812 } else if (b1 || b2) {
813 G4ThreeVector limits[2], u;
814 if (b1) {
815 limits[0] = n1 * dmin1;
816 limits[1] = n1 * dmax1;
817 u = iT.TransformAxis(n2);
818 } else {
819 limits[0] = n2 * dmin2;
820 limits[1] = n2 * dmax2;
821 u = iT.TransformAxis(n1);
822 }
823
824 for (G4ThreeVector& c : limits) iT.ApplyPointTransform(c); // to solid coordinates
825 for (int i = 0; i < 2; i++) {
826 vector<solution_t> ts = RCross(limits[i], n0t, u);
827 for (solution_t r : ts) {
828 double tt = r.t + limits[i] * n0t;
829 G4ThreeVector p = n0t * r.t + u * r.s + limits[i];
830 // cout<<r.t<<" "<<r.s<<" "<<endl;
831 if (pmax < tt) { pmax = tt; smax = p;}
832 if (pmin > tt) { pmin = tt; smin = p;}
833 }
834 }
835
836 vector<Plane_t> planes(2);
837 G4ThreeVector n;
838 if (b1) {
839 n = iT.TransformAxis(n1);
840 } else {
841 n = iT.TransformAxis(n2);
842 }
843 planes[0] = { n, -limits[0]* n};
844 planes[1] = { -n, limits[1]* n};
845 vector<G4ThreeVector> vside = PhiCrossN(planes);
846
847 for (const G4ThreeVector& p : vside) {
848 // double t = n0t*(p-limits[0]);
849 double tt = n0t * p;
850 // cout<<tt<<" "<<p<<" "<<endl;
851 if (pmax < tt) { pmax = tt; smax = p;}
852 if (pmin > tt) { pmin = tt; smin = p;}
853 }
854 }
855 // maximal distance in +- directions
856 G4ThreeVector rp = maxdist(n0t), rm = maxdist(-n0t);
857 if (bb.Inside(T.TransformPoint(rm))) {
858 double tt = rm * n0t;
859 if (pmin > tt) {pmin = tt; smin = rm;}
860 }
861 if (bb.Inside(T.TransformPoint(rp))) {
862 double tt = rp * n0t;
863 if (pmax < tt) {pmax = tt; smax = rp;}
864 }
865
866 // to mother volume coordinate system
867 T.ApplyPointTransform(smin);
868 T.ApplyPointTransform(smax);
869 pmin = n0 * smin;
870 pmax = n0 * smax;
871
872 pmin -= kCarTolerance;
873 pmax += kCarTolerance;
874 // bool hit = pmin > -kInfinity && pmax < kInfinity;
875 bool hit = pmin < pmax;
876
877#if COMPARE==10
878 auto surfhit = [this, &bb, &T, &n0, &n0t](double & pmin, double & pmax, bool print = false)->bool {
879 const int N = 1000 * 1000;
880 if (fsurf.size() == 0) for (int i = 0; i < N; i++) fsurf.push_back(GetPointOnSurface());
881
882 int umin = -1, umax = -1;
883 double wmin = 1e99, wmax = -1e99;
884 for (int i = 0; i < N; i++)
885 {
886 if (bb.Inside(T.TransformPoint(fsurf[i]))) {
887 double w = n0t * fsurf[i];
888 if (wmin > w) {wmin = w; umin = i;}
889 if (wmax < w) {wmax = w; umax = i;}
890 }
891 }
892 if (print)cout << umin << " " << umax << " " << wmin << " " << wmax << endl;
893 if (umin >= 0 && umax >= 0)
894 {
895 G4ThreeVector qmin = fsurf[umin], qmax = fsurf[umax];
896 T.ApplyPointTransform(qmin);
897 T.ApplyPointTransform(qmax);
898 pmin = n0 * qmin, pmax = n0 * qmax;
899 return true;
900 }
901 return false;
902 };
903
904 bool res = fshape->CalculateExtent(A, bb, T, pMin, pMax);
905 double srfmin = kInfinity, srfmax = -srfmin;
906 bool sHit = surfhit(srfmin, srfmax);
907 double diff = kCarTolerance;
908 diff = 10;
909 // if (abs(pmin - pMin) > diff || abs(pmax - pMax) > diff || hit != res) {
910 if ((abs(pmin - srfmin) > diff || abs(pmax - srfmax) > diff) && sHit) {
911 cout << "===================================\n";
912 cout << GetName() << " " << fcache.size() << " " << fphi << " " << fdphi << " " << ftwopi << "\n";
913 cout << hit << " " << res << " " << b1 << " " << b2 << "\n";
914 if (sHit) {
915 cout << "ss " << srfmin << " " << srfmax << "\n";
916 } else {
917 cout << "ss : not in bounding box" << "\n";
918 }
919 cout << "my " << pmin << " " << pmax << "\n";
920 cout << "tc " << pMin << " " << pMax << "\n";
921 cout << "df " << pmin - pMin << " " << pmax - pMax << "\n";
922 G4ThreeVector bmin(bb.GetMinXExtent(), bb.GetMinYExtent(), bb.GetMinZExtent());
923 G4ThreeVector bmax(bb.GetMaxXExtent(), bb.GetMaxYExtent(), bb.GetMaxZExtent());
924 cout << "Axis=" << A << " " << bmin << " " << bmax << " " << T << "\n";
925 cout << rp << " " << rm << "\n";
926 cout << smin << " " << smax << "\n";
927 cout << flush;
928 // _exit(0);
929 }
930 // cout<<endl;
931#endif
932 pMin = pmin;
933 pMax = pmax;
934
935 return hit;
936}
double R
typedef autogenerated by FFTW
std::vector< double > linecross(const G4ThreeVector &, const G4ThreeVector &) const
calculate all ray solid's surface intersection return ordered vector
G4ThreeVector GetPointOnSurface() const
Get point on surface.
TString rn()
Get random string.
Definition tools.h:38
double clip(double x, int Nx, double A, double xmi, double xma)
Performs a clip on x w.r.t xmi and xma.
Definition func.h:78
double dz
difference in z
Definition BelleLathe.h:34
double r
r coordinate
Definition BelleLathe.h:33
double zmin
minimal z value
Definition BelleLathe.h:39
double z
z coordinate
Definition BelleLathe.h:32
double ta
ratio of dr over dz
Definition BelleLathe.h:43
double zmax
maximal z value
Definition BelleLathe.h:40

◆ Clone()

G4VSolid * Clone ( ) const

Make a clone of the object.

Definition at line 1818 of file BelleLathe.cc.

1819{
1820 return new BelleLathe(*this);
1821}
BelleLathe(const G4String &pName)
Constructor for "nominal" BelleLathe whose parameters are to be set by a G4VPVParamaterisation later.

◆ ComputeDimensions()

void ComputeDimensions ( G4VPVParameterisation * p,
const G4int n,
const G4VPhysicalVolume * pRep )

compute the dimensions

Definition at line 346 of file BelleLathe.cc.

349{
350 G4Exception("BelleLathe::ComputeDimensions()",
351 "GeomSolids0001", FatalException,
352 "BelleLathe does not support Parameterisation.");
353 // std::cout<<"ComputeDimensions"<<std::endl;
354 // p->ComputeDimensions(*this,n,pRep);
355}

◆ CreatePolyhedron()

G4Polyhedron * CreatePolyhedron ( ) const

create polyhedron

Definition at line 2010 of file BelleLathe.cc.

2011{
2012 eartrim();
2013 return new PolyhedronBelleLathe(fcontour, ftlist, fphi, fdphi);
2014}
void eartrim() const
ear trim

◆ DescribeYourselfTo()

void DescribeYourselfTo ( G4VGraphicsScene & scene) const

Visualisation function.

Definition at line 1851 of file BelleLathe.cc.

1852{
1853 scene.AddSolid(*this);
1854}

◆ DistanceToIn() [1/2]

G4double DistanceToIn ( const G4ThreeVector & p) const

Calculate exact shortest distance to any boundary from outside.

Definition at line 1165 of file BelleLathe.cc.

1166{
1167 COUNTER(2);
1168 double d = 0;
1169 // int sector = 0, plane = 0;
1170 if (ftwopi) {
1171 zr_t r = {p.z(), p.perp()};
1172 d = max(mindist(r), 0.0);
1173 } else {
1174 double d0 = fn0x * p.x() + fn0y * p.y();
1175 double d1 = fn1x * p.x() + fn1y * p.y();
1176
1177 if (fgtpi) {
1178 if (d0 > 0 && d1 > 0) { // outside sector
1179 if (d0 < d1) {
1180 zr_t r = {p.z(), -fn0y * p.x() + fn0x * p.y()}; // projection on plane
1181 d = sqrt(pow(max(mindist(r), 0.0), 2) + d0 * d0);
1182 } else {
1183 zr_t r = {p.z(), fn1y * p.x() - fn1x * p.y()}; // projection on plane
1184 d = sqrt(pow(max(mindist(r), 0.0), 2) + d1 * d1);
1185 }
1186 } else {
1187 zr_t r = {p.z(), p.perp()};
1188 d = max(mindist(r), 0.0);
1189 }
1190 } else {
1191 if (d0 > 0 || d1 > 0) { // outside sector
1192 if (d0 < 0) {
1193 zr_t r = {p.z(), fn1y * p.x() - fn1x * p.y()}; // projection on plane
1194 d = sqrt(pow(max(mindist(r), 0.0), 2) + d1 * d1);
1195 } else {
1196 zr_t r = {p.z(), -fn0y * p.x() + fn0x * p.y()}; // projection on plane
1197 d = sqrt(pow(max(mindist(r), 0.0), 2) + d0 * d0);
1198 }
1199 } else {
1200 zr_t r = {p.z(), p.perp()};
1201 d = max(mindist(r), 0.0);
1202 }
1203 }
1204 }
1205#if COMPARE==1
1206 // double dd = fshape->Inside(p) == 2 ? 0.0 : fshape->DistanceToIn(p);
1207 double dd = fshape->DistanceToIn(p);
1208 // if (abs(d - dd) > kCarTolerance) {
1209 if (dd > d && abs(d - dd) > kCarTolerance) {
1210 int oldprec = cout.precision(16);
1211 EInside inside = fshape->Inside(p);
1212 zr_t r = {p.z(), p.perp()};
1213 cout << GetName() << " DistanceToIn(p) " << p << " " << r << " " << d << " " << dd << " " << d - dd << " " << inside << endl;
1214 cout.precision(oldprec);
1215 // exit(0);
1216 }
1217#endif
1218 MATCHOUT("BelleLathe::DistanceToIn(p) " << p << " res= " << d);
1219 return d;
1220}
double mindist(const zr_t &) const
minimal distance
double sqrt(double a)
sqrt for double
Definition beamHelpers.h:28

◆ DistanceToIn() [2/2]

G4double DistanceToIn ( const G4ThreeVector & p,
const G4ThreeVector & v ) const

Calculate distance to shape from outside - return kInfinity if no intersection.

Definition at line 1255 of file BelleLathe.cc.

1256{
1257 // return fshape->DistanceToIn(p, n);
1258 auto getnormal = [this, &p, &n](int i, double t) ->G4ThreeVector{
1259 const int imax = fcache.size();
1260 G4ThreeVector o;
1261 if (i < 0)
1262 {
1263 } else if (i < imax)
1264 {
1265 const cachezr_t& s = fcache[i];
1266 if (s.dz == 0.0) {
1267 o.setZ(copysign(1, s.dr));
1268 } else {
1269 double x = p.x() + n.x() * t;
1270 double y = p.y() + n.y() * t;
1271 double sth = s.dr * s.is, cth = -s.dz * s.is;
1272 double ir = cth / sqrt(x * x + y * y);
1273 o.set(x * ir, y * ir, sth);
1274 }
1275 } else if (i == imax)
1276 {
1277 o.setX(fn0x), o.setY(fn0y);
1278 } else
1279 {
1280 o.setX(fn1x), o.setY(fn1y);
1281 }
1282 return o;
1283 };
1284
1285 auto hitside = [this, &p, &n](double t, const cachezr_t& s) -> bool {
1286 double z = p.z() + n.z() * t;
1287 // cout<<t<<" "<<x<<" "<<y<<" "<<z<<endl;
1288 bool k = s.zmin < z && z <= s.zmax;
1289 if (k && !ftwopi)
1290 {
1291 double x = p.x() + n.x() * t;
1292 double y = p.y() + n.y() * t;
1293 k = k && insector(x, y);
1294 }
1295 return k;
1296 };
1297
1298 auto hitzside = [this, &p, &n](double t, const cachezr_t& s) -> bool {
1299 double x = p.x() + n.x() * t;
1300 double y = p.y() + n.y() * t;
1301 double r2 = x * x + y * y;
1302 bool k = s.r2min <= r2 && r2 < s.r2max;
1303 if (k && !ftwopi)
1304 {
1305 k = k && insector(x, y);
1306 }
1307 return k;
1308 };
1309
1310 auto hitphi0side = [this, &p, &n](double t) -> bool {
1311 double x = p.x() + n.x() * t;
1312 double y = p.y() + n.y() * t;
1313 double r = x * fc0 + y * fs0;
1314 if (r >= frmin)
1315 {
1316 double z = p.z() + n.z() * t;
1317 zr_t zr = {z, r};
1318 return wn_poly(zr) == 2;
1319 }
1320 return false;
1321 };
1322
1323 auto hitphi1side = [this, &p, &n](double t) -> bool {
1324 double x = p.x() + n.x() * t;
1325 double y = p.y() + n.y() * t;
1326 double r = x * fc1 + y * fs1;
1327 if (r >= frmin)
1328 {
1329 double z = p.z() + n.z() * t;
1330 zr_t zr = {z, r};
1331 return wn_poly(zr) == 2;
1332 }
1333 return false;
1334 };
1335
1336 double tmin = kInfinity;
1337 const int imax = fcache.size();
1338 int iseg = -1, isurface = -1;
1339 const double delta = 0.5 * kCarTolerance;
1340 double inz = 1 / n.z();
1341 double nn = dotxy(n, n), np = dotxy(n, p), pp = dotxy(p, p);
1342 double pz = p.z(), pr = sqrt(pp);
1343 for (int i = 0; i < imax; i++) { // loop over sides
1344 const cachezr_t& s = fcache[i];
1345 double dz = pz - s.z, dr = pr - s.r;
1346 double d = dz * s.dr - dr * s.dz;
1347 bool surface = false;
1348 if (abs(d * s.is) < delta) {
1349 double dot = dz * s.dz + dr * s.dr;
1350 if (dot >= 0 && dot <= s.s2) {
1351 surface = true;
1352 isurface = i;
1353 }
1354 }
1355 if (s.dz == 0.0) { // z-plane
1356 if (!surface) {
1357 double t = -dz * inz;
1358 if (0 < t && t < tmin && hitzside(t, s)) { tmin = t; iseg = i;}
1359 }
1360 } else {
1361 double A, B, R2;
1362 if (s.dr == 0.0) { // cylinder
1363 double R = s.r;
1364 R2 = R * R;
1365
1366 A = -nn;
1367 B = np;
1368 } else { // cone
1369 double taz = s.ta * dz;
1370 double R = taz + s.r;
1371 R2 = R * R;
1372
1373 double nzta = n.z() * s.ta;
1374 A = nzta * nzta - nn;
1375 B = np - nzta * R;
1376 }
1377 double C = pp - R2;
1378 double D = B * B + C * A;
1379 if (D > 0) {
1380 // double sD = sqrt(D), iA = 1 / A;
1381 // double t0 = (B + sD) * iA, t1 = (B - sD) * iA;
1382 double sD = sqrt(D), sum = B + copysign(sD, B);
1383 double t0 = -C / sum, t1 = sum / A;
1384 if (surface) { // exclude solution on surface
1385 if (abs(t0) > abs(t1)) {
1386 if (t0 > 0 && t0 < tmin && hitside(t0, s)) { tmin = t0; iseg = i;}
1387 } else {
1388 if (t1 > 0 && t1 < tmin && hitside(t1, s)) { tmin = t1; iseg = i;}
1389 }
1390 } else {
1391 if (t0 > 0 && t0 < tmin && hitside(t0, s)) { tmin = t0; iseg = i;}
1392 if (t1 > 0 && t1 < tmin && hitside(t1, s)) { tmin = t1; iseg = i;}
1393 }
1394 }
1395 }
1396 }
1397
1398 if (!ftwopi) {
1399 do { // side at phi0
1400 double vn = fn0x * n.x() + fn0y * n.y();
1401 if (vn < 0) {
1402 double d = fn0x * p.x() + fn0y * p.y();
1403 double t = -d / vn;
1404 if (hitphi0side(t)) {
1405 bool surface = std::abs(d) < delta;
1406 if (surface) {
1407 tmin = 0; iseg = imax + 0;
1408 } else {
1409 if (0 < t && t < tmin) {tmin = t; iseg = imax + 0;}
1410
1411 }
1412 }
1413 }
1414 } while (0);
1415
1416 do { // side at phi0+dphi
1417 double vn = fn1x * n.x() + fn1y * n.y();
1418 if (vn < 0) {
1419 double d = fn1x * p.x() + fn1y * p.y();
1420 double t = -d / vn;
1421 if (hitphi1side(t)) {
1422 bool surface = std::abs(d) < delta;
1423 if (surface) {
1424 tmin = 0; iseg = imax + 1;
1425 } else {
1426 if (0 < t && t < tmin) { tmin = t; iseg = imax + 1;}
1427 }
1428 }
1429 }
1430 } while (0);
1431 }
1432
1433 if (iseg >= 0) {
1434 if (getnormal(iseg, tmin)*n > 0) tmin = 0;
1435 // if (getnormal(iseg, tmin)*n > 0) tmin = kInfinity; // mimic genericpolycone
1436 }
1437
1438 auto convex = [this, imax](int i) -> bool{
1439 if (i < imax)
1440 return fcache[i].isconvex;
1441 else
1442 return !fgtpi;
1443 };
1444
1445 if (tmin >= 0 && tmin < kInfinity) {
1446 if (isurface >= 0) if (convex(isurface) && getnormal(isurface, 0)*n >= 0) tmin = kInfinity;
1447 } else {
1448 if (Inside(p) == kSurface) {
1449 if (isurface >= 0) {
1450 tmin = (getnormal(isurface, 0) * n >= 0) ? kInfinity : 0; // mimic genericpolycone
1451 }
1452 }
1453 }
1454
1455#if COMPARE==1
1456 // double dd = fshape->Inside(p) == 2 ? 0.0 : fshape->DistanceToIn(p, n);
1457 double dd = fshape->DistanceToIn(p, n);
1458 if (abs(tmin - dd) > 1e-10) {
1459 int oldprec = cout.precision(16);
1460 EInside inside = fshape->Inside(p);
1461 cout << GetName() << " DistanceToIn(p,v) " << p << " " << n << " " << tmin << " " << dd << " " << tmin - dd << " " << inside << " "
1462 << Inside(p) << " iseg = " << iseg << " " << isurface << endl;
1463 if (isurface >= 0) cout << getnormal(isurface, 0) << endl;
1464 cout.precision(oldprec);
1465 }
1466#endif
1467 tmin = max(0.0, tmin);
1468 MATCHOUT("BelleLathe::DistanceToIn(p,n) " << p << " " << n << " res= " << tmin);
1469 return tmin;
1470}
int wn_poly(const zr_t &) const
wn_poly
EInside Inside(const G4ThreeVector &p) const
Return whether point inside/outside/on surface, using tolerance.
T dot(GeneralVector< T > a, GeneralVector< T > b)
dot product of two general vectors

◆ DistanceToOut() [1/2]

G4double DistanceToOut ( const G4ThreeVector & p) const

Calculate exact shortest distance to any boundary from inside.

Definition at line 1224 of file BelleLathe.cc.

1225{
1226 // return ref->DistanceToOut(p);
1227 COUNTER(3);
1228 zr_t r = {p.z(), p.perp()};
1229 double d = mindist(r);
1230 if (!ftwopi) {
1231 double d0 = fn0x * p.x() + fn0y * p.y();
1232 double d1 = fn1x * p.x() + fn1y * p.y();
1233 if (fgtpi) {
1234 d = max(d, min(d0, d1));
1235 } else {
1236 d = max(d, max(d0, d1));
1237 }
1238 }
1239 d = max(-d, 0.0);
1240#if COMPARE==1
1241 double dd = fshape->Inside(p) == 0 ? 0.0 : fshape->DistanceToOut(p);
1242 if (abs(d - dd) > kCarTolerance) {
1243 int oldprec = cout.precision(16);
1244 zr_t r = {p.z(), p.perp()};
1245 // cout<<r<<endl;
1246 cout << GetName() << " DistanceToOut(p) " << p << " " << r << " " << d << " " << dd << " " << d - dd << endl;
1247 cout.precision(oldprec);
1248 }
1249#endif
1250 MATCHOUT("BelleLathe::DistanceToOut(p) " << p.x() << " " << p.y() << " " << p.z() << " res= " << d);
1251 return d;
1252}

◆ DistanceToOut() [2/2]

G4double DistanceToOut ( const G4ThreeVector & p,
const G4ThreeVector & v,
const G4bool calcNorm = false,
G4bool * validNorm = 0,
G4ThreeVector * n = 0 ) const

Calculate distance to surface of shape from inside.

Definition at line 1473 of file BelleLathe.cc.

1475{
1476 // return fshape->DistanceToOut(p, v, calcNorm, validNorm, n);
1477 auto getnormal = [this, &p, &v](int i, double t)->G4ThreeVector{
1478 const int imax = fcache.size();
1479 G4ThreeVector o;
1480 if (i < 0)
1481 {
1482 } else if (i < imax)
1483 {
1484 const cachezr_t& s = fcache[i];
1485 if (s.dz == 0.0) {
1486 o.setZ(copysign(1, s.dr));
1487 } else {
1488 double x = p.x() + v.x() * t;
1489 double y = p.y() + v.y() * t;
1490 double sth = s.dr * s.is, cth = -s.dz * s.is;
1491 double ir = cth / sqrt(x * x + y * y);
1492 o.set(x * ir, y * ir, sth);
1493 }
1494 } else if (i == imax)
1495 {
1496 o.setX(fn0x), o.setY(fn0y);
1497 } else
1498 {
1499 o.setX(fn1x), o.setY(fn1y);
1500 }
1501 return o;
1502 };
1503
1504 double nn = dotxy(v, v), np = dotxy(v, p), pp = dotxy(p, p);
1505 auto hitside = [this, &p, &v, nn, np, pp](double t, const cachezr_t& s) -> bool {
1506 double z = p.z() + v.z() * t;
1507 // cout<<t<<" "<<x<<" "<<y<<" "<<z<<endl;
1508 double dot = v.z() * s.dr * sqrt(pp + ((np + np) + nn * t) * t) - s.dz * (np + nn * t);
1509 bool k = s.zmin < z && z <= s.zmax && dot > 0;
1510 if (k && !ftwopi)
1511 {
1512 double x = p.x() + v.x() * t;
1513 double y = p.y() + v.y() * t;
1514
1515 k = k && insector(x, y);
1516 }
1517 return k;
1518 };
1519
1520 auto hitzside = [this, &p, &v](double t, const cachezr_t& s) -> bool {
1521 double x = p.x() + v.x() * t;
1522 double y = p.y() + v.y() * t;
1523 double r2 = x * x + y * y;
1524 bool k = s.dr * v.z() > 0 && s.r2min <= r2 && r2 < s.r2max;
1525 if (k && !ftwopi)
1526 {
1527 k = k && insector(x, y);
1528 }
1529 return k;
1530 };
1531
1532 auto hitphi0side = [this, &p, &v](double t) -> bool {
1533 double x = p.x() + v.x() * t;
1534 double y = p.y() + v.y() * t;
1535 double r = x * fc0 + y * fs0;
1536 if (r >= frmin)
1537 {
1538 double z = p.z() + v.z() * t;
1539 zr_t zr = {z, r};
1540 return wn_poly(zr) == 2;
1541 }
1542 return false;
1543 };
1544
1545 auto hitphi1side = [this, &p, &v](double t) -> bool {
1546 double x = p.x() + v.x() * t;
1547 double y = p.y() + v.y() * t;
1548 double r = x * fc1 + y * fs1;
1549 if (r >= frmin)
1550 {
1551 double z = p.z() + v.z() * t;
1552 zr_t zr = {z, r};
1553 return wn_poly(zr) == 2;
1554 }
1555 return false;
1556 };
1557
1558 COUNTER(5);
1559 double tmin = kInfinity;
1560
1561 const int imax = fcache.size();
1562 int iseg = -1, isurface = -1;
1563
1564 const double delta = 0.5 * kCarTolerance;
1565 double inz = 1 / v.z();
1566 double pz = p.z(), pr = sqrt(pp);
1567
1568 for (int i = 0; i < imax; i++) {
1569 const cachezr_t& s = fcache[i];
1570
1571 double d = (pz - s.z) * s.dr - (pr - s.r) * s.dz;
1572 bool surface = abs(d * s.is) < delta;
1573 if (surface) isurface = i;
1574 if (s.dz == 0.0) {
1575 double t = (s.z - p.z()) * inz;
1576 if (surface) {
1577 if (hitzside(t, s)) {tmin = 0; iseg = i; break;}
1578 } else {
1579 if (0 < t && t < tmin && hitzside(t, s)) {tmin = t; iseg = i;}
1580 }
1581 } else {
1582 double A, B, R2;
1583 if (s.dr == 0.0) { // cylinder
1584 double R = s.r;
1585 R2 = R * R;
1586
1587 A = -nn;
1588 B = np;
1589 } else { // cone
1590 double taz = s.ta * (p.z() - s.z);
1591 double R = taz + s.r;
1592 R2 = R * R;
1593
1594 double nzta = v.z() * s.ta;
1595 A = nzta * nzta - nn;
1596 B = np - nzta * R;
1597 }
1598 double C = pp - R2;
1599 double D = B * B + C * A;
1600 if (D > 0) {
1601 double sD = sqrt(D);
1602 double sum = B + copysign(sD, B);
1603 double t0 = -C / sum, t1 = sum / A;
1604 // cout<<t0<<" "<<t1<<" "<<endl;
1605 if (surface) { //exclude solution on surface
1606 if (abs(t0) < abs(t1)) {
1607 if (hitside(t0, s)) { tmin = 0; iseg = i; break;}
1608 if (0 < t1 && t1 < tmin && hitside(t1, s)) { tmin = t1; iseg = i;}
1609 } else {
1610 if (hitside(t1, s)) { tmin = 0; iseg = i; break;}
1611 if (0 < t0 && t0 < tmin && hitside(t0, s)) { tmin = t0; iseg = i;}
1612 }
1613 } else { // check both solutions
1614 if (0 < t0 && t0 < tmin && hitside(t0, s)) { tmin = t0; iseg = i;}
1615 if (0 < t1 && t1 < tmin && hitside(t1, s)) { tmin = t1; iseg = i;}
1616 }
1617 }
1618 }
1619 // cout<<i<<" "<<iseg<<" "<<sqrt(d*d*s.is2)<<" "<<tmin<<" "<<s.zmin<<" "<<s.zmax<<endl;
1620 }
1621
1622 if (!ftwopi) {
1623 do { // side at phi0
1624 double vn = fn0x * v.x() + fn0y * v.y();
1625 if (vn > 0) {
1626 double d = fn0x * p.x() + fn0y * p.y();
1627 double t = -d / vn;
1628 if (hitphi0side(t)) {
1629 bool surface = std::abs(d) < delta;
1630 if (surface) {
1631 tmin = 0; iseg = imax + 0;
1632 } else {
1633 if (0 < t && t < tmin) {tmin = t; iseg = imax + 0;}
1634
1635 }
1636 }
1637 }
1638 } while (0);
1639
1640 do { // side at phi0+dphi
1641 double vn = fn1x * v.x() + fn1y * v.y();
1642 if (vn > 0) {
1643 double d = fn1x * p.x() + fn1y * p.y();
1644 double t = -d / vn;
1645 if (hitphi1side(t)) {
1646 bool surface = std::abs(d) < delta;
1647 if (surface) {
1648 tmin = 0; iseg = imax + 1;
1649 } else {
1650 if (0 < t && t < tmin) { tmin = t; iseg = imax + 1;}
1651 }
1652 }
1653 }
1654 } while (0);
1655 }
1656
1657 auto convex = [this, imax](int i) -> bool{
1658 if (i < imax)
1659 return fcache[i].isconvex;
1660 else
1661 return !fgtpi;
1662 };
1663
1664 if (calcNorm) {
1665 if (tmin >= 0 && tmin < kInfinity) {
1666 *n = getnormal(iseg, tmin);
1667 *validNorm = convex(iseg);
1668 } else {
1669 if (Inside(p) == kSurface) {
1670 if (isurface >= 0) {
1671 *n = getnormal(isurface, tmin);
1672 *validNorm = convex(isurface);
1673 tmin = 0;
1674 }
1675 } else {
1676 *validNorm = false;
1677 }
1678 }
1679 }
1680 // cout<<"tmin "<<tmin<<endl;
1681#if COMPARE==1
1682 do {
1683 // G4ThreeVector p0(1210.555046, -292.9578965, -36.71671492);
1684 // if ((p - p0).mag() > 1e-2)continue;
1685 bool isvalid;
1686 G4ThreeVector norm;
1687 double dd = fshape->DistanceToOut(p, v, calcNorm, &isvalid, &norm);
1688 if (abs(tmin - dd) > 1e-10 || (calcNorm && *validNorm != isvalid)) {
1689 int oldprec = cout.precision(16);
1690 cout << GetName() << " DistanceToOut(p,v) p,v =" << curl_t(p) << curl_t(v) << " calcNorm=" << calcNorm
1691 << " myInside=" << Inside(p) << " tmin=" << tmin << " dd=" << dd << " d=" << tmin - dd << " iseg=" << iseg << " isurf=" << isurface
1692 << " ";
1693 if (calcNorm) cout << "myIsValid = " << *validNorm << " tIsValid=" << isvalid << " myn=" << (*n) << " tn=" << (norm);
1694 cout << endl;
1695 cout.precision(oldprec);
1696 // _exit(0);
1697 }
1698 } while (0);
1699#endif
1700 MATCHOUT("BelleLathe::DistanceToOut(p,v) " << p << " " << v << " res= " << tmin);
1701 return tmin;
1702}

◆ eartrim()

void eartrim ( ) const
protected

ear trim

Definition at line 1704 of file BelleLathe.cc.

1705{
1706 ftlist.clear();
1707 unsigned int n = fcontour.size();
1708 vector<int> indx;
1709 for (unsigned int i = 0; i < n; i++) indx.push_back(i);
1710 int count = 0;
1711 while (indx.size() > 3 && ++count < 200) {
1712 unsigned int ni = indx.size();
1713 for (unsigned int i = 0; i < ni; i++) {
1714 int i0 = indx[i], i1 = indx[(i + 1) % ni], i2 = indx[(i + 2) % ni];
1715 double nx = fcontour[i2].z - fcontour[i0].z;
1716 double ny = fcontour[i2].r - fcontour[i0].r;
1717 double d1 = nx * (fcontour[i1].r - fcontour[i0].r) - ny * (fcontour[i1].z - fcontour[i0].z);
1718 bool ear = true;
1719 for (unsigned int j = 0; j < ni - 3; j++) {
1720 int k = indx[(i + 3 + j) % ni];
1721 double d = nx * (fcontour[k].r - fcontour[i0].r) - ny * (fcontour[k].z - fcontour[i0].z);
1722 if (d * d1 > 0) {
1723 ear = false;
1724 break;
1725 }
1726 }
1727 if (ear) {
1728 triangle_t t = {i0, i1, i2};
1729 ftlist.push_back(t);
1730 indx.erase(indx.begin() + (i + 1) % ni);
1731 break;
1732 }
1733 }
1734 }
1735 if (indx.size() == 3) {
1736 triangle_t t = {indx[0], indx[1], indx[2]};
1737 ftlist.push_back(t);
1738 }
1739}

◆ GetCubicVolume()

G4double GetCubicVolume ( )
inline

Get cubic volume.

Definition at line 123 of file BelleLathe.h.

123{return fCubicVolume;}

◆ GetEntityType()

G4GeometryType GetEntityType ( ) const

Get entity type.

Definition at line 1812 of file BelleLathe.cc.

1813{
1814 return G4String("BelleLathe");
1815}

◆ GetPointOnSurface()

G4ThreeVector GetPointOnSurface ( ) const

Get point on surface.

Definition at line 1766 of file BelleLathe.cc.

1767{
1768 auto GetPointOnTriangle = [this](const triangle_t& t)-> G4ThreeVector{
1769 // barycentric coordinates
1770 double a1 = CLHEP::RandFlat::shoot(0., 1.), a2 = CLHEP::RandFlat::shoot(0., 1.);
1771 if (a1 + a2 > 1) { a1 = 1 - a1; a2 = 1 - a2;}
1772 double a0 = 1 - (a1 + a2);
1773 const zr_t& p0 = fcontour[t.i0], &p1 = fcontour[t.i1], &p2 = fcontour[t.i2];
1774 zr_t p = {p0.z* a0 + p1.z* a1 + p2.z * a2, p0.r* a0 + p1.r* a1 + p2.r * a2};
1775 double c, s;
1776 if (CLHEP::RandFlat::shoot(0., 1.) > 0.5) // select phi side
1777 {
1778 c = -fn0y; s = fn0x;
1779 } else
1780 {
1781 c = fn1y; s = -fn1x;
1782 }
1783 G4ThreeVector r1(p.r * c, p.r * s, p.z);
1784 return r1;
1785 };
1786
1787 double rnd = CLHEP::RandFlat::shoot(0., farea.back());
1788 std::vector<double>::const_iterator it = std::lower_bound(farea.begin(), farea.end(), rnd);
1789 unsigned int i = it - farea.begin();
1790
1791 if (!ftwopi) {
1792 if (i < ftlist.size()) {
1793 return GetPointOnTriangle(ftlist[i]);
1794 } else {
1795 i -= ftlist.size();
1796 }
1797 }
1798
1799 const cachezr_t& s = fcache[i];
1800 double I = 2 * s.r + s.dr;
1801 double Iw = CLHEP::RandFlat::shoot(0., I);
1802 double q = sqrt(Iw * s.dr + s.r * s.r);
1803 double t = Iw / (q + s.r);
1804 double z = s.z + s.dz * t;
1805 double r = s.r + s.dr * t;
1806 double phi = CLHEP::RandFlat::shoot(fphi, fphi + fdphi);
1807 double x = r * cos(phi), y = r * sin(phi);
1808 return G4ThreeVector(x, y, z);
1809}
double r
r coordinate
Definition BelleLathe.h:27
double z
z coordinate
Definition BelleLathe.h:26

◆ GetSurfaceArea()

G4double GetSurfaceArea ( )
inline

Get surface area.

Definition at line 126 of file BelleLathe.h.

126{return fSurfaceArea;}

◆ getvolarea()

void getvolarea ( )
protected

get volume area

Definition at line 1741 of file BelleLathe.cc.

1742{
1743 double vol = 0;
1744 for (const cachezr_t& s : fcache) vol += s.dz * ((3 * s.r) * (s.r + s.dr) + s.dr * s.dr);
1745 fCubicVolume = -fdphi * vol / 6;
1746
1747 double totalarea = 0;
1748 if (!ftwopi) {
1749 eartrim();
1750 for (const triangle_t& t : ftlist) {
1751 const zr_t& p0 = fcontour[t.i0], &p1 = fcontour[t.i1], &p2 = fcontour[t.i2];
1752 double area = (p1.z - p0.z) * (p2.r - p0.r) - (p1.r - p0.r) * (p2.z - p0.z);
1753 totalarea += abs(area);
1754 farea.push_back(totalarea);
1755 }
1756 }
1757
1758 for (const cachezr_t& s : fcache) {
1759 double area = fdphi * (s.r + 0.5 * s.dr) * sqrt(s.dz * s.dz + s.dr * s.dr);
1760 totalarea += area;
1761 farea.push_back(totalarea);
1762 }
1763 fSurfaceArea = farea.back();
1764}

◆ Init()

void Init ( const std::vector< zr_t > & c,
double phi0,
double dphi )
protected

initialize

Definition at line 101 of file BelleLathe.cc.

102{
103 vector<zr_t> contour = c;
104 // remove duplicated vertices
105 do {
106 vector<zr_t>::iterator it0 = contour.begin(), it1 = it0 + 1;
107 for (; it1 != contour.end();) {
108 const zr_t& s0 = *it0, &s1 = *it1;
109 if (abs(s0.z - s1.z) < kCarTolerance && abs(s0.r - s1.r) < kCarTolerance)
110 it1 = contour.erase(it1);
111 else {
112 ++it0; ++it1;
113 }
114 }
115 // cppcheck-suppress containerOutOfBounds ; contour should be valid here
116 const zr_t& s0 = *it0, &s1 = contour[0]; // cppcheck-suppress invalidContainer ; contour should be valid here
117 if (abs(s0.z - s1.z) < kCarTolerance && abs(s0.r - s1.r) < kCarTolerance) contour.erase(it0);
118 } while (0);
119
120 // remove vertices on the same line
121 do {
122 vector<zr_t>::iterator it0 = contour.begin(), it1 = it0 + 1, it2 = it1 + 1;
123 for (; it0 != contour.end();) {
124 const zr_t& s0 = *it0, &s1 = *it1, &s2 = *it2;
125 double dr2 = s2.r - s0.r, dz2 = s2.z - s0.z;
126 double d = (s1.z - s0.z) * dr2 - (s1.r - s0.r) * dz2;
127
128 if (d * d < kCarTolerance * kCarTolerance * (dr2 * dr2 + dz2 * dz2)) {
129 it1 = contour.erase(it1);
130 it2 = it1;
131 if (++it2 >= contour.end()) it2 = contour.begin();
132 it0 = it1;
133 if (--it0 < contour.begin()) it0 = (++contour.rbegin()).base();
134
135 } else {
136 ++it0;
137 if (++it1 >= contour.end()) it1 = contour.begin();
138 if (++it2 >= contour.end()) it2 = contour.begin();
139 }
140
141 }
142 } while (0);
143
144 double sum = 0;
145 zr_t p0 = contour[0];
146 for (int i = 1, imax = contour.size(); i < imax; i++) {
147 zr_t p1 = contour[i];
148 sum += (p1.z - p0.z) * (p1.r + p0.r);
149 p0 = p1;
150 }
151 zr_t p1 = contour[0];
152 sum += (p1.z - p0.z) * (p1.r + p0.r);
153
154 // If contour is Clockwise: reverse contour
155 if (sum > 0)
156 std::reverse(contour.begin(), contour.end());
157
158 fcontour = contour;
159
160 auto convexside = [this](cachezr_t& s, double eps) -> void {
161 s.isconvex = false;
162 if (s.dz > 0) return;
163 vector<zr_t>::const_iterator it = fcontour.begin();
164 double a = s.dz * s.is, b = s.dr * s.is, cc = b * s.z - a * s.r;
165 bool dp = false, dm = false;
166 s.isconvex = true;
167 do
168 {
169 const zr_t& p = *it;
170 double d = a * p.r - b * p.z + cc; // distance to line
171 dm = dm || (d < -eps);
172 dp = dp || (d > eps);
173 if (dm && dp) {s.isconvex = false; return;}
174 } while (++it != fcontour.end());
175 };
176
177 frmin = kInfinity;
178 frmax = -kInfinity;
179 fzmin = kInfinity;
180 fzmax = -kInfinity;
181 fcache.reserve(fcontour.size());
182 for (int i = 0, n = fcontour.size(); i < n; i++) {
183 const zr_t& s0 = fcontour[i], &s1 = fcontour[(i + 1) % n];
184 cachezr_t t;
185 t.z = s0.z;
186 t.r = s0.r;
187 t.dz = s1.z - s0.z;
188 t.dr = s1.r - s0.r;
189 t.s2 = t.dz * t.dz + t.dr * t.dr;
190 t.is2 = 1 / t.s2;
191 t.is = sqrt(t.is2);
192 t.zmin = min(s0.z, s1.z);
193 t.zmax = max(s0.z, s1.z);
194 t.r2min = pow(min(s0.r, s1.r), 2);
195 t.r2max = pow(max(s0.r, s1.r), 2);
196 t.ta = (s1.r - s0.r) / (s1.z - s0.z);
197 convexside(t, kCarTolerance);
198 fcache.push_back(t);
199
200 frmax = max(frmax, s0.r);
201 frmin = min(frmin, s0.r);
202 fzmax = max(fzmax, s0.z);
203 fzmin = min(fzmin, s0.z);
204 }
205
206 fphi = phi0;
207 fdphi = dphi;
208
209 fdphi = std::min(2 * M_PI, fdphi);
210 fdphi = std::max(0.0, fdphi);
211 fc0 = cos(fphi);
212 fs0 = sin(fphi);
213 fc1 = cos(fphi + fdphi);
214 fs1 = sin(fphi + fdphi);
215
216 fn0x = fs0;
217 fn0y = -fc0;
218 fn1x = -fs1;
219 fn1y = fc1;
220 fgtpi = fdphi > M_PI;
221 ftwopi = abs(fdphi - 2 * M_PI) < kCarTolerance;
222
223 // cout << ftwopi << " " << fgtpi << " " << fn0y << " " << fn0x << " " << fn1y << " " << fn1x << endl;
224
225 for (int i = 0, n = fcontour.size(); i < n; i++) {
226 const zr_t& s = fcontour[i];
227 fz.push_back(s.z);
228 }
229 sort(fz.begin(), fz.end());
230 fz.erase(std::unique(fz.begin(), fz.end()), fz.end());
231
232 for (int i = 1, ni = fz.size(); i < ni; i++) {
233 double a = fz[i - 1], b = fz[i];
234 findx.push_back(fseg.size());
235 for (int j = 0, nj = fcache.size(); j < nj; j++) {
236 const cachezr_t& sj = fcache[j];
237 double cc = sj.zmin, d = sj.zmax;
238 if (cc != d and b > cc and d > a) { // overlap
239 fseg.push_back(j);
240 }
241 }
242 }
243 findx.push_back(fseg.size());
244
245 getvolarea();
246
247#if COMPARE>0
248 auto getpolycone = [](const G4String & pName, double phi0, double dphi, const vector<zr_t>& c) -> G4GenericPolycone* {
249 vector<double> r, z;
250 r.reserve(c.size());
251 z.reserve(c.size());
252 for (int i = 0, imax = c.size(); i < imax; i++)
253 {
254 r.push_back(c[i].r);
255 z.push_back(c[i].z);
256 }
257 return new G4GenericPolycone(pName, phi0, dphi, c.size(), r.data(), z.data());
258 };
259 fshape = getpolycone(GetName(), phi0, dphi, fcontour);
260#else
261 fshape = nullptr;
262#endif
263// StreamInfo(G4cout);
264}
void getvolarea()
get volume area

◆ insector()

bool insector ( double x,
double y ) const
inlineprotected

True if (x,y) is within the shape rotation.

Definition at line 939 of file BelleLathe.cc.

940{
941 double d0 = fn0x * x + fn0y * y;
942 double d1 = fn1x * x + fn1y * y;
943 bool b0 = d0 < 0, b1 = d1 < 0;
944 return fgtpi ? b0 || b1 : b0 && b1;
945}

◆ Inside()

EInside Inside ( const G4ThreeVector & p) const

Return whether point inside/outside/on surface, using tolerance.

Definition at line 985 of file BelleLathe.cc.

986{
987 COUNTER(0);
988 const double delta = 0.5 * kCarTolerance;
989 EInside res = kInside;
990 if (!ftwopi) {
991 double d0 = fn0x * p.x() + fn0y * p.y();
992 double d1 = fn1x * p.x() + fn1y * p.y();
993 if (fgtpi) {
994 if (d0 > delta && d1 > delta) { res = kOutside;}
995 else if (d0 > -delta && d1 > -delta) { res = kSurface;}
996 } else {
997 if (d0 > delta || d1 > delta) { res = kOutside;}
998 else if (d0 > -delta || d1 > -delta) { res = kSurface;}
999 }
1000 }
1001 if (res != kOutside) {
1002 zr_t r = {p.z(), p.perp()};
1003 double d = mindist(r);
1004 if (res == kSurface && d < delta) res = kSurface;
1005 else if (d > delta) res = kOutside;
1006 else if (d > -delta) res = kSurface;
1007 else res = kInside;
1008 }
1009
1010#if COMPARE==1
1011 EInside dd = fshape->Inside(p);
1012 if (1 || dd != res) {
1013 double d0 = fn0x * p.x() + fn0y * p.y();
1014 double d1 = fn1x * p.x() + fn1y * p.y();
1015 // if (abs(d0) > kCarTolerance && abs(d1) > kCarTolerance) {
1016 int oldprec = cout.precision(16);
1017 zr_t r = {p.z(), p.perp()};
1018 cout << GetName() << " Inside(p) " << p << " " << r << " my=" << res << " tc=" << dd <<
1019 " dist=" << mindist(r) << " " << d0 << " " << d1 << endl;
1020 cout.precision(oldprec);
1021 // }
1022 }
1023#endif
1024 MATCHOUT("BelleLathe::Inside(p) " << p << " res= " << res);
1025 return res;
1026}

◆ linecross()

vector< double > linecross ( const G4ThreeVector & p,
const G4ThreeVector & n ) const
protected

calculate all ray solid's surface intersection return ordered vector

Definition at line 429 of file BelleLathe.cc.

430{
431 auto hitside = [this, &p, &n](double t, double zmin, double zmax) -> bool {
432 double z = p.z() + n.z() * t;
433 bool k = zmin < z && z <= zmax;
434 if (k && !ftwopi)
435 {
436 double x = p.x() + n.x() * t;
437 double y = p.y() + n.y() * t;
438 k = k && insector(x, y);
439 }
440 return k;
441 };
442
443 auto hitzside = [this, &p, &n](double t, double r2min, double r2max) -> bool {
444 double x = p.x() + n.x() * t;
445 double y = p.y() + n.y() * t;
446 double r2 = x * x + y * y;
447 bool k = r2min <= r2 && r2 < r2max;
448 if (k && !ftwopi)
449 {
450 k = k && insector(x, y);
451 }
452 return k;
453 };
454
455 vector<double> tc;
456 double inz = 1 / n.z();
457 double nn = Belle2::ECL::dotxy(n, n), np = dotxy(n, p), pp = dotxy(p, p);
458 for (const cachezr_t& s : fcache) { // loop over sides
459 if (s.dz == 0.0) { // z-plane
460 double t = (s.z - p.z()) * inz;
461 if (hitzside(t, s.r2min, s.r2max)) { tc.push_back(t); }
462 } else {
463 double ta = s.ta;
464 double A, B, R2;
465 if (s.dr == 0.0) { // cylinder
466 double R = s.r;
467 R2 = R * R;
468
469 A = -nn;
470 B = np;
471 } else { // cone
472 double taz = ta * (p.z() - s.z);
473 double R = taz + s.r;
474 R2 = R * R;
475
476 double nzta = n.z() * ta;
477 A = nzta * nzta - nn;
478 B = np - nzta * R;
479 }
480 double D = B * B + (pp - R2) * A;
481 if (D > 0) {
482 double sD = sqrt(D), iA = 1 / A;
483 double t0 = (B + sD) * iA, t1 = (B - sD) * iA;
484 if (hitside(t0, s.zmin, s.zmax)) tc.push_back(t0);
485 if (hitside(t1, s.zmin, s.zmax)) tc.push_back(t1);
486 }
487 }
488 }
489
490 if (!ftwopi) {
491 do { // side at phi0
492 double d = fn0x * p.x() + fn0y * p.y();
493 double vn = fn0x * n.x() + fn0y * n.y();
494 double t = -d / vn;
495 G4ThreeVector r = p + n * t;
496 zr_t zr = {r.z(), fc0 * r.x() + fs0 * r.y()};
497 if (vn != 0 && wn_poly(zr) == 2) tc.push_back(t);
498 } while (0);
499
500 do { // side at phi0+dphi
501 double d = fn1x * p.x() + fn1y * p.y();
502 double vn = fn1x * n.x() + fn1y * n.y();
503 double t = -d / vn;
504 G4ThreeVector r = p + n * t;
505 zr_t zr = {r.z(), fc1 * r.x() + fs1 * r.y()};
506 if (vn != 0 && wn_poly(zr) == 2) tc.push_back(t);
507 } while (0);
508 }
509
510 sort(tc.begin(), tc.end());
511 return tc;
512}

◆ mindist()

double mindist ( const zr_t & r) const
protected

minimal distance

Definition at line 964 of file BelleLathe.cc.

965{
966 double d = kInfinity;
967 int i = 0, n = fcache.size();
968 do {
969 const cachezr_t& s = fcache[i];
970 double dz = r.z - s.z, dr = r.r - s.r;
971 double dot = s.dz * dz + s.dr * dr; // projection of the point on the segment
972 if (dot < 0) {
973 d = min(d, dz * dz + dr * dr); // distance to the first point of the segment
974 } else if (dot <= s.s2) { // point should be within the segment
975 double crs = s.dr * dz - s.dz * dr;
976 d = min(d, crs * crs * s.is2);
977 }
978 } while (++i < n);
979 d = sqrt(d);
980 d = (wn_poly(r) == 2) ? -d : d;
981 return d;
982}

◆ normal()

zr_t normal ( const zr_t & r,
double & d2 ) const
protected

return normal

Definition at line 1028 of file BelleLathe.cc.

1029{
1030 double d = std::numeric_limits<double>::infinity(), t = 0;
1031 int iseg = -1;
1032 for (int i = 0, imax = fcache.size(); i < imax; i++) {
1033 const cachezr_t& s = fcache[i];
1034 double dz = r.z - s.z, dr = r.r - s.r;
1035 double dot = s.dz * dz + s.dr * dr; // projection of the point on the segment
1036 if (dot < 0) {
1037 double dist = dz * dz + dr * dr; // distance to the first point of the segment
1038 if (dist < d) { d = dist; t = dot * s.is2; iseg = i;}
1039 } else if (dot <= s.s2) { // point should be within the segment
1040 double crs = s.dr * dz - s.dz * dr;
1041 double dist = crs * crs * s.is2;
1042 if (dist < d) { d = dist; t = dot * s.is2; iseg = i;}
1043 }
1044 }
1045 d2 = d;
1046
1047 auto getn = [this](int i)->zr_t{
1048 int imax = fcache.size();
1049 int i0 = i;
1050 if (i == -1) i0 = imax;
1051 const cachezr_t& s = fcache[i0];
1052 double is = sqrt(s.is2);
1053 return {s.dr * is, -s.dz * is};
1054 };
1055 return getn(iseg);
1056
1057 if (t < 0.0) {
1058 const cachezr_t& s = fcache[iseg];
1059 zr_t dist = {r.z - s.z, r.r - s.r};
1060 double dist2 = dist.z * dist.z + dist.r * dist.r;
1061 if (dist2 > 1e-18) {
1062 double q = 1 / sqrt(dist2);
1063 if (wn_poly(r) == 2) q = -q;
1064 return {dist.z * q, dist.r * q};
1065 } else {
1066 zr_t n = getn(iseg), np = getn(iseg - 1);
1067 n.z += np.z; n.r += np.r;
1068 double n2 = n.z * n.z + n.r * n.r;
1069 double q = 1 / sqrt(n2);
1070 n.z *= q, n.r *= q;
1071 return n;
1072 }
1073 }
1074 return getn(iseg);
1075}

◆ operator=()

BelleLathe & operator= ( const BelleLathe & rhs)

assignment operator

Definition at line 306 of file BelleLathe.cc.

307{
308 // Check assignment to self
309 if (this == &rhs) { return *this; }
310
311 // Copy base class data
312 G4CSGSolid::operator=(rhs);
313
314 // Copy data
315 fcontour = rhs.fcontour;
316 fcache = rhs.fcache;
317 fz = rhs.fz;
318 findx = rhs.findx;
319 fseg = rhs.fseg;
320 farea = rhs.farea;
321 ftlist = rhs.ftlist;
322 fphi = rhs.fphi;
323 fdphi = rhs.fdphi;
324 fs0 = rhs.fs0;
325 fc0 = rhs.fc0;
326 fs1 = rhs.fs1;
327 fc1 = rhs.fc1;
328 fn0x = rhs.fn0x;
329 fn0y = rhs.fn0y;
330 fn1x = rhs.fn1x;
331 fn1y = rhs.fn1y;
332 frmin = rhs.frmin;
333 frmax = rhs.frmax;
334 fzmin = rhs.fzmin;
335 fzmax = rhs.fzmax;
336 fgtpi = rhs.fgtpi;
337 ftwopi = rhs.ftwopi;
338 fshape = rhs.fshape;
339 fsurf = rhs.fsurf;
340 return *this;
341}

◆ StreamInfo()

std::ostream & StreamInfo ( std::ostream & os) const

Stream object contents to an output stream.

Definition at line 1824 of file BelleLathe.cc.

1825{
1826 G4int oldprc = os.precision(16);
1827 os << "-----------------------------------------------------------\n"
1828 << " *** Dump for solid - " << GetName() << " ***\n"
1829 << " ===================================================\n"
1830 << " Solid type: BelleLathe\n"
1831 << " Contour: " << fcontour.size() << " sides, {z, r} points \n";
1832 for (int i = 0, imax = fcontour.size(); i < imax; i++) {
1833 os << fcontour[i] << ", ";
1834 }
1835 os << "\n";
1836 for (int i = 0, imax = fcontour.size(); i < imax; i++) {
1837 os << fcache[i].isconvex << ", ";
1838 }
1839 os << "\n";
1840 os << "phi0 = " << fphi << ", dphi = " << fdphi << ", Full Circle = " << (ftwopi ? "yes" : "no") << "\n";
1841 double xmin = fzmin - 0.05 * (fzmax - fzmin), xmax = fzmax + 0.05 * (fzmax - fzmin);
1842 double ymin = frmin - 0.05 * (frmax - frmin), ymax = frmax + 0.05 * (frmax - frmin);
1843 os << " BB: " << xmin << ", " << xmax << ", " << ymin << ", " << ymax << endl;
1844 os << "-----------------------------------------------------------\n";
1845 os.precision(oldprc);
1846
1847 return os;
1848}

◆ SurfaceNormal()

G4ThreeVector SurfaceNormal ( const G4ThreeVector & p) const

Calculate side nearest to p, and return normal.

Definition at line 1079 of file BelleLathe.cc.

1080{
1081 COUNTER(1);
1082
1083 auto side = [this](const zr_t & r, double d, int iside) {
1084 double nx = (iside) ? fn1x : fn0x, ny = (iside) ? fn1y : fn0y;
1085 if (wn_poly(r) == 2) return G4ThreeVector(nx, ny, 0);
1086 double cphi = (iside) ? fc1 : fc0, sphi = (iside) ? fs1 : fc0;
1087
1088 double d2; zr_t n = normal(r, d2);
1089 double x = cphi * n.r, y = sphi * n.r;
1090 double u = sqrt(d2);
1091 d2 += d * d;
1092 G4ThreeVector res;
1093 if (d2 > 0) {
1094 double q = 1 / sqrt(d2);
1095 double cpsi = u * q, spsi = d * q;
1096 res.set(x * cpsi - y * spsi, x * spsi + y * cpsi, n.z);
1097 }
1098 res.set(x, y, n.z);
1099 return res;
1100 };
1101
1102 G4ThreeVector res;
1103 zr_t r = {p.z(), p.perp()};
1104 double d2; zr_t n = normal(r, d2);
1105 double d = sqrt(d2);
1106 double pt = hypot(p.x(), p.y());
1107
1108 if (pt > 0) {
1109 double ir = n.r / pt;
1110 res = G4ThreeVector(ir * p.x(), ir * p.y(), n.z);
1111 } else
1112 res = G4ThreeVector(n.r, 0, n.z);
1113
1114 if (!ftwopi) {
1115 double d0 = fn0x * p.x() + fn0y * p.y();
1116 double d1 = fn1x * p.x() + fn1y * p.y();
1117 zr_t r0 = {p.z(), fc0 * p.x() + fs0 * p.y()}; // projection on plane phi
1118 zr_t r1 = {p.z(), fc1 * p.x() + fs1 * p.y()}; // projection on plane phi+dphi
1119 if (fgtpi) {
1120 if (d0 > 0 && d1 > 0) { // outside sector
1121 if (d0 < d1) {
1122 res = side(r0, d0, 0); goto exit;
1123 } else {
1124 res = side(r1, -d1, 1); goto exit;
1125 }
1126 } else {// inside sector
1127 if (wn_poly(r) == 2) { // point p inside the solid
1128 if (abs(d0) < d && abs(d0) < abs(d1)) { res = G4ThreeVector(fn0x, fn0y, 0); goto exit;}
1129 if (abs(d1) < d && abs(d1) < abs(d0)) { res = G4ThreeVector(fn1x, fn1y, 0); goto exit;}
1130 }
1131 }
1132 } else {
1133 if (d0 > 0 || d1 > 0) { // outside sector
1134 if (d0 < 0) {
1135 res = side(r1, -d1, 1); goto exit;
1136 } else {
1137 res = side(r0, d0, 0); goto exit;
1138 }
1139 } else {
1140 if (wn_poly(r) == 2) { // point p inside the solid
1141 if (abs(d0) < d && abs(d0) < abs(d1)) { res = G4ThreeVector(fn0x, fn0y, 0); goto exit;}
1142 if (abs(d1) < d && abs(d1) < abs(d0)) { res = G4ThreeVector(fn1x, fn1y, 0); goto exit;}
1143 }
1144 }
1145 }
1146 }
1147exit:
1148#if COMPARE==1
1149 G4ThreeVector dd = fshape->SurfaceNormal(p);
1150 if ((res - dd).mag() > 1e-11) {
1151 int oldprec = cout.precision(16);
1152 EInside inside = fshape->Inside(p);
1153 cout << GetName() << " SurfaceNormal(p) " << p << " " << res << " " << dd << " " << res - dd << " " << inside << endl;
1154 cout.precision(oldprec);
1155 // _exit(0);
1156 }
1157#endif
1158 MATCHOUT("BelleLathe::SurfaceNormal(p,n) " << p << " res= " << res);
1159 return res;
1160}
zr_t normal(const zr_t &, double &) const
return normal

◆ wn_poly()

int wn_poly ( const zr_t & r) const
protected

wn_poly

Definition at line 947 of file BelleLathe.cc.

948{
949 int wn = 0;
950 vector<double>::const_iterator it = upper_bound(fz.begin(), fz.end(), r.z);
951 // cout<<r<<" "<<fz.size()<<" "<<it-fz.begin()<<endl;
952 if (it != fz.begin() && it != fz.end()) {
953 int k = it - fz.begin();
954 for (int i = findx[k - 1]; i != findx[k]; i++) {
955 const cachezr_t& s = fcache[fseg[i]];
956 double dz = r.z - s.z, dr = r.r - s.r;
957 double crs = s.dr * dz - s.dz * dr;
958 wn -= (crs > 0) - (crs < 0);
959 }
960 }
961 return wn;
962}

Member Data Documentation

◆ farea

std::vector<double> farea
mutableprivate

vector of area values

Definition at line 176 of file BelleLathe.h.

◆ fc0

double fc0 = 0.0
private

fc0

Definition at line 182 of file BelleLathe.h.

◆ fc1

double fc1 = 0.0
private

fc1

Definition at line 184 of file BelleLathe.h.

◆ fcache

std::vector<cachezr_t> fcache
private

vector of cached zr structs

Definition at line 172 of file BelleLathe.h.

◆ fcontour

std::vector<zr_t> fcontour
private

vector of zr structs

Definition at line 171 of file BelleLathe.h.

◆ fdphi

double fdphi = 0.0
private

finishing angle

Definition at line 180 of file BelleLathe.h.

◆ fgtpi

bool fgtpi
private

greater than pi?

Definition at line 193 of file BelleLathe.h.

◆ findx

std::vector<int> findx
private

vector of indices

Definition at line 174 of file BelleLathe.h.

◆ fn0x

double fn0x = 0.0
private

fn0x

Definition at line 185 of file BelleLathe.h.

◆ fn0y

double fn0y = 0.0
private

fn0y

Definition at line 186 of file BelleLathe.h.

◆ fn1x

double fn1x = 0.0
private

fn1x

Definition at line 187 of file BelleLathe.h.

◆ fn1y

double fn1y = 0.0
private

fn1y

Definition at line 188 of file BelleLathe.h.

◆ fphi

double fphi = 0.0
private

starting angle

Definition at line 179 of file BelleLathe.h.

◆ frmax

double frmax = 0.0
private

maximal r value

Definition at line 190 of file BelleLathe.h.

◆ frmin

double frmin = 0.0
private

minimal r value

Definition at line 189 of file BelleLathe.h.

◆ fs0

double fs0 = 0.0
private

fs0

Definition at line 181 of file BelleLathe.h.

◆ fs1

double fs1 = 0.0
private

fs1

Definition at line 183 of file BelleLathe.h.

◆ fseg

std::vector<int> fseg
private

vector of segments

Definition at line 175 of file BelleLathe.h.

◆ fshape

G4VSolid* fshape = nullptr
private

shape

Definition at line 196 of file BelleLathe.h.

◆ fsurf

std::vector<G4ThreeVector> fsurf
mutableprivate

vector of surfaces

Definition at line 197 of file BelleLathe.h.

◆ ftlist

std::vector<triangle_t> ftlist
mutableprivate

vector of triangle structs

Definition at line 177 of file BelleLathe.h.

◆ ftwopi

bool ftwopi
private

bound within +- 2pi?

Definition at line 194 of file BelleLathe.h.

◆ fz

std::vector<double> fz
private

vector of z values

Definition at line 173 of file BelleLathe.h.

◆ fzmax

double fzmax = 0.0
private

maximal z value

Definition at line 192 of file BelleLathe.h.

◆ fzmin

double fzmin = 0.0
private

minimal z value

Definition at line 191 of file BelleLathe.h.


The documentation for this class was generated from the following files: