52 #ifdef BUILD_CONES_DLL
53 #define EGS_CONES_EXPORT __declspec(dllexport)
55 #define EGS_CONES_EXPORT __declspec(dllimport)
57 #define EGS_CONES_LOCAL
61 #ifdef HAVE_VISIBILITY
62 #define EGS_CONES_EXPORT __attribute__ ((visibility ("default")))
63 #define EGS_CONES_LOCAL __attribute__ ((visibility ("hidden")))
65 #define EGS_CONES_EXPORT
66 #define EGS_CONES_LOCAL
132 EGS_Float gamma, g12;
144 const EGS_Float *distance=0,
const string &N=
"")
147 open(
true), is_cyl(
false) {
161 egsWarning(
"EGS_SimpleCone: the distance to the closing plane must be positive\n");
169 EGS_Float Rtop, EGS_Float Rbottom,
bool Open=
true,
const string &N=
"")
176 if (fabs(Rtop - Rbottom) < boundaryTolerance) {
186 else if (Rtop < Rbottom) {
187 EGS_Float aux = dz*Rtop/(Rbottom-Rtop);
189 gamma = Rbottom/(aux+dz);
190 g12 = 1 + gamma*gamma;
195 EGS_Float aux = dz*Rbottom/(Rtop-Rbottom);
196 xo = Xo + a*(aux+dz);
198 gamma = Rtop/(aux+dz);
199 g12 = 1 + gamma*gamma;
215 if (!open && (aa < 0 || aa+d1 > 0)) {
221 EGS_Float r2 = xp.length2() - aa*aa;
229 EGS_Float r2 = xp.length2();
230 if (r2 <= aa*aa*g12) {
251 EGS_Float &t,
int *newmed=0,
EGS_Vector *normal=0) {
256 EGS_Float r2 = xp.length2();
267 EGS_Float A = 1 - b*b;
268 EGS_Float B = c - b*aa;
269 EGS_Float C = r2 - aa*aa - Ro2;
274 EGS_Float D = B*B-A*C;
275 if (D < 0 || (C > 0 && B > 0)) {
280 d = B<=0 ? (sqrt(D)-B)/A : -C/(sqrt(D)+B);
297 EGS_Float D = B*B-A*C;
312 EGS_Float aux = aa + d*b;
313 if (aux < 0 || aux+d1 > 0) {
320 if (newmed && ireg < 0) {
324 EGS_Float lam = aa+b*d;
327 *normal = ireg < 0 ? aux : aux*(-1);
330 return (!ireg ? -1 : 0);
350 else if (!open && b>0) {
351 EGS_Float tt = -d1/b;
381 if (aa+d1 > 0 && b < 0) {
382 EGS_Float tt = -(aa+d1)/b;
384 EGS_Float r2p = r2 + tt*(tt + 2*c);
385 if (r2p <= d1*d1*g12) {
399 if (r2 <= aa*aa*g12) {
407 EGS_Float tt = -(aa+d1)/b;
409 EGS_Float r2p = r2 + tt*(tt + 2*c);
410 if (r2p <= d1*d1*g12) {
432 EGS_Float A = 1 - b*b*g12;
433 EGS_Float B = c - aa*b*g12;
434 EGS_Float C = r2 - aa*aa*g12;
438 if (fabs(A) < boundaryTolerance) {
442 if ((!ireg && B>0) || (ireg && B<0)) {
443 EGS_Float ttt = -C/(2*B);
445 if (ttt >= 0 && lam >= 0) {
471 EGS_Float D = B*B-A*C;
476 if (!ireg && !(A<0 && B<0)) {
478 ttt = -C/(B+sqrt(D));
484 else if (ireg && !(A>0 && B>0)) {
489 ttt = -(sqrt(D)+B)/A;
497 if (ttt >= -boundaryTolerance && lam >= 0) {
503 if (tt > t || (!open && ireg && d1 + aa + tt*b > 0)) {
510 int inew = ireg ? 0 : -1;
514 *newmed = inew ? -1 : med;
517 *normal = xp + u*t - a*(lam*g12);
530 EGS_Float hownear(
int ireg,
const EGS_Vector &x) {
534 EGS_Float ag = aa*gamma;
535 EGS_Float r2 = xp.length2();
541 if (open || (aa > 0 && aa+d1 < 0)) {
542 r2 = sqrt(r2 - aa*aa);
551 r2 = sqrt(r2 - aa*aa);
564 EGS_Float aux = r2-Ro;
566 return sqrt(aa*aa + aux*aux);
568 EGS_Float tp = aa+d1;
569 return sqrt(tp*tp + aux*aux);
574 if (aa < 0 && ag*ag > r2*g12) {
579 EGS_Float r2a2 = r2-aa*aa;
580 EGS_Float r2a = sqrt(r2a2);
581 EGS_Float tc = fabs((ag-r2a)*g12i);
589 EGS_Float tp = d1+aa;
599 else if (tp > 0 && r2 < aa*aa*g12) {
601 EGS_Float aux = r2a - Ro;
602 tc = sqrt(tp*tp + aux*aux);
609 else if (tp + tc*gamma*g12i > 0) {
610 EGS_Float aux = r2a + d1*gamma;
611 tc = sqrt(aux*aux + tp*tp);
619 const string &getType()
const {
624 void printInfo()
const;
637 EGS_Float getGamma()
const {
642 EGS_Float getRadius(
const EGS_Vector &x)
const {
646 EGS_Float xp = (x-xo)*a;
745 EGS_Float gamma, g12;
755 const EGS_Float *distances,
const string &N=
"")
773 d =
new EGS_Float [nc-1];
774 for (
int j=1; j<nc; j++) {
775 d[j-1] = distances[j-1];
776 if (d[j-1] <= d_old) {
777 egsFatal(
"EGS_ParallelCones: " "distances must be in increasing order\n");
779 xo[j] = xo[0] + a*d[j-1];
800 EGS_Float r2 = xp.length2();
801 if (r2 <= aa*aa*g12) {
814 EGS_Float r2 = xp.length2();
815 if (r2 > aa*aa*g12) {
818 EGS_Float r2a2 = r2 - aa*aa;
819 for (
int j=0; j<nc-1; j++) {
820 EGS_Float aj = aa - d[j];
821 EGS_Float ajg = aj*gamma;
822 if (aj < 0 || r2a2 > ajg*ajg) {
854 EGS_Float r2 = xp.length2();
856 EGS_Float A = 1 - b*b*g12;
857 EGS_Float B = c - aa*b*g12;
858 EGS_Float C = r2 - aa*aa*g12;
863 if (fabs(A) < boundaryTolerance) {
864 EGS_Float ttt = -C/(2*B);
866 if (ttt >= 0 && lam >= 0) {
873 EGS_Float D = B*B-A*C;
874 if (D >= 0 && !(A > 0 && B > 0)) {
875 EGS_Float ttt = B < 0 ? C/(sqrt(D)-B) : -(sqrt(D)+B)/A;
877 if (ttt >= 0 && lam >= 0) {
884 int inew = ireg < 0 ? 0 : ireg+1;
887 *newmed = medium(inew);
890 *normal = xp + u*t - a*(lam*g12);
895 if (ireg < 0 || hit) {
903 EGS_Float aa = xp*a, b = u*a, r2 = xp.length2(), c = u*xp;
904 EGS_Float A = 1 - b*b*g12, B = c - aa*b*g12, C = r2 - aa*aa*g12;
905 EGS_Float to =
veryFar, lamo = -1;
906 if (fabs(A) < boundaryTolerance) {
910 EGS_Float ttt = -C/(2*B);
912 if (ttt >= 0 && lamo >= 0) {
918 EGS_Float D = B*B-A*C;
920 if (D >= 0 && !(A < 0 && B < 0)) {
921 EGS_Float ttt = B > 0 ? -C/(B+sqrt(D)) : (sqrt(D)-B)/A;
923 if (ttt >= 0 && lamo >= 0) {
932 *newmed = inew < 0 ? -1 : medium(inew);
935 *normal = xp + u*t - a*(lamo*g12);
944 EGS_Float hownear(
int ireg,
const EGS_Vector &x) {
946 if (ireg < 0 || ireg < nc-1) {
955 EGS_Float ag = aa*gamma;
956 EGS_Float r2 = xp.length2();
957 if (aa < 0 && ag*ag > r2*g12) {
961 tc = fabs((ag-sqrt(r2-aa*aa))*g12i);
969 EGS_Float ag = aa*gamma;
970 EGS_Float r2 = xp.length2();
971 EGS_Float tco = fabs((ag-sqrt(r2-aa*aa))*g12i);
972 return tco < tc ? tco : tc;
976 int getMaxStep()
const {
981 const string &getType()
const {
986 void printInfo()
const;
1065 EGS_Float *gamma, *g12, *g12i;
1074 EGS_Float *Gamma,
int Flag = 0,
const string &Name =
"") :
1078 egsFatal(
"EGS_ConeSet: number of cones must be positive\n");
1081 gamma =
new EGS_Float [nc];
1082 g12 =
new EGS_Float [nc];
1083 g12i =
new EGS_Float [nc];
1084 if (flag < 0 || flag > 2) {
1085 egsWarning(
"EGS_ConeSet: flag must be 0,1 or 2, reseting to 0\n");
1088 for (
int j=0; j<nc; j++) {
1089 if (Gamma[j] <= 0) {
1090 egsFatal(
"EGS_ConeSet: gamma's must be positive\n");
1093 if (Gamma[j] <= gamma[j-1])
egsFatal(
"EGS_ConeSet: "
1094 "gamma's must be in increasing order\n");
1096 gamma[j] = Gamma[j];
1097 g12[j] = 1 + gamma[j]*gamma[j];
1098 g12i[j] = 1/sqrt(g12[j]);
1122 EGS_Float aa = xp*a;
1123 if (flag == 0 && aa < 0) {
1126 EGS_Float r2 = xp.length2();
1127 if (r2 <= aa*aa*g12[nc-1]) {
1135 EGS_Float aa = xp*a;
1136 if (flag == 0 && aa < 0) {
1139 EGS_Float r2 = xp.length2();
1141 for (j=0; j<nc; j++)
if (r2 <= aa*aa*g12[j]) {
1156 bool isRealRegion(
int ireg)
const {
1157 if (ireg < 0 || ireg >= nreg) {
1160 return flag != 1 ? true : (ireg != nc);
1168 EGS_Float &t,
int *newmed = 0,
EGS_Vector *normal = 0) {
1170 EGS_Float aa = xp*a, b = u*a, r2 = xp.length2(), c = u*xp;
1173 if (!xp.length2()) {
1175 int inew = isWhere(xp + u);
1182 *newmed = inew >= 0 ? medium(inew) : -1;
1187 if (ireg != 0 && ireg != 2*nc) {
1193 if (ireg < 0 || ireg == nc) {
1197 gam12 = ireg < nc ? g12[ireg-1] : g12[2*nc-ireg-1];
1199 EGS_Float A=1-b*b*gam12, B=c-aa*b*gam12, C=r2-aa*aa*gam12;
1202 EGS_Float tt = -1, lam;
1204 if (fabs(A) < boundaryTolerance) {
1205 if ((ireg < nc && b > 0) || (ireg >= nc && b < 0)) {
1210 EGS_Float D = B*B-A*C;
1211 if (D >= 0 && !(A > 0 && B > 0)) {
1212 tt = B < 0 ? C/(sqrt(D)-B) : -(sqrt(D)+B)/A;
1218 if (ireg == nc || ireg == -1) {
1224 inew = lam >= 0 ? nc-1 : nc+1;
1228 else if (!flag && lam>=0) {
1238 inew = lam >= 0 ? ireg-1 : ireg+1;
1241 if (hit && tt <= t) {
1244 *newmed = medium(inew);
1247 *normal = xp + u*t - a*(lam*gam12);
1248 normal->normalize();
1253 if (ireg < 0 || ireg == nc || hit) {
1258 EGS_Float gam12 = ireg < nc ? g12[ireg] : g12[2*nc-ireg];
1259 EGS_Float A=1-b*b*gam12, B=c-aa*b*gam12, C=r2-aa*aa*gam12;
1261 if (fabs(A) < boundaryTolerance) {
1262 if ((ireg < nc && b < 0) || (ireg > nc && b > 0)) {
1267 EGS_Float D = B*B-A*C;
1269 if (D >= 0 && !(A < 0 && B < 0)) {
1270 tt = B > 0 ? -C/(B+sqrt(D)) : (sqrt(D)-B)/A;
1276 EGS_Float lam = aa + b*tt;
1277 if ((ireg < nc && lam < 0) || (ireg > nc && lam > 0)) {
1285 if (inew == nc && flag < 2) {
1291 if (inew == nc && flag < 2) {
1296 *newmed = inew < 0 ? -1 : medium(inew);
1299 *normal = xp + u*t - a*(lam*gam12);
1300 normal->normalize();
1307 EGS_Float hownear(
int ireg,
const EGS_Vector &x) {
1310 EGS_Float aa = xp*a, r2 = xp.length2(), ag;
1313 if (ireg != 0 && ireg != 2*nc) {
1315 if (ireg < 0 || ireg == nc) {
1319 i = ireg < nc ? ireg-1 : 2*nc-ireg-1;
1322 if (flag == 0 && aa < 0 && ag*ag > r2*g12[i]) {
1326 tc = fabs((fabs(ag)-sqrt(r2-aa*aa))*g12i[i]);
1329 if (ireg < 0 || ireg == nc) {
1335 ag = aa*gamma[ireg];
1336 gam12i = g12i[ireg];
1339 ag = -aa*gamma[2*nc-ireg];
1340 gam12i = g12i[2*nc-ireg];
1342 EGS_Float tco = fabs((ag-sqrt(r2-aa*aa))*gam12i);
1344 return tco < tc ? tco : tc;
1347 int getMaxStep()
const {
1351 const string &getType()
const {
1355 void printInfo()
const;
1469 :
EGS_BaseGeometry(Name), xo(Xo), a(A), nl(0), nltot(0), nmax(0), same_Rout(
true), Rout(0),
1480 void addLayer(EGS_Float thick,
const vector<EGS_Float> &rtop,
1481 const vector<EGS_Float> &rbottom,
1482 const vector<string> &med_names);
1485 int medium(
int ireg)
const {
1487 int ir = ireg - il*nmax;
1488 return cones[il][ir]->medium(0);
1494 if (p < pos[0] || p > pos[nl]) {
1497 int il = findRegion(p,nl+1,pos);
1498 return cones[il][nr[il]-1]->isInside(x);
1504 if (p < pos[0] || p > pos[nl]) {
1507 int il = findRegion(p,nl+1,pos);
1508 int ir = isWhere(il,x);
1509 return ir < 0 ? -1 : il*nmax+ir;
1518 bool isRealRegion(
int ireg)
const {
1519 if (ireg < 0 || ireg >= nreg) {
1523 int ir = ireg - il*nmax;
1524 return (ir < nr[il]);
1529 EGS_Float &t,
int *newmed=0,
EGS_Vector *normal=0) {
1543 tp = (pos[il+1]-xp)/up;
1547 tp = (pos[il]-xp)/up;
1560 int ir = ireg - il*nmax;
1562 int irnew = cones[il][ir]->howfar(0,x,u,t,newmed,normal);
1565 irnew = ir < nr[il]-1 ? ir+1 : -1;
1570 int irnew1 = cones[il][ir-1]->howfar(-1,x,u,t,newmed,normal);
1583 *newmed = cones[il][irnew]->medium(0);
1585 return il*nmax + irnew;
1594 int ilnew = il + dir;
1596 *normal = dir > 0 ? a*(-1) : a;
1598 if (ilnew < 0 || ilnew >= nl) {
1603 if (dir > 0 && flag[il] >= 2) {
1605 *newmed = cones[il+1][ir]->medium(0);
1611 if (dir < 0 && (flag[il] == 1 || flag[il] == 3)) {
1613 *newmed = cones[il-1][ir]->medium(0);
1621 ir = isWhere(il,tmp);
1626 *newmed = cones[il][ir]->medium(0);
1643 tp = (pos[0]-xp)/up;
1650 int ir = isWhere(0, tmp);
1665 int inew_g = howfar(ir,tmp,u,tb,0,normal);
1666 if (inew_g < 0 && tb <= boundaryTolerance) {
1672 *newmed = cones[0][ir]->medium(0);
1682 else if (xp >= pos[nl]) {
1686 tp = (pos[nl]-xp)/up;
1693 int ir = isWhere(il, tmp);
1708 int inew_g = howfar(il*nmax+ir,tmp,u,tb,0,normal);
1709 if (inew_g < 0 && tb <= boundaryTolerance) {
1715 *newmed = cones[il][ir]->medium(0);
1743 int irnow = isWhere(x);
1759 int inew_g = howfar(irnow,x,u,tb,0,&tmp_normal);
1760 if (inew_g < 0 && tb <= boundaryTolerance) {
1766 int irnew = cones[0][nr[0]-1]->howfar(ireg,x,u,tt,0,&tmp_normal);
1771 EGS_Float aux = xp + up*tt;
1772 if (aux < pos[0] || aux > pos[nl] ||
1773 (aux == pos[0] && up <= 0) ||
1774 (aux == pos[nl] && up >= 0)) {
1777 il = findRegion(aux,nl+1,pos);
1779 *newmed = cones[il][nr[il]-1]->medium(0);
1782 *normal = tmp_normal;
1785 return il*nmax + nr[il]-1;
1789 il = findRegion(xp,nl+1,pos);
1794 bool isc = cones[il][nr[il]-1]->isInside(x);
1803 tp = (pos[il+1] - xp)/up;
1807 tp = (pos[il] - xp)/up;
1815 if (tp < boundaryTolerance) {
1817 if (il < 0 || il >= nl) {
1820 isc = cones[il][nr[il]-1]->isInside(x);
1825 int isc_new = cones[il][nr[il]-1]->howfar(0,x,u,tc);
1826 if (!(isc_new < 0 && tc < boundaryTolerance)) {
1827 egsWarning(
"EGS_ConeStack::howfar: called from the outside"
1828 " but I find x=(%g,%g,%g) to be inside\n", x.
x,x.
y,x.
z);
1829 egsWarning(
"layer=%d distance to planes=%g\n",il,tp);
1830 egsWarning(
"distance to outer cone=%g\n",tc);
1839 for (EGS_I64 loopCount=0; loopCount<=
loopMax; ++loopCount) {
1841 egsFatal(
"EGS_ConeStack::howfar: Too many iterations were required! Input may be invalid, or consider increasing loopMax.");
1848 tp = (pos[il+1] - xp)/up;
1852 tp = (pos[il] - xp)/up;
1860 EGS_Float tt = t - ttot;
1863 int irnew = cones[il][nr[il]-1]->howfar(-1,tmp,u,tt,&tmp_med,&tmp_normal);
1865 if (tp > ttot + tt) {
1871 *normal = tmp_normal;
1873 return il*nmax+nr[il]-1;
1876 if (tp > t || !dir) {
1880 if (il < 0 || il >= nl) {
1886 int itest = isWhere(il,tmp);
1890 *newmed = cones[il][itest]->medium(0);
1893 *normal = dir > 0 ? a*(-1) : a;
1895 return il*nmax + itest;
1902 EGS_Float hownear(
int ireg,
const EGS_Vector &x) {
1910 int ir = ireg - il*nmax;
1911 tp = min(xp-pos[il],pos[il+1]-xp);
1912 tc = cones[il][ir]->hownear(0,x);
1914 tc = min(tc,cones[il][ir-1]->hownear(-1,x));
1926 if (xp >= pos[nl]) {
1927 return xp - pos[nl];
1929 int il = findRegion(xp,nl+1,pos);
1930 tp = min(xp-pos[il],pos[il+1]-xp);
1931 return min(tp,cones[il][nr[il]-1]->hownear(-1,x));
1936 int getMaxStep()
const {
1938 for (
int j=0; j<nl; ++j) {
1939 nstep += 2*nr[j] + 1;
1945 const string &getType()
const {
1950 void printInfo()
const;
1953 int nLayer()
const {
1958 void shiftLabelRegions(
const int i,
const int index) {
1959 for (
size_t k=0; k<labels[i].regions.size(); k++) {
1960 labels[i].regions[k] += index*nmax;
1974 EGS_Float Rout, Rout2;
1992 inline int isWhere(
int il,
const EGS_Vector &x) {
1993 if (!cones[il][nr[il]-1]->isInside(x)) {
1996 for (
int j=0; j<nr[il]-1; j++) {
1997 if (cones[il][j]->isInside(x)) {
Base geometry class. Every geometry class must be derived from EGS_BaseGeometry.
A set of cones with different opening angles but the same axis and apexes.
A set of "parallel cones" (i.e. cones with the same axis and opening angles but different apexes)
A single cone that may be open (i.e. extends to infinity or closed by a plane perpendicular to the co...
A class representing 3D vectors.
EGS_BaseGeometry class header file.
Global egspp functions header file.
Attempts to fix broken math header files.
EGS_InfoFunction EGS_EXPORT egsFatal
Always use this function for reporting fatal errors.
const EGS_I64 loopMax
The maximum number of iterations for near-infinite loops.
EGS_InfoFunction EGS_EXPORT egsWarning
Always use this function for reporting warnings.
const EGS_Float veryFar
A very large float.