167 const G4AffineTransform& pTransform, G4double& pMin,
168 G4double& pMax)
const {
169 const auto& bounds = fImpl->kernel.Bounds();
170 const G4BoundingEnvelope envelope(bounds.min, bounds.max);
171 return envelope.CalculateExtent(pAxis, pVoxelLimit, G4Transform3D(pTransform), pMin, pMax);
177 const auto currentGeneration = fImpl->kernel.ShapeGeneration();
180 std::unique_lock<std::mutex> lock(fImpl->polyhedronMutex);
181 fImpl->polyhedronCV.wait(lock, [
this, currentGeneration] {
182 return !fImpl->polyhedronBuilding || fImpl->polyhedronGeneration == currentGeneration;
184 if (fImpl->cachedPolyhedron && fImpl->polyhedronGeneration == currentGeneration) {
185 return new G4Polyhedron(*fImpl->cachedPolyhedron);
187 fImpl->polyhedronBuilding =
true;
190 std::unique_ptr<G4Polyhedron> freshPolyhedron;
196 G4TessellatedSolid tessellatedSolid(GetName() +
"_polyhedron");
197 G4int facetCount = 0;
199 for (TopExp_Explorer explorer(fImpl->kernel.Shape(), TopAbs_FACE); explorer.More();
201 const TopoDS_Face& face = TopoDS::Face(explorer.Current());
202 TopLoc_Location location;
203 const Handle(Poly_Triangulation) & triangulation = BRep_Tool::Triangulation(face, location);
204 if (triangulation.IsNull()) {
208 const gp_Trsf& transform = location.Transformation();
209 const bool reverseWinding = face.Orientation() == TopAbs_REVERSED;
211 for (Standard_Integer triangleIndex = 1; triangleIndex <= triangulation->NbTriangles();
213 Standard_Integer index1 = 0;
214 Standard_Integer index2 = 0;
215 Standard_Integer index3 = 0;
216 triangulation->Triangle(triangleIndex).Get(index1, index2, index3);
218 if (reverseWinding) {
219 std::swap(index2, index3);
222 const gp_Pnt point1 = triangulation->Node(index1).Transformed(transform);
223 const gp_Pnt point2 = triangulation->Node(index2).Transformed(transform);
224 const gp_Pnt point3 = triangulation->Node(index3).Transformed(transform);
227 new G4TriangularFacet(G4ThreeVector(point1.X(), point1.Y(), point1.Z()),
228 G4ThreeVector(point2.X(), point2.Y(), point2.Z()),
229 G4ThreeVector(point3.X(), point3.Y(), point3.Z()), ABSOLUTE);
230 if (!facet->IsDefined() || !tessellatedSolid.AddFacet(facet)) {
238 if (facetCount > 0) {
239 tessellatedSolid.SetSolidClosed(
true);
240 G4Polyhedron* tmp = tessellatedSolid.GetPolyhedron();
241 if (tmp !=
nullptr) {
242 freshPolyhedron = std::make_unique<G4Polyhedron>(*tmp);
246 std::unique_lock<std::mutex> lock(fImpl->polyhedronMutex);
247 fImpl->polyhedronBuilding =
false;
249 fImpl->polyhedronCV.notify_all();
254 std::unique_lock<std::mutex> lock(fImpl->polyhedronMutex);
255 bool cacheWritten =
false;
256 if (freshPolyhedron && fImpl->kernel.ShapeGeneration() == currentGeneration) {
257 fImpl->cachedPolyhedron = std::make_unique<G4Polyhedron>(*freshPolyhedron);
258 fImpl->polyhedronGeneration = currentGeneration;
261 fImpl->polyhedronBuilding =
false;
262 fImpl->polyhedronCV.notify_all();
264 return new G4Polyhedron(*fImpl->cachedPolyhedron);
268 return freshPolyhedron ?
new G4Polyhedron(*freshPolyhedron) :
nullptr;