G4OCCT 0.1.0
Geant4 interface to Open CASCADE Technology (OCCT) geometry definitions
Loading...
Searching...
No Matches
G4OCCTSolid.hh
Go to the documentation of this file.
1// SPDX-License-Identifier: LGPL-2.1-or-later
2// Copyright (C) 2026 G4OCCT Contributors
3
6
7#ifndef G4OCCT_G4OCCTSolid_hh
8#define G4OCCT_G4OCCTSolid_hh
9
10#include <G4Cache.hh>
11#include <G4Polyhedron.hh>
12#include <G4ThreeVector.hh>
13#include <G4VSolid.hh>
14
15// OCCT shape representation
16#include <BRepAdaptor_Surface.hxx>
17#include <BRepClass3d_SolidClassifier.hxx>
18#include <BRepExtrema_TriangleSet.hxx>
19#include <Bnd_Box.hxx>
20#include <IntCurvesFace_Intersector.hxx>
21#include <TopoDS_Face.hxx>
22#include <TopoDS_Shape.hxx>
23#include <TopoDS_TShape.hxx>
24#include <gp_Pln.hxx>
25#include <gp_Pnt2d.hxx>
26
27#include <atomic>
28#include <condition_variable>
29#include <cstdint>
30#include <limits>
31#include <memory>
32#include <mutex>
33#include <optional>
34#include <stdexcept>
35#include <string>
36#include <unordered_map>
37#include <utility>
38#include <vector>
39
70class G4OCCTSolid : public G4VSolid {
71public:
79 G4OCCTSolid(const G4String& name, const TopoDS_Shape& shape);
80
81 ~G4OCCTSolid() override;
82
95 static G4OCCTSolid* FromSTEP(const G4String& name, const std::string& path);
96
97 // ── G4VSolid pure-virtual interface ───────────────────────────────────────
98
100 EInside Inside(const G4ThreeVector& p) const override;
101
103 G4ThreeVector SurfaceNormal(const G4ThreeVector& p) const override;
104
108 G4double DistanceToIn(const G4ThreeVector& p, const G4ThreeVector& v) const override;
109
122 G4double DistanceToIn(const G4ThreeVector& p) const override;
123
127 G4double DistanceToOut(const G4ThreeVector& p, const G4ThreeVector& v,
128 const G4bool calcNorm = false, G4bool* validNorm = nullptr,
129 G4ThreeVector* n = nullptr) const override;
130
133 G4double DistanceToOut(const G4ThreeVector& p) const override;
134
157 G4ThreeVector GetPointOnSurface() const override;
158
159 // ── G4OCCTSolid distance functions ────────────────────────────────────────
160
164 G4double ExactDistanceToIn(const G4ThreeVector& p) const;
165
170 G4double ExactDistanceToOut(const G4ThreeVector& p) const;
171
174 G4double GetCubicVolume() override;
175
178 G4double GetSurfaceArea() override;
179
181 G4GeometryType GetEntityType() const override;
182
184 G4VisExtent GetExtent() const override;
185
187 void BoundingLimits(G4ThreeVector& pMin, G4ThreeVector& pMax) const override;
188
190 G4bool CalculateExtent(const EAxis pAxis, const G4VoxelLimits& pVoxelLimit,
191 const G4AffineTransform& pTransform, G4double& pMin,
192 G4double& pMax) const override;
193
195 void DescribeYourselfTo(G4VGraphicsScene& scene) const override;
196
198 G4Polyhedron* CreatePolyhedron() const override;
199
201 std::ostream& StreamInfo(std::ostream& os) const override;
202
203 // ── G4OCCTSolid-specific interface ────────────────────────────────────────
204
206 const TopoDS_Shape& GetOCCTShape() const { return fShape; }
207
215 void SetOCCTShape(const TopoDS_Shape& shape) {
216 if (shape.IsNull()) {
217 throw std::invalid_argument("G4OCCTSolid::SetOCCTShape: shape must not be null");
218 }
219 fShape = shape;
220 ComputeBounds();
221 {
222 std::unique_lock<std::mutex> lock(fPolyhedronMutex);
223 fCachedPolyhedron.reset();
224 }
225 {
226 std::unique_lock<std::mutex> lock(fVolumeAreaMutex);
227 fCachedVolume.reset();
228 fCachedSurfaceArea.reset();
229 }
230 {
231 std::unique_lock<std::mutex> lock(fSurfaceCacheMutex);
232 fSurfaceCache.reset();
233 }
234 fShapeGeneration.fetch_add(1, std::memory_order_release);
235 }
236
237private:
240 struct FaceBounds {
241 TopoDS_Face face;
242 Bnd_Box box;
243 BRepAdaptor_Surface adaptor;
244 std::optional<gp_Pln> plane;
249 std::vector<gp_Pnt2d> uvPolygon;
253 std::optional<G4ThreeVector> outwardNormal;
254 };
255
257 struct ClosestFaceMatch {
258 TopoDS_Face face;
259 G4double distance{kInfinity};
263 std::size_t faceIndex{0};
267 std::optional<std::pair<Standard_Real, Standard_Real>> uv;
268 };
269
271 struct AxisAlignedBounds {
272 G4ThreeVector min;
273 G4ThreeVector max;
274 };
275
282 struct ClassifierCache {
283 std::uint64_t generation{std::numeric_limits<std::uint64_t>::max()};
284 std::optional<BRepClass3d_SolidClassifier> classifier;
285 };
286
308 struct IntersectorCache {
309 std::uint64_t generation{std::numeric_limits<std::uint64_t>::max()};
310 std::vector<std::unique_ptr<IntCurvesFace_Intersector>> faceIntersectors;
311 std::vector<Bnd_Box> expandedBoxes;
312 };
313
316 struct InscribedSphere {
317 G4ThreeVector centre;
318 G4double radius;
319 };
320
332 struct SphereCacheData {
333 std::vector<InscribedSphere> spheres;
334 std::uint64_t generation{std::numeric_limits<std::uint64_t>::max()};
335 };
336
338 static constexpr std::size_t kMaxInscribedSpheres = 64;
339
347 struct SurfaceTriangle {
348 G4ThreeVector p1, p2, p3;
349 std::uint32_t
350 faceIndex;
351 };
352
361 struct SurfaceSamplingCache {
362 std::vector<TopoDS_Face> faces;
363 std::vector<SurfaceTriangle> triangles;
364 std::vector<G4double> cumulativeAreas;
365 G4double totalArea{0.0};
366 };
367
370 TopoDS_Shape fShape;
371
376 AxisAlignedBounds fCachedBounds;
377
383 std::vector<FaceBounds> fFaceBoundsCache;
384
399 std::unordered_map<const TopoDS_TShape*, std::vector<std::size_t>> fFaceAdaptorIndex;
400
410 std::vector<InscribedSphere> fInitialSpheres;
411
420 Handle(BRepExtrema_TriangleSet) fTriangleSet;
421
431 G4double fBVHDeflection{0.0};
432
442 std::vector<G4double> fFaceDeflections;
443
447 bool fAllFacesPlanar{false};
448
452 std::atomic<std::uint64_t> fShapeGeneration{0};
453
458 mutable G4Cache<ClassifierCache> fClassifierCache;
459
464 mutable G4Cache<IntersectorCache> fIntersectorCache;
465
471 mutable G4Cache<SphereCacheData> fSphereCache;
472
480 mutable std::unique_ptr<G4Polyhedron> fCachedPolyhedron;
481
487 mutable std::uint64_t fPolyhedronGeneration{std::numeric_limits<std::uint64_t>::max()};
488
493 mutable bool fPolyhedronBuilding{false};
494
497 mutable std::mutex fPolyhedronMutex;
498
501 mutable std::condition_variable fPolyhedronCV;
502
505 mutable std::optional<G4double> fCachedVolume;
506
509 mutable std::optional<G4double> fCachedSurfaceArea;
510
512 mutable std::mutex fVolumeAreaMutex;
513
517 mutable std::optional<SurfaceSamplingCache> fSurfaceCache;
518
523 mutable std::uint64_t fSurfaceCacheGeneration{std::numeric_limits<std::uint64_t>::max()};
524
527 mutable std::mutex fSurfaceCacheMutex;
528
531 BRepClass3d_SolidClassifier& GetOrCreateClassifier() const;
532
537 IntersectorCache& GetOrCreateIntersector() const;
538
541 SphereCacheData& GetOrInitSphereCache() const;
542
547 void TryInsertSphere(const G4ThreeVector& centre, G4double d) const;
548
554 void ComputeBounds();
555
562 void ComputeInitialSpheres();
563
566 G4double AABBLowerBound(const G4ThreeVector& p) const;
567
574 G4double BVHLowerBoundDistance(const G4ThreeVector& p) const;
575
587 G4double PlanarFaceLowerBoundDistance(const G4ThreeVector& p) const;
588
596 static std::optional<ClosestFaceMatch>
597 TryFindClosestFace(const std::vector<FaceBounds>& faceBoundsCache, const G4ThreeVector& point,
598 G4double maxDistance = kInfinity);
599
605 const SurfaceSamplingCache& GetOrBuildSurfaceCache() const;
606};
607
608#endif // G4OCCT_G4OCCTSolid_hh
Geant4 solid wrapping an Open CASCADE Technology (OCCT) TopoDS_Shape.
G4double ExactDistanceToOut(const G4ThreeVector &p) const
EInside Inside(const G4ThreeVector &p) const override
Return kInside, kSurface, or kOutside for point p.
G4double GetCubicVolume() override
G4double DistanceToOut(const G4ThreeVector &p, const G4ThreeVector &v, const G4bool calcNorm=false, G4bool *validNorm=nullptr, G4ThreeVector *n=nullptr) const override
G4Polyhedron * CreatePolyhedron() const override
Create a polyhedron representation for visualisation.
G4double DistanceToIn(const G4ThreeVector &p, const G4ThreeVector &v) const override
void SetOCCTShape(const TopoDS_Shape &shape)
void BoundingLimits(G4ThreeVector &pMin, G4ThreeVector &pMax) const override
Return the axis-aligned bounding box limits.
G4ThreeVector SurfaceNormal(const G4ThreeVector &p) const override
Return the outward unit normal at surface point p.
G4bool CalculateExtent(const EAxis pAxis, const G4VoxelLimits &pVoxelLimit, const G4AffineTransform &pTransform, G4double &pMin, G4double &pMax) const override
Calculate the extent of the solid in the given axis.
~G4OCCTSolid() override
G4double GetSurfaceArea() override
G4GeometryType GetEntityType() const override
Return a string identifying the entity type.
const TopoDS_Shape & GetOCCTShape() const
Read access to the underlying OCCT shape.
G4ThreeVector GetPointOnSurface() const override
G4VisExtent GetExtent() const override
Return the axis-aligned bounding box extent.
std::ostream & StreamInfo(std::ostream &os) const override
Stream a human-readable description.
static G4OCCTSolid * FromSTEP(const G4String &name, const std::string &path)
void DescribeYourselfTo(G4VGraphicsScene &scene) const override
Describe the solid to the graphics scene.
G4double ExactDistanceToIn(const G4ThreeVector &p) const