46 : fMin(pMin), fMax(pMax)
59 : fPolygons(&polygons)
63 CheckBoundingPolygons();
67 G4double xmin = kInfinity, ymin = kInfinity, zmin = kInfinity;
68 G4double xmax = -kInfinity, ymax = -kInfinity, zmax = -kInfinity;
69 for (
auto ibase = fPolygons->cbegin(); ibase != fPolygons->cend(); ++ibase)
71 for (
auto ipoint = (*ibase)->cbegin(); ipoint != (*ibase)->cend(); ++ipoint)
74 if (x < xmin) xmin = x;
75 if (x > xmax) xmax = x;
77 if (y < ymin) ymin = y;
78 if (y > ymax) ymax = y;
80 if (z < zmin) zmin = z;
81 if (z > zmax) zmax = z;
84 fMin.
set(xmin,ymin,zmin);
85 fMax.
set(xmax,ymax,zmax);
99 const std::vector<const G4ThreeVectorList*>& polygons)
100 : fMin(pMin), fMax(pMax), fPolygons(&polygons)
105 CheckBoundingPolygons();
120void G4BoundingEnvelope::CheckBoundingBox()
122 if (fMin.
x() >= fMax.
x() || fMin.
y() >= fMax.
y() || fMin.
z() >= fMax.
z())
124 std::ostringstream message;
125 message <<
"Badly defined bounding box (min >= max)!"
126 <<
"\npMin = " << fMin
127 <<
"\npMax = " << fMax;
128 G4Exception(
"G4BoundingEnvelope::CheckBoundingBox()",
138void G4BoundingEnvelope::CheckBoundingPolygons()
140 G4int nbases = fPolygons->size();
143 std::ostringstream message;
144 message <<
"Wrong number of polygons in the sequence: " << nbases
145 <<
"\nShould be at least two!";
146 G4Exception(
"G4BoundingEnvelope::CheckBoundingPolygons()",
151 G4int nsize = std::max((*fPolygons)[0]->size(),(*fPolygons)[1]->size());
154 std::ostringstream message;
155 message <<
"Badly constructed polygons!"
156 <<
"\nNumber of polygons: " << nbases
157 <<
"\nPolygon #0 size: " << (*fPolygons)[0]->size()
158 <<
"\nPolygon #1 size: " << (*fPolygons)[1]->size()
160 G4Exception(
"G4BoundingEnvelope::CheckBoundingPolygons()",
165 for (
G4int k=0; k<nbases; ++k)
167 G4int np = (*fPolygons)[k]->size();
168 if (np == nsize)
continue;
169 if (np == 1 && k==0)
continue;
170 if (np == 1 && k==nbases-1)
continue;
171 std::ostringstream message;
172 message <<
"Badly constructed polygons!"
173 <<
"\nNumber of polygons: " << nbases
174 <<
"\nPolygon #" << k <<
" size: " << np
175 <<
"\nexpected size: " << nsize;
176 G4Exception(
"G4BoundingEnvelope::SetBoundingPolygons()",
205 if (pTransform3D.
xx()==1 && pTransform3D.
yy()==1 && pTransform3D.
zz()==1)
221 if (xmin >= xminlim && xmax <= xmaxlim &&
222 ymin >= yminlim && ymax <= ymaxlim &&
223 zmin >= zminlim && zmax <= zmaxlim)
249 G4double scale = FindScaleFactor(pTransform3D);
255 G4double radius = 0.5*scale*(fMax-fMin).mag() + delta;
260 if (center.
x()-radius > xmaxlim)
return true;
261 if (center.
y()-radius > ymaxlim)
return true;
262 if (center.
z()-radius > zmaxlim)
return true;
263 if (center.
x()+radius < xminlim)
return true;
264 if (center.
y()+radius < yminlim)
return true;
265 if (center.
z()+radius < zminlim)
return true;
290 if (pTransform3D.
xx()==1 && pTransform3D.
yy()==1 && pTransform3D.
zz()==1)
306 if (fPolygons ==
nullptr)
332 G4double scale = FindScaleFactor(pTransform3D);
338 G4double radius = 0.5*scale*(fMax-fMin).mag() + delta;
343 if (center.
x()-radius >= xminlim && center.
x()+radius <= xmaxlim &&
344 center.
y()-radius >= yminlim && center.
y()+radius <= ymaxlim &&
345 center.
z()-radius >= zminlim && center.
z()+radius <= zmaxlim )
350 cx = pTransform3D.
xx();
351 cy = pTransform3D.
xy();
352 cz = pTransform3D.
xz();
353 cd = pTransform3D.
dx();
357 cx = pTransform3D.
yx();
358 cy = pTransform3D.
yy();
359 cz = pTransform3D.
yz();
360 cd = pTransform3D.
dy();
364 cx = pTransform3D.
zx();
365 cy = pTransform3D.
zy();
366 cz = pTransform3D.
zz();
367 cd = pTransform3D.
dz();
371 cx = cy = cz = cd = kInfinity;
373 G4double emin = kInfinity, emax = -kInfinity;
374 if (fPolygons ==
nullptr)
377 coor = cx*fMin.
x() + cy*fMin.
y() + cz*fMin.
z() + cd;
378 if (coor < emin) emin = coor;
379 if (coor > emax) emax = coor;
380 coor = cx*fMax.
x() + cy*fMin.
y() + cz*fMin.
z() + cd;
381 if (coor < emin) emin = coor;
382 if (coor > emax) emax = coor;
383 coor = cx*fMax.
x() + cy*fMax.
y() + cz*fMin.
z() + cd;
384 if (coor < emin) emin = coor;
385 if (coor > emax) emax = coor;
386 coor = cx*fMin.
x() + cy*fMax.
y() + cz*fMin.
z() + cd;
387 if (coor < emin) emin = coor;
388 if (coor > emax) emax = coor;
389 coor = cx*fMin.
x() + cy*fMin.
y() + cz*fMax.
z() + cd;
390 if (coor < emin) emin = coor;
391 if (coor > emax) emax = coor;
392 coor = cx*fMax.
x() + cy*fMin.
y() + cz*fMax.
z() + cd;
393 if (coor < emin) emin = coor;
394 if (coor > emax) emax = coor;
395 coor = cx*fMax.
x() + cy*fMax.
y() + cz*fMax.
z() + cd;
396 if (coor < emin) emin = coor;
397 if (coor > emax) emax = coor;
398 coor = cx*fMin.
x() + cy*fMax.
y() + cz*fMax.
z() + cd;
399 if (coor < emin) emin = coor;
400 if (coor > emax) emax = coor;
404 for (
auto ibase=fPolygons->cbegin(); ibase!=fPolygons->cend(); ++ibase)
406 for (
auto ipoint=(*ibase)->cbegin(); ipoint!=(*ibase)->cend(); ++ipoint)
408 G4double coor = ipoint->x()*cx + ipoint->y()*cy + ipoint->z()*cz + cd;
409 if (coor < emin) emin = coor;
410 if (coor > emax) emax = coor;
422 if (center.
x()-radius > xmaxlim)
return false;
423 if (center.
y()-radius > ymaxlim)
return false;
424 if (center.
z()-radius > zmaxlim)
return false;
425 if (center.
x()+radius < xminlim)
return false;
426 if (center.
y()+radius < yminlim)
return false;
427 if (center.
z()+radius < zminlim)
return false;
431 G4int nbases = (fPolygons == 0) ? 2 : fPolygons->size();
432 std::vector<G4Polygon3D*> bases(nbases);
433 if (fPolygons ==
nullptr)
440 for (
G4int i=0; i<nbases; ++i)
442 bases[i] =
new G4Polygon3D((*fPolygons)[i]->size());
448 TransformVertices(pTransform3D, bases);
456 for (
auto i=0; i<3; ++i)
462 limits.
AddLimit(axis[i], emin, emax);
469 extent.first =
G4Point3D( kInfinity, kInfinity, kInfinity);
470 extent.second =
G4Point3D(-kInfinity,-kInfinity,-kInfinity);
471 for (
G4int k=0; k<nbases-1; ++k)
477 GetPrismAABB(*baseA, *baseB, prismAABB);
487 if (extent.first.x() > prismAABB.first.x())
488 extent.first.setX( prismAABB.first.x() );
489 if (extent.first.y() > prismAABB.first.y())
490 extent.first.setY( prismAABB.first.y() );
491 if (extent.first.z() > prismAABB.first.z())
492 extent.first.setZ( prismAABB.first.z() );
493 if (extent.second.x() < prismAABB.second.x())
494 extent.second.setX(prismAABB.second.x());
495 if (extent.second.y() < prismAABB.second.y())
496 extent.second.setY(prismAABB.second.y());
497 if (extent.second.z() < prismAABB.second.z())
498 extent.second.setZ(prismAABB.second.z());
511 std::vector<G4Segment3D> vecEdges;
512 CreateListOfEdges(*baseA, *baseB, vecEdges);
513 if (ClipEdgesByVoxel(vecEdges, limits, extent))
continue;
533 if (bits == 0xFFF)
continue;
535 std::vector<G4Plane3D> vecPlanes;
536 CreateListOfPlanes(*baseA, *baseB, vecPlanes);
537 ClipVoxelByPlanes(bits, limits, vecPlanes, prismAABB, extent);
542 for (
G4int i=0; i<nbases; ++i) {
delete bases[i]; bases[i] = 0; }
547 if (pAxis ==
kXAxis) { emin = extent.first.x(); emax = extent.second.x(); }
548 if (pAxis ==
kYAxis) { emin = extent.first.y(); emax = extent.second.y(); }
549 if (pAxis ==
kZAxis) { emin = extent.first.z(); emax = extent.second.z(); }
551 if (emin > emax)
return false;
567G4BoundingEnvelope::FindScaleFactor(
const G4Transform3D& pTransform3D)
const
569 if (pTransform3D.
xx() == 1. &&
570 pTransform3D.
yy() == 1. &&
571 pTransform3D.
zz() == 1.)
return 1.;
576 G4double sxsx = xx*xx + yx*yx + zx*zx;
580 G4double sysy = xy*xy + yy*yy + zy*zy;
584 G4double szsz = xz*xz + yz*yz + zz*zz;
585 G4double ss = std::max(std::max(sxsx,sysy),szsz);
586 return (ss <= 1.) ? 1. : std::sqrt(ss);
594G4BoundingEnvelope::TransformVertices(
const G4Transform3D& pTransform3D,
595 std::vector<G4Polygon3D*>& pBases)
const
598 std::vector<const G4ThreeVectorList*> aabb(2);
599 aabb[0] = &baseA; aabb[1] = &baseB;
600 if (fPolygons ==
nullptr)
602 baseA[0].set(fMin.
x(),fMin.
y(),fMin.
z());
603 baseA[1].set(fMax.
x(),fMin.
y(),fMin.
z());
604 baseA[2].set(fMax.
x(),fMax.
y(),fMin.
z());
605 baseA[3].set(fMin.
x(),fMax.
y(),fMin.
z());
606 baseB[0].set(fMin.
x(),fMin.
y(),fMax.
z());
607 baseB[1].set(fMax.
x(),fMin.
y(),fMax.
z());
608 baseB[2].set(fMax.
x(),fMax.
y(),fMax.
z());
609 baseB[3].set(fMin.
x(),fMax.
y(),fMax.
z());
611 std::vector<const G4ThreeVectorList*>::const_iterator ia, iaend;
612 std::vector<G4Polygon3D*>::iterator ib = pBases.begin();
613 ia = (fPolygons == 0) ? aabb.begin() : fPolygons->begin();
614 iaend = (fPolygons == 0) ? aabb.end() : fPolygons->end();
616 if (pTransform3D.
xx()==1 && pTransform3D.
yy()==1 && pTransform3D.
zz()==1)
619 for ( ; ia != iaend; ++ia, ++ib)
621 G4ThreeVectorList::const_iterator ka = (*ia)->begin();
622 G4Polygon3D::iterator kb = (*ib)->begin();
623 for ( ; ka != (*ia)->end(); ++ka, ++kb) { (*kb) = (*ka) + offset; }
628 for ( ; ia != iaend; ++ia, ++ib)
630 G4ThreeVectorList::const_iterator ka = (*ia)->begin();
631 G4Polygon3D::iterator kb = (*ib)->begin();
632 for ( ; ka != (*ia)->end(); ++ka, ++kb)
645G4BoundingEnvelope::GetPrismAABB(
const G4Polygon3D& pBaseA,
649 G4double xmin = kInfinity, ymin = kInfinity, zmin = kInfinity;
650 G4double xmax = -kInfinity, ymax = -kInfinity, zmax = -kInfinity;
654 for (
auto it1 = pBaseA.cbegin(); it1 != pBaseA.cend(); ++it1)
657 if (x < xmin) xmin = x;
658 if (x > xmax) xmax = x;
660 if (y < ymin) ymin = y;
661 if (y > ymax) ymax = y;
663 if (z < zmin) zmin = z;
664 if (z > zmax) zmax = z;
669 for (
auto it2 = pBaseB.cbegin(); it2 != pBaseB.cend(); ++it2)
672 if (x < xmin) xmin = x;
673 if (x > xmax) xmax = x;
675 if (y < ymin) ymin = y;
676 if (y > ymax) ymax = y;
678 if (z < zmin) zmin = z;
679 if (z > zmax) zmax = z;
685 pAABB.second =
G4Point3D(xmax,ymax,zmax);
693G4BoundingEnvelope::CreateListOfEdges(
const G4Polygon3D& baseA,
695 std::vector<G4Segment3D>& pEdges)
const
697 G4int na = baseA.size();
698 G4int nb = baseB.size();
704 for (
G4int i=0; i<na; ++i)
716 for (
G4int i=0; i<na; ++i)
727 for (
G4int i=0; i<nb; ++i)
741G4BoundingEnvelope::CreateListOfPlanes(
const G4Polygon3D& baseA,
743 std::vector<G4Plane3D>& pPlanes)
const
747 G4int na = baseA.size();
748 G4int nb = baseB.size();
749 G4Point3D pa(0.,0.,0.), pb(0.,0.,0.), p0;
751 for (
G4int i=0; i<na; ++i) pa += baseA[i];
752 for (
G4int i=0; i<nb; ++i) pb += baseB[i];
753 pa /= na; pb /= nb; p0 = (pa+pb)/2.;
761 for (
G4int i=0; i<na; ++i)
763 norm = (baseB[k]-baseA[i]).cross(baseA[k]-baseB[i]);
766 pPlanes.push_back(
G4Plane3D(norm,baseA[i]));
770 norm = (baseA[2]-baseA[0]).cross(baseA[1]-pa);
775 norm = (baseB[2]-baseB[0]).cross(baseB[1]-pb);
784 for (
G4int i=0; i<na; ++i)
786 norm = (baseA[i]-baseB[0]).cross(baseA[k]-baseB[0]);
789 pPlanes.push_back(
G4Plane3D(norm,baseB[0]));
793 norm = (baseA[2]-baseA[0]).cross(baseA[1]-pa);
802 for (
G4int i=0; i<nb; ++i)
804 norm = (baseB[i]-baseA[0]).cross(baseB[k]-baseA[0]);
807 pPlanes.push_back(
G4Plane3D(norm,baseA[0]));
811 norm = (baseB[2]-baseB[0]).cross(baseB[1]-pb);
820 G4int nplanes = pPlanes.size();
821 for (
G4int i=0; i<nplanes; ++i)
823 pPlanes[i].normalize();
824 if (pPlanes[i].distance(p0) > 0)
826 pPlanes[i] =
G4Plane3D(-pPlanes[i].a(),-pPlanes[i].b(),
827 -pPlanes[i].c(),-pPlanes[i].d());
839G4BoundingEnvelope::ClipEdgesByVoxel(
const std::vector<G4Segment3D>& pEdges,
847 G4int nedges = pEdges.size();
848 for (
G4int k=0; k<nedges; ++k)
852 if (std::abs(p1.
x()-p2.
x())+
853 std::abs(p1.
y()-p2.
y())+
861 if (d2 > 0.0) { done =
false;
continue; }
862 p1 = (p2*d1-p1*d2)/(d1-d2);
866 if (d2 > 0.0) { p2 = (p1*d2-p2*d1)/(d2-d1); }
874 if (d2 > 0.) { done =
false;
continue; }
875 p1 = (p2*d1-p1*d2)/(d1-d2);
879 if (d2 > 0.) { p2 = (p1*d2-p2*d1)/(d2-d1); }
887 if (d2 > 0.) { done =
false;
continue; }
888 p1 = (p2*d1-p1*d2)/(d1-d2);
892 if (d2 > 0.) { p2 = (p1*d2-p2*d1)/(d2-d1); }
900 if (d2 > 0.) { done =
false;
continue; }
901 p1 = (p2*d1-p1*d2)/(d1-d2);
905 if (d2 > 0.) { p2 = (p1*d2-p2*d1)/(d2-d1); }
913 if (d2 > 0.) { done =
false;
continue; }
914 p1 = (p2*d1-p1*d2)/(d1-d2);
918 if (d2 > 0.) { p2 = (p1*d2-p2*d1)/(d2-d1); }
926 if (d2 > 0.) { done =
false;
continue; }
927 p1 = (p2*d1-p1*d2)/(d1-d2);
931 if (d2 > 0.) { p2 = (p1*d2-p2*d1)/(d2-d1); }
935 emin.
setX(std::min(std::min(p1.
x(),p2.
x()),emin.
x()));
936 emin.
setY(std::min(std::min(p1.
y(),p2.
y()),emin.
y()));
937 emin.
setZ(std::min(std::min(p1.
z(),p2.
z()),emin.
z()));
939 emax.
setX(std::max(std::max(p1.
x(),p2.
x()),emax.
x()));
940 emax.
setY(std::max(std::max(p1.
y(),p2.
y()),emax.
y()));
941 emax.
setZ(std::max(std::max(p1.
z(),p2.
z()),emax.
z()));
946 pExtent.first = emin;
947 pExtent.second = emax;
957G4BoundingEnvelope::ClipVoxelByPlanes(
G4int pBits,
959 const std::vector<G4Plane3D>& pPlanes,
978 std::vector<G4Segment3D> edges(12);
979 G4int i = 0, bits = pBits;
982 edges[i ].first.set( xmin,ymin,zmin);
983 edges[i++].second.set(xmax,ymin,zmin);
987 edges[i ].first.set( xmax,ymin,zmin);
988 edges[i++].second.set(xmax,ymax,zmin);
992 edges[i ].first.set( xmax,ymax,zmin);
993 edges[i++].second.set(xmin,ymax,zmin);
997 edges[i ].first.set( xmin,ymax,zmin);
998 edges[i++].second.set(xmin,ymin,zmin);
1001 if (!(bits & 0x010))
1003 edges[i ].first.set( xmin,ymin,zmax);
1004 edges[i++].second.set(xmax,ymin,zmax);
1006 if (!(bits & 0x020))
1008 edges[i ].first.set( xmax,ymin,zmax);
1009 edges[i++].second.set(xmax,ymax,zmax);
1011 if (!(bits & 0x040))
1013 edges[i ].first.set( xmax,ymax,zmax);
1014 edges[i++].second.set(xmin,ymax,zmax);
1016 if (!(bits & 0x080))
1018 edges[i ].first.set( xmin,ymax,zmax);
1019 edges[i++].second.set(xmin,ymin,zmax);
1022 if (!(bits & 0x100))
1024 edges[i ].first.set( xmin,ymin,zmin);
1025 edges[i++].second.set(xmin,ymin,zmax);
1027 if (!(bits & 0x200))
1029 edges[i ].first.set( xmax,ymin,zmin);
1030 edges[i++].second.set(xmax,ymin,zmax);
1032 if (!(bits & 0x400))
1034 edges[i ].first.set( xmax,ymax,zmin);
1035 edges[i++].second.set(xmax,ymax,zmax);
1037 if (!(bits & 0x800))
1039 edges[i ].first.set( xmin,ymax,zmin);
1040 edges[i++].second.set(xmin,ymax,zmax);
1046 for (
auto iedge = edges.cbegin(); iedge != edges.cend(); ++iedge)
1051 for (
auto iplane = pPlanes.cbegin(); iplane != pPlanes.cend(); ++iplane)
1054 G4double d1 = iplane->distance(p1);
1055 G4double d2 = iplane->distance(p2);
1058 if (d2 > 0.0) { exist =
false;
break; }
1059 p1 = (p2*d1-p1*d2)/(d1-d2);
1063 if (d2 > 0.0) { p2 = (p1*d2-p2*d1)/(d2-d1); }
1069 emin.
setX(std::min(std::min(p1.
x(),p2.
x()),emin.
x()));
1070 emin.
setY(std::min(std::min(p1.
y(),p2.
y()),emin.
y()));
1071 emin.
setZ(std::min(std::min(p1.
z(),p2.
z()),emin.
z()));
1073 emax.
setX(std::max(std::max(p1.
x(),p2.
x()),emax.
x()));
1074 emax.
setY(std::max(std::max(p1.
y(),p2.
y()),emax.
y()));
1075 emax.
setZ(std::max(std::max(p1.
z(),p2.
z()),emax.
z()));
1081 pExtent.first = emin;
1082 pExtent.second = emax;
const G4double kCarTolerance
std::pair< G4Point3D, G4Point3D > G4Segment3D
std::vector< G4Point3D > G4Polygon3D
std::vector< G4ThreeVector > G4ThreeVectorList
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *description)
HepGeom::Plane3D< G4double > G4Plane3D
HepGeom::Point3D< G4double > G4Point3D
void set(double x, double y, double z)
G4bool BoundingBoxVsVoxelLimits(const EAxis pAxis, const G4VoxelLimits &pVoxelLimits, const G4Transform3D &pTransform3D, G4double &pMin, G4double &pMax) const
G4bool CalculateExtent(const EAxis pAxis, const G4VoxelLimits &pVoxelLimits, const G4Transform3D &pTransform3D, G4double &pMin, G4double &pMax) const
G4BoundingEnvelope(const G4ThreeVector &pMin, const G4ThreeVector &pMax)
G4double GetSurfaceTolerance() const
static G4GeometryTolerance * GetInstance()
G4double GetMinExtent(const EAxis pAxis) const
G4double GetMinZExtent() const
void AddLimit(const EAxis pAxis, const G4double pMin, const G4double pMax)
G4double GetMaxExtent(const EAxis pAxis) const
G4double GetMaxYExtent() const
G4double GetMaxZExtent() const
G4double GetMinYExtent() const
G4double GetMinXExtent() const
G4double GetMaxXExtent() const