50 #ifdef BUILD_CONES_DLL
51 #define EGS_CONES_EXPORT __declspec(dllexport)
53 #define EGS_CONES_EXPORT __declspec(dllimport)
55 #define EGS_CONES_LOCAL
59 #ifdef HAVE_VISIBILITY
60 #define EGS_CONES_EXPORT __attribute__ ((visibility ("default")))
61 #define EGS_CONES_LOCAL __attribute__ ((visibility ("hidden")))
63 #define EGS_CONES_EXPORT
64 #define EGS_CONES_LOCAL
130 EGS_Float gamma, g12;
142 const EGS_Float *distance=0,
const string &N=
"")
145 open(
true), is_cyl(
false) {
159 egsWarning(
"EGS_SimpleCone: the distance to the closing plane must be positive\n");
167 EGS_Float Rtop, EGS_Float Rbottom,
bool Open=
true,
const string &N=
"")
174 if (fabs(Rtop - Rbottom) < boundaryTolerance) {
184 else if (Rtop < Rbottom) {
185 EGS_Float aux = dz*Rtop/(Rbottom-Rtop);
187 gamma = Rbottom/(aux+dz);
188 g12 = 1 + gamma*gamma;
193 EGS_Float aux = dz*Rbottom/(Rtop-Rbottom);
194 xo = Xo + a*(aux+dz);
196 gamma = Rtop/(aux+dz);
197 g12 = 1 + gamma*gamma;
213 if (!open && (aa < 0 || aa+d1 > 0)) {
219 EGS_Float r2 = xp.length2() - aa*aa;
227 EGS_Float r2 = xp.length2();
228 if (r2 <= aa*aa*g12) {
249 EGS_Float &t,
int *newmed=0,
EGS_Vector *normal=0) {
254 EGS_Float r2 = xp.length2();
265 EGS_Float A = 1 - b*b;
266 EGS_Float B = c - b*aa;
267 EGS_Float C = r2 - aa*aa - Ro2;
272 EGS_Float D = B*B-A*C;
273 if (D < 0 || (C > 0 && B > 0)) {
278 d = B<=0 ? (sqrt(D)-B)/A : -C/(sqrt(D)+B);
295 EGS_Float D = B*B-A*C;
310 EGS_Float aux = aa + d*b;
311 if (aux < 0 || aux+d1 > 0) {
318 if (newmed && ireg < 0) {
322 EGS_Float lam = aa+b*d;
325 *normal = ireg < 0 ? aux : aux*(-1);
328 return (!ireg ? -1 : 0);
348 else if (!open && b>0) {
349 EGS_Float tt = -d1/b;
379 if (aa+d1 > 0 && b < 0) {
380 EGS_Float tt = -(aa+d1)/b;
382 EGS_Float r2p = r2 + tt*(tt + 2*c);
383 if (r2p <= d1*d1*g12) {
397 if (r2 <= aa*aa*g12) {
405 EGS_Float tt = -(aa+d1)/b;
407 EGS_Float r2p = r2 + tt*(tt + 2*c);
408 if (r2p <= d1*d1*g12) {
430 EGS_Float A = 1 - b*b*g12;
431 EGS_Float B = c - aa*b*g12;
432 EGS_Float C = r2 - aa*aa*g12;
436 if (fabs(A) < boundaryTolerance) {
440 if ((!ireg && B>0) || (ireg && B<0)) {
441 EGS_Float ttt = -C/(2*B);
443 if (ttt >= 0 && lam >= 0) {
469 EGS_Float D = B*B-A*C;
474 if (!ireg && !(A<0 && B<0)) {
476 ttt = -C/(B+sqrt(D));
482 else if (ireg && !(A>0 && B>0)) {
487 ttt = -(sqrt(D)+B)/A;
495 if (ttt >= -boundaryTolerance && lam >= 0) {
501 if (tt > t || (!open && ireg && d1 + aa + tt*b > 0)) {
508 int inew = ireg ? 0 : -1;
512 *newmed = inew ? -1 : med;
515 *normal = xp + u*t - a*(lam*g12);
528 EGS_Float hownear(
int ireg,
const EGS_Vector &x) {
532 EGS_Float ag = aa*gamma;
533 EGS_Float r2 = xp.length2();
539 if (open || (aa > 0 && aa+d1 < 0)) {
540 r2 = sqrt(r2 - aa*aa);
549 r2 = sqrt(r2 - aa*aa);
562 EGS_Float aux = r2-Ro;
564 return sqrt(aa*aa + aux*aux);
566 EGS_Float tp = aa+d1;
567 return sqrt(tp*tp + aux*aux);
572 if (aa < 0 && ag*ag > r2*g12) {
577 EGS_Float r2a2 = r2-aa*aa;
578 EGS_Float r2a = sqrt(r2a2);
579 EGS_Float tc = fabs((ag-r2a)*g12i);
587 EGS_Float tp = d1+aa;
597 else if (tp > 0 && r2 < aa*aa*g12) {
599 EGS_Float aux = r2a - Ro;
600 tc = sqrt(tp*tp + aux*aux);
607 else if (tp + tc*gamma*g12i > 0) {
608 EGS_Float aux = r2a + d1*gamma;
609 tc = sqrt(aux*aux + tp*tp);
617 const string &getType()
const {
622 void printInfo()
const;
635 EGS_Float getGamma()
const {
640 EGS_Float getRadius(
const EGS_Vector &x)
const {
644 EGS_Float xp = (x-xo)*a;
743 EGS_Float gamma, g12;
753 const EGS_Float *distances,
const string &N=
"")
771 d =
new EGS_Float [nc-1];
772 for (
int j=1; j<nc; j++) {
773 d[j-1] = distances[j-1];
774 if (d[j-1] <= d_old) {
775 egsFatal(
"EGS_ParallelCones: " "distances must be in increasing order\n");
777 xo[j] = xo[0] + a*d[j-1];
798 EGS_Float r2 = xp.length2();
799 if (r2 <= aa*aa*g12) {
812 EGS_Float r2 = xp.length2();
813 if (r2 > aa*aa*g12) {
816 EGS_Float r2a2 = r2 - aa*aa;
817 for (
int j=0; j<nc-1; j++) {
818 EGS_Float aj = aa - d[j];
819 EGS_Float ajg = aj*gamma;
820 if (aj < 0 || r2a2 > ajg*ajg) {
852 EGS_Float r2 = xp.length2();
854 EGS_Float A = 1 - b*b*g12;
855 EGS_Float B = c - aa*b*g12;
856 EGS_Float C = r2 - aa*aa*g12;
861 if (fabs(A) < boundaryTolerance) {
862 EGS_Float ttt = -C/(2*B);
864 if (ttt >= 0 && lam >= 0) {
871 EGS_Float D = B*B-A*C;
872 if (D >= 0 && !(A > 0 && B > 0)) {
873 EGS_Float ttt = B < 0 ? C/(sqrt(D)-B) : -(sqrt(D)+B)/A;
875 if (ttt >= 0 && lam >= 0) {
882 int inew = ireg < 0 ? 0 : ireg+1;
885 *newmed = medium(inew);
888 *normal = xp + u*t - a*(lam*g12);
893 if (ireg < 0 || hit) {
901 EGS_Float aa = xp*a, b = u*a, r2 = xp.length2(), c = u*xp;
902 EGS_Float A = 1 - b*b*g12, B = c - aa*b*g12, C = r2 - aa*aa*g12;
903 EGS_Float to =
veryFar, lamo = -1;
904 if (fabs(A) < boundaryTolerance) {
908 EGS_Float ttt = -C/(2*B);
910 if (ttt >= 0 && lamo >= 0) {
916 EGS_Float D = B*B-A*C;
918 if (D >= 0 && !(A < 0 && B < 0)) {
919 EGS_Float ttt = B > 0 ? -C/(B+sqrt(D)) : (sqrt(D)-B)/A;
921 if (ttt >= 0 && lamo >= 0) {
930 *newmed = inew < 0 ? -1 : medium(inew);
933 *normal = xp + u*t - a*(lamo*g12);
942 EGS_Float hownear(
int ireg,
const EGS_Vector &x) {
944 if (ireg < 0 || ireg < nc-1) {
953 EGS_Float ag = aa*gamma;
954 EGS_Float r2 = xp.length2();
955 if (aa < 0 && ag*ag > r2*g12) {
959 tc = fabs((ag-sqrt(r2-aa*aa))*g12i);
967 EGS_Float ag = aa*gamma;
968 EGS_Float r2 = xp.length2();
969 EGS_Float tco = fabs((ag-sqrt(r2-aa*aa))*g12i);
970 return tco < tc ? tco : tc;
974 int getMaxStep()
const {
979 const string &getType()
const {
984 void printInfo()
const;
1063 EGS_Float *gamma, *g12, *g12i;
1072 EGS_Float *Gamma,
int Flag = 0,
const string &Name =
"") :
1076 egsFatal(
"EGS_ConeSet: number of cones must be positive\n");
1079 gamma =
new EGS_Float [nc];
1080 g12 =
new EGS_Float [nc];
1081 g12i =
new EGS_Float [nc];
1082 if (flag < 0 || flag > 2) {
1083 egsWarning(
"EGS_ConeSet: flag must be 0,1 or 2, reseting to 0\n");
1086 for (
int j=0; j<nc; j++) {
1087 if (Gamma[j] <= 0) {
1088 egsFatal(
"EGS_ConeSet: gamma's must be positive\n");
1091 if (Gamma[j] <= gamma[j-1])
egsFatal(
"EGS_ConeSet: "
1092 "gamma's must be in increasing order\n");
1094 gamma[j] = Gamma[j];
1095 g12[j] = 1 + gamma[j]*gamma[j];
1096 g12i[j] = 1/sqrt(g12[j]);
1120 EGS_Float aa = xp*a;
1121 if (flag == 0 && aa < 0) {
1124 EGS_Float r2 = xp.length2();
1125 if (r2 <= aa*aa*g12[nc-1]) {
1133 EGS_Float aa = xp*a;
1134 if (flag == 0 && aa < 0) {
1137 EGS_Float r2 = xp.length2();
1139 for (j=0; j<nc; j++)
if (r2 <= aa*aa*g12[j]) {
1154 bool isRealRegion(
int ireg)
const {
1155 if (ireg < 0 || ireg >= nreg) {
1158 return flag != 1 ?
true : (ireg != nc);
1166 EGS_Float &t,
int *newmed = 0,
EGS_Vector *normal = 0) {
1168 EGS_Float aa = xp*a, b = u*a, r2 = xp.length2(), c = u*xp;
1171 if (!xp.length2()) {
1173 int inew = isWhere(xp + u);
1180 *newmed = inew >= 0 ? medium(inew) : -1;
1185 if (ireg != 0 && ireg != 2*nc) {
1191 if (ireg < 0 || ireg == nc) {
1195 gam12 = ireg < nc ? g12[ireg-1] : g12[2*nc-ireg-1];
1197 EGS_Float A=1-b*b*gam12, B=c-aa*b*gam12, C=r2-aa*aa*gam12;
1200 EGS_Float tt = -1, lam;
1202 if (fabs(A) < boundaryTolerance) {
1203 if ((ireg < nc && b > 0) || (ireg >= nc && b < 0)) {
1208 EGS_Float D = B*B-A*C;
1209 if (D >= 0 && !(A > 0 && B > 0)) {
1210 tt = B < 0 ? C/(sqrt(D)-B) : -(sqrt(D)+B)/A;
1216 if (ireg == nc || ireg == -1) {
1222 inew = lam >= 0 ? nc-1 : nc+1;
1226 else if (!flag && lam>=0) {
1236 inew = lam >= 0 ? ireg-1 : ireg+1;
1239 if (hit && tt <= t) {
1242 *newmed = medium(inew);
1245 *normal = xp + u*t - a*(lam*gam12);
1246 normal->normalize();
1251 if (ireg < 0 || ireg == nc || hit) {
1256 EGS_Float gam12 = ireg < nc ? g12[ireg] : g12[2*nc-ireg];
1257 EGS_Float A=1-b*b*gam12, B=c-aa*b*gam12, C=r2-aa*aa*gam12;
1259 if (fabs(A) < boundaryTolerance) {
1260 if ((ireg < nc && b < 0) || (ireg > nc && b > 0)) {
1265 EGS_Float D = B*B-A*C;
1267 if (D >= 0 && !(A < 0 && B < 0)) {
1268 tt = B > 0 ? -C/(B+sqrt(D)) : (sqrt(D)-B)/A;
1274 EGS_Float lam = aa + b*tt;
1275 if ((ireg < nc && lam < 0) || (ireg > nc && lam > 0)) {
1283 if (inew == nc && flag < 2) {
1289 if (inew == nc && flag < 2) {
1294 *newmed = inew < 0 ? -1 : medium(inew);
1297 *normal = xp + u*t - a*(lam*gam12);
1298 normal->normalize();
1305 EGS_Float hownear(
int ireg,
const EGS_Vector &x) {
1308 EGS_Float aa = xp*a, r2 = xp.length2(), ag;
1311 if (ireg != 0 && ireg != 2*nc) {
1313 if (ireg < 0 || ireg == nc) {
1317 i = ireg < nc ? ireg-1 : 2*nc-ireg-1;
1320 if (flag == 0 && aa < 0 && ag*ag > r2*g12[i]) {
1324 tc = fabs((fabs(ag)-sqrt(r2-aa*aa))*g12i[i]);
1327 if (ireg < 0 || ireg == nc) {
1333 ag = aa*gamma[ireg];
1334 gam12i = g12i[ireg];
1337 ag = -aa*gamma[2*nc-ireg];
1338 gam12i = g12i[2*nc-ireg];
1340 EGS_Float tco = fabs((ag-sqrt(r2-aa*aa))*gam12i);
1342 return tco < tc ? tco : tc;
1345 int getMaxStep()
const {
1349 const string &getType()
const {
1353 void printInfo()
const;
1467 :
EGS_BaseGeometry(Name), xo(Xo), a(A), nl(0), nltot(0), nmax(0), same_Rout(
true), Rout(0),
1478 void addLayer(EGS_Float thick,
const vector<EGS_Float> &rtop,
1479 const vector<EGS_Float> &rbottom,
1480 const vector<string> &med_names);
1483 int medium(
int ireg)
const {
1485 int ir = ireg - il*nmax;
1486 return cones[il][ir]->medium(0);
1492 if (p < pos[0] || p > pos[nl]) {
1495 int il = findRegion(p,nl+1,pos);
1496 return cones[il][nr[il]-1]->isInside(x);
1502 if (p < pos[0] || p > pos[nl]) {
1505 int il = findRegion(p,nl+1,pos);
1506 int ir = isWhere(il,x);
1507 return ir < 0 ? -1 : il*nmax+ir;
1516 bool isRealRegion(
int ireg)
const {
1517 if (ireg < 0 || ireg >= nreg) {
1521 int ir = ireg - il*nmax;
1522 return (ir < nr[il]);
1527 EGS_Float &t,
int *newmed=0,
EGS_Vector *normal=0) {
1541 tp = (pos[il+1]-xp)/up;
1545 tp = (pos[il]-xp)/up;
1558 int ir = ireg - il*nmax;
1560 int irnew = cones[il][ir]->howfar(0,x,u,t,newmed,normal);
1563 irnew = ir < nr[il]-1 ? ir+1 : -1;
1568 int irnew1 = cones[il][ir-1]->howfar(-1,x,u,t,newmed,normal);
1581 *newmed = cones[il][irnew]->medium(0);
1583 return il*nmax + irnew;
1592 int ilnew = il + dir;
1594 *normal = dir > 0 ? a*(-1) : a;
1596 if (ilnew < 0 || ilnew >= nl) {
1601 if (dir > 0 && flag[il] >= 2) {
1603 *newmed = cones[il+1][ir]->medium(0);
1609 if (dir < 0 && (flag[il] == 1 || flag[il] == 3)) {
1611 *newmed = cones[il-1][ir]->medium(0);
1619 ir = isWhere(il,tmp);
1624 *newmed = cones[il][ir]->medium(0);
1641 tp = (pos[0]-xp)/up;
1648 int ir = isWhere(0, tmp);
1663 int inew_g = howfar(ir,tmp,u,tb,0,normal);
1664 if (inew_g < 0 && tb <= boundaryTolerance) {
1670 *newmed = cones[0][ir]->medium(0);
1680 else if (xp >= pos[nl]) {
1684 tp = (pos[nl]-xp)/up;
1691 int ir = isWhere(il, tmp);
1706 int inew_g = howfar(il*nmax+ir,tmp,u,tb,0,normal);
1707 if (inew_g < 0 && tb <= boundaryTolerance) {
1713 *newmed = cones[il][ir]->medium(0);
1741 int irnow = isWhere(x);
1757 int inew_g = howfar(irnow,x,u,tb,0,&tmp_normal);
1758 if (inew_g < 0 && tb <= boundaryTolerance) {
1764 int irnew = cones[0][nr[0]-1]->howfar(ireg,x,u,tt,0,&tmp_normal);
1769 EGS_Float aux = xp + up*tt;
1770 if (aux < pos[0] || aux > pos[nl] ||
1771 (aux == pos[0] && up <= 0) ||
1772 (aux == pos[nl] && up >= 0)) {
1775 il = findRegion(aux,nl+1,pos);
1777 *newmed = cones[il][nr[il]-1]->medium(0);
1780 *normal = tmp_normal;
1783 return il*nmax + nr[il]-1;
1787 il = findRegion(xp,nl+1,pos);
1792 bool isc = cones[il][nr[il]-1]->isInside(x);
1801 tp = (pos[il+1] - xp)/up;
1805 tp = (pos[il] - xp)/up;
1813 if (tp < boundaryTolerance) {
1815 if (il < 0 || il >= nl) {
1818 isc = cones[il][nr[il]-1]->isInside(x);
1823 int isc_new = cones[il][nr[il]-1]->howfar(0,x,u,tc);
1824 if (!(isc_new < 0 && tc < boundaryTolerance)) {
1825 egsWarning(
"EGS_ConeStack::howfar: called from the outside"
1826 " but I find x=(%g,%g,%g) to be inside\n", x.
x,x.
y,x.
z);
1827 egsWarning(
"layer=%d distance to planes=%g\n",il,tp);
1828 egsWarning(
"distance to outer cone=%g\n",tc);
1837 for (EGS_I64 loopCount=0; loopCount<=
loopMax; ++loopCount) {
1839 egsFatal(
"EGS_ConeStack::howfar: Too many iterations were required! Input may be invalid, or consider increasing loopMax.");
1846 tp = (pos[il+1] - xp)/up;
1850 tp = (pos[il] - xp)/up;
1858 EGS_Float tt = t - ttot;
1861 int irnew = cones[il][nr[il]-1]->howfar(-1,tmp,u,tt,&tmp_med,&tmp_normal);
1863 if (tp > ttot + tt) {
1869 *normal = tmp_normal;
1871 return il*nmax+nr[il]-1;
1874 if (tp > t || !dir) {
1878 if (il < 0 || il >= nl) {
1884 int itest = isWhere(il,tmp);
1888 *newmed = cones[il][itest]->medium(0);
1891 *normal = dir > 0 ? a*(-1) : a;
1893 return il*nmax + itest;
1900 EGS_Float hownear(
int ireg,
const EGS_Vector &x) {
1908 int ir = ireg - il*nmax;
1909 tp = min(xp-pos[il],pos[il+1]-xp);
1910 tc = cones[il][ir]->hownear(0,x);
1912 tc = min(tc,cones[il][ir-1]->hownear(-1,x));
1924 if (xp >= pos[nl]) {
1925 return xp - pos[nl];
1927 int il = findRegion(xp,nl+1,pos);
1928 tp = min(xp-pos[il],pos[il+1]-xp);
1929 return min(tp,cones[il][nr[il]-1]->hownear(-1,x));
1934 int getMaxStep()
const {
1936 for (
int j=0; j<nl; ++j) {
1937 nstep += 2*nr[j] + 1;
1943 const string &getType()
const {
1948 void printInfo()
const;
1951 int nLayer()
const {
1956 void shiftLabelRegions(
const int i,
const int index) {
1957 for (
size_t k=0; k<labels[i].regions.size(); k++) {
1958 labels[i].regions[k] += index*nmax;
1972 EGS_Float Rout, Rout2;
1990 inline int isWhere(
int il,
const EGS_Vector &x) {
1991 if (!cones[il][nr[il]-1]->isInside(x)) {
1994 for (
int j=0; j<nr[il]-1; j++) {
1995 if (cones[il][j]->isInside(x)) {
const EGS_I64 loopMax
The maximum number of iterations for near-infinite loops.
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.
Global egspp functions header file.
A set of "parallel cones" (i.e. cones with the same axis and opening angles but different apexes) ...
const EGS_Float veryFar
A very large float.
Base geometry class. Every geometry class must be derived from EGS_BaseGeometry.
EGS_InfoFunction EGS_EXPORT egsFatal
Always use this function for reporting fatal errors.
A set of cones with different opening angles but the same axis and apexes.
Attempts to fix broken math header files.
EGS_BaseGeometry class header file.
EGS_InfoFunction EGS_EXPORT egsWarning
Always use this function for reporting warnings.