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 : TGeoBBox(name, 0.0, 0.0, 0.0)
38 , fBridge(std::make_unique<g4occt::detail::TGeoOCCTSolidBridge>(shape)) {
40}
41
43
44TGeoOCCTSolid* TGeoOCCTSolid::FromSTEP(const char* name, const std::string& path) {
45 auto result = std::unique_ptr<TGeoOCCTSolid>(new TGeoOCCTSolid());
46 result->SetName(name);
47 result->fBridge = g4occt::detail::TGeoOCCTSolidBridge::FromSTEP(name, path);
48 result->ComputeBBox();
49 return result.release();
50}
51
52Double_t TGeoOCCTSolid::Capacity() const { return fBridge ? fBridge->CapacityCm3() : 0.0; }
53
55 Double_t origin[3] = {0.0, 0.0, 0.0};
56 if (!fBridge) {
57 SetBoxDimensions(0.0, 0.0, 0.0, origin);
58 return;
59 }
60 const auto bounds = fBridge->Bounds();
61 origin[0] = bounds.origin[0];
62 origin[1] = bounds.origin[1];
63 origin[2] = bounds.origin[2];
64 SetBoxDimensions(bounds.dx, bounds.dy, bounds.dz, origin);
65}
66
67void TGeoOCCTSolid::ComputeNormal(const Double_t* point, const Double_t* /*dir*/,
68 Double_t* norm) const {
69 if (!fBridge) {
70 norm[0] = 0.0;
71 norm[1] = 0.0;
72 norm[2] = 1.0;
73 return;
74 }
75 fBridge->SurfaceNormalCm(point, norm);
76}
77
78Bool_t TGeoOCCTSolid::Contains(const Double_t* point) const {
79 if (!fBridge) {
80 return kFALSE;
81 }
82 const auto classification = fBridge->ClassifyCm(point);
84}
85
86Bool_t TGeoOCCTSolid::CouldBeCrossed(const Double_t* point, const Double_t* dir) const {
87 return TGeoBBox::CouldBeCrossed(point, dir);
88}
89
90Int_t TGeoOCCTSolid::DistancetoPrimitive(Int_t px, Int_t py) {
91 return TGeoBBox::DistancetoPrimitive(px, py);
92}
93
94Double_t TGeoOCCTSolid::DistFromInside(const Double_t* point, const Double_t* dir, Int_t /*iact*/,
95 Double_t step, Double_t* safe) const {
96 if (!fBridge) {
97 return std::max(0.0, std::min(step, TGeoShape::Big()));
98 }
99 const double dist = fBridge->DistFromInsideCm(point, dir, safe);
100 return ClampDistanceToStep(dist, step, g4occt::detail::TGeoOCCTSolidBridge::InfinityCm());
101}
102
103Double_t TGeoOCCTSolid::DistFromOutside(const Double_t* point, const Double_t* dir, Int_t /*iact*/,
104 Double_t step, Double_t* safe) const {
105 if (!fBridge) {
106 return std::max(0.0, std::min(step, TGeoShape::Big()));
107 }
108 const double dist = fBridge->DistFromOutsideCm(point, dir, safe);
109 return ClampDistanceToStep(dist, step, g4occt::detail::TGeoOCCTSolidBridge::InfinityCm());
110}
111
112TGeoVolume* TGeoOCCTSolid::Divide(TGeoVolume* /*voldiv*/, const char* /*divname*/, Int_t /*iaxis*/,
113 Int_t /*ndiv*/, Double_t /*start*/, Double_t /*step*/) {
114 Error("Divide", "TGeoOCCTSolid does not support ROOT volume divisions");
115 return nullptr;
116}
117
118const char* TGeoOCCTSolid::GetAxisName(Int_t iaxis) const { return TGeoBBox::GetAxisName(iaxis); }
119
120Double_t TGeoOCCTSolid::GetAxisRange(Int_t iaxis, Double_t& xlo, Double_t& xhi) const {
121 return TGeoBBox::GetAxisRange(iaxis, xlo, xhi);
122}
123
124void TGeoOCCTSolid::GetBoundingCylinder(Double_t* param) const {
125 TGeoBBox::GetBoundingCylinder(param);
126}
127
128const TBuffer3D& TGeoOCCTSolid::GetBuffer3D(Int_t reqSections, Bool_t localFrame) const {
129 EnsureDisplayHelper();
130 return fDisplayHelper->GetBuffer3D(reqSections, localFrame);
131}
132
133Int_t TGeoOCCTSolid::GetByteCount() const { return 6 * static_cast<Int_t>(sizeof(Double_t)); }
134
135Bool_t TGeoOCCTSolid::GetPointsOnSegments(Int_t npoints, Double_t* array) const {
136 EnsureDisplayHelper();
137 return fDisplayHelper->GetPointsOnSegments(npoints, array);
138}
139
140Int_t TGeoOCCTSolid::GetFittingBox(const TGeoBBox* parambox, TGeoMatrix* mat, Double_t& dx,
141 Double_t& dy, Double_t& dz) const {
142 return TGeoBBox::GetFittingBox(parambox, mat, dx, dy, dz);
143}
144
145void TGeoOCCTSolid::GetMeshNumbers(Int_t& nvert, Int_t& nsegs, Int_t& npols) const {
146 EnsureDisplayHelper();
147 fDisplayHelper->GetMeshNumbers(nvert, nsegs, npols);
148}
149
150TGeoShape* TGeoOCCTSolid::GetMakeRuntimeShape(TGeoShape* /*mother*/, TGeoMatrix* /*mat*/) const {
151 if (!fBridge) {
152 return nullptr;
153 }
154 auto* runtime = new TGeoOCCTSolid(GetName(), GetOCCTShape());
155 runtime->SetRuntime();
156 return runtime;
157}
158
159Bool_t TGeoOCCTSolid::IsCylType() const { return kFALSE; }
160
161Bool_t TGeoOCCTSolid::IsValidBox() const { return TGeoBBox::IsValidBox(); }
162
164 if (!fBridge) {
165 Info("InspectShape", "Uninitialized TGeoOCCTSolid");
166 return;
167 }
168 const auto bounds = fBridge->Bounds();
169 EnsureDisplayHelper();
170 Int_t nvert = 0;
171 Int_t nsegs = 0;
172 Int_t npols = 0;
173 fDisplayHelper->GetMeshNumbers(nvert, nsegs, npols);
174 Info("InspectShape",
175 "TGeoOCCTSolid '%s' bbox=(dx=%g, dy=%g, dz=%g) cm origin=(%g,%g,%g) cm mesh=(nvert=%d, "
176 "nsegs=%d, npols=%d)",
177 GetName(), bounds.dx, bounds.dy, bounds.dz, bounds.origin[0], bounds.origin[1],
178 bounds.origin[2], nvert, nsegs, npols);
179}
180
181TBuffer3D* TGeoOCCTSolid::MakeBuffer3D() const {
182 EnsureDisplayHelper();
183 return fDisplayHelper->MakeBuffer3D();
184}
185
186Double_t TGeoOCCTSolid::Safety(const Double_t* point, Bool_t in) const {
187 return fBridge ? fBridge->SafetyCm(point, in == kTRUE) : 0.0;
188}
189
190void TGeoOCCTSolid::SetDimensions(Double_t* /*param*/) {
191 Error("SetDimensions",
192 "TGeoOCCTSolid does not support parameterized dimension mutation; use SetOCCTShape");
193}
194
195void TGeoOCCTSolid::SetPoints(Double_t* points) const {
196 EnsureDisplayHelper();
197 fDisplayHelper->SetPoints(points);
198}
199
200void TGeoOCCTSolid::SetPoints(Float_t* points) const {
201 EnsureDisplayHelper();
202 fDisplayHelper->SetPoints(points);
203}
204
205void TGeoOCCTSolid::SetSegsAndPols(TBuffer3D& buff) const {
206 EnsureDisplayHelper();
207 fDisplayHelper->SetSegsAndPols(buff);
208}
209
211 EnsureDisplayHelper();
212 fDisplayHelper->Sizeof3D();
213}
214
215const TopoDS_Shape& TGeoOCCTSolid::GetOCCTShape() const {
216 if (!fBridge) {
217 throw std::runtime_error(
218 "TGeoOCCTSolid::GetOCCTShape called on an uninitialized TGeoOCCTSolid");
219 }
220 return fBridge->Shape();
221}
222
223void TGeoOCCTSolid::SetOCCTShape(const TopoDS_Shape& shape) {
224 if (!fBridge) {
225 fBridge = std::make_unique<g4occt::detail::TGeoOCCTSolidBridge>(shape);
226 } else {
227 fBridge->SetShape(shape);
228 }
229 ComputeBBox();
230 fDisplayHelper.reset();
231 fDisplayGeneration = std::numeric_limits<std::uint64_t>::max();
232}
233
234void TGeoOCCTSolid::EnsureDisplayHelper() const {
235 if (!fBridge) {
236 if (!fDisplayHelper) {
237 fDisplayHelper = std::make_unique<TGeoTessellated>(GetName(), 0);
238 fDisplayHelper->CloseShape(true, true, false);
239 }
240 return;
241 }
242
243 const std::uint64_t generation = fBridge->ShapeGeneration();
244 if (fDisplayHelper && fDisplayGeneration == generation) {
245 return;
246 }
247
248 const auto mesh = fBridge->DisplayMesh();
249 if (mesh->triangles.size() > static_cast<std::size_t>(std::numeric_limits<int>::max())) {
250 throw std::runtime_error("TGeoOCCTSolid::EnsureDisplayHelper mesh exceeds TGeoTessellated "
251 "facet-count limit");
252 }
253 auto helper =
254 std::make_unique<TGeoTessellated>(GetName(), static_cast<int>(mesh->triangles.size()));
255 for (const auto& tri : mesh->triangles) {
256 helper->AddFacet(TGeoTessellated::Vertex_t(tri.p1[0], tri.p1[1], tri.p1[2]),
257 TGeoTessellated::Vertex_t(tri.p2[0], tri.p2[1], tri.p2[2]),
258 TGeoTessellated::Vertex_t(tri.p3[0], tri.p3[1], tri.p3[2]));
259 }
260 helper->CloseShape(true, true, false);
261 fDisplayHelper = std::move(helper);
262 fDisplayGeneration = generation;
263}
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)