47 : fMin(pMin), fMax(pMax)
60 : fPolygons(&polygons)
64 CheckBoundingPolygons();
68 G4double xmin = kInfinity, ymin = kInfinity, zmin = kInfinity;
69 G4double xmax = -kInfinity, ymax = -kInfinity, zmax = -kInfinity;
70 for (
const auto & polygon : *fPolygons)
72 for (
const auto & ipoint : *polygon)
75 if (x < xmin) { xmin = x; }
76 if (x > xmax) { xmax = x; }
78 if (y < ymin) { ymin = y; }
79 if (y > ymax) { ymax = y; }
81 if (z < zmin) { zmin = z; }
82 if (z > zmax) { zmax = z; }
85 fMin.set(xmin,ymin,zmin);
86 fMax.set(xmax,ymax,zmax);
100 const std::vector<const G4ThreeVectorList*>& polygons)
101 : fMin(pMin), fMax(pMax), fPolygons(&polygons)
106 CheckBoundingPolygons();
113void G4BoundingEnvelope::CheckBoundingBox()
115 if (fMin.
x() >= fMax.
x() || fMin.
y() >= fMax.
y() || fMin.
z() >= fMax.
z())
117 std::ostringstream message;
118 message <<
"Badly defined bounding box (min >= max)!"
119 <<
"\npMin = " << fMin
120 <<
"\npMax = " << fMax;
121 G4Exception(
"G4BoundingEnvelope::CheckBoundingBox()",
131void G4BoundingEnvelope::CheckBoundingPolygons()
133 std::size_t nbases = fPolygons->size();
136 std::ostringstream message;
137 message <<
"Wrong number of polygons in the sequence: " << nbases
138 <<
"\nShould be at least two!";
139 G4Exception(
"G4BoundingEnvelope::CheckBoundingPolygons()",
144 std::size_t nsize = std::max((*fPolygons)[0]->size(),(*fPolygons)[1]->size());
147 std::ostringstream message;
148 message <<
"Badly constructed polygons!"
149 <<
"\nNumber of polygons: " << nbases
150 <<
"\nPolygon #0 size: " << (*fPolygons)[0]->size()
151 <<
"\nPolygon #1 size: " << (*fPolygons)[1]->size()
153 G4Exception(
"G4BoundingEnvelope::CheckBoundingPolygons()",
158 for (std::size_t k=0; k<nbases; ++k)
160 std::size_t np = (*fPolygons)[k]->size();
161 if (np == nsize) {
continue; }
162 if (np == 1 && k==0) {
continue; }
163 if (np == 1 && k==nbases-1) {
continue; }
164 std::ostringstream message;
165 message <<
"Badly constructed polygons!"
166 <<
"\nNumber of polygons: " << nbases
167 <<
"\nPolygon #" << k <<
" size: " << np
168 <<
"\nexpected size: " << nsize;
169 G4Exception(
"G4BoundingEnvelope::SetBoundingPolygons()",
198 if (pTransform3D.
xx()==1 && pTransform3D.
yy()==1 && pTransform3D.
zz()==1)
214 if (xmin >= xminlim && xmax <= xmaxlim &&
215 ymin >= yminlim && ymax <= ymaxlim &&
216 zmin >= zminlim && zmax <= zmaxlim)
242 G4double scale = FindScaleFactor(pTransform3D);
248 G4double radius = 0.5*scale*(fMax-fMin).mag() + delta;
253 if (center.
x()-radius > xmaxlim) {
return true; }
254 if (center.
y()-radius > ymaxlim) {
return true; }
255 if (center.
z()-radius > zmaxlim) {
return true; }
256 if (center.
x()+radius < xminlim) {
return true; }
257 if (center.
y()+radius < yminlim) {
return true; }
258 if (center.
z()+radius < zminlim) {
return true; }
283 if (pTransform3D.
xx()==1 && pTransform3D.
yy()==1 && pTransform3D.
zz()==1)
299 if (fPolygons ==
nullptr)
325 G4double scale = FindScaleFactor(pTransform3D);
331 G4double radius = 0.5*scale*(fMax-fMin).mag() + delta;
336 if (center.
x()-radius >= xminlim && center.
x()+radius <= xmaxlim &&
337 center.
y()-radius >= yminlim && center.
y()+radius <= ymaxlim &&
338 center.
z()-radius >= zminlim && center.
z()+radius <= zmaxlim )
343 cx = pTransform3D.
xx();
344 cy = pTransform3D.
xy();
345 cz = pTransform3D.
xz();
346 cd = pTransform3D.
dx();
350 cx = pTransform3D.
yx();
351 cy = pTransform3D.
yy();
352 cz = pTransform3D.
yz();
353 cd = pTransform3D.
dy();
357 cx = pTransform3D.
zx();
358 cy = pTransform3D.
zy();
359 cz = pTransform3D.
zz();
360 cd = pTransform3D.
dz();
364 cx = cy = cz = cd = kInfinity;
366 G4double emin = kInfinity, emax = -kInfinity;
367 if (fPolygons ==
nullptr)
370 coor = cx*fMin.x() + cy*fMin.y() + cz*fMin.z() + cd;
371 if (coor < emin) { emin = coor; }
372 if (coor > emax) { emax = coor; }
373 coor = cx*fMax.x() + cy*fMin.y() + cz*fMin.z() + cd;
374 if (coor < emin) { emin = coor; }
375 if (coor > emax) { emax = coor; }
376 coor = cx*fMax.x() + cy*fMax.y() + cz*fMin.z() + cd;
377 if (coor < emin) { emin = coor; }
378 if (coor > emax) { emax = coor; }
379 coor = cx*fMin.x() + cy*fMax.y() + cz*fMin.z() + cd;
380 if (coor < emin) { emin = coor; }
381 if (coor > emax) { emax = coor; }
382 coor = cx*fMin.x() + cy*fMin.y() + cz*fMax.z() + cd;
383 if (coor < emin) { emin = coor; }
384 if (coor > emax) { emax = coor; }
385 coor = cx*fMax.x() + cy*fMin.y() + cz*fMax.z() + cd;
386 if (coor < emin) { emin = coor; }
387 if (coor > emax) { emax = coor; }
388 coor = cx*fMax.x() + cy*fMax.y() + cz*fMax.z() + cd;
389 if (coor < emin) { emin = coor; }
390 if (coor > emax) { emax = coor; }
391 coor = cx*fMin.x() + cy*fMax.y() + cz*fMax.z() + cd;
392 if (coor < emin) { emin = coor; }
393 if (coor > emax) { emax = coor; }
397 for (
const auto & polygon : *fPolygons)
399 for (
const auto & ipoint : *polygon)
401 G4double coor = ipoint.x()*cx + ipoint.y()*cy + ipoint.z()*cz + cd;
402 if (coor < emin) { emin = coor; }
403 if (coor > emax) { emax = coor; }
415 if (center.
x()-radius > xmaxlim) {
return false; }
416 if (center.
y()-radius > ymaxlim) {
return false; }
417 if (center.
z()-radius > zmaxlim) {
return false; }
418 if (center.
x()+radius < xminlim) {
return false; }
419 if (center.
y()+radius < yminlim) {
return false; }
420 if (center.
z()+radius < zminlim) {
return false; }
424 std::vector<G4Point3D> vertices;
425 std::vector<std::pair<G4int, G4int>> bases;
426 TransformVertices(pTransform3D, vertices, bases);
427 std::size_t nbases = bases.size();
435 for (
const auto & iAxis : axes)
449 extent.first =
G4Point3D( kInfinity, kInfinity, kInfinity);
450 extent.second =
G4Point3D(-kInfinity,-kInfinity,-kInfinity);
451 for (std::size_t k=0; k<nbases-1; ++k)
453 baseA.resize(bases[k].second);
454 for (
G4int i = 0; i < bases[k].second; ++i)
456 baseA[i] = vertices[bases[k].first + i];
459 baseB.resize(bases[k+1].second);
460 for (
G4int i = 0; i < bases[k+1].second; ++i)
462 baseB[i] = vertices[bases[k+1].first + i];
467 GetPrismAABB(baseA, baseB, prismAABB);
477 if (extent.first.x() > prismAABB.first.x())
479 extent.first.setX( prismAABB.first.x() );
481 if (extent.first.y() > prismAABB.first.y())
483 extent.first.setY( prismAABB.first.y() );
485 if (extent.first.z() > prismAABB.first.z())
487 extent.first.setZ( prismAABB.first.z() );
489 if (extent.second.x() < prismAABB.second.x())
491 extent.second.setX(prismAABB.second.x());
493 if (extent.second.y() < prismAABB.second.y())
495 extent.second.setY(prismAABB.second.y());
497 if (extent.second.z() < prismAABB.second.z())
499 extent.second.setZ(prismAABB.second.z());
505 if (prismAABB.first.x() > limits.
GetMaxXExtent()) {
continue; }
506 if (prismAABB.first.y() > limits.
GetMaxYExtent()) {
continue; }
507 if (prismAABB.first.z() > limits.
GetMaxZExtent()) {
continue; }
508 if (prismAABB.second.x() < limits.
GetMinXExtent()) {
continue; }
509 if (prismAABB.second.y() < limits.
GetMinYExtent()) {
continue; }
510 if (prismAABB.second.z() < limits.
GetMinZExtent()) {
continue; }
513 std::vector<G4Segment3D> vecEdges;
514 CreateListOfEdges(baseA, baseB, vecEdges);
515 if (ClipEdgesByVoxel(vecEdges, limits, extent)) {
continue; }
547 if (bits == 0xFFF) {
continue; }
549 std::vector<G4Plane3D> vecPlanes;
550 CreateListOfPlanes(baseA, baseB, vecPlanes);
551 ClipVoxelByPlanes(bits, limits, vecPlanes, prismAABB, extent);
557 if (pAxis ==
kXAxis) { emin = extent.first.x(); emax = extent.second.x(); }
558 if (pAxis ==
kYAxis) { emin = extent.first.y(); emax = extent.second.y(); }
559 if (pAxis ==
kZAxis) { emin = extent.first.z(); emax = extent.second.z(); }
561 if (emin > emax) {
return false; }
576G4BoundingEnvelope::FindScaleFactor(
const G4Transform3D& pTransform3D)
const
578 if (pTransform3D.
xx() == 1. &&
579 pTransform3D.
yy() == 1. &&
580 pTransform3D.
zz() == 1.) {
return 1.; }
585 G4double sxsx = xx*xx + yx*yx + zx*zx;
589 G4double sysy = xy*xy + yy*yy + zy*zy;
593 G4double szsz = xz*xz + yz*yz + zz*zz;
594 G4double ss = std::max(std::max(sxsx,sysy),szsz);
595 return (ss <= 1.) ? 1. : std::sqrt(ss);
605 std::vector<G4Point3D>& pVertices,
606 std::vector<std::pair<G4int, G4int>>& pBases)
const
609 std::vector<const G4ThreeVectorList*> aabb(2);
612 if (fPolygons ==
nullptr)
614 baseA[0].set(fMin.x(),fMin.y(),fMin.z());
615 baseA[1].set(fMax.x(),fMin.y(),fMin.z());
616 baseA[2].set(fMax.x(),fMax.y(),fMin.z());
617 baseA[3].set(fMin.x(),fMax.y(),fMin.z());
618 baseB[0].set(fMin.x(),fMin.y(),fMax.z());
619 baseB[1].set(fMax.x(),fMin.y(),fMax.z());
620 baseB[2].set(fMax.x(),fMax.y(),fMax.z());
621 baseB[3].set(fMin.x(),fMax.y(),fMax.z());
623 auto ia = (fPolygons ==
nullptr) ? aabb.cbegin() : fPolygons->cbegin();
624 auto iaend = (fPolygons ==
nullptr) ? aabb.cend() : fPolygons->cend();
629 for (
auto i = ia; i != iaend; ++i)
631 auto nv = (
G4int)(*i)->size();
632 pBases.emplace_back(index, nv);
638 if (pTransform3D.
xx() == 1. &&
639 pTransform3D.
yy() == 1. &&
640 pTransform3D.
zz() == 1.)
643 for (
auto i = ia; i != iaend; ++i)
645 for (
const auto & k : **i)
647 pVertices.emplace_back(k +
offset);
653 for (
auto i = ia; i != iaend; ++i)
655 for (
const auto & k : **i)
657 pVertices.push_back(pTransform3D*
G4Point3D(k));
668G4BoundingEnvelope::GetPrismAABB(
const G4Polygon3D& pBaseA,
672 G4double xmin = kInfinity, ymin = kInfinity, zmin = kInfinity;
673 G4double xmax = -kInfinity, ymax = -kInfinity, zmax = -kInfinity;
677 for (
const auto & it1 : pBaseA)
680 if (x < xmin) { xmin = x; }
681 if (x > xmax) { xmax = x; }
683 if (y < ymin) { ymin = y; }
684 if (y > ymax) { ymax = y; }
686 if (z < zmin) { zmin = z; }
687 if (z > zmax) { zmax = z; }
692 for (
const auto & it2 : pBaseB)
695 if (x < xmin) { xmin = x; }
696 if (x > xmax) { xmax = x; }
698 if (y < ymin) { ymin = y; }
699 if (y > ymax) { ymax = y; }
701 if (z < zmin) { zmin = z; }
702 if (z > zmax) { zmax = z; }
708 pAABB.second =
G4Point3D(xmax,ymax,zmax);
716G4BoundingEnvelope::CreateListOfEdges(
const G4Polygon3D& baseA,
718 std::vector<G4Segment3D>& pEdges)
const
720 std::size_t na = baseA.size();
721 std::size_t nb = baseB.size();
726 std::size_t k = na - 1;
727 for (std::size_t i=0; i<na; ++i)
729 pEdges.emplace_back(baseA[i],baseB[i]);
730 pEdges.emplace_back(baseA[i],baseA[k]);
731 pEdges.emplace_back(baseB[i],baseB[k]);
738 std::size_t k = na - 1;
739 for (std::size_t i=0; i<na; ++i)
741 pEdges.emplace_back(baseA[i],baseA[k]);
742 pEdges.emplace_back(baseA[i],baseB[0]);
749 std::size_t k = nb - 1;
750 for (std::size_t i=0; i<nb; ++i)
752 pEdges.emplace_back(baseB[i],baseB[k]);
753 pEdges.emplace_back(baseB[i],baseA[0]);
764G4BoundingEnvelope::CreateListOfPlanes(
const G4Polygon3D& baseA,
766 std::vector<G4Plane3D>& pPlanes)
const
770 std::size_t na = baseA.size();
771 std::size_t nb = baseB.size();
772 G4Point3D pa(0.,0.,0.), pb(0.,0.,0.), p0;
774 for (std::size_t i=0; i<na; ++i) { pa += baseA[i]; }
775 for (std::size_t i=0; i<nb; ++i) { pb += baseB[i]; }
776 pa /= na; pb /= nb; p0 = (pa+pb)/2.;
783 std::size_t k = na - 1;
784 for (std::size_t i=0; i<na; ++i)
786 norm = (baseB[k]-baseA[i]).cross(baseA[k]-baseB[i]);
789 pPlanes.emplace_back(norm,baseA[i]);
793 norm = (baseA[2]-baseA[0]).cross(baseA[1]-pa);
796 pPlanes.emplace_back(norm,pa);
798 norm = (baseB[2]-baseB[0]).cross(baseB[1]-pb);
801 pPlanes.emplace_back(norm,pb);
806 std::size_t k = na - 1;
807 for (std::size_t i=0; i<na; ++i)
809 norm = (baseA[i]-baseB[0]).cross(baseA[k]-baseB[0]);
812 pPlanes.emplace_back(norm,baseB[0]);
816 norm = (baseA[2]-baseA[0]).cross(baseA[1]-pa);
819 pPlanes.emplace_back(norm,pa);
824 std::size_t k = nb - 1;
825 for (std::size_t i=0; i<nb; ++i)
827 norm = (baseB[i]-baseA[0]).cross(baseB[k]-baseA[0]);
830 pPlanes.emplace_back(norm,baseA[0]);
834 norm = (baseB[2]-baseB[0]).cross(baseB[1]-pb);
837 pPlanes.emplace_back(norm,pb);
843 std::size_t nplanes = pPlanes.size();
844 for (std::size_t i=0; i<nplanes; ++i)
846 pPlanes[i].normalize();
847 if (pPlanes[i].distance(p0) > 0)
849 pPlanes[i] =
G4Plane3D(-pPlanes[i].a(),-pPlanes[i].b(),
850 -pPlanes[i].c(),-pPlanes[i].d());
862G4BoundingEnvelope::ClipEdgesByVoxel(
const std::vector<G4Segment3D>& pEdges,
870 std::size_t nedges = pEdges.size();
871 for (std::size_t k=0; k<nedges; ++k)
875 if (std::abs(p1.
x()-p2.
x())+
876 std::abs(p1.
y()-p2.
y())+
884 if (d2 > 0.0) { done =
false;
continue; }
885 p1 = (p2*d1-p1*d2)/(d1-d2);
889 if (d2 > 0.0) { p2 = (p1*d2-p2*d1)/(d2-d1); }
897 if (d2 > 0.) { done =
false;
continue; }
898 p1 = (p2*d1-p1*d2)/(d1-d2);
902 if (d2 > 0.) { p2 = (p1*d2-p2*d1)/(d2-d1); }
910 if (d2 > 0.) { done =
false;
continue; }
911 p1 = (p2*d1-p1*d2)/(d1-d2);
915 if (d2 > 0.) { p2 = (p1*d2-p2*d1)/(d2-d1); }
923 if (d2 > 0.) { done =
false;
continue; }
924 p1 = (p2*d1-p1*d2)/(d1-d2);
928 if (d2 > 0.) { p2 = (p1*d2-p2*d1)/(d2-d1); }
936 if (d2 > 0.) { done =
false;
continue; }
937 p1 = (p2*d1-p1*d2)/(d1-d2);
941 if (d2 > 0.) { p2 = (p1*d2-p2*d1)/(d2-d1); }
949 if (d2 > 0.) { done =
false;
continue; }
950 p1 = (p2*d1-p1*d2)/(d1-d2);
954 if (d2 > 0.) { p2 = (p1*d2-p2*d1)/(d2-d1); }
958 emin.
setX(std::min(std::min(p1.
x(),p2.
x()),emin.
x()));
959 emin.
setY(std::min(std::min(p1.
y(),p2.
y()),emin.
y()));
960 emin.
setZ(std::min(std::min(p1.
z(),p2.
z()),emin.
z()));
962 emax.
setX(std::max(std::max(p1.
x(),p2.
x()),emax.
x()));
963 emax.
setY(std::max(std::max(p1.
y(),p2.
y()),emax.
y()));
964 emax.
setZ(std::max(std::max(p1.
z(),p2.
z()),emax.
z()));
969 pExtent.first = emin;
970 pExtent.second = emax;
980G4BoundingEnvelope::ClipVoxelByPlanes(
G4int pBits,
982 const std::vector<G4Plane3D>& pPlanes,
1001 std::vector<G4Segment3D> edges(12);
1002 G4int i = 0, bits = pBits;
1003 if ((bits & 0x001) == 0)
1005 edges[i ].first.set( xmin,ymin,zmin);
1006 edges[i++].second.set(xmax,ymin,zmin);
1008 if ((bits & 0x002) == 0)
1010 edges[i ].first.set( xmax,ymin,zmin);
1011 edges[i++].second.set(xmax,ymax,zmin);
1013 if ((bits & 0x004) == 0)
1015 edges[i ].first.set( xmax,ymax,zmin);
1016 edges[i++].second.set(xmin,ymax,zmin);
1018 if ((bits & 0x008) == 0)
1020 edges[i ].first.set( xmin,ymax,zmin);
1021 edges[i++].second.set(xmin,ymin,zmin);
1024 if ((bits & 0x010) == 0)
1026 edges[i ].first.set( xmin,ymin,zmax);
1027 edges[i++].second.set(xmax,ymin,zmax);
1029 if ((bits & 0x020) == 0)
1031 edges[i ].first.set( xmax,ymin,zmax);
1032 edges[i++].second.set(xmax,ymax,zmax);
1034 if ((bits & 0x040) == 0)
1036 edges[i ].first.set( xmax,ymax,zmax);
1037 edges[i++].second.set(xmin,ymax,zmax);
1039 if ((bits & 0x080) == 0)
1041 edges[i ].first.set( xmin,ymax,zmax);
1042 edges[i++].second.set(xmin,ymin,zmax);
1045 if ((bits & 0x100) == 0)
1047 edges[i ].first.set( xmin,ymin,zmin);
1048 edges[i++].second.set(xmin,ymin,zmax);
1050 if ((bits & 0x200) == 0)
1052 edges[i ].first.set( xmax,ymin,zmin);
1053 edges[i++].second.set(xmax,ymin,zmax);
1055 if ((bits & 0x400) == 0)
1057 edges[i ].first.set( xmax,ymax,zmin);
1058 edges[i++].second.set(xmax,ymax,zmax);
1060 if ((bits & 0x800) == 0)
1062 edges[i ].first.set( xmin,ymax,zmin);
1063 edges[i++].second.set(xmin,ymax,zmax);
1069 for (
const auto & edge : edges)
1074 for (
const auto & plane : pPlanes)
1081 if (d2 > 0.0) { exist =
false;
break; }
1082 p1 = (p2*d1-p1*d2)/(d1-d2);
1086 if (d2 > 0.0) { p2 = (p1*d2-p2*d1)/(d2-d1); }
1092 emin.
setX(std::min(std::min(p1.
x(),p2.
x()),emin.
x()));
1093 emin.
setY(std::min(std::min(p1.
y(),p2.
y()),emin.
y()));
1094 emin.
setZ(std::min(std::min(p1.
z(),p2.
z()),emin.
z()));
1096 emax.
setX(std::max(std::max(p1.
x(),p2.
x()),emax.
x()));
1097 emax.
setY(std::max(std::max(p1.
y(),p2.
y()),emax.
y()));
1098 emax.
setZ(std::max(std::max(p1.
z(),p2.
z()),emax.
z()));
1104 pExtent.first = emin;
1105 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)
G4ThreadLocal T * G4GeomSplitter< T >::offset
HepGeom::Normal3D< G4double > G4Normal3D
HepGeom::Plane3D< G4double > G4Plane3D
HepGeom::Point3D< G4double > G4Point3D
CLHEP::Hep3Vector G4ThreeVector
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()
G4VoxelLimits represents limitation/restrictions of space, where restrictions are only made perpendic...
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