184 #ifdef BUILD_OCTREE_DLL
185 #define EGS_OCTREE_EXPORT __declspec(dllexport)
187 #define EGS_OCTREE_EXPORT __declspec(dllimport)
189 #define EGS_OCTREE_LOCAL
193 #ifdef HAVE_VISIBILITY
194 #define EGS_OCTREE_EXPORT __attribute__ ((visibility ("default")))
195 #define EGS_OCTREE_LOCAL __attribute__ ((visibility ("hidden")))
197 #define EGS_OCTREE_EXPORT
198 #define EGS_OCTREE_LOCAL
208 int ixmin, iymin, izmin;
209 int ixmax, iymax, izmax;
214 vmin(boxMin), vmax(boxMax), nx(bboxRes[0]), ny(bboxRes[1]), nz(bboxRes[2]) {
216 ixmin = iymin = izmin = 0;
217 ixmax = iymax = izmax = 0;
226 if (b2.vmin.
x < b1.vmin.
x) {
227 b1.vmin.
x = b2.vmin.
x;
229 if (b2.vmin.
y < b1.vmin.
y) {
230 b1.vmin.
y = b2.vmin.
y;
232 if (b2.vmin.
z < b1.vmin.
z) {
233 b1.vmin.
z = b2.vmin.
z;
235 if (b2.vmax.
x > b1.vmax.
x) {
236 b1.vmax.
x = b2.vmax.
x;
238 if (b2.vmax.
y > b1.vmax.
y) {
239 b1.vmax.
y = b2.vmax.
y;
241 if (b2.vmax.
z > b1.vmax.
z) {
242 b1.vmax.
z = b2.vmax.
z;
246 EGS_Float dx1 = (b1.vmax.
x-b1.vmin.
x)/b1.nx;
247 EGS_Float dy1 = (b1.vmax.
y-b1.vmin.
y)/b1.ny;
248 EGS_Float dz1 = (b1.vmax.
z-b1.vmin.
z)/b1.nz;
249 EGS_Float dx2 = (b2.vmax.
x-b2.vmin.
x)/b2.nx;
250 EGS_Float dy2 = (b2.vmax.
y-b2.vmin.
y)/b2.ny;
251 EGS_Float dz2 = (b2.vmax.
z-b2.vmin.
z)/b2.nz;
255 b1.nx = (int)((b1.vmax.
x - b1.vmin.
x + 0.5*dx2) / dx2);
258 b1.nx = (int)((b1.vmax.
x - b1.vmin.
x +0.5*dx1) / dx1);
261 b1.ny = (int)((b1.vmax.
y - b1.vmin.
y + 0.5*dy2) / dy2);
264 b1.ny = (int)((b1.vmax.
y - b1.vmin.
y +0.5*dy1) / dy1);
267 b1.nz = (int)((b1.vmax.
z - b1.vmin.
z + 0.5*dz2) / dz2);
270 b1.nz = (int)((b1.vmax.
z - b1.vmin.
z +0.5*dz1) / dz1);
280 if (b2.vmin.
x < vmin.
x) {
283 if (b2.vmin.
y < vmin.
y) {
286 if (b2.vmin.
z < vmin.
z) {
289 if (b2.vmax.
x > vmax.
x) {
292 if (b2.vmax.
y > vmax.
y) {
295 if (b2.vmax.
z > vmax.
z) {
300 EGS_Float dx1 = (vmax.
x-vmin.
x)/nx;
301 EGS_Float dy1 = (vmax.
y-vmin.
y)/ny;
302 EGS_Float dz1 = (vmax.
z-vmin.
z)/nz;
303 EGS_Float dx2 = (b2.vmax.
x-b2.vmin.
x)/b2.nx;
304 EGS_Float dy2 = (b2.vmax.
y-b2.vmin.
y)/b2.ny;
305 EGS_Float dz2 = (b2.vmax.
z-b2.vmin.
z)/b2.nz;
309 nx = (int)((vmax.
x - vmin.
x + 0.5*dx2) / dx2);
312 nx = (int)((vmax.
x - vmin.
x +0.5*dx1) / dx1);
315 ny = (int)((vmax.
y - vmin.
y + 0.5*dy2) / dy2);
318 ny = (int)((vmax.
y - vmin.
y +0.5*dy1) / dy1);
321 nz = (int)((vmax.
z - vmin.
z + 0.5*dz2) / dz2);
324 nz = (int)((vmax.
z - vmin.
z +0.5*dz1) / dz1);
353 void createChildren() {
357 egsFatal(
"EGS_Octree_node::createChildren(): Memory allocation error");
359 for (
int i=0; i<8; i++) {
361 child[i].ix = (ix << 1) | (i>>0 & 0x1);
362 child[i].iy = (iy << 1) | (i>>1 & 0x1);
370 void deleteChildren() {
372 for (
int i=0; i<8; i++) {
373 child[i].deleteChildren();
381 int collapseChildren() {
383 for (
int i=0; i<8; i++) {
400 int shift = bbox.maxlevel -
level;
403 if (ii < bbox.ixmin) {
407 if (ii > bbox.ixmax) {
411 if (ii < bbox.iymin) {
415 if (ii > bbox.iymax) {
419 if (ii < bbox.izmin) {
423 if (ii > bbox.izmax) {
432 int shift = bbox.maxlevel -
level;
436 if (bbox.ixmin > iimin) {
439 iimax = ~(~ix<<shift);
440 if (bbox.ixmax < iimax) {
448 if (bbox.iymin > iimin) {
451 iimax = ~(~iy<<shift);
452 if (bbox.iymax < iimax) {
460 if (bbox.izmin > iimin) {
463 iimax = ~(~
iz<<shift);
464 if (bbox.izmax < iimax) {
524 EGS_Float bbxmin, bbymin, bbzmin;
525 EGS_Float bbxmax, bbymax, bbzmax;
526 EGS_Float xmin, ymin, zmin;
527 EGS_Float xmax, ymax, zmax;
528 EGS_Float dx, dy, dz, dxi, dyi, dzi;
529 int ixmin, iymin, izmin;
530 int ixmax, iymax, izmax;
534 long int nLeaf, nLeafMax;
535 vector<EGS_Octree_node *> tmp;
543 for (
int i=1; i<vBox.size(); i++) {
546 vBox.push_back(bbox);
554 dx = (bbox.vmax.
x - bbox.vmin.
x) / bbox.nx;
555 dy = (bbox.vmax.
y - bbox.vmin.
y) / bbox.ny;
556 dz = (bbox.vmax.
z - bbox.vmin.
z) / bbox.nz;
571 maxlevel = (int) ceil(log((EGS_Float)res)/0.6931471805599452862);
580 xmax = bbox.vmin.
x + dx*n;
581 ymax = bbox.vmin.
y + dy*n;
582 zmax = bbox.vmin.
z + dz*n;
586 for (
int i=0; i<vBox.size(); i++) {
588 box->ixmin = (int)((box->vmin.
x - xmin + 0.5*dx) * dxi);
589 box->iymin = (int)((box->vmin.
y - ymin + 0.5*dy) * dyi);
590 box->izmin = (int)((box->vmin.
z - zmin + 0.5*dz) * dzi);
591 box->nx = (int)((box->vmax.
x - box->vmin.
x + 0.5*dx) * dxi);
592 box->ny = (int)((box->vmax.
y - box->vmin.
y + 0.5*dy) * dyi);
593 box->nz = (int)((box->vmax.
z - box->vmin.
z + 0.5*dz) * dzi);
594 box->ixmax = box->ixmin + box->nx - 1;
595 box->iymax = box->iymin + box->ny - 1;
596 box->izmax = box->izmin + box->nz - 1;
615 box->nx = box->ixmax - box->ixmin + 1;
616 box->ny = box->iymax - box->iymin + 1;
617 box->nz = box->izmax - box->izmin + 1;
635 bbxmin = box->vmin.
x;
636 bbxmax = box->vmax.
x;
637 bbymin = box->vmin.
y;
638 bbymax = box->vmax.
y;
639 bbzmin = box->vmin.
z;
640 bbzmax = box->vmax.
z;
650 growOctree(root, vBox, pruneTree);
656 for (
int i=0; i<
nreg; i++) {
660 tmp.erase(tmp.begin(),tmp.end());
665 statOctree(root, vBox);
672 root->deleteChildren();
680 void statOctree(
EGS_Octree_node *node, vector<EGS_Octree_bbox> &vBox) {
682 for (
int i=0; i<8; i++) {
683 statOctree(node->
child+i, vBox);
686 else if (node->insideBBox(vBox[vBox.size()-1]) && node->
medium>=0) {
687 int shift = maxlevel - node->
level;
689 nLeafMax += 1<<(3*shift);
695 void growOctree(
EGS_Octree_node *node, vector<EGS_Octree_bbox> &vBox,
bool prune) {
698 bool refineNode =
false;
701 if (node->
level < maxlevel) {
706 for (
int i=0; i<vBox.size()-1; i++) {
707 int boxlevel = vBox[i].level;
708 if (node->insideBBox(vBox[i])) {
716 for (
int i=0; i<vBox.size()-1; i++) {
717 int boxlevel = vBox[i].level;
718 if (!node->insideBBox(vBox[i]) && node->intersectBBox(vBox[i])) {
719 if (boxlevel > level) {
727 if (node->
level < level) {
734 node->createChildren();
735 for (
int i=0; i<8; i++) {
736 growOctree(node->
child+i, vBox, prune);
739 if (node->collapseChildren()) {
740 tmp.resize(tmp.size()-8);
741 node->
region = tmp.size();
748 bool insideSomeBox =
false;
749 for (
int i=0; i<vBox.size()-1; i++) {
750 if (node->insideBBox(vBox[i])) {
751 insideSomeBox =
true;
757 int shift = maxlevel - node->
level;
758 int ix = node->ix << shift;
759 int iy = node->iy << shift;
760 int iz = node->
iz << shift;
761 int ireg = geom->
isWhere(
EGS_Vector(xmin+(ix+0.5)*dx, ymin+(iy+0.5)*dy, zmin+(iz+0.5)*dz));
766 node->
region = tmp.size();
776 if (ixn < ixmin || ixn > ixmax) {
781 int shift = maxlevel - node->
level;
782 if (iyn < node->iy<<shift) {
783 iyn = node->iy<<shift;
785 else if (iyn > ~(~node->iy<<shift)) {
786 iyn = ~(~node->iy<<shift);
788 if (izn < node->iz<<shift) {
789 izn = node->
iz<<shift;
791 else if (izn > ~(~node->
iz<<shift)) {
792 izn = ~(~node->
iz<<shift);
796 int diff = node->ix ^ (ixn>>shift);
798 while (diff & (1<<shift)) {
802 shift = maxlevel - node->
level;
803 while (node->
child) {
806 childIndex = (ixn>>shift & 0x1);
807 childIndex |= (iyn>>shift & 0x1) << 1;
808 childIndex |= (izn>>shift & 0x1) << 2;
809 node = node->
child + childIndex;
811 shift = maxlevel - node->
level;
821 if (iyn < iymin || iyn > iymax) {
826 int shift = maxlevel - node->
level;
827 if (ixn < node->ix<<shift) {
828 ixn = node->ix<<shift;
830 else if (ixn > ~(~node->ix<<shift)) {
831 ixn = ~(~node->ix<<shift);
833 if (izn < node->iz<<shift) {
834 izn = node->
iz<<shift;
836 else if (izn > ~(~node->
iz<<shift)) {
837 izn = ~(~node->
iz<<shift);
841 int diff = node->iy ^ (iyn>>shift);
843 while (diff & (1<<shift)) {
847 shift = maxlevel - node->
level;
848 while (node->
child) {
851 childIndex = (ixn>>shift & 0x1);
852 childIndex |= (iyn>>shift & 0x1) << 1;
853 childIndex |= (izn>>shift & 0x1) << 2;
854 node = node->
child + childIndex;
864 if (izn < izmin || izn > izmax) {
869 int shift = maxlevel - node->
level;
870 if (ixn < node->ix<<shift) {
871 ixn = node->ix<<shift;
873 else if (ixn > ~(~node->ix<<shift)) {
874 ixn = ~(~node->ix<<shift);
876 if (iyn < node->iy<<shift) {
877 iyn = node->iy<<shift;
879 else if (iyn > ~(~node->iy<<shift)) {
880 iyn = ~(~node->iy<<shift);
884 int diff = node->
iz ^ (izn>>shift);
886 while (diff & (1<<shift)) {
890 shift = maxlevel - node->
level;
891 while (node->
child) {
894 childIndex = (ixn>>shift & 0x1);
895 childIndex |= (iyn>>shift & 0x1) << 1;
896 childIndex |= (izn>>shift & 0x1) << 2;
897 node = node->
child + childIndex;
905 if ((ix<ixmin) || (ix>ixmax) || (iy<iymin) || (iy>iymax) || (iz<izmin) || (iz>izmax)) {
909 int shift = maxlevel;
910 while (node->
child) {
913 childIndex = (ix>>shift & 0x1);
914 childIndex |= (iy>>shift & 0x1) << 1;
915 childIndex |= (iz>>shift & 0x1) << 2;
916 node = node->
child + childIndex;
923 void setIndices(
const EGS_Vector &r,
int &ix,
int &iy,
int &iz) {
924 ix = (int)((r.
x-xmin)*dxi);
925 iy = (int)((r.
y-ymin)*dyi);
926 iz = (int)((r.
z-zmin)*dzi);
950 if (r.
x >= bbxmin && r.
x <= bbxmax &&
951 r.
y >= bbymin && r.
y <= bbymax &&
952 r.
z >= bbzmin && r.
z <= bbzmax) {
965 setIndices(r,ix,iy,iz);
966 return getNode(ix,iy,iz)->region;
982 setIndices(r, ix, iy, iz);
983 return getNode(ix,iy,iz)->region;
988 int medium(
int ireg)
const {
989 return nodeReg[ireg]->
medium;
1004 int shift = maxlevel - node->
level;
1017 xBound = xmin + (ix+1)*dx;
1019 EGS_Float d = (xBound-r.
x) / u.
x;
1036 xBound = xmin + ix*dx;
1038 EGS_Float d = (xBound-r.
x) / u.
x;
1058 yBound = ymin + (iy+1)*dy;
1060 EGS_Float d = (yBound - r.
y) / u.
y;
1077 yBound = ymin + iy*dy;
1079 EGS_Float d = (yBound-r.
y) / u.
y;
1098 zBound = zmin + (iz+1)*dz;
1100 EGS_Float d = (zBound-r.
z) / u.
z;
1117 zBound = zmin + iz*dz;
1119 EGS_Float d = (zBound-r.
z) / u.
z;
1136 setIndices(ryz, tmp, iy, iz);
1137 node = getNeighborNodeX(node, ix, iy, iz);
1139 else if (crossed==1) {
1141 setIndices(rxz, ix, tmp, iz);
1142 node = getNeighborNodeY(node, ix, iy, iz);
1144 else if (crossed==2) {
1146 setIndices(rxy, ix, iy, tmp);
1147 node = getNeighborNodeZ(node, ix, iy, iz);
1163 int ix=0, iy=0, iz=0;
1164 EGS_Float d, tlong = 2*t;
1168 if (r.
x <= bbxmin && u.
x > 0) {
1170 d = (bbxmin-r.
x) / u.
x;
1172 else if (r.
x >= bbxmax && u.
x < 0) {
1174 d = (bbxmax-r.
x) / u.
x;
1180 EGS_Float yy = r.
y + u.
y*d;
1181 EGS_Float zz = r.
z + u.
z*d;
1182 if (yy >= bbymin && yy <= bbymax && zz >= bbzmin && zz <= bbzmax) {
1184 setIndices(rr, tmp, iy, iz);
1189 node = getNode(ix,iy,iz);
1195 if (r.
y <= bbymin && u.
y > 0) {
1197 d = (bbymin-r.
y) / u.
y;
1199 else if (r.
y >= bbymax && u.
y < 0) {
1201 d = (bbymax-r.
y) / u.
y;
1207 EGS_Float xx = r.
x + u.
x*d;
1208 EGS_Float zz = r.
z + u.
z*d;
1209 if (xx >= bbxmin && xx <= bbxmax && zz >= bbzmin && zz <= bbzmax) {
1211 setIndices(rr, ix, tmp, iz);
1216 node = getNode(ix,iy,iz);
1222 if (r.
z <= bbzmin && u.
z > 0) {
1224 d = (bbzmin-r.
z) / u.
z;
1226 else if (r.
z >= bbzmax && u.
z < 0) {
1228 d = (bbzmax-r.
z) / u.
z;
1234 EGS_Float xx = r.
x + u.
x*d;
1235 EGS_Float yy = r.
y + u.
y*d;
1236 if (xx >= bbxmin && xx <= bbxmax && yy >= bbymin && yy <= bbymax) {
1238 setIndices(rr, ix, iy, tmp);
1243 node = getNode(ix,iy,iz);
1259 inew = howfarOut(r, u, t, normal);
1262 inew = howfarIn(nodeReg[ireg], r, u, t, normal);
1266 if (inew>=0 && newmed) {
1267 *newmed = nodeReg[inew]->
medium;
1274 EGS_Float hownearIn(
int ireg,
const EGS_Vector &r) {
1276 int shift = maxlevel - node->
level;
1277 EGS_Float t1, t2, tx, ty, tz;
1281 imin = node->ix << shift;
1282 imax = ~(~node->ix << shift);
1283 t1 = (r.
x-xmin)-dx*imin;
1284 t2 = dx*(imax-imin+1)-t1;
1285 tx = t1 < t2 ? t1 : t2;
1288 imin = node->iy << shift;
1289 imax = ~(~node->iy << shift);
1290 t1 = (r.
y-ymin)-dy*imin;
1291 t2 = dy*(imax-imin+1)-t1;
1292 ty = t1 < t2 ? t1 : t2;
1295 imin = node->
iz << shift;
1296 imax = ~(~node->
iz << shift);
1297 t1 = (r.
z-zmin)-dz*imin;
1298 t2 = dz*(imax-imin+1)-t1;
1299 tz = t1 < t2 ? t1 : t2;
1301 return tx<ty && tx<tz ? tx : ty<tz ? ty : tz;
1308 return hownearIn(ireg, r);
1311 EGS_Float s1=0, s2=0;
1312 if (r.
x < bbxmin || r.
x > bbxmax) {
1313 EGS_Float t = r.
x < bbxmin ? bbxmin-r.
x : r.
x-bbxmax;
1318 if (r.
y < bbymin || r.
y > bbymax) {
1319 EGS_Float t = r.
y < bbymin ? bbymin-r.
y : r.
y-bbymax;
1324 if (r.
z < bbzmin || r.
z > bbzmax) {
1325 EGS_Float t = r.
z < bbzmin ? bbzmin-r.
z : r.
z-bbzmax;
1330 return nc == 1 ? s1 : sqrt(s2);
1335 const string &
getType()
const {
Base geometry class. Every geometry class must be derived from EGS_BaseGeometry.
virtual EGS_Float hownear(int ireg, const EGS_Vector &x)=0
Calculate the distance to a boundary for position x in any direction.
virtual int inside(const EGS_Vector &x)=0
Returns the region index, if inside, or -1 if outside (obsolete)
virtual const string & getType() const =0
Get the geometry type.
int nreg
Number of local regions in this geometry.
virtual int howfar(int ireg, const EGS_Vector &x, const EGS_Vector &u, EGS_Float &t, int *newmed=0, EGS_Vector *normal=0)=0
Calculate the distance to a boundary from x along the direction u.
virtual bool isInside(const EGS_Vector &x)=0
Is the position x inside the geometry?
virtual int medium(int ireg) const
Returns the medium index in region ireg.
virtual void printInfo() const
Print information about this geometry.
EGS_BaseGeometry(const string &Name)
Construct a geometry named Name.
virtual int isWhere(const EGS_Vector &x)=0
In which region is poisition x?
EGS_Octree_node * child
pointer to children nodes, NULL is there are no children
EGS_Octree_node * parent
pointer to the parent node (only root node can have parent set to NULL)
short medium
medium index for the node
int iz
octree indices, representing the binary location code of the node in x, y, z;
int region
region number of the node
unsigned short level
depth of the node (root node is level 0)
A class representing 3D vectors.
EGS_BaseGeometry class header file.
Global egspp functions header file.
EGS_InfoFunction EGS_EXPORT egsFatal
Always use this function for reporting fatal errors.