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> 
   28 typedef int counter_t[6];
 
   29 map<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();
 
   63   return o << 
"{" << v.
z << 
",  " << v.
r << 
"}";
 
   70   explicit curl_t(
const G4ThreeVector& _v): v(_v) {}
 
   75   return o << 
"{" << c.v.x() << 
", " << c.v.y() << 
", " << c.v.z() << 
"}, ";
 
   79 BelleLathe::BelleLathe(
const G4String& pName, 
double phi0, 
double dphi, 
const vector<zr_t>& c)
 
   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.");
 
  356 vector<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;
 
  376 inline 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);
 
  396 vector<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);
 
 1927 void 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> 
 2016 double 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;
 
 2053 inline 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);
 
 2059 inline 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);
 
 2066 int 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);
 
 2077 double 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;
 
 2111 double 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
std::ostream & operator<<(std::ostream &output, const IntervalOfValidity &iov)
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