BDSIM
BDSIM is a Geant4 extension toolkit for simulation of particle transport in accelerator beamlines.
Loading...
Searching...
No Matches
BDSGeometryInspector.cc
1/*
2Beam Delivery Simulation (BDSIM) Copyright (C) BDSIM Collaboration, 2001 - 2026.
3
4This file is part of BDSIM.
5
6BDSIM is free software: you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published
8by the Free Software Foundation version 3 of the License.
9
10BDSIM is distributed in the hope that it will be useful, but
11WITHOUT ANY WARRANTY; without even the implied warranty of
12MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13GNU General Public License for more details.
14
15You should have received a copy of the GNU General Public License
16along with BDSIM. If not, see <http://www.gnu.org/licenses/>.
17*/
18#include "BDSExtent.hh"
19#include "BDSGeometryInspector.hh"
20#include "BDSGlobalConstants.hh"
21
22#include "globals.hh"
23#include "G4AffineTransform.hh"
24#include "G4Box.hh"
25#include "G4CutTubs.hh"
26#include "G4DisplacedSolid.hh"
27#include "G4EllipticalTube.hh"
28#include "G4IntersectionSolid.hh"
29#include "G4SubtractionSolid.hh"
30#include "G4Tubs.hh"
31#include "G4UnionSolid.hh"
32#include "G4Version.hh"
33#include "G4VSolid.hh"
34
35#include <utility>
36
37// for Geant4.10.2 and below we have a different algorithm as some accessors are not available
38#if G4VERSION_NUMBER < 1030
39#include "G4VisExtent.hh"
40#include <algorithm>
41#include <cmath>
42#endif
43
44std::pair<BDSExtent, BDSExtent> BDS::DetermineExtents(const G4VSolid* solid)
45{
46 G4String className = solid->GetEntityType();
47 if (className == "G4DisplacedSolid")
48 {return BDS::InspectDisplacedSolid(solid);}
49 else if (className == "G4SubtractionSolid")
50 {return BDS::InspectSubtractionSolid(solid);}
51 else if (className == "G4IntersectionSolid")
52 {return BDS::InspectIntersectionSolid(solid);}
53 else if (className == "G4UnionSolid")
54 {return BDS::InspectUnionSolid(solid);}
55 else if (className == "G4Box")
56 {return BDS::InspectBox(solid);}
57 else if (className == "G4Tubs")
58 {return BDS::InspectTubs(solid);}
59 else if (className == "G4CutTubs")
60 {return BDS::InspectCutTubs(solid);}
61 else if (className == "G4EllipticalTube")
62 {return BDS::InspectEllipticalTube(solid);}
63 else
64 {
65 G4ThreeVector low, high;
66 solid->BoundingLimits(low, high);
67 // take abs of low and high
68 BDSExtent outer = BDSExtent(std::max(std::abs(low.x()), std::abs(high.x())),
69 std::max(std::abs(low.y()), std::abs(high.y())),
70 std::max(std::abs(low.z()), std::abs(high.z())));
71 BDSExtent inner = BDSExtent();
72 return std::make_pair(outer, inner);
73 }
74}
75
76std::pair<BDSExtent, BDSExtent> BDS::InspectDisplacedSolid(const G4VSolid* solidIn)
77{
78 const G4DisplacedSolid* solid = dynamic_cast<const G4DisplacedSolid*>(solidIn);
79 if (!solid)
80 {return std::make_pair(BDSExtent(), BDSExtent());}
81
82 const G4VSolid* constituentSolid = solid->GetConstituentMovedSolid();
83
84 auto ext = BDS::DetermineExtents(constituentSolid);
85 G4AffineTransform transform = solid->GetTransform();
86
87 // only going to shift x,y without any rotation.
88 G4ThreeVector translation = transform.NetTranslation();
89 BDSExtent outer = ext.first.Translate(translation.x(), translation.y(), 0);
90 BDSExtent inner = ext.second.Translate(translation.x(), translation.y(), 0);
91
92 return std::make_pair(outer, inner);
93}
94
95std::pair<BDSExtent, BDSExtent> BDS::InspectSubtractionSolid(const G4VSolid* solidIn)
96{
97 const G4SubtractionSolid* solid = dynamic_cast<const G4SubtractionSolid*>(solidIn);
98 if (!solid)
99 {return std::make_pair(BDSExtent(), BDSExtent());}
100
101 const G4VSolid* a = solid->GetConstituentSolid(0);
102 const G4VSolid* b = solid->GetConstituentSolid(1);
103
104 auto extA = BDS::DetermineExtents(a);
105 auto extB = BDS::DetermineExtents(b);
106
107 BDSExtent outer = extA.first.TransverselyLessThan(extB.first) ? extB.first : extA.first;
108
109 // Here we make an ASSUMPTION that the b solid is the interior one - convention.
110 // Also it's the outer extent of that solid.
111 BDSExtent inner = extB.first;
112
113 return std::make_pair(outer, inner);
114}
115
116std::pair<BDSExtent, BDSExtent> BDS::InspectIntersectionSolid(const G4VSolid* solidIn)
117{
118 const G4IntersectionSolid* solid = dynamic_cast<const G4IntersectionSolid*>(solidIn);
119 if (!solid)
120 {return std::make_pair(BDSExtent(), BDSExtent());}
121
122 const G4VSolid* a = solid->GetConstituentSolid(0);
123 const G4VSolid* b = solid->GetConstituentSolid(1);
124
125 auto extA = BDS::DetermineExtents(a);
126 auto extB = BDS::DetermineExtents(b);
127
128 BDSExtent outer = extA.first.TransverselyLessThan(extB.first) ? extB.first : extA.first;
129 BDSExtent inner = extA.first.TransverselyLessThan(extB.first) ? extA.second : extB.second;
130
131 return std::make_pair(outer, inner);
132}
133
134std::pair<BDSExtent, BDSExtent> BDS::InspectUnionSolid(const G4VSolid* solidIn)
135{
136 const G4UnionSolid* solid = dynamic_cast<const G4UnionSolid*>(solidIn);
137 if (!solid)
138 {return std::make_pair(BDSExtent(), BDSExtent());}
139
140 const G4VSolid* a = solid->GetConstituentSolid(0);
141 const G4VSolid* b = solid->GetConstituentSolid(1);
142
143 auto extA = BDS::DetermineExtents(a);
144 auto extB = BDS::DetermineExtents(b);
145
146 BDSExtent outer = extA.first.TransverselyLessThan(extB.first) ? extB.first : extA.first;
147 BDSExtent inner = extA.first.TransverselyLessThan(extB.first) ? extA.second : extB.second;
148
149 return std::make_pair(outer, inner);
150}
151
152std::pair<BDSExtent, BDSExtent> BDS::InspectBox(const G4VSolid* solidIn)
153{
154 const G4Box* solid = dynamic_cast<const G4Box*>(solidIn);
155 if (!solid)
156 {return std::make_pair(BDSExtent(), BDSExtent());}
157
158 G4double dx = solid->GetXHalfLength();
159 G4double dy = solid->GetYHalfLength();
160 G4double dz = solid->GetZHalfLength();
161
162 // accurate along z, but margin in x,y
163 G4double lsl = BDSGlobalConstants::Instance()->LengthSafetyLarge();
164 BDSExtent outer(dx + lsl, dy + lsl, dz); // symmetric +/-
165 BDSExtent inner = BDSExtent();
166 return std::make_pair(outer, inner);
167}
168
169std::pair<BDSExtent, BDSExtent> BDS::InspectTubs(const G4VSolid* solidIn)
170{
171 const G4Tubs* solid = dynamic_cast<const G4Tubs*>(solidIn);
172 if (!solid)
173 {return std::make_pair(BDSExtent(), BDSExtent());}
174
175 G4double innerR = solid->GetInnerRadius();
176 G4double outerR = solid->GetOuterRadius();
177 G4double zHalfL = solid->GetZHalfLength();
178
179 G4double lsl = BDSGlobalConstants::Instance()->LengthSafetyLarge();
180 BDSExtent outer(outerR + lsl, outerR + lsl, zHalfL);
181 BDSExtent inner(innerR, innerR, zHalfL);
182 return std::make_pair(outer, inner);
183}
184
185std::pair<BDSExtent, BDSExtent> BDS::InspectCutTubs(const G4VSolid* solidIn)
186{
187 G4ThreeVector zminV = G4ThreeVector();
188 G4ThreeVector zmaxV = G4ThreeVector();
189#if G4VERSION_NUMBER > 1039
190 solidIn->BoundingLimits(zminV, zmaxV);
191#elif G4VERSION_NUMBER > 1029
192 solidIn->Extent(zminV, zmaxV);
193#else
194 G4VisExtent v = solidIn->GetExtent();
195 zmaxV = G4ThreeVector(std::max(std::abs(v.GetXmin()),std::abs(v.GetXmax())),
196 std::max(std::abs(v.GetYmin()),std::abs(v.GetYmax())),
197 std::max(std::abs(v.GetZmin()),std::abs(v.GetZmax())));
198#endif
199
200 const G4CutTubs* solid = dynamic_cast<const G4CutTubs*>(solidIn);
201 if (!solid)
202 {return std::make_pair(BDSExtent(zmaxV), BDSExtent());}
203
204 G4double innerR = solid->GetInnerRadius();
205 G4double outerR = solid->GetOuterRadius();
206 G4double lsl = BDSGlobalConstants::Instance()->LengthSafetyLarge();
207 outerR += lsl;
208
209 BDSExtent outer(-outerR, outerR,
210 -outerR, outerR,
211 -zmaxV.z(), zmaxV.z());
212 BDSExtent inner(-innerR, innerR,
213 -innerR, innerR,
214 -zmaxV.z(), zmaxV.z());
215 return std::make_pair(outer, inner);
216}
217
218std::pair<BDSExtent, BDSExtent> BDS::InspectEllipticalTube(const G4VSolid* solidIn)
219{
220 const G4EllipticalTube* solid = dynamic_cast<const G4EllipticalTube*>(solidIn);
221 if (!solid)
222 {return std::make_pair(BDSExtent(), BDSExtent());}
223
224 G4double dX = solid->GetDx();
225 G4double dY = solid->GetDy();
226 G4double dZ = solid->GetDz();
227
228 G4double lsl = BDSGlobalConstants::Instance()->LengthSafetyLarge();
229 BDSExtent outer(dX + lsl, dY + lsl, dZ);
230 BDSExtent inner(0, 0, dZ);
231 return std::make_pair(outer, inner);
232}
Holder for +- extents in 3 dimensions.
Definition BDSExtent.hh:38
BDSExtent Translate(const G4ThreeVector &offset) const
Provide a new copy of this extent with an offset applied.
Definition BDSExtent.hh:124
G4bool TransverselyLessThan(const BDSExtent &r) const
Comparison operator for x,y only. Ignores z (length).
Definition BDSExtent.hh:190
static BDSGlobalConstants * Instance()
Access method.
std::pair< BDSExtent, BDSExtent > InspectIntersectionSolid(const G4VSolid *solidIn)
Inspect a G4IntersectionSolid.
std::pair< BDSExtent, BDSExtent > InspectEllipticalTube(const G4VSolid *solidIn)
Inspect a G4EllipticalTube.
std::pair< BDSExtent, BDSExtent > InspectCutTubs(const G4VSolid *solidIn)
Inspect a G4CutTubs.
std::pair< BDSExtent, BDSExtent > InspectSubtractionSolid(const G4VSolid *solidIn)
std::pair< BDSExtent, BDSExtent > DetermineExtents(const G4VSolid *solid)
std::pair< BDSExtent, BDSExtent > InspectBox(const G4VSolid *solidIn)
Inspect a G4Box.
std::pair< BDSExtent, BDSExtent > InspectTubs(const G4VSolid *solidIn)
Inspect a G4Tubs.
std::pair< BDSExtent, BDSExtent > InspectDisplacedSolid(const G4VSolid *solidIn)
Inspect a G4DisplacedSolid.
std::pair< BDSExtent, BDSExtent > InspectUnionSolid(const G4VSolid *solidIn)
Inspect a G4UnionSolid.