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