10#include <ecl/geometry/BelleLathe.h>
13#include <G4AffineTransform.hh>
14#include <G4VoxelLimits.hh>
15#include <G4VGraphicsScene.hh>
16#include <G4VPVParameterisation.hh>
19#include <CLHEP/Random/RandFlat.h>
28typedef int counter_t[6];
29map<string, counter_t> counterl;
30#define COUNTER(x) counterl[GetName()][x]++
53 inline double dotxy(
const G4ThreeVector& p,
const G4ThreeVector& n)
55 return p.x() * n.x() + p.y() * n.y();
61ostream& operator <<(ostream& o,
const zr_t& v)
63 return o <<
"{" << v.
z <<
", " << v.
r <<
"}";
70 explicit curl_t(
const G4ThreeVector& _v):
v(_v) {}
73ostream& operator <<(ostream& o,
const curl_t& c)
75 return o <<
"{" << c.v.x() <<
", " << c.v.y() <<
", " << c.v.z() <<
"}, ";
89 for (
int i = 0; i < n; i++) {
90 zr_t t = {z[i], rin[i]};
93 for (
int i = n - 1; i >= 0; i--) {
94 zr_t t = {z[i], rout[i]};
98 Init(contour, phi0, dphi);
103 vector<zr_t> contour = c;
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);
115 const zr_t& s0 = *it0, &s1 = contour[0];
116 if (abs(s0.
z - s1.z) < kCarTolerance && abs(s0.
r - s1.r) < kCarTolerance) contour.erase(it0);
121 vector<zr_t>::iterator it0 = contour.begin(), it1 = it0 + 1, it2 = it1 + 1;
122 for (; it0 != contour.end();) {
123 const zr_t& s0 = *it0, &s1 = *it1, &s2 = *it2;
124 double dr2 = s2.
r - s0.
r, dz2 = s2.z - s0.
z;
125 double d = (s1.z - s0.
z) * dr2 - (s1.r - s0.
r) * dz2;
127 if (d * d < kCarTolerance * kCarTolerance * (dr2 * dr2 + dz2 * dz2)) {
128 it1 = contour.erase(it1);
130 if (++it2 >= contour.end()) it2 = contour.begin();
132 if (--it0 < contour.begin()) it0 = (++contour.rbegin()).base();
136 if (++it1 >= contour.end()) it1 = contour.begin();
137 if (++it2 >= contour.end()) it2 = contour.begin();
144 zr_t p0 = contour[0];
145 for (
int i = 1, imax = contour.size(); i < imax; i++) {
146 zr_t p1 = contour[i];
147 sum += (p1.z - p0.
z) * (p1.r + p0.
r);
150 zr_t p1 = contour[0];
151 sum += (p1.z - p0.
z) * (p1.r + p0.
r);
155 std::reverse(contour.begin(), contour.end());
159 auto convexside = [
this](
cachezr_t& s,
double eps) ->
void {
161 if (s.dz > 0)
return;
162 vector<zr_t>::const_iterator it =
fcontour.begin();
163 double a = s.dz * s.is, b = s.dr * s.is, cc = b * s.z - a * s.r;
164 bool dp =
false, dm =
false;
169 double d = a * p.r - b * p.z + cc;
170 dm = dm || (d < -eps);
171 dp = dp || (d > eps);
172 if (dm && dp) {s.isconvex =
false;
return;}
181 for (
int i = 0, n =
fcontour.size(); i < n; i++) {
188 t.s2 = t.dz * t.dz + t.dr * t.dr;
191 t.zmin = min(s0.
z, s1.z);
192 t.zmax = max(s0.
z, s1.z);
193 t.r2min = pow(min(s0.
r, s1.r), 2);
194 t.r2max = pow(max(s0.
r, s1.r), 2);
195 t.ta = (s1.r - s0.
r) / (s1.z - s0.
z);
196 convexside(t, kCarTolerance);
224 for (
int i = 0, n =
fcontour.size(); i < n; i++) {
228 sort(
fz.begin(),
fz.end());
229 fz.erase(std::unique(
fz.begin(),
fz.end()),
fz.end());
231 for (
int i = 1, ni =
fz.size(); i < ni; i++) {
232 double a =
fz[i - 1], b =
fz[i];
234 for (
int j = 0, nj =
fcache.size(); j < nj; j++) {
237 if (cc != d and b > cc and d > a) {
247 auto getpolycone = [](
const G4String & pName,
double phi0,
double dphi,
const vector<zr_t>& c) -> G4GenericPolycone* {
251 for (
int i = 0, imax = c.size(); i < imax; i++)
256 return new G4GenericPolycone(pName, phi0, dphi, c.size(), r.data(), z.data());
272 Init(a, 0, 2 * M_PI);
281 Init(b, 0, 2 * M_PI);
288 cout << GetName() <<
" ";
289 for (
int i = 0; i < 6; i++) cout << counterl[GetName()][i] <<
" "; cout << endl;
295 : G4CSGSolid(rhs), fcontour(rhs.fcontour), fcache(rhs.fcache), fz(rhs.fz),
296 findx(rhs.findx), fseg(rhs.fseg), farea(rhs.farea), ftlist(rhs.ftlist),
297 fphi(rhs.fphi), fdphi(rhs.fdphi), fs0(rhs.fs0), fc0(rhs.fc0), fs1(rhs.fs1),
298 fc1(rhs.fc1), fn0x(rhs.fn0x), fn0y(rhs.fn0y), fn1x(rhs.fn1x), fn1y(rhs.fn1y),
299 frmin(rhs.frmin), frmax(rhs.frmax), fzmin(rhs.fzmin), fzmax(rhs.fzmax),
300 fgtpi(rhs.fgtpi), ftwopi(rhs.ftwopi), fshape(rhs.fshape), fsurf(rhs.fsurf)
308 if (
this == &rhs) {
return *
this; }
311 G4CSGSolid::operator=(rhs);
347 const G4VPhysicalVolume*)
349 G4Exception(
"BelleLathe::ComputeDimensions()",
350 "GeomSolids0001", FatalException,
351 "BelleLathe does not support Parameterisation.");
356vector<double> quadsolve(
double a,
double b,
double c)
361 double D = b * b - a * c;
364 double sum = b + ((b > 0) ? sD : -sD);
365 double t0 = -c / sum;
366 double t1 = -sum / a;
376inline int quadsolve(
double a,
double b,
double c,
double& t0,
double& t1)
380 double D = b * b - a * c;
383 double sum = b + ((b > 0) ? sD : -sD);
396vector<solution_t> extremum(
double A,
double B,
double C,
double D,
double E,
double F)
399 vector<solution_t> res;
400 if (abs(B) < abs(A)) {
401 double a = 4 * A * C - B * B;
402 double b = 2 * (2 * A *
E - B * D);
403 double c = 4 * A * F - D * D;
404 vector<double> ss = quadsolve(a, b, c);
406 if (fpclassify(s) == FP_INFINITE)
continue;
407 double t = -(s * B + D) / (2 * A);
412 double B2 = B * B, CD = C * D, BE = B *
E;
413 double a = A * (4 * A * C - B2);
414 double b = 2 * A * (2 * CD - BE);
415 double c = D * (CD - BE) + B2 * F;
416 vector<double> ts = quadsolve(a, b, c);
418 if (fpclassify(t) == FP_INFINITE)
continue;
419 double s = -(2 * t * A + D) / B;
430 auto hitside = [
this, &p, &n](
double t,
double zmin,
double zmax) ->
bool {
431 double z = p.z() + n.z() * t;
432 bool k = zmin < z && z <= zmax;
435 double x = p.x() + n.x() * t;
436 double y = p.y() + n.y() * t;
442 auto hitzside = [
this, &p, &n](
double t,
double r2min,
double r2max) ->
bool {
443 double x = p.x() + n.x() * t;
444 double y = p.y() + n.y() * t;
445 double r2 = x * x + y * y;
446 bool k = r2min <= r2 && r2 < r2max;
455 double inz = 1 / n.z();
456 double nn = Belle2::ECL::dotxy(n, n), np = dotxy(n, p), pp = dotxy(p, p);
459 double t = (s.z - p.z()) * inz;
460 if (hitzside(t, s.r2min, s.r2max)) { tc.push_back(t); }
471 double taz = ta * (p.z() - s.z);
472 double R = taz + s.r;
475 double nzta = n.z() * ta;
476 A = nzta * nzta - nn;
479 double D = B * B + (pp - R2) * A;
481 double sD =
sqrt(D), iA = 1 / A;
482 double t0 = (B + sD) * iA, t1 = (B - sD) * iA;
483 if (hitside(t0, s.zmin, s.zmax)) tc.push_back(t0);
484 if (hitside(t1, s.zmin, s.zmax)) tc.push_back(t1);
491 double d =
fn0x * p.x() +
fn0y * p.y();
492 double vn =
fn0x * n.x() +
fn0y * n.y();
494 G4ThreeVector r = p + n * t;
496 if (vn != 0 &&
wn_poly(zr) == 2) tc.push_back(t);
500 double d =
fn1x * p.x() +
fn1y * p.y();
501 double vn =
fn1x * n.x() +
fn1y * n.y();
503 G4ThreeVector r = p + n * t;
505 if (vn != 0 &&
wn_poly(zr) == 2) tc.push_back(t);
509 sort(tc.begin(), tc.end());
515 const G4VoxelLimits& bb,
516 const G4AffineTransform& T,
517 G4double& pMin, G4double& pMax)
const
519 auto maxdist = [
this](
const G4ThreeVector & n) -> G4ThreeVector {
521 int i = 0, nsize =
fcache.size();
524 double nr = hypot(n.x(), n.y()), nz = n.z();
525 double dmax = -kInfinity,
R = 0, Z = 0;
528 double d1 = nz * s.z + nr * s.r;
529 if (dmax < d1) {
R = s.r; Z = s.z; dmax = d1;}
530 }
while (++i < nsize);
533 r.set(
R * n.x(),
R * n.y(), Z);
536 r.set(
R * cos(phi),
R * sin(phi), Z);
540 double dmax = -kInfinity;
544 G4ThreeVector rf(-
fn0y * s.r,
fn0x * s.r, s.z), rl(
fn1y * s.r, -
fn1x * s.r, s.z);
545 double d0 = rf * n, d1 = rl * n;
547 if (dmax < d0) { r = rf; dmax = d0;}
548 if (dmax < d1) { r = rl; dmax = d1;}
549 }
while (++i < nsize);
554 struct seg_t {
int i0, i1;};
555 auto clip = [](vector<G4ThreeVector>& vlist, vector<seg_t>& slist,
const G4ThreeVector & n,
double dist) {
560 for (
const G4ThreeVector& v : vlist) d.push_back(v * n + dist);
562 for (seg_t s : slist) {
563 double prod = d[s.i0] * d[s.i1];
566 G4ThreeVector
rn = (vlist[s.i0] * d[s.i1] - vlist[s.i1] * d[s.i0]) * (1 / (d[s.i1] - d[s.i0]));
567 lone.push_back(vlist.size()); vlist.push_back(
rn);
569 s = {lone.back(), s.i1};
571 s = {s.i0, lone.back()};
573 }
else if (prod == 0) {
574 if (d[s.i0] == 0 && d[s.i1] > 0) {
575 lone.push_back(s.i0);
576 }
else if (d[s.i0] > 0 && d[s.i1] == 0) {
577 lone.push_back(s.i1);
580 if (d[s.i0] < 0)
continue;
586 int imax = -1, jmax = -1;
588 for (
unsigned int i = 0; i < lone.size(); i++) {
589 for (
unsigned int j = i + 1; j < lone.size(); j++) {
590 double d2 = (vlist[lone[i]] - vlist[lone[j]]).mag2();
591 if (d2 > dmax) { imax = lone[i]; jmax = lone[j];}
597 G4ThreeVector k = vlist[jmax] - vlist[imax];
598 sort(lone.begin(), lone.end(), [&k, &vlist, &imax](
int i,
int j) {return k * (vlist[i] - vlist[imax]) < k * (vlist[j] - vlist[imax]);});
600 for (
unsigned int i = 0; i < lone.size(); i += 2) {
601 seg_t t = {lone[i], lone[i + 1]};
602 for (
const seg_t& s : snew) {
603 if (t.i1 == s.i0) { snew.push_back(t);
break;}
604 if (t.i0 == s.i0) { swap(t.i0, t.i1); snew.push_back(t);
break;}
611 auto PhiCrossN = [
this, clip](
const vector<Plane_t>& planes) {
614 vector<G4ThreeVector> vlist;
616 vector<G4ThreeVector> res;
618 int nsize =
fcache.size();
619 vlist.reserve(nsize);
620 slist.reserve(nsize);
621 for (
int iphi = 0; iphi < 2; iphi++) {
630 G4ThreeVector r(kx * s.r, ky * s.r, s.z);
632 seg_t t = {i, i + 1};
634 }
while (++i < nsize - 1);
636 G4ThreeVector r(kx * s.r, ky * s.r, s.z);
638 seg_t t = {nsize - 1, 0};
643 for (
const Plane_t& p : planes) {
645 clip(vlist, slist, p.n, p.d);
648 vector<bool> bv(vlist.size(),
false);
650 for (vector<seg_t>::const_iterator it = slist.begin(); it != slist.end(); ++it) {
655 for (
unsigned int i = 0; i < vlist.size(); i++) {
656 if (!bv[i])
continue;
657 res.push_back(vlist[i]);
663 auto RCross = [
this](
const G4ThreeVector & op,
const G4ThreeVector & k,
const G4ThreeVector & u) {
666 vector<solution_t> ts;
667 int nsize =
fcache.size();
673 double r0 = seg.
r, z0 = seg.
z, tg = seg.
ta, tg2 = tg * tg;
674 double rtg = r0 * tg;
676 G4ThreeVector o(op.x(), op.y(), op.z() - z0);
678 double ko = k * o, uo = u * o, ck = k.z(), cu = u.z(), co = o.z();
679 double k2 = 1, u2 = 1, o2 = o * o;
680 double ck2 = ck * ck, cu2 = cu * cu, co2 = co * co;
681 double dr2 = r0 * r0 - o2;
684 double q1 = co * q0 + rtg;
686 double F00 = co2 * q0 + 2 * co * rtg + dr2;
687 double F10 = 2 * (ck * q1 - ko);
688 double F20 = ck2 * q0 - k2;
689 double F01 = 2 * (cu * q1 - uo);
690 double F11 = 2 * ck * cu * q0;
691 double F02 = cu2 * q0 - u2;
693 vector<solution_t> res = extremum(F02, F11, F20, F01, F10, F00);
695 double t = r.s, s = r.t;
696 G4ThreeVector p = t * k + s * u + op;
697 if (seg.
zmin < p.z() && p.z() < seg.
zmax) {
704 double a = -(ck2 * u2 + cu2 * k2);
706 if (abs(cu) > abs(ck)) {
707 double b = 2 * (ck * (cu * uo - co * u2) - cu2 * ko);
708 double c = co * (2 * cu * uo - co * u2) + cu2 * dr2;
709 vector<double> tv = quadsolve(a, b, c);
710 for (
double t : tv) {
711 double s = -(co + ck * t) / cu;
712 G4ThreeVector p = t * k + s * u + op;
719 double b = 2 * (cu * (ck * ko - co * k2) - ck2 * uo);
720 double c = co * (2 * ck * ko - co * k2) + ck2 * dr2;
721 vector<double> sv = quadsolve(a, b, c);
722 for (
double s : sv) {
723 double t = -(co + cu * s) / ck;
724 G4ThreeVector p = t * k + s * u + op;
732 }
while (++i < nsize);
736 bool b1 =
false, b2 =
false;
737 G4ThreeVector n0, n1, n2;
739 case kXAxis: n0.set(1, 0, 0); n1.set(0, 1, 0); n2.set(0, 0, 1); b1 = bb.IsYLimited(); b2 = bb.IsZLimited();
break;
740 case kYAxis: n0.set(0, 1, 0); n1.set(1, 0, 0); n2.set(0, 0, 1); b1 = bb.IsXLimited(); b2 = bb.IsZLimited();
break;
741 case kZAxis: n0.set(0, 0, 1); n1.set(1, 0, 0); n2.set(0, 1, 0); b1 = bb.IsXLimited(); b2 = bb.IsYLimited();
break;
745 double dmin1 = -kInfinity, dmax1 = kInfinity;
748 case kXAxis: dmin1 = bb.GetMinYExtent(); dmax1 = bb.GetMaxYExtent();
break;
749 case kYAxis: dmin1 = bb.GetMinXExtent(); dmax1 = bb.GetMaxXExtent();
break;
750 case kZAxis: dmin1 = bb.GetMinXExtent(); dmax1 = bb.GetMaxXExtent();
break;
755 double dmin2 = -kInfinity, dmax2 = kInfinity;
758 case kXAxis: dmin2 = bb.GetMinZExtent(); dmax2 = bb.GetMaxZExtent();
break;
759 case kYAxis: dmin2 = bb.GetMinZExtent(); dmax2 = bb.GetMaxZExtent();
break;
760 case kZAxis: dmin2 = bb.GetMinYExtent(); dmax2 = bb.GetMaxYExtent();
break;
765 G4AffineTransform iT = T.Inverse();
767 G4ThreeVector n0t = iT.TransformAxis(n0);
768 G4ThreeVector smin = n0t * kInfinity, smax = (-kInfinity) * n0t;
769 double pmin = kInfinity, pmax = -pmin;
771 G4ThreeVector corners[] = {n1* dmin1 + n2 * dmin2, n1* dmax1 + n2 * dmin2, n1* dmax1 + n2 * dmax2, n1* dmin1 + n2 * dmax2};
772 for (G4ThreeVector& c : corners) iT.ApplyPointTransform(c);
774 vector<Plane_t> planes;
775 for (
int i = 0; i < 4; i++) {
776 const G4ThreeVector& c0 = corners[i], &c1 = corners[(i + 1) % 4];
777 vector<double> dists =
linecross(c0, n0t);
779 for (
double t : dists) {
780 G4ThreeVector p = n0t * t + c0;
781 double tt = t + c0 * n0t;
783 if (pmax < tt) { pmax = tt; smax = p;}
784 if (pmin > tt) { pmin = tt; smin = p;}
787 G4ThreeVector u = c1 - c0, un = u.unit();
788 vector<solution_t> ts = RCross(c0, n0t, un);
789 double umax = u.mag();
791 if (0 < r.s && r.s < umax) {
792 double tt = r.t + c0 * n0t;
793 G4ThreeVector p = n0t * r.t + un * r.s + c0;
795 if (pmax < tt) { pmax = tt; smax = p;}
796 if (pmin > tt) { pmin = tt; smin = p;}
799 planes.push_back({ -un, un * c1});
802 vector<G4ThreeVector> vside = PhiCrossN(planes);
803 for (G4ThreeVector& p : vside) {
806 if (pmax < tt) { pmax = tt; smax = p;}
807 if (pmin > tt) { pmin = tt; smin = p;}
810 }
else if (b1 || b2) {
811 G4ThreeVector limits[2], u;
813 limits[0] = n1 * dmin1;
814 limits[1] = n1 * dmax1;
815 u = iT.TransformAxis(n2);
817 limits[0] = n2 * dmin2;
818 limits[1] = n2 * dmax2;
819 u = iT.TransformAxis(n1);
822 for (G4ThreeVector& c : limits) iT.ApplyPointTransform(c);
823 for (
int i = 0; i < 2; i++) {
824 vector<solution_t> ts = RCross(limits[i], n0t, u);
826 double tt = r.t + limits[i] * n0t;
827 G4ThreeVector p = n0t * r.t + u * r.s + limits[i];
829 if (pmax < tt) { pmax = tt; smax = p;}
830 if (pmin > tt) { pmin = tt; smin = p;}
834 vector<Plane_t> planes(2);
837 n = iT.TransformAxis(n1);
839 n = iT.TransformAxis(n2);
841 planes[0] = { n, -limits[0]* n};
842 planes[1] = { -n, limits[1]* n};
843 vector<G4ThreeVector> vside = PhiCrossN(planes);
845 for (G4ThreeVector& p : vside) {
849 if (pmax < tt) { pmax = tt; smax = p;}
850 if (pmin > tt) { pmin = tt; smin = p;}
854 G4ThreeVector rp = maxdist(n0t), rm = maxdist(-n0t);
855 if (bb.Inside(T.TransformPoint(rm))) {
856 double tt = rm * n0t;
857 if (pmin > tt) {pmin = tt; smin = rm;}
859 if (bb.Inside(T.TransformPoint(rp))) {
860 double tt = rp * n0t;
861 if (pmax < tt) {pmax = tt; smax = rp;}
865 T.ApplyPointTransform(smin);
866 T.ApplyPointTransform(smax);
870 pmin -= kCarTolerance;
871 pmax += kCarTolerance;
873 bool hit = pmin < pmax;
876 auto surfhit = [
this, &bb, &T, &n0, &n0t](
double & pmin,
double & pmax,
bool print =
false)->
bool {
877 const int N = 1000 * 1000;
880 int umin = -1, umax = -1;
881 double wmin = 1e99, wmax = -1e99;
882 for (
int i = 0; i < N; i++)
884 if (bb.Inside(T.TransformPoint(
fsurf[i]))) {
885 double w = n0t *
fsurf[i];
886 if (wmin > w) {wmin = w; umin = i;}
887 if (wmax < w) {wmax = w; umax = i;}
890 if (print)cout << umin <<
" " << umax <<
" " << wmin <<
" " << wmax << endl;
891 if (umin >= 0 && umax >= 0)
893 G4ThreeVector qmin =
fsurf[umin], qmax =
fsurf[umax];
894 T.ApplyPointTransform(qmin);
895 T.ApplyPointTransform(qmax);
896 pmin = n0 * qmin, pmax = n0 * qmax;
902 bool res =
fshape->CalculateExtent(A, bb, T, pMin, pMax);
903 double srfmin = kInfinity, srfmax = -srfmin;
904 bool sHit = surfhit(srfmin, srfmax);
905 double diff = kCarTolerance;
908 if ((abs(pmin - srfmin) > diff || abs(pmax - srfmax) > diff) && sHit) {
909 cout <<
"===================================\n";
911 cout << hit <<
" " << res <<
" " << b1 <<
" " << b2 <<
"\n";
913 cout <<
"ss " << srfmin <<
" " << srfmax <<
"\n";
915 cout <<
"ss : not in bounding box" <<
"\n";
917 cout <<
"my " << pmin <<
" " << pmax <<
"\n";
918 cout <<
"tc " << pMin <<
" " << pMax <<
"\n";
919 cout <<
"df " << pmin - pMin <<
" " << pmax - pMax <<
"\n";
920 G4ThreeVector bmin(bb.GetMinXExtent(), bb.GetMinYExtent(), bb.GetMinZExtent());
921 G4ThreeVector bmax(bb.GetMaxXExtent(), bb.GetMaxYExtent(), bb.GetMaxZExtent());
922 cout <<
"Axis=" << A <<
" " << bmin <<
" " << bmax <<
" " << T <<
"\n";
923 cout << rp <<
" " << rm <<
"\n";
924 cout << smin <<
" " << smax <<
"\n";
941 bool b0 = d0 < 0, b1 = d1 < 0;
942 return fgtpi ? b0 || b1 : b0 && b1;
948 vector<double>::const_iterator it = upper_bound(
fz.begin(),
fz.end(), r.z);
950 if (it !=
fz.begin() && it !=
fz.end()) {
951 int k = it -
fz.begin();
952 for (
int i =
findx[k - 1]; i !=
findx[k]; i++) {
954 double dz = r.z - s.z, dr = r.r - s.r;
955 double crs = s.dr * dz - s.dz * dr;
956 wn -= (crs > 0) - (crs < 0);
964 double d = kInfinity;
965 int i = 0, n =
fcache.size();
968 double dz = r.z - s.z, dr = r.r - s.r;
969 double dot = s.dz * dz + s.dr * dr;
971 d = min(d, dz * dz + dr * dr);
972 }
else if (
dot <= s.s2) {
973 double crs = s.dr * dz - s.dz * dr;
974 d = min(d, crs * crs * s.is2);
978 d = (
wn_poly(r) == 2) ? -d : d;
986 const double delta = 0.5 * kCarTolerance;
987 EInside res = kInside;
989 double d0 =
fn0x * p.x() +
fn0y * p.y();
990 double d1 =
fn1x * p.x() +
fn1y * p.y();
992 if (d0 > delta && d1 > delta) { res = kOutside;}
993 else if (d0 > -delta && d1 > -delta) { res = kSurface;}
995 if (d0 > delta || d1 > delta) { res = kOutside;}
996 else if (d0 > -delta || d1 > -delta) { res = kSurface;}
999 if (res != kOutside) {
1000 zr_t r = {p.z(), p.perp()};
1002 if (res == kSurface && d < delta) res = kSurface;
1003 else if (d > delta) res = kOutside;
1004 else if (d > -delta) res = kSurface;
1009 EInside dd =
fshape->Inside(p);
1010 if (1 || dd != res) {
1011 double d0 =
fn0x * p.x() +
fn0y * p.y();
1012 double d1 =
fn1x * p.x() +
fn1y * p.y();
1014 int oldprec = cout.precision(16);
1015 zr_t r = {p.z(), p.perp()};
1016 cout << GetName() <<
" Inside(p) " << p <<
" " << r <<
" my=" << res <<
" tc=" << dd <<
1017 " dist=" <<
mindist(r) <<
" " << d0 <<
" " << d1 << endl;
1018 cout.precision(oldprec);
1022 MATCHOUT(
"BelleLathe::Inside(p) " << p <<
" res= " << res);
1028 double d = std::numeric_limits<double>::infinity(), t = 0;
1030 for (
int i = 0, imax =
fcache.size(); i < imax; i++) {
1032 double dz = r.z - s.z, dr = r.r - s.r;
1033 double dot = s.dz * dz + s.dr * dr;
1035 double dist = dz * dz + dr * dr;
1036 if (dist < d) { d = dist; t =
dot * s.is2; iseg = i;}
1037 }
else if (
dot <= s.s2) {
1038 double crs = s.dr * dz - s.dz * dr;
1039 double dist = crs * crs * s.is2;
1040 if (dist < d) { d = dist; t =
dot * s.is2; iseg = i;}
1045 auto getn = [
this](
int i)->
zr_t{
1046 int imax =
fcache.size();
1048 if (i == -1) i0 = imax;
1050 double is =
sqrt(s.is2);
1051 return {s.dr * is, -s.dz * is};
1057 zr_t dist = {r.z - s.z, r.r - s.r};
1058 double dist2 = dist.
z * dist.
z + dist.
r * dist.
r;
1059 if (dist2 > 1e-18) {
1060 double q = 1 /
sqrt(dist2);
1062 return {dist.
z * q, dist.
r * q};
1064 zr_t n = getn(iseg), np = getn(iseg - 1);
1065 n.z += np.z; n.r += np.r;
1066 double n2 = n.z * n.z + n.r * n.r;
1067 double q = 1 /
sqrt(n2);
1081 auto side = [
this](
const zr_t & r,
double d,
int iside) {
1083 if (
wn_poly(r) == 2)
return G4ThreeVector(nx, ny, 0);
1084 double cphi = (iside) ?
fc1 :
fc0, sphi = (iside) ?
fs1 :
fc0;
1087 double x = cphi * n.r, y = sphi * n.r;
1088 double u =
sqrt(d2);
1092 double q = 1 /
sqrt(d2);
1093 double cpsi = u * q, spsi = d * q;
1094 res.set(x * cpsi - y * spsi, x * spsi + y * cpsi, n.z);
1101 zr_t r = {p.z(), p.perp()};
1103 double d =
sqrt(d2);
1104 double pt = hypot(p.x(), p.y());
1107 double ir = n.r / pt;
1108 res = G4ThreeVector(ir * p.x(), ir * p.y(), n.z);
1110 res = G4ThreeVector(n.r, 0, n.z);
1113 double d0 =
fn0x * p.x() +
fn0y * p.y();
1114 double d1 =
fn1x * p.x() +
fn1y * p.y();
1115 zr_t r0 = {p.z(),
fc0 * p.x() +
fs0 * p.y()};
1116 zr_t r1 = {p.z(),
fc1 * p.x() +
fs1 * p.y()};
1118 if (d0 > 0 && d1 > 0) {
1120 res = side(r0, d0, 0);
goto exit;
1122 res = side(r1, -d1, 1);
goto exit;
1126 if (abs(d0) < d && abs(d0) < abs(d1)) { res = G4ThreeVector(
fn0x,
fn0y, 0);
goto exit;}
1127 if (abs(d1) < d && abs(d1) < abs(d0)) { res = G4ThreeVector(
fn1x,
fn1y, 0);
goto exit;}
1131 if (d0 > 0 || d1 > 0) {
1133 res = side(r1, -d1, 1);
goto exit;
1135 res = side(r0, d0, 0);
goto exit;
1139 if (abs(d0) < d && abs(d0) < abs(d1)) { res = G4ThreeVector(
fn0x,
fn0y, 0);
goto exit;}
1140 if (abs(d1) < d && abs(d1) < abs(d0)) { res = G4ThreeVector(
fn1x,
fn1y, 0);
goto exit;}
1147 G4ThreeVector dd =
fshape->SurfaceNormal(p);
1148 if ((res - dd).mag() > 1e-11) {
1149 int oldprec = cout.precision(16);
1150 EInside inside =
fshape->Inside(p);
1151 cout << GetName() <<
" SurfaceNormal(p) " << p <<
" " << res <<
" " << dd <<
" " << res - dd <<
" " << inside << endl;
1152 cout.precision(oldprec);
1156 MATCHOUT(
"BelleLathe::SurfaceNormal(p,n) " << p <<
" res= " << res);
1169 zr_t r = {p.z(), p.perp()};
1172 double d0 =
fn0x * p.x() +
fn0y * p.y();
1173 double d1 =
fn1x * p.x() +
fn1y * p.y();
1176 if (d0 > 0 && d1 > 0) {
1185 zr_t r = {p.z(), p.perp()};
1189 if (d0 > 0 || d1 > 0) {
1198 zr_t r = {p.z(), p.perp()};
1205 double dd =
fshape->DistanceToIn(p);
1207 if (dd > d && abs(d - dd) > kCarTolerance) {
1208 int oldprec = cout.precision(16);
1209 EInside inside =
fshape->Inside(p);
1210 zr_t r = {p.z(), p.perp()};
1211 cout << GetName() <<
" DistanceToIn(p) " << p <<
" " << r <<
" " << d <<
" " << dd <<
" " << d - dd <<
" " << inside << endl;
1212 cout.precision(oldprec);
1216 MATCHOUT(
"BelleLathe::DistanceToIn(p) " << p <<
" res= " << d);
1226 zr_t r = {p.z(), p.perp()};
1229 double d0 =
fn0x * p.x() +
fn0y * p.y();
1230 double d1 =
fn1x * p.x() +
fn1y * p.y();
1232 d = max(d, min(d0, d1));
1234 d = max(d, max(d0, d1));
1239 double dd =
fshape->Inside(p) == 0 ? 0.0 :
fshape->DistanceToOut(p);
1240 if (abs(d - dd) > kCarTolerance) {
1241 int oldprec = cout.precision(16);
1242 zr_t r = {p.z(), p.perp()};
1244 cout << GetName() <<
" DistanceToOut(p) " << p <<
" " << r <<
" " << d <<
" " << dd <<
" " << d - dd << endl;
1245 cout.precision(oldprec);
1248 MATCHOUT(
"BelleLathe::DistanceToOut(p) " << p.x() <<
" " << p.y() <<
" " << p.z() <<
" res= " << d);
1256 auto getnormal = [
this, &p, &n](
int i,
double t) ->G4ThreeVector{
1257 const int imax =
fcache.size();
1261 }
else if (i < imax)
1265 o.setZ(copysign(1, s.dr));
1267 double x = p.x() + n.x() * t;
1268 double y = p.y() + n.y() * t;
1269 double sth = s.dr * s.is, cth = -s.dz * s.is;
1270 double ir = cth /
sqrt(x * x + y * y);
1271 o.set(x * ir, y * ir, sth);
1273 }
else if (i == imax)
1283 auto hitside = [
this, &p, &n](
double t,
const cachezr_t& s) ->
bool {
1284 double z = p.z() + n.z() * t;
1286 bool k = s.zmin < z && z <= s.zmax;
1289 double x = p.x() + n.x() * t;
1290 double y = p.y() + n.y() * t;
1296 auto hitzside = [
this, &p, &n](
double t,
const cachezr_t& s) ->
bool {
1297 double x = p.x() + n.x() * t;
1298 double y = p.y() + n.y() * t;
1299 double r2 = x * x + y * y;
1300 bool k = s.r2min <= r2 && r2 < s.r2max;
1308 auto hitphi0side = [
this, &p, &n](
double t) ->
bool {
1309 double x = p.x() + n.x() * t;
1310 double y = p.y() + n.y() * t;
1311 double r = x *
fc0 + y *
fs0;
1314 double z = p.z() + n.z() * t;
1321 auto hitphi1side = [
this, &p, &n](
double t) ->
bool {
1322 double x = p.x() + n.x() * t;
1323 double y = p.y() + n.y() * t;
1324 double r = x *
fc1 + y *
fs1;
1327 double z = p.z() + n.z() * t;
1334 double tmin = kInfinity;
1335 const int imax =
fcache.size();
1336 int iseg = -1, isurface = -1;
1337 const double delta = 0.5 * kCarTolerance;
1338 double inz = 1 / n.z();
1339 double nn = dotxy(n, n), np = dotxy(n, p), pp = dotxy(p, p);
1340 double pz = p.z(), pr =
sqrt(pp);
1341 for (
int i = 0; i < imax; i++) {
1343 double dz = pz - s.z, dr = pr - s.r;
1344 double d = dz * s.dr - dr * s.dz;
1345 bool surface =
false;
1346 if (abs(d * s.is) < delta) {
1347 double dot = dz * s.dz + dr * s.dr;
1348 if (
dot >= 0 &&
dot <= s.s2) {
1355 double t = -dz * inz;
1356 if (0 < t && t < tmin && hitzside(t, s)) { tmin = t; iseg = i;}
1367 double taz = s.ta * dz;
1368 double R = taz + s.r;
1371 double nzta = n.z() * s.ta;
1372 A = nzta * nzta - nn;
1376 double D = B * B + C * A;
1380 double sD =
sqrt(D), sum = B + copysign(sD, B);
1381 double t0 = -C / sum, t1 = sum / A;
1383 if (abs(t0) > abs(t1)) {
1384 if (t0 > 0 && t0 < tmin && hitside(t0, s)) { tmin = t0; iseg = i;}
1386 if (t1 > 0 && t1 < tmin && hitside(t1, s)) { tmin = t1; iseg = i;}
1389 if (t0 > 0 && t0 < tmin && hitside(t0, s)) { tmin = t0; iseg = i;}
1390 if (t1 > 0 && t1 < tmin && hitside(t1, s)) { tmin = t1; iseg = i;}
1398 double vn =
fn0x * n.x() +
fn0y * n.y();
1400 double d =
fn0x * p.x() +
fn0y * p.y();
1402 if (hitphi0side(t)) {
1403 bool surface = std::abs(d) < delta;
1405 tmin = 0; iseg = imax + 0;
1407 if (0 < t && t < tmin) {tmin = t; iseg = imax + 0;}
1415 double vn =
fn1x * n.x() +
fn1y * n.y();
1417 double d =
fn1x * p.x() +
fn1y * p.y();
1419 if (hitphi1side(t)) {
1420 bool surface = std::abs(d) < delta;
1422 tmin = 0; iseg = imax + 1;
1424 if (0 < t && t < tmin) { tmin = t; iseg = imax + 1;}
1432 if (getnormal(iseg, tmin)*n > 0) tmin = 0;
1436 auto convex = [
this, imax](
int i) ->
bool{
1438 return fcache[i].isconvex;
1443 if (tmin >= 0 && tmin < kInfinity) {
1444 if (isurface >= 0)
if (convex(isurface) && getnormal(isurface, 0)*n >= 0) tmin = kInfinity;
1446 if (
Inside(p) == kSurface) {
1447 if (isurface >= 0) {
1448 tmin = (getnormal(isurface, 0) * n >= 0) ? kInfinity : 0;
1455 double dd =
fshape->DistanceToIn(p, n);
1456 if (abs(tmin - dd) > 1e-10) {
1457 int oldprec = cout.precision(16);
1458 EInside inside =
fshape->Inside(p);
1459 cout << GetName() <<
" DistanceToIn(p,v) " << p <<
" " << n <<
" " << tmin <<
" " << dd <<
" " << tmin - dd <<
" " << inside <<
" "
1460 <<
Inside(p) <<
" iseg = " << iseg <<
" " << isurface << endl;
1461 if (isurface >= 0) cout << getnormal(isurface, 0) << endl;
1462 cout.precision(oldprec);
1465 tmin = max(0.0, tmin);
1466 MATCHOUT(
"BelleLathe::DistanceToIn(p,n) " << p <<
" " << n <<
" res= " << tmin);
1472 const G4bool calcNorm, G4bool* IsValid, G4ThreeVector* _n)
const
1475 auto getnormal = [
this, &p, &n](
int i,
double t)->G4ThreeVector{
1476 const int imax =
fcache.size();
1480 }
else if (i < imax)
1484 o.setZ(copysign(1, s.dr));
1486 double x = p.x() + n.x() * t;
1487 double y = p.y() + n.y() * t;
1488 double sth = s.dr * s.is, cth = -s.dz * s.is;
1489 double ir = cth /
sqrt(x * x + y * y);
1490 o.set(x * ir, y * ir, sth);
1492 }
else if (i == imax)
1502 double nn = dotxy(n, n), np = dotxy(n, p), pp = dotxy(p, p);
1503 auto hitside = [
this, &p, &n, nn, np, pp](
double t,
const cachezr_t& s) ->
bool {
1504 double z = p.z() + n.z() * t;
1506 double dot = n.z() * s.dr *
sqrt(pp + ((np + np) + nn * t) * t) - s.dz * (np + nn * t);
1507 bool k = s.zmin < z && z <= s.zmax &&
dot > 0;
1510 double x = p.x() + n.x() * t;
1511 double y = p.y() + n.y() * t;
1518 auto hitzside = [
this, &p, &n](
double t,
const cachezr_t& s) ->
bool {
1519 double x = p.x() + n.x() * t;
1520 double y = p.y() + n.y() * t;
1521 double r2 = x * x + y * y;
1522 bool k = s.dr * n.z() > 0 && s.r2min <= r2 && r2 < s.r2max;
1530 auto hitphi0side = [
this, &p, &n](
double t) ->
bool {
1531 double x = p.x() + n.x() * t;
1532 double y = p.y() + n.y() * t;
1533 double r = x *
fc0 + y *
fs0;
1536 double z = p.z() + n.z() * t;
1543 auto hitphi1side = [
this, &p, &n](
double t) ->
bool {
1544 double x = p.x() + n.x() * t;
1545 double y = p.y() + n.y() * t;
1546 double r = x *
fc1 + y *
fs1;
1549 double z = p.z() + n.z() * t;
1557 double tmin = kInfinity;
1559 const int imax =
fcache.size();
1560 int iseg = -1, isurface = -1;
1562 const double delta = 0.5 * kCarTolerance;
1563 double inz = 1 / n.z();
1564 double pz = p.z(), pr =
sqrt(pp);
1566 for (
int i = 0; i < imax; i++) {
1569 double d = (pz - s.z) * s.dr - (pr - s.r) * s.dz;
1570 bool surface = abs(d * s.is) < delta;
1571 if (surface) isurface = i;
1573 double t = (s.z - p.z()) * inz;
1575 if (hitzside(t, s)) {tmin = 0; iseg = i;
break;}
1577 if (0 < t && t < tmin && hitzside(t, s)) {tmin = t; iseg = i;}
1588 double taz = s.ta * (p.z() - s.z);
1589 double R = taz + s.r;
1592 double nzta = n.z() * s.ta;
1593 A = nzta * nzta - nn;
1597 double D = B * B + C * A;
1599 double sD =
sqrt(D);
1600 double sum = B + copysign(sD, B);
1601 double t0 = -C / sum, t1 = sum / A;
1604 if (abs(t0) < abs(t1)) {
1605 if (hitside(t0, s)) { tmin = 0; iseg = i;
break;}
1606 if (0 < t1 && t1 < tmin && hitside(t1, s)) { tmin = t1; iseg = i;}
1608 if (hitside(t1, s)) { tmin = 0; iseg = i;
break;}
1609 if (0 < t0 && t0 < tmin && hitside(t0, s)) { tmin = t0; iseg = i;}
1612 if (0 < t0 && t0 < tmin && hitside(t0, s)) { tmin = t0; iseg = i;}
1613 if (0 < t1 && t1 < tmin && hitside(t1, s)) { tmin = t1; iseg = i;}
1622 double vn =
fn0x * n.x() +
fn0y * n.y();
1624 double d =
fn0x * p.x() +
fn0y * p.y();
1626 if (hitphi0side(t)) {
1627 bool surface = std::abs(d) < delta;
1629 tmin = 0; iseg = imax + 0;
1631 if (0 < t && t < tmin) {tmin = t; iseg = imax + 0;}
1639 double vn =
fn1x * n.x() +
fn1y * n.y();
1641 double d =
fn1x * p.x() +
fn1y * p.y();
1643 if (hitphi1side(t)) {
1644 bool surface = std::abs(d) < delta;
1646 tmin = 0; iseg = imax + 1;
1648 if (0 < t && t < tmin) { tmin = t; iseg = imax + 1;}
1655 auto convex = [
this, imax](
int i) ->
bool{
1657 return fcache[i].isconvex;
1663 if (tmin >= 0 && tmin < kInfinity) {
1664 *_n = getnormal(iseg, tmin);
1665 *IsValid = convex(iseg);
1667 if (
Inside(p) == kSurface) {
1668 if (isurface >= 0) {
1669 *_n = getnormal(isurface, tmin);
1670 *IsValid = convex(isurface);
1685 double dd =
fshape->DistanceToOut(p, n, calcNorm, &isvalid, &norm);
1686 if (abs(tmin - dd) > 1e-10 || (calcNorm && *IsValid != isvalid)) {
1687 int oldprec = cout.precision(16);
1688 cout << GetName() <<
" DistanceToOut(p,v) p,n =" <<
curl_t(p) <<
curl_t(n) <<
" calcNorm=" << calcNorm
1689 <<
" myInside=" <<
Inside(p) <<
" tmin=" << tmin <<
" dd=" << dd <<
" d=" << tmin - dd <<
" iseg=" << iseg <<
" isurf=" << isurface
1691 if (calcNorm) cout <<
"myIsValid = " << *IsValid <<
" tIsValid=" << isvalid <<
" myn=" << (*_n) <<
" tn=" << (norm);
1693 cout.precision(oldprec);
1698 MATCHOUT(
"BelleLathe::DistanceToOut(p,n) " << p <<
" " << n <<
" res= " << tmin);
1707 for (
unsigned int i = 0; i < n; i++) indx.push_back(i);
1709 while (indx.size() > 3 && ++count < 200) {
1710 unsigned int ni = indx.size();
1711 for (
unsigned int i = 0; i < ni; i++) {
1712 int i0 = indx[i], i1 = indx[(i + 1) % ni], i2 = indx[(i + 2) % ni];
1717 for (
unsigned int j = 0; j < ni - 3; j++) {
1718 int k = indx[(i + 3 + j) % ni];
1728 indx.erase(indx.begin() + (i + 1) % ni);
1733 if (indx.size() == 3) {
1742 for (
const cachezr_t& s :
fcache) vol += s.dz * ((3 * s.r) * (s.r + s.dr) + s.dr * s.dr);
1743 fCubicVolume = -
fdphi * vol / 6;
1745 double totalarea = 0;
1750 double area = (p1.z - p0.
z) * (p2.r - p0.
r) - (p1.r - p0.
r) * (p2.z - p0.
z);
1751 totalarea += abs(area);
1752 farea.push_back(totalarea);
1757 double area =
fdphi * (s.r + 0.5 * s.dr) *
sqrt(s.dz * s.dz + s.dr * s.dr);
1759 farea.push_back(totalarea);
1761 fSurfaceArea =
farea.back();
1766 auto GetPointOnTriangle = [
this](
const triangle_t& t)-> G4ThreeVector{
1768 double a1 = CLHEP::RandFlat::shoot(0., 1.), a2 = CLHEP::RandFlat::shoot(0., 1.);
1769 if (a1 + a2 > 1) { a1 = 1 - a1; a2 = 1 - a2;}
1770 double a0 = 1 - (a1 + a2);
1772 zr_t p = {p0.
z* a0 + p1.z* a1 + p2.z * a2, p0.
r* a0 + p1.r* a1 + p2.r * a2};
1774 if (CLHEP::RandFlat::shoot(0., 1.) > 0.5)
1781 G4ThreeVector r1(p.r * c, p.r * s, p.z);
1785 double rnd = CLHEP::RandFlat::shoot(0.,
farea.back());
1786 std::vector<double>::const_iterator it = std::lower_bound(
farea.begin(),
farea.end(), rnd);
1787 unsigned int i = it -
farea.begin();
1791 return GetPointOnTriangle(
ftlist[i]);
1798 double I = 2 * s.r + s.dr;
1799 double Iw = CLHEP::RandFlat::shoot(0., I);
1800 double q =
sqrt(Iw * s.dr + s.r * s.r);
1801 double t = Iw / (q + s.r);
1802 double z = s.z + s.dz * t;
1803 double r = s.r + s.dr * t;
1805 double x = r * cos(phi), y = r * sin(phi);
1806 return G4ThreeVector(x, y, z);
1812 return G4String(
"BelleLathe");
1824 G4int oldprc = os.precision(16);
1825 os <<
"-----------------------------------------------------------\n"
1826 <<
" *** Dump for solid - " << GetName() <<
" ***\n"
1827 <<
" ===================================================\n"
1828 <<
" Solid type: BelleLathe\n"
1829 <<
" Contour: " <<
fcontour.size() <<
" sides, {z, r} points \n";
1830 for (
int i = 0, imax =
fcontour.size(); i < imax; i++) {
1834 for (
int i = 0, imax =
fcontour.size(); i < imax; i++) {
1835 os <<
fcache[i].isconvex <<
", ";
1838 os <<
"phi0 = " <<
fphi <<
", dphi = " <<
fdphi <<
", Full Circle = " << (
ftwopi ?
"yes" :
"no") <<
"\n";
1841 os <<
" BB: " << xmin <<
", " << xmax <<
", " << ymin <<
", " << ymax << endl;
1842 os <<
"-----------------------------------------------------------\n";
1843 os.precision(oldprc);
1851 scene.AddSolid(*
this);
1857 std::vector<vector_t> points;
1861 const double inf = std::numeric_limits<double>::infinity();
1862 G4ThreeVector minimum(inf, inf, inf), maximum(-inf, -inf, -inf);
1865 if (
fdphi < 2 * M_PI) {
1867 points.push_back(point);
1869 points.push_back(point);
1874 points.push_back(point);
1877 points.push_back(point);
1885 points.push_back(point);
1888 point.
x = -
frmax; point.
y = 0;
1889 points.push_back(point);
1892 point.
x = 0; point.
y = -
frmax;
1893 points.push_back(point);
1897 points.push_back(point);
1900 for (std::vector<vector_t>::size_type i = 0; i != points.size(); i++) {
1902 if (points[i].x < minimum.x())
1903 minimum.setX(points[i].x);
1906 if (points[i].y < minimum.y())
1907 minimum.setY(points[i].y);
1910 if (points[i].x > maximum.x())
1911 maximum.setX(points[i].x);
1914 if (points[i].y > maximum.y())
1915 maximum.setY(points[i].y);
1919 minimum.setZ(
fzmin);
1920 maximum.setZ(
fzmax);
1927void takePolyhedron(
const HepPolyhedron& p)
1929 int i, nnode, iNodes[5], iVis[4], iFaces[4];
1931 for (
int iface = 1; iface <= p.GetNoFacets(); iface++) {
1932 p.GetFacet(iface, nnode, iNodes, iVis, iFaces);
1933 for (i = 0; i < nnode; i++) {
1934 if (iNodes[i] < 1 || iNodes[i] > p.GetNoVertices()) {
1937 <<
"BooleanProcessor::takePolyhedron : problem 1."
1940 if (iFaces[i] < 1 || iFaces[i] > p.GetNoFacets()) {
1943 <<
"BooleanProcessor::takePolyhedron : problem 2. "
1944 << i <<
" " << iFaces[i] <<
" " << p.GetNoFacets() << G4endl;
1952 int nphi = GetNumberOfRotationSteps();
1953 bool twopi = abs(dphi - 2 * M_PI) < 1e-6;
1958 AllocateMemory(nv, nf);
1960 auto vnum = [nphi, n](
int iphi,
int ip) {
1961 return (iphi % nphi) * n + (ip % n) + 1;
1965 double dfi = dphi / nphi;
1966 for (
int i = 0; i < nphi; i++) {
1967 double fi = phi + i * dfi;
1968 double cf = cos(fi), sf = sin(fi);
1969 for (
int j = 0; j < n; j++) pV[vnum(i, j)].set(v[j].r * cf, v[j].r * sf, v[j].z);
1970 for (
int j = 0; j < n; j++) pF[fcount++ ] = G4Facet(vnum(i, j), 0, vnum(i, j + 1), 0, vnum(i + 1, j + 1), 0, vnum(i + 1, j), 0);
1974 nphi = int(nphi * (dphi / (2 * M_PI)) + 0.5);
1975 nphi = nphi > 3 ? nphi : 3;
1980 int nf = n * (nphi - 1) + 2 * t.size();
1981 AllocateMemory(nv, nf);
1983 auto vnum = [n](
int iphi,
int ip) {
1984 return iphi * n + (ip % n) + 1;
1988 double dfi = dphi / (nphi - 1);
1989 for (
int i = 0; i < nphi; i++) {
1990 double fi = phi + i * dfi;
1991 double cf = cos(fi), sf = sin(fi);
1992 for (
int j = 0; j < n; j++) pV[vnum(i, j)].set(v[j].r * cf, v[j].r * sf, v[j].z);
1993 if (i == nphi - 1)
break;
1994 for (
int j = 0; j < n; j++) pF[fcount++] = G4Facet(vnum(i, j), 0, vnum(i, j + 1), 0, vnum(i + 1, j + 1), 0, vnum(i + 1, j), 0);
1997 for (
const triangle_t& k : t) pF[fcount++] = G4Facet(vnum(0, k.i0), 0, vnum(0, k.i2), 0, vnum(0, k.i1), 0, 0, 0);
1999 for (
const triangle_t& k : t) pF[fcount++] = G4Facet(vnum(i, k.i0), 0, vnum(i, k.i1), 0, vnum(i, k.i2), 0, 0, 0);
2015#include <immintrin.h>
2016double mindistsimd(
const zr_t& r,
const vector<cachezr_t>& contour)
2018 double d = kInfinity;
2019 int i = 0, n = contour.size();
2020 __m128d zero = _mm_set_sd(0);
2021 __m128d one = _mm_set_sd(1);
2025 double dz = r.z - s.z, dr = r.r - s.r;
2026 double crs = s.dr * dz - s.dz * dr;
2027 double dot = s.dz * dz + s.dr * dr;
2029 __m128d crssd = _mm_set_sd(crs);
2030 __m128d maskgt = _mm_cmpgt_sd(crssd, zero);
2031 __m128d masklt = _mm_cmplt_sd(crssd, zero);
2032 __m128d left = _mm_sub_sd(_mm_and_pd(maskgt, one), _mm_and_pd(masklt, one));
2033 __m128d z = _mm_set_sd(s.z);
2034 __m128d mask = _mm_and_pd(_mm_cmple_sd(_mm_set_sd(s.zmin), z), _mm_cmplt_sd(z, _mm_set_sd(s.zmax)));
2035 left = _mm_and_pd(mask, left);
2036 double du = dz * dz + dr * dr;
2037 double dv = crs * crs * s.is2;
2039 masklt = _mm_cmplt_sd(_mm_set_sd(
dot), zero);
2040 maskgt = _mm_cmpgt_sd(_mm_set_sd(
dot), _mm_set_sd(s.s2));
2042 __m128d uu = _mm_or_pd(_mm_and_pd(maskgt, _mm_set_sd(kInfinity)), _mm_andnot_pd(maskgt, _mm_set_sd(dv)));
2043 __m128d vv = _mm_or_pd(_mm_and_pd(masklt, _mm_set_sd(min(d, du))), _mm_andnot_pd(masklt, _mm_set_sd(min(d, uu[0]))));
2048 d = (wn == 2) ? -d : d;
2053inline int left(
const zr_t& r0,
const zr_t& r1,
const zr_t& r)
2055 double d = (r1.z - r0.
z) * (r.r - r0.
r) - (r.z - r0.
z) * (r1.r - r0.
r);
2056 return (d > 0) - (d < 0);
2059inline int checkside(
const zr_t& s0,
const zr_t& s1,
const zr_t& r)
2061 double zmin = min(s0.
z, s1.
z), zmax = max(s0.
z, s1.
z);
2062 if (zmin <= r.z && r.z < zmax)
return left(s0, s1, r);
2066int wn_poly(
const zr_t& r,
const vector<zr_t>& contour)
2069 int i = 0, n = contour.size() - 1;
2071 wn += checkside(contour[i], contour[i + 1], r);
2073 wn += checkside(contour[n], contour[0], r);
2077double mindist(
const zr_t& r,
const vector<zr_t>& contour)
2080 double d = kInfinity;
2081 auto dist = [&contour, &d, &r, &wn](
int i0,
int i1)->
void {
2082 const zr_t& s0 = contour[i0], &s1 = contour[i1];
2083 double zmin = min(s0.
z, s1.z), zmax = max(s0.
z, s1.z);
2084 double sz = s1.z - s0.
z, sr = s1.r - s0.
r;
2085 double dz = r.z - s0.
z, dr = r.r - s0.
r;
2086 double crs = dz * sr - sz * dr;
2087 if (zmin <= r.z && r.z < zmax) wn -= (crs > 0) - (crs < 0);
2088 double dot = sz * dz + sr * dr;
2089 double s2 = sz * sz + sr * sr;
2090 if (
dot > s2)
return;
2093 double d2 = dz * dz + dr * dr;
2097 d = min(d, crs * crs / s2);
2101 int i = 0, n = contour.size() - 1;
2102 do {dist(i, i + 1);}
while (++i < n);
2105 d = (wn == 2) ? -d : d;
2111double mindist(
const zr_t& r,
const vector<cachezr_t>& contour)
2113 double d = kInfinity;
2114 int wn = 0, i = 0, n = contour.size();
2117 double dz = r.z - s.z, dr = r.r - s.r;
2118 double crs = s.dr * dz - s.dz * dr;
2119 double dot = s.dz * dz + s.dr * dr;
2120 if (s.zmin <= r.z && r.z < s.zmax) wn -= (crs > 0) - (crs < 0);
2121 if (
dot > s.s2)
continue;
2123 d = min(d, dz * dz + dr * dr);
2125 d = min(d, crs * crs * s.is2);
2131 d = (wn == 2) ? -d : d;
double fzmax
maximal z value
void getvolarea()
get volume area
double fphi
starting angle
std::vector< double > fz
vector of z values
G4GeometryType GetEntityType() const
Get entity type.
std::vector< int > findx
vector of indices
std::vector< triangle_t > ftlist
vector of triangle structs
void DescribeYourselfTo(G4VGraphicsScene &scene) const
Visualisation function.
void Init(const std::vector< zr_t > &, double, double)
initialize
bool ftwopi
bound within +- 2pi?
std::vector< double > farea
vector of area values
G4Polyhedron * CreatePolyhedron() const
create polyhedron
std::vector< int > fseg
vector of segments
double fdphi
finishing angle
std::vector< double > linecross(const G4ThreeVector &, const G4ThreeVector &) const
calculate all ray solid's surface intersection return ordered vector
BelleLathe & operator=(const BelleLathe &rhs)
assignment operator
void BoundingLimits(G4ThreeVector &pMin, G4ThreeVector &pMax) const
Two vectors define an axis-parallel bounding box for the shape.
virtual ~BelleLathe()
Destructor.
std::vector< zr_t > fcontour
vector of zr structs
bool fgtpi
greater than pi?
std::vector< cachezr_t > fcache
vector of cached zr structs
double mindist(const zr_t &) const
minimal distance
BelleLathe(const G4String &pName)
Constructor for "nominal" BelleLathe whose parameters are to be set by a G4VPVParamaterisation later.
double fzmin
minimal z value
zr_t normal(const zr_t &, double &) const
return normal
bool insector(double, double) const
True if (x,y) is within the shape rotation.
G4ThreeVector GetPointOnSurface() const
Get point on surface.
double frmax
maximal r value
G4bool CalculateExtent(const EAxis pAxis, const G4VoxelLimits &pVoxelLimit, const G4AffineTransform &pTransform, G4double &pMin, G4double &pMax) const
calculate the extent of the volume
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.
double frmin
minimal r value
void eartrim() const
ear trim
std::vector< G4ThreeVector > fsurf
vector of surfaces
G4VSolid * Clone() const
Make a clone of the object.
std::ostream & StreamInfo(std::ostream &os) const
Stream object contents to an output stream.
int wn_poly(const zr_t &) const
wn_poly
EInside Inside(const G4ThreeVector &p) const
Return whether point inside/outside/on surface, using tolerance.
void ComputeDimensions(G4VPVParameterisation *p, const G4int n, const G4VPhysicalVolume *pRep)
compute the dimensions
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.
virtual ~PolyhedronBelleLathe()
destructor
PolyhedronBelleLathe(const std::vector< zr_t > &, const std::vector< triangle_t > &, double, double)
constructor
double sqrt(double a)
sqrt for double
T dot(GeneralVector< T > a, GeneralVector< T > b)
dot product of two general vectors
TString rn()
Get random string.
Abstract base class for different kinds of events.
double zmin
minimal z value
double ta
ratio of dr over dz
double zmax
maximal z value
struct for a three vector
simple struct with z and r coordinates
G4ThreeVector n
Normal unit vector (x,y,z)
curl_t(const G4ThreeVector &_v)
constructor