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);
116 const zr_t& s0 = *it0, &s1 = contour[0];
117 if (abs(s0.
z - s1.z) < kCarTolerance && abs(s0.
r - s1.r) < kCarTolerance) contour.erase(it0);
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;
128 if (d * d < kCarTolerance * kCarTolerance * (dr2 * dr2 + dz2 * dz2)) {
129 it1 = contour.erase(it1);
131 if (++it2 >= contour.end()) it2 = contour.begin();
133 if (--it0 < contour.begin()) it0 = (++contour.rbegin()).base();
137 if (++it1 >= contour.end()) it1 = contour.begin();
138 if (++it2 >= contour.end()) it2 = contour.begin();
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);
151 zr_t p1 = contour[0];
152 sum += (p1.z - p0.
z) * (p1.r + p0.
r);
156 std::reverse(contour.begin(), contour.end());
160 auto convexside = [
this](
cachezr_t& s,
double eps) ->
void {
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;
170 double d = a * p.r - b * p.z + cc;
171 dm = dm || (d < -eps);
172 dp = dp || (d > eps);
173 if (dm && dp) {s.isconvex =
false;
return;}
182 for (
int i = 0, n =
fcontour.size(); i < n; i++) {
189 t.s2 = t.dz * t.dz + t.dr * t.dr;
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);
225 for (
int i = 0, n =
fcontour.size(); i < n; i++) {
229 sort(
fz.begin(),
fz.end());
230 fz.erase(std::unique(
fz.begin(),
fz.end()),
fz.end());
232 for (
int i = 1, ni =
fz.size(); i < ni; i++) {
233 double a =
fz[i - 1], b =
fz[i];
235 for (
int j = 0, nj =
fcache.size(); j < nj; j++) {
238 if (cc != d and b > cc and d > a) {
248 auto getpolycone = [](
const G4String & pName,
double phi0,
double dphi,
const vector<zr_t>& c) -> G4GenericPolycone* {
252 for (
int i = 0, imax = c.size(); i < imax; i++)
257 return new G4GenericPolycone(pName, phi0, dphi, c.size(), r.data(), z.data());
516 const G4VoxelLimits& bb,
517 const G4AffineTransform& T,
518 G4double& pMin, G4double& pMax)
const
520 auto maxdist = [
this](
const G4ThreeVector & n) -> G4ThreeVector {
522 int i = 0, nsize =
fcache.size();
525 double nr = hypot(n.x(), n.y()), nz = n.z();
526 double dmax = -kInfinity,
R = 0, Z = 0;
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);
534 r.set(
R * n.x(),
R * n.y(), Z);
537 r.set(
R * cos(phi),
R * sin(phi), Z);
541 double dmax = -kInfinity;
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;
548 if (dmax < d0) { r = rf; dmax = d0;}
549 if (dmax < d1) { r = rl; dmax = d1;}
550 }
while (++i < nsize);
555 struct seg_t {
int i0, i1;};
556 auto clip = [](vector<G4ThreeVector>& vlist, vector<seg_t>& slist,
const G4ThreeVector & n,
double dist) {
561 for (
const G4ThreeVector& v : vlist) d.push_back(v * n + dist);
563 for (seg_t s : slist) {
564 double prod = d[s.i0] * d[s.i1];
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);
570 s = {lone.back(), s.i1};
572 s = {s.i0, lone.back()};
574 }
else if (prod == 0) {
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);
581 if (d[s.i0] < 0)
continue;
587 int imax = -1, jmax = -1;
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];}
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]);});
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;}
612 auto PhiCrossN = [
this, clip](
const vector<Plane_t>& planes) {
615 vector<G4ThreeVector> vlist;
617 vector<G4ThreeVector> res;
619 int nsize =
fcache.size();
620 vlist.reserve(nsize);
621 slist.reserve(nsize);
622 for (
int iphi = 0; iphi < 2; iphi++) {
631 G4ThreeVector r(kx * s.r, ky * s.r, s.z);
633 seg_t t = {i, i + 1};
635 }
while (++i < nsize - 1);
637 G4ThreeVector r(kx * s.r, ky * s.r, s.z);
639 seg_t t = {nsize - 1, 0};
644 for (
const Plane_t& p : planes) {
646 clip(vlist, slist, p.n, p.d);
649 vector<bool> bv(vlist.size(),
false);
651 for (vector<seg_t>::const_iterator it = slist.begin(); it != slist.end(); ++it) {
656 for (
unsigned int i = 0; i < vlist.size(); i++) {
657 if (!bv[i])
continue;
658 res.push_back(vlist[i]);
664 auto RCross = [
this](
const G4ThreeVector & op,
const G4ThreeVector & k,
const G4ThreeVector & u) {
667 vector<solution_t> ts;
668 int nsize =
fcache.size();
674 double r0 = seg.
r, z0 = seg.
z, tg = seg.
ta;
675 double rtg = r0 * tg;
677 G4ThreeVector o(op.x(), op.y(), op.z() - z0);
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;
684 double tg2 = tg * tg, co2 = co * co;
686 double q1 = co * q0 + rtg;
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;
695 vector<solution_t> res = extremum(F02, F11, F20, F01, F10, F00);
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) {
706 double a = -(ck2 * u2 + cu2 * k2);
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;
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;
734 }
while (++i < nsize);
738 bool b1 =
false, b2 =
false;
739 G4ThreeVector n0, n1, n2;
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;
747 double dmin1 = -kInfinity, dmax1 = kInfinity;
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;
757 double dmin2 = -kInfinity, dmax2 = kInfinity;
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;
767 G4AffineTransform iT = T.Inverse();
769 G4ThreeVector n0t = iT.TransformAxis(n0);
770 G4ThreeVector smin = n0t * kInfinity, smax = (-kInfinity) * n0t;
771 double pmin = kInfinity, pmax = -pmin;
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);
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);
781 for (
double t : dists) {
782 G4ThreeVector p = n0t * t + c0;
783 double tt = t + c0 * n0t;
785 if (pmax < tt) { pmax = tt; smax = p;}
786 if (pmin > tt) { pmin = tt; smin = p;}
789 G4ThreeVector u = c1 - c0, un = u.unit();
790 vector<solution_t> ts = RCross(c0, n0t, un);
791 double umax = u.mag();
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;
797 if (pmax < tt) { pmax = tt; smax = p;}
798 if (pmin > tt) { pmin = tt; smin = p;}
801 planes.push_back({ -un, un * c1});
804 vector<G4ThreeVector> vside = PhiCrossN(planes);
805 for (
const G4ThreeVector& p : vside) {
808 if (pmax < tt) { pmax = tt; smax = p;}
809 if (pmin > tt) { pmin = tt; smin = p;}
812 }
else if (b1 || b2) {
813 G4ThreeVector limits[2], u;
815 limits[0] = n1 * dmin1;
816 limits[1] = n1 * dmax1;
817 u = iT.TransformAxis(n2);
819 limits[0] = n2 * dmin2;
820 limits[1] = n2 * dmax2;
821 u = iT.TransformAxis(n1);
824 for (G4ThreeVector& c : limits) iT.ApplyPointTransform(c);
825 for (
int i = 0; i < 2; i++) {
826 vector<solution_t> ts = RCross(limits[i], n0t, u);
828 double tt = r.t + limits[i] * n0t;
829 G4ThreeVector p = n0t * r.t + u * r.s + limits[i];
831 if (pmax < tt) { pmax = tt; smax = p;}
832 if (pmin > tt) { pmin = tt; smin = p;}
836 vector<Plane_t> planes(2);
839 n = iT.TransformAxis(n1);
841 n = iT.TransformAxis(n2);
843 planes[0] = { n, -limits[0]* n};
844 planes[1] = { -n, limits[1]* n};
845 vector<G4ThreeVector> vside = PhiCrossN(planes);
847 for (
const G4ThreeVector& p : vside) {
851 if (pmax < tt) { pmax = tt; smax = p;}
852 if (pmin > tt) { pmin = tt; smin = p;}
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;}
861 if (bb.Inside(T.TransformPoint(rp))) {
862 double tt = rp * n0t;
863 if (pmax < tt) {pmax = tt; smax = rp;}
867 T.ApplyPointTransform(smin);
868 T.ApplyPointTransform(smax);
872 pmin -= kCarTolerance;
873 pmax += kCarTolerance;
875 bool hit = pmin < pmax;
878 auto surfhit = [
this, &bb, &T, &n0, &n0t](
double & pmin,
double & pmax,
bool print =
false)->
bool {
879 const int N = 1000 * 1000;
882 int umin = -1, umax = -1;
883 double wmin = 1e99, wmax = -1e99;
884 for (
int i = 0; i < N; i++)
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;}
892 if (print)cout << umin <<
" " << umax <<
" " << wmin <<
" " << wmax << endl;
893 if (umin >= 0 && umax >= 0)
895 G4ThreeVector qmin =
fsurf[umin], qmax =
fsurf[umax];
896 T.ApplyPointTransform(qmin);
897 T.ApplyPointTransform(qmax);
898 pmin = n0 * qmin, pmax = n0 * qmax;
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;
910 if ((abs(pmin - srfmin) > diff || abs(pmax - srfmax) > diff) && sHit) {
911 cout <<
"===================================\n";
913 cout << hit <<
" " << res <<
" " << b1 <<
" " << b2 <<
"\n";
915 cout <<
"ss " << srfmin <<
" " << srfmax <<
"\n";
917 cout <<
"ss : not in bounding box" <<
"\n";
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";
1258 auto getnormal = [
this, &p, &n](
int i,
double t) ->G4ThreeVector{
1259 const int imax =
fcache.size();
1263 }
else if (i < imax)
1267 o.setZ(copysign(1, s.dr));
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);
1275 }
else if (i == imax)
1285 auto hitside = [
this, &p, &n](
double t,
const cachezr_t& s) ->
bool {
1286 double z = p.z() + n.z() * t;
1288 bool k = s.zmin < z && z <= s.zmax;
1291 double x = p.x() + n.x() * t;
1292 double y = p.y() + n.y() * t;
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;
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;
1316 double z = p.z() + n.z() * t;
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;
1329 double z = p.z() + n.z() * t;
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++) {
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) {
1357 double t = -dz * inz;
1358 if (0 < t && t < tmin && hitzside(t, s)) { tmin = t; iseg = i;}
1369 double taz = s.ta * dz;
1370 double R = taz + s.r;
1373 double nzta = n.z() * s.ta;
1374 A = nzta * nzta - nn;
1378 double D = B * B + C * A;
1382 double sD =
sqrt(D), sum = B + copysign(sD, B);
1383 double t0 = -C / sum, t1 = sum / A;
1385 if (abs(t0) > abs(t1)) {
1386 if (t0 > 0 && t0 < tmin && hitside(t0, s)) { tmin = t0; iseg = i;}
1388 if (t1 > 0 && t1 < tmin && hitside(t1, s)) { tmin = t1; iseg = i;}
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;}
1400 double vn =
fn0x * n.x() +
fn0y * n.y();
1402 double d =
fn0x * p.x() +
fn0y * p.y();
1404 if (hitphi0side(t)) {
1405 bool surface = std::abs(d) < delta;
1407 tmin = 0; iseg = imax + 0;
1409 if (0 < t && t < tmin) {tmin = t; iseg = imax + 0;}
1417 double vn =
fn1x * n.x() +
fn1y * n.y();
1419 double d =
fn1x * p.x() +
fn1y * p.y();
1421 if (hitphi1side(t)) {
1422 bool surface = std::abs(d) < delta;
1424 tmin = 0; iseg = imax + 1;
1426 if (0 < t && t < tmin) { tmin = t; iseg = imax + 1;}
1434 if (getnormal(iseg, tmin)*n > 0) tmin = 0;
1438 auto convex = [
this, imax](
int i) ->
bool{
1440 return fcache[i].isconvex;
1445 if (tmin >= 0 && tmin < kInfinity) {
1446 if (isurface >= 0)
if (convex(isurface) && getnormal(isurface, 0)*n >= 0) tmin = kInfinity;
1448 if (
Inside(p) == kSurface) {
1449 if (isurface >= 0) {
1450 tmin = (getnormal(isurface, 0) * n >= 0) ? kInfinity : 0;
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);
1467 tmin = max(0.0, tmin);
1468 MATCHOUT(
"BelleLathe::DistanceToIn(p,n) " << p <<
" " << n <<
" res= " << tmin);
1474 const G4bool calcNorm, G4bool* validNorm, G4ThreeVector* n)
const
1477 auto getnormal = [
this, &p, &v](
int i,
double t)->G4ThreeVector{
1478 const int imax =
fcache.size();
1482 }
else if (i < imax)
1486 o.setZ(copysign(1, s.dr));
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);
1494 }
else if (i == imax)
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;
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;
1512 double x = p.x() + v.x() * t;
1513 double y = p.y() + v.y() * t;
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;
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;
1538 double z = p.z() + v.z() * t;
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;
1551 double z = p.z() + v.z() * t;
1559 double tmin = kInfinity;
1561 const int imax =
fcache.size();
1562 int iseg = -1, isurface = -1;
1564 const double delta = 0.5 * kCarTolerance;
1565 double inz = 1 / v.z();
1566 double pz = p.z(), pr =
sqrt(pp);
1568 for (
int i = 0; i < imax; i++) {
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;
1575 double t = (s.z - p.z()) * inz;
1577 if (hitzside(t, s)) {tmin = 0; iseg = i;
break;}
1579 if (0 < t && t < tmin && hitzside(t, s)) {tmin = t; iseg = i;}
1590 double taz = s.ta * (p.z() - s.z);
1591 double R = taz + s.r;
1594 double nzta = v.z() * s.ta;
1595 A = nzta * nzta - nn;
1599 double D = B * B + C * A;
1601 double sD =
sqrt(D);
1602 double sum = B + copysign(sD, B);
1603 double t0 = -C / sum, t1 = sum / A;
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;}
1610 if (hitside(t1, s)) { tmin = 0; iseg = i;
break;}
1611 if (0 < t0 && t0 < tmin && hitside(t0, s)) { tmin = t0; iseg = i;}
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;}
1624 double vn =
fn0x * v.x() +
fn0y * v.y();
1626 double d =
fn0x * p.x() +
fn0y * p.y();
1628 if (hitphi0side(t)) {
1629 bool surface = std::abs(d) < delta;
1631 tmin = 0; iseg = imax + 0;
1633 if (0 < t && t < tmin) {tmin = t; iseg = imax + 0;}
1641 double vn =
fn1x * v.x() +
fn1y * v.y();
1643 double d =
fn1x * p.x() +
fn1y * p.y();
1645 if (hitphi1side(t)) {
1646 bool surface = std::abs(d) < delta;
1648 tmin = 0; iseg = imax + 1;
1650 if (0 < t && t < tmin) { tmin = t; iseg = imax + 1;}
1657 auto convex = [
this, imax](
int i) ->
bool{
1659 return fcache[i].isconvex;
1665 if (tmin >= 0 && tmin < kInfinity) {
1666 *n = getnormal(iseg, tmin);
1667 *validNorm = convex(iseg);
1669 if (
Inside(p) == kSurface) {
1670 if (isurface >= 0) {
1671 *n = getnormal(isurface, tmin);
1672 *validNorm = convex(isurface);
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
1693 if (calcNorm) cout <<
"myIsValid = " << *validNorm <<
" tIsValid=" << isvalid <<
" myn=" << (*n) <<
" tn=" << (norm);
1695 cout.precision(oldprec);
1700 MATCHOUT(
"BelleLathe::DistanceToOut(p,v) " << p <<
" " << v <<
" res= " << tmin);
1954 int nphi = GetNumberOfRotationSteps();
1955 bool twopi = abs(dphi - 2 * M_PI) < 1e-6;
1960 AllocateMemory(nv, nf);
1962 auto vnum = [nphi, n](
int iphi,
int ip) {
1963 return (iphi % nphi) * n + (ip % n) + 1;
1967 double dfi = dphi / nphi;
1968 for (
int i = 0; i < nphi; i++) {
1969 double fi = phi + i * dfi;
1970 double cf = cos(fi), sf = sin(fi);
1971 for (
int j = 0; j < n; j++) pV[vnum(i, j)].set(v[j].r * cf, v[j].r * sf, v[j].z);
1972 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);
1976 nphi = int(nphi * (dphi / (2 * M_PI)) + 0.5);
1977 nphi = nphi > 3 ? nphi : 3;
1982 int nf = n * (nphi - 1) + 2 * t.size();
1983 AllocateMemory(nv, nf);
1985 auto vnum = [n](
int iphi,
int ip) {
1986 return iphi * n + (ip % n) + 1;
1990 double dfi = dphi / (nphi - 1);
1991 for (
int i = 0; i < nphi; i++) {
1992 double fi = phi + i * dfi;
1993 double cf = cos(fi), sf = sin(fi);
1994 for (
int j = 0; j < n; j++) pV[vnum(i, j)].set(v[j].r * cf, v[j].r * sf, v[j].z);
1995 if (i == nphi - 1)
break;
1996 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);
1999 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);
2001 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);