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 (
auto ipoint = polygon->cbegin(); ipoint != polygon->cend(); ++ipoint)
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 (
auto ipoint=polygon->cbegin(); ipoint!=polygon->cend(); ++ipoint)
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)
455 baseA[i] = vertices[bases[k].first + i];
457 baseB.resize(bases[k+1].second);
458 for (
G4int i = 0; i < bases[k+1].second; ++i)
459 baseB[i] = vertices[bases[k+1].first + i];
463 GetPrismAABB(baseA, baseB, prismAABB);
473 if (extent.first.x() > prismAABB.first.x())
474 extent.first.setX( prismAABB.first.x() );
475 if (extent.first.y() > prismAABB.first.y())
476 extent.first.setY( prismAABB.first.y() );
477 if (extent.first.z() > prismAABB.first.z())
478 extent.first.setZ( prismAABB.first.z() );
479 if (extent.second.x() < prismAABB.second.x())
480 extent.second.setX(prismAABB.second.x());
481 if (extent.second.y() < prismAABB.second.y())
482 extent.second.setY(prismAABB.second.y());
483 if (extent.second.z() < prismAABB.second.z())
484 extent.second.setZ(prismAABB.second.z());
497 std::vector<G4Segment3D> vecEdges;
498 CreateListOfEdges(baseA, baseB, vecEdges);
499 if (ClipEdgesByVoxel(vecEdges, limits, extent))
continue;
519 if (bits == 0xFFF)
continue;
521 std::vector<G4Plane3D> vecPlanes;
522 CreateListOfPlanes(baseA, baseB, vecPlanes);
523 ClipVoxelByPlanes(bits, limits, vecPlanes, prismAABB, extent);
529 if (pAxis ==
kXAxis) { emin = extent.first.x(); emax = extent.second.x(); }
530 if (pAxis ==
kYAxis) { emin = extent.first.y(); emax = extent.second.y(); }
531 if (pAxis ==
kZAxis) { emin = extent.first.z(); emax = extent.second.z(); }
533 if (emin > emax)
return false;
548G4BoundingEnvelope::FindScaleFactor(
const G4Transform3D& pTransform3D)
const
550 if (pTransform3D.
xx() == 1. &&
551 pTransform3D.
yy() == 1. &&
552 pTransform3D.
zz() == 1.)
return 1.;
557 G4double sxsx = xx*xx + yx*yx + zx*zx;
561 G4double sysy = xy*xy + yy*yy + zy*zy;
565 G4double szsz = xz*xz + yz*yz + zz*zz;
566 G4double ss = std::max(std::max(sxsx,sysy),szsz);
567 return (ss <= 1.) ? 1. : std::sqrt(ss);
577 std::vector<G4Point3D>& pVertices,
578 std::vector<std::pair<G4int, G4int>>& pBases)
const
581 std::vector<const G4ThreeVectorList*> aabb(2);
584 if (fPolygons ==
nullptr)
586 baseA[0].set(fMin.
x(),fMin.
y(),fMin.
z());
587 baseA[1].set(fMax.
x(),fMin.
y(),fMin.
z());
588 baseA[2].set(fMax.
x(),fMax.
y(),fMin.
z());
589 baseA[3].set(fMin.
x(),fMax.
y(),fMin.
z());
590 baseB[0].set(fMin.
x(),fMin.
y(),fMax.
z());
591 baseB[1].set(fMax.
x(),fMin.
y(),fMax.
z());
592 baseB[2].set(fMax.
x(),fMax.
y(),fMax.
z());
593 baseB[3].set(fMin.
x(),fMax.
y(),fMax.
z());
595 auto ia = (fPolygons ==
nullptr) ? aabb.cbegin() : fPolygons->cbegin();
596 auto iaend = (fPolygons ==
nullptr) ? aabb.cend() : fPolygons->cend();
601 for (
auto i = ia; i != iaend; ++i)
603 auto nv = (
G4int)(*i)->size();
604 pBases.emplace_back(index, nv);
610 if (pTransform3D.
xx() == 1. &&
611 pTransform3D.
yy() == 1. &&
612 pTransform3D.
zz() == 1.)
615 for (
auto i = ia; i != iaend; ++i)
616 for (
auto k = (*i)->cbegin(); k != (*i)->cend(); ++k)
617 pVertices.emplace_back((*k) + offset);
621 for (
auto i = ia; i != iaend; ++i)
622 for (
auto k = (*i)->cbegin(); k != (*i)->cend(); ++k)
623 pVertices.push_back(pTransform3D*
G4Point3D(*k));
632G4BoundingEnvelope::GetPrismAABB(
const G4Polygon3D& pBaseA,
636 G4double xmin = kInfinity, ymin = kInfinity, zmin = kInfinity;
637 G4double xmax = -kInfinity, ymax = -kInfinity, zmax = -kInfinity;
641 for (
const auto & it1 : pBaseA)
644 if (x < xmin) xmin = x;
645 if (x > xmax) xmax = x;
647 if (y < ymin) ymin = y;
648 if (y > ymax) ymax = y;
650 if (z < zmin) zmin = z;
651 if (z > zmax) zmax = z;
656 for (
const auto & it2 : pBaseB)
659 if (x < xmin) xmin = x;
660 if (x > xmax) xmax = x;
662 if (y < ymin) ymin = y;
663 if (y > ymax) ymax = y;
665 if (z < zmin) zmin = z;
666 if (z > zmax) zmax = z;
672 pAABB.second =
G4Point3D(xmax,ymax,zmax);
680G4BoundingEnvelope::CreateListOfEdges(
const G4Polygon3D& baseA,
682 std::vector<G4Segment3D>& pEdges)
const
684 std::size_t na = baseA.size();
685 std::size_t nb = baseB.size();
690 std::size_t k = na - 1;
691 for (std::size_t i=0; i<na; ++i)
693 pEdges.emplace_back(baseA[i],baseB[i]);
694 pEdges.emplace_back(baseA[i],baseA[k]);
695 pEdges.emplace_back(baseB[i],baseB[k]);
702 std::size_t k = na - 1;
703 for (std::size_t i=0; i<na; ++i)
705 pEdges.emplace_back(baseA[i],baseA[k]);
706 pEdges.emplace_back(baseA[i],baseB[0]);
713 std::size_t k = nb - 1;
714 for (std::size_t i=0; i<nb; ++i)
716 pEdges.emplace_back(baseB[i],baseB[k]);
717 pEdges.emplace_back(baseB[i],baseA[0]);
728G4BoundingEnvelope::CreateListOfPlanes(
const G4Polygon3D& baseA,
730 std::vector<G4Plane3D>& pPlanes)
const
734 std::size_t na = baseA.size();
735 std::size_t nb = baseB.size();
736 G4Point3D pa(0.,0.,0.), pb(0.,0.,0.), p0;
738 for (std::size_t i=0; i<na; ++i) pa += baseA[i];
739 for (std::size_t i=0; i<nb; ++i) pb += baseB[i];
740 pa /= na; pb /= nb; p0 = (pa+pb)/2.;
747 std::size_t k = na - 1;
748 for (std::size_t i=0; i<na; ++i)
750 norm = (baseB[k]-baseA[i]).cross(baseA[k]-baseB[i]);
753 pPlanes.emplace_back(norm,baseA[i]);
757 norm = (baseA[2]-baseA[0]).cross(baseA[1]-pa);
760 pPlanes.emplace_back(norm,pa);
762 norm = (baseB[2]-baseB[0]).cross(baseB[1]-pb);
765 pPlanes.emplace_back(norm,pb);
770 std::size_t k = na - 1;
771 for (std::size_t i=0; i<na; ++i)
773 norm = (baseA[i]-baseB[0]).cross(baseA[k]-baseB[0]);
776 pPlanes.emplace_back(norm,baseB[0]);
780 norm = (baseA[2]-baseA[0]).cross(baseA[1]-pa);
783 pPlanes.emplace_back(norm,pa);
788 std::size_t k = nb - 1;
789 for (std::size_t i=0; i<nb; ++i)
791 norm = (baseB[i]-baseA[0]).cross(baseB[k]-baseA[0]);
794 pPlanes.emplace_back(norm,baseA[0]);
798 norm = (baseB[2]-baseB[0]).cross(baseB[1]-pb);
801 pPlanes.emplace_back(norm,pb);
807 std::size_t nplanes = pPlanes.size();
808 for (std::size_t i=0; i<nplanes; ++i)
810 pPlanes[i].normalize();
811 if (pPlanes[i].distance(p0) > 0)
813 pPlanes[i] =
G4Plane3D(-pPlanes[i].a(),-pPlanes[i].b(),
814 -pPlanes[i].c(),-pPlanes[i].d());
826G4BoundingEnvelope::ClipEdgesByVoxel(
const std::vector<G4Segment3D>& pEdges,
834 std::size_t nedges = pEdges.size();
835 for (std::size_t k=0; k<nedges; ++k)
839 if (std::abs(p1.
x()-p2.
x())+
840 std::abs(p1.
y()-p2.
y())+
848 if (d2 > 0.0) { done =
false;
continue; }
849 p1 = (p2*d1-p1*d2)/(d1-d2);
853 if (d2 > 0.0) { p2 = (p1*d2-p2*d1)/(d2-d1); }
861 if (d2 > 0.) { done =
false;
continue; }
862 p1 = (p2*d1-p1*d2)/(d1-d2);
866 if (d2 > 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); }
922 emin.
setX(std::min(std::min(p1.
x(),p2.
x()),emin.
x()));
923 emin.
setY(std::min(std::min(p1.
y(),p2.
y()),emin.
y()));
924 emin.
setZ(std::min(std::min(p1.
z(),p2.
z()),emin.
z()));
926 emax.
setX(std::max(std::max(p1.
x(),p2.
x()),emax.
x()));
927 emax.
setY(std::max(std::max(p1.
y(),p2.
y()),emax.
y()));
928 emax.
setZ(std::max(std::max(p1.
z(),p2.
z()),emax.
z()));
933 pExtent.first = emin;
934 pExtent.second = emax;
944G4BoundingEnvelope::ClipVoxelByPlanes(
G4int pBits,
946 const std::vector<G4Plane3D>& pPlanes,
965 std::vector<G4Segment3D> edges(12);
966 G4int i = 0, bits = pBits;
967 if ((bits & 0x001) == 0)
969 edges[i ].first.set( xmin,ymin,zmin);
970 edges[i++].second.set(xmax,ymin,zmin);
972 if ((bits & 0x002) == 0)
974 edges[i ].first.set( xmax,ymin,zmin);
975 edges[i++].second.set(xmax,ymax,zmin);
977 if ((bits & 0x004) == 0)
979 edges[i ].first.set( xmax,ymax,zmin);
980 edges[i++].second.set(xmin,ymax,zmin);
982 if ((bits & 0x008) == 0)
984 edges[i ].first.set( xmin,ymax,zmin);
985 edges[i++].second.set(xmin,ymin,zmin);
988 if ((bits & 0x010) == 0)
990 edges[i ].first.set( xmin,ymin,zmax);
991 edges[i++].second.set(xmax,ymin,zmax);
993 if ((bits & 0x020) == 0)
995 edges[i ].first.set( xmax,ymin,zmax);
996 edges[i++].second.set(xmax,ymax,zmax);
998 if ((bits & 0x040) == 0)
1000 edges[i ].first.set( xmax,ymax,zmax);
1001 edges[i++].second.set(xmin,ymax,zmax);
1003 if ((bits & 0x080) == 0)
1005 edges[i ].first.set( xmin,ymax,zmax);
1006 edges[i++].second.set(xmin,ymin,zmax);
1009 if ((bits & 0x100) == 0)
1011 edges[i ].first.set( xmin,ymin,zmin);
1012 edges[i++].second.set(xmin,ymin,zmax);
1014 if ((bits & 0x200) == 0)
1016 edges[i ].first.set( xmax,ymin,zmin);
1017 edges[i++].second.set(xmax,ymin,zmax);
1019 if ((bits & 0x400) == 0)
1021 edges[i ].first.set( xmax,ymax,zmin);
1022 edges[i++].second.set(xmax,ymax,zmax);
1024 if ((bits & 0x800) == 0)
1026 edges[i ].first.set( xmin,ymax,zmin);
1027 edges[i++].second.set(xmin,ymax,zmax);
1033 for (
const auto & edge : edges)
1038 for (
const auto & plane : pPlanes)
1045 if (d2 > 0.0) { exist =
false;
break; }
1046 p1 = (p2*d1-p1*d2)/(d1-d2);
1050 if (d2 > 0.0) { p2 = (p1*d2-p2*d1)/(d2-d1); }
1056 emin.
setX(std::min(std::min(p1.
x(),p2.
x()),emin.
x()));
1057 emin.
setY(std::min(std::min(p1.
y(),p2.
y()),emin.
y()));
1058 emin.
setZ(std::min(std::min(p1.
z(),p2.
z()),emin.
z()));
1060 emax.
setX(std::max(std::max(p1.
x(),p2.
x()),emax.
x()));
1061 emax.
setY(std::max(std::max(p1.
y(),p2.
y()),emax.
y()));
1062 emax.
setZ(std::max(std::max(p1.
z(),p2.
z()),emax.
z()));
1068 pExtent.first = emin;
1069 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