G4OCCT 0.1.0
Geant4 interface to Open CASCADE Technology (OCCT) geometry definitions
Loading...
Searching...
No Matches
TGeoOCCTSolid.cc
Go to the documentation of this file.
1// SPDX-License-Identifier: LGPL-2.1-or-later
2// Copyright (C) 2026 G4OCCT Contributors
3
6
8
10
11#include <TBuffer3D.h>
12#include <TError.h>
13#include <TGeoBBox.h>
14#include <TGeoTessellated.h>
15
16#include <algorithm>
17#include <cmath>
18#include <cstddef>
19#include <limits>
20#include <stdexcept>
21
22namespace {
23
24double ClampDistanceToStep(const double dist, const double step, const double infinityCm) {
25 const double boundedStep = std::max(0.0, std::min(step, TGeoShape::Big()));
26 if (std::isinf(dist) || dist >= 0.5 * infinityCm) {
27 return boundedStep;
28 }
29 return std::min(dist, boundedStep);
30}
31
32} // namespace
33
35
36TGeoOCCTSolid::TGeoOCCTSolid(const char* name, const TopoDS_Shape& shape)
37 : TGeoShape(name), fBridge(std::make_unique<g4occt::detail::TGeoOCCTSolidBridge>(shape)) {}
38
40
41TGeoOCCTSolid* TGeoOCCTSolid::FromSTEP(const char* name, const std::string& path) {
42 auto result = std::unique_ptr<TGeoOCCTSolid>(new TGeoOCCTSolid());
43 result->SetName(name);
44 result->fBridge = g4occt::detail::TGeoOCCTSolidBridge::FromSTEP(name, path);
45 return result.release();
46}
47
48Double_t TGeoOCCTSolid::Capacity() const { return fBridge ? fBridge->CapacityCm3() : 0.0; }
49
51
52void TGeoOCCTSolid::ComputeNormal(const Double_t* point, const Double_t* /*dir*/,
53 Double_t* norm) const {
54 if (!fBridge) {
55 norm[0] = 0.0;
56 norm[1] = 0.0;
57 norm[2] = 1.0;
58 return;
59 }
60 fBridge->SurfaceNormalCm(point, norm);
61}
62
63Bool_t TGeoOCCTSolid::Contains(const Double_t* point) const {
64 if (!fBridge) {
65 return kFALSE;
66 }
67 const auto classification = fBridge->ClassifyCm(point);
69}
70
71Bool_t TGeoOCCTSolid::CouldBeCrossed(const Double_t* point, const Double_t* dir) const {
72 auto bbox = BuildBBoxHelper();
73 return bbox.CouldBeCrossed(point, dir);
74}
75
76Int_t TGeoOCCTSolid::DistancetoPrimitive(Int_t px, Int_t py) {
77 auto bbox = BuildBBoxHelper();
78 return bbox.DistancetoPrimitive(px, py);
79}
80
81Double_t TGeoOCCTSolid::DistFromInside(const Double_t* point, const Double_t* dir, Int_t /*iact*/,
82 Double_t step, Double_t* safe) const {
83 if (!fBridge) {
84 return std::max(0.0, std::min(step, TGeoShape::Big()));
85 }
86 const double dist = fBridge->DistFromInsideCm(point, dir, safe);
87 return ClampDistanceToStep(dist, step, g4occt::detail::TGeoOCCTSolidBridge::InfinityCm());
88}
89
90Double_t TGeoOCCTSolid::DistFromOutside(const Double_t* point, const Double_t* dir, Int_t /*iact*/,
91 Double_t step, Double_t* safe) const {
92 if (!fBridge) {
93 return std::max(0.0, std::min(step, TGeoShape::Big()));
94 }
95 const double dist = fBridge->DistFromOutsideCm(point, dir, safe);
96 return ClampDistanceToStep(dist, step, g4occt::detail::TGeoOCCTSolidBridge::InfinityCm());
97}
98
99TGeoVolume* TGeoOCCTSolid::Divide(TGeoVolume* /*voldiv*/, const char* /*divname*/, Int_t /*iaxis*/,
100 Int_t /*ndiv*/, Double_t /*start*/, Double_t /*step*/) {
101 Error("Divide", "TGeoOCCTSolid does not support ROOT volume divisions");
102 return nullptr;
103}
104
105const char* TGeoOCCTSolid::GetAxisName(Int_t iaxis) const {
106 auto bbox = BuildBBoxHelper();
107 return bbox.GetAxisName(iaxis);
108}
109
110Double_t TGeoOCCTSolid::GetAxisRange(Int_t iaxis, Double_t& xlo, Double_t& xhi) const {
111 auto bbox = BuildBBoxHelper();
112 return bbox.GetAxisRange(iaxis, xlo, xhi);
113}
114
115void TGeoOCCTSolid::GetBoundingCylinder(Double_t* param) const {
116 auto bbox = BuildBBoxHelper();
117 bbox.GetBoundingCylinder(param);
118}
119
120const TBuffer3D& TGeoOCCTSolid::GetBuffer3D(Int_t reqSections, Bool_t localFrame) const {
121 EnsureDisplayHelper();
122 return fDisplayHelper->GetBuffer3D(reqSections, localFrame);
123}
124
125Int_t TGeoOCCTSolid::GetByteCount() const { return 6 * static_cast<Int_t>(sizeof(Double_t)); }
126
127Bool_t TGeoOCCTSolid::GetPointsOnSegments(Int_t npoints, Double_t* array) const {
128 EnsureDisplayHelper();
129 return fDisplayHelper->GetPointsOnSegments(npoints, array);
130}
131
132Int_t TGeoOCCTSolid::GetFittingBox(const TGeoBBox* parambox, TGeoMatrix* mat, Double_t& dx,
133 Double_t& dy, Double_t& dz) const {
134 auto bbox = BuildBBoxHelper();
135 return bbox.GetFittingBox(parambox, mat, dx, dy, dz);
136}
137
138void TGeoOCCTSolid::GetMeshNumbers(Int_t& nvert, Int_t& nsegs, Int_t& npols) const {
139 EnsureDisplayHelper();
140 fDisplayHelper->GetMeshNumbers(nvert, nsegs, npols);
141}
142
143TGeoShape* TGeoOCCTSolid::GetMakeRuntimeShape(TGeoShape* /*mother*/, TGeoMatrix* /*mat*/) const {
144 if (!fBridge) {
145 return nullptr;
146 }
147 auto* runtime = new TGeoOCCTSolid(GetName(), GetOCCTShape());
148 runtime->SetRuntime();
149 return runtime;
150}
151
152Bool_t TGeoOCCTSolid::IsCylType() const { return kFALSE; }
153
155 auto bbox = BuildBBoxHelper();
156 return bbox.IsValidBox();
157}
158
160 if (!fBridge) {
161 Info("InspectShape", "Uninitialized TGeoOCCTSolid");
162 return;
163 }
164 const auto bounds = fBridge->Bounds();
165 EnsureDisplayHelper();
166 Int_t nvert = 0;
167 Int_t nsegs = 0;
168 Int_t npols = 0;
169 fDisplayHelper->GetMeshNumbers(nvert, nsegs, npols);
170 Info("InspectShape",
171 "TGeoOCCTSolid '%s' bbox=(dx=%g, dy=%g, dz=%g) cm origin=(%g,%g,%g) cm mesh=(nvert=%d, "
172 "nsegs=%d, npols=%d)",
173 GetName(), bounds.dx, bounds.dy, bounds.dz, bounds.origin[0], bounds.origin[1],
174 bounds.origin[2], nvert, nsegs, npols);
175}
176
177TBuffer3D* TGeoOCCTSolid::MakeBuffer3D() const {
178 EnsureDisplayHelper();
179 return fDisplayHelper->MakeBuffer3D();
180}
181
182Double_t TGeoOCCTSolid::Safety(const Double_t* point, Bool_t in) const {
183 return fBridge ? fBridge->SafetyCm(point, in == kTRUE) : 0.0;
184}
185
186void TGeoOCCTSolid::SetDimensions(Double_t* /*param*/) {
187 Error("SetDimensions",
188 "TGeoOCCTSolid does not support parameterized dimension mutation; use SetOCCTShape");
189}
190
191void TGeoOCCTSolid::SetPoints(Double_t* points) const {
192 EnsureDisplayHelper();
193 fDisplayHelper->SetPoints(points);
194}
195
196void TGeoOCCTSolid::SetPoints(Float_t* points) const {
197 EnsureDisplayHelper();
198 fDisplayHelper->SetPoints(points);
199}
200
201void TGeoOCCTSolid::SetSegsAndPols(TBuffer3D& buff) const {
202 EnsureDisplayHelper();
203 fDisplayHelper->SetSegsAndPols(buff);
204}
205
207 EnsureDisplayHelper();
208 fDisplayHelper->Sizeof3D();
209}
210
211const TopoDS_Shape& TGeoOCCTSolid::GetOCCTShape() const {
212 if (!fBridge) {
213 throw std::runtime_error(
214 "TGeoOCCTSolid::GetOCCTShape called on an uninitialized TGeoOCCTSolid");
215 }
216 return fBridge->Shape();
217}
218
219void TGeoOCCTSolid::SetOCCTShape(const TopoDS_Shape& shape) {
220 if (!fBridge) {
221 fBridge = std::make_unique<g4occt::detail::TGeoOCCTSolidBridge>(shape);
222 } else {
223 fBridge->SetShape(shape);
224 }
225 fDisplayHelper.reset();
226 fDisplayGeneration = std::numeric_limits<std::uint64_t>::max();
227}
228
229TGeoBBox TGeoOCCTSolid::BuildBBoxHelper() const {
230 if (!fBridge) {
231 Double_t origin[3] = {0.0, 0.0, 0.0};
232 return TGeoBBox(0.0, 0.0, 0.0, origin);
233 }
234 const auto bounds = fBridge->Bounds();
235 Double_t origin[3] = {bounds.origin[0], bounds.origin[1], bounds.origin[2]};
236 return TGeoBBox(bounds.dx, bounds.dy, bounds.dz, origin);
237}
238
239void TGeoOCCTSolid::EnsureDisplayHelper() const {
240 if (!fBridge) {
241 if (!fDisplayHelper) {
242 fDisplayHelper = std::make_unique<TGeoTessellated>(GetName(), 0);
243 fDisplayHelper->CloseShape(true, true, false);
244 }
245 return;
246 }
247
248 const std::uint64_t generation = fBridge->ShapeGeneration();
249 if (fDisplayHelper && fDisplayGeneration == generation) {
250 return;
251 }
252
253 const auto mesh = fBridge->DisplayMesh();
254 if (mesh->triangles.size() > static_cast<std::size_t>(std::numeric_limits<int>::max())) {
255 throw std::runtime_error("TGeoOCCTSolid::EnsureDisplayHelper mesh exceeds TGeoTessellated "
256 "facet-count limit");
257 }
258 auto helper =
259 std::make_unique<TGeoTessellated>(GetName(), static_cast<int>(mesh->triangles.size()));
260 for (const auto& tri : mesh->triangles) {
261 helper->AddFacet(TGeoTessellated::Vertex_t(tri.p1[0], tri.p1[1], tri.p1[2]),
262 TGeoTessellated::Vertex_t(tri.p2[0], tri.p2[1], tri.p2[2]),
263 TGeoTessellated::Vertex_t(tri.p3[0], tri.p3[1], tri.p3[2]));
264 }
265 helper->CloseShape(true, true, false);
266 fDisplayHelper = std::move(helper);
267 fDisplayGeneration = generation;
268}
ROOT-independent bridge from TGeoOCCTSolid to the shared OCCT kernel.
ROOT/TGeo shape adapter over the shared G4OCCT solid-query kernel.
ROOT/TGeo adapter backed by the shared G4OCCT solid-query kernel.
Double_t Safety(const Double_t *point, Bool_t in=kTRUE) const override
void ComputeNormal(const Double_t *point, const Double_t *dir, Double_t *norm) const override
void SetDimensions(Double_t *param) override
Int_t GetFittingBox(const TGeoBBox *parambox, TGeoMatrix *mat, Double_t &dx, Double_t &dy, Double_t &dz) const override
TGeoShape * GetMakeRuntimeShape(TGeoShape *mother, TGeoMatrix *mat) const override
void SetSegsAndPols(TBuffer3D &buff) const override
Bool_t CouldBeCrossed(const Double_t *point, const Double_t *dir) const override
const TopoDS_Shape & GetOCCTShape() const
Int_t DistancetoPrimitive(Int_t px, Int_t py) override
~TGeoOCCTSolid() override
Bool_t IsValidBox() const override
Int_t GetByteCount() const override
TGeoVolume * Divide(TGeoVolume *voldiv, const char *divname, Int_t iaxis, Int_t ndiv, Double_t start, Double_t step) override
const TBuffer3D & GetBuffer3D(Int_t reqSections, Bool_t localFrame) const override
Bool_t GetPointsOnSegments(Int_t npoints, Double_t *array) const override
void SetOCCTShape(const TopoDS_Shape &shape)
Double_t Capacity() const override
void ComputeBBox() override
TBuffer3D * MakeBuffer3D() const override
void InspectShape() const override
Double_t GetAxisRange(Int_t iaxis, Double_t &xlo, Double_t &xhi) const override
Bool_t IsCylType() const override
Bool_t Contains(const Double_t *point) const override
Double_t DistFromInside(const Double_t *point, const Double_t *dir, Int_t iact=1, Double_t step=TGeoShape::Big(), Double_t *safe=nullptr) const override
void SetPoints(Double_t *points) const override
static TGeoOCCTSolid * FromSTEP(const char *name, const std::string &path)
void GetBoundingCylinder(Double_t *param) const override
const char * GetAxisName(Int_t iaxis) const override
void Sizeof3D() const override
void GetMeshNumbers(Int_t &nvert, Int_t &nsegs, Int_t &npols) const override
Double_t DistFromOutside(const Double_t *point, const Double_t *dir, Int_t iact=1, Double_t step=TGeoShape::Big(), Double_t *safe=nullptr) const override
static std::unique_ptr< TGeoOCCTSolidBridge > FromSTEP(const std::string &name, const std::string &path)