DLG4::VolumeBuilders
A fluent interface for Geant4 geometry definition.
Loading...
Searching...
No Matches
BoxBuilder.cc
Go to the documentation of this file.
1/*
2 * VolumeMaker.cc
3 *
4 * Created on: Jun 29, 2024
5 * Author: D. S. Leonard
6 */
7// Presently includes src for VolumeMaker and GeantMultiPlane classes
8// See header for documentation.
9
10#include "BoxBuilder.hh"
11#include <string>
13#include <G4Polycone.hh>
14#include <G4Polyhedra.hh>
15//#include "disableable_shared_from_this.hh"
16#include <G4Box.hh>
17
18#include "i_shared_ptr.hh"
19#include "StructureBuilder.hpp"
21
22class G4String;
23using namespace DLG4::Utilities;
25namespace DLG4::VolumeBuilders {
26
27//Geant Box constructing methods //////////////////////////////////////////////////
28 //Factories
29 // Factory methods for creating a BoxBuilder. These have been rewritten to
30 // delegate directly to the BoxBuilder's member methods.
31 // Yes, AI cranked out the duplication and delegation here after telling it exactly how to!
32
33 BoxBuilderPtr CreateBoxBuilder(const G4String &name) {
34 auto object = BoxBuilderPtr(new BoxBuilder(name));
35 return object;
36 }
37
38 BoxBuilderPtr CreateBoxBuilder(const G4String &name, const G4double unit) {
39 auto object = BoxBuilderPtr(new BoxBuilder(name));
40 object->SetDefaultUnit(unit);
41 return object;
42 }
43
44
45 BoxBuilderPtr CreateDeltasBoxBuilder(const G4double unit, const G4String &name,
46 const G4double edge_x,
47 const G4double x_delta,
48 const G4double edge_y, const G4double y_delta, const G4double edge_z,
49 const G4double z_delta) {
50 auto object = BoxBuilderPtr(new BoxBuilder(name));
51 object->SetXEdgeDelta(unit, edge_x, x_delta)
52 ->SetYEdgeDelta(unit, edge_y, y_delta)
53 ->SetZEdgeDelta(unit, edge_z, z_delta);
54 return object;
55 }
56
57 BoxBuilderPtr CreateDeltasBoxBuilder(const G4String &name, const G4double edge_x,
58 const G4double x_delta,
59 const G4double edge_y,
60 const G4double y_delta, const G4double edge_z, const G4double z_delta) {
61 auto object = BoxBuilderPtr(new BoxBuilder(name));
62 object->SetXEdgeDelta(edge_x, x_delta)
63 ->SetYEdgeDelta(edge_y, y_delta)
64 ->SetZEdgeDelta(edge_z, z_delta);
65 return object;
66 }
67
68 BoxBuilderPtr CreateZDeltaBoxBuilder(const G4double unit, const G4String &name,
69 const G4double x_full_size,
70 const G4double y_full_size,
71 const G4double edge_z, const G4double z_delta) {
72 if (x_full_size <= 0 || y_full_size <= 0) {
73 throw std::invalid_argument("Error in CreateZDeltaBoxBuilder(): for volume " + name
74 + ": Sizes provided without end offsets must be positive.\n");
75 }
76 auto object = BoxBuilderPtr(new BoxBuilder(name));
77 object->SetXSize(unit, x_full_size)
78 ->SetYSize(unit, y_full_size)
79 ->SetZEdgeDelta(unit, edge_z, z_delta);
80 return object;
81 }
82
83 BoxBuilderPtr CreateZDeltaBoxBuilder(const G4String &name, const G4double x_full_size,
84 const G4double y_full_size, const G4double edge_z,
85 const G4double z_delta) {
86 if (x_full_size <= 0 || y_full_size <= 0) {
87 throw std::invalid_argument("Error in CreateZDeltaBoxBuilder(): for volume " + name
88 + ": Sizes provided without end offsets must be positive.\n");
89 }
90 auto object = BoxBuilderPtr(new BoxBuilder(name));
91 object->SetXSize(x_full_size)
92 ->SetYSize(y_full_size)
93 ->SetZEdgeDelta(edge_z, z_delta);
94 return object;
95 }
96
97 BoxBuilderPtr CreateCenteredBoxBuilder(const G4double unit, const G4String &name,
98 const G4double x_full_size, const G4double y_full_size,
99 const G4double z_full_size) {
100 if (x_full_size <= 0 || y_full_size <= 0 || z_full_size <= 0) {
101 throw std::invalid_argument("Error in CreateCenteredBoxBuilder(): for volume " + name
102 + ": Sizes provided must be positive.\n");
103 }
104 auto object = BoxBuilderPtr(new BoxBuilder(name));
105 object->SetXSize(unit, x_full_size)
106 ->SetYSize(unit, y_full_size)
107 ->SetZSize(unit, z_full_size);
108 return object;
109 }
110
111 BoxBuilderPtr CreateCenteredBoxBuilder(const G4String &name, const G4double x_full_size,
112 const G4double y_full_size,
113 const G4double z_full_size) {
114 if (x_full_size <= 0 || y_full_size <= 0 || z_full_size <= 0) {
115 throw std::invalid_argument("Error in CreateCenteredBoxBuilder(): for volume " + name
116 + ": Sizes provided must be positive.\n");
117 }
118 auto object = BoxBuilderPtr(new BoxBuilder(name));
119 object->SetXSize(x_full_size)
120 ->SetYSize(y_full_size)
121 ->SetZSize(z_full_size);
122 return object;
123 }
124
125 BoxBuilderPtr CreateEdgesBoxBuilder(const G4String &name, const G4double x_edge1,
126 const G4double x_edge2, const G4double y_edge1,
127 const G4double y_edge2, const G4double z_edge1, const G4double z_edge2) {
128 auto object = BoxBuilderPtr(new BoxBuilder(name));
129 object->SetXEdges(x_edge1, x_edge2)
130 ->SetYEdges(y_edge1, y_edge2)
131 ->SetZEdges(z_edge1, z_edge2);
132 return object;
133 }
134
135 BoxBuilderPtr CreateEdgesBoxBuilder(const G4double unit, const G4String &name,
136 const G4double x_edge1, const G4double x_edge2,
137 const G4double y_edge1, const G4double y_edge2, const G4double z_edge1,
138 const G4double z_edge2) {
139 auto object = BoxBuilderPtr(new BoxBuilder(name));
140 object->SetXEdges(unit, x_edge1, x_edge2)
141 ->SetYEdges(unit, y_edge1, y_edge2)
142 ->SetZEdges(unit, z_edge1, z_edge2);
143 return object;
144 }
145}
146
148 BoxBuilderPtr BoxBuilder::SetXSizeDimensioned(const G4double size) {
149 x_size_ = size;
150 return shared_from_this();
151 }
152
153 BoxBuilderPtr BoxBuilder::SetYSizeDimensioned(const G4double size) {
154 y_size_ = size;
155 return shared_from_this();
156 }
157
158 BoxBuilderPtr BoxBuilder::SetZSizeDimensioned(const G4double size) {
159 z_size_ = size;
160 return shared_from_this();
161 }
162
163 BoxBuilderPtr BoxBuilder::SetInternalOffsetDimensioned(const G4double x, const G4double y,
164 const G4double z) {
165 this->builder_configs_->internal_offset = G4ThreeVector(x, y, z);
166 PropagateTransform();
167 return shared_from_this();
168 }
169
170 // These methods use the builder's effective default unit.
171 BoxBuilderPtr BoxBuilder::SetXSize(const G4double x_size) {
172 return SetXSize(this->GetEffectiveDefaultUnit(), x_size);
173 }
174
175 BoxBuilderPtr BoxBuilder::SetYSize(const G4double y_size) {
176 return SetYSize(this->GetEffectiveDefaultUnit(), y_size);
177 }
178
179 BoxBuilderPtr BoxBuilder::SetZSize(const G4double z_size) {
180 return SetZSize(this->GetEffectiveDefaultUnit(), z_size);
181 }
182
183 BoxBuilderPtr BoxBuilder::SetXEdges(const G4double x_edge1, const G4double x_edge2) {
184 return SetXEdges(this->GetEffectiveDefaultUnit(), x_edge1, x_edge2);
185 }
186
187 BoxBuilderPtr BoxBuilder::SetYEdges(const G4double y_edge1, const G4double y_edge2) {
188 return SetYEdges(this->GetEffectiveDefaultUnit(), y_edge1, y_edge2);
189 }
190
191 BoxBuilderPtr BoxBuilder::SetZEdges(const G4double z_edge1, const G4double z_edge2) {
192 return SetZEdges(this->GetEffectiveDefaultUnit(), z_edge1, z_edge2);
193 }
194
195 BoxBuilderPtr BoxBuilder::SetXEdgeDelta(const G4double x_edge, const G4double x_delta) {
196 return SetXEdgeDelta(this->GetEffectiveDefaultUnit(), x_edge, x_delta);
197 }
198
199 BoxBuilderPtr BoxBuilder::SetYEdgeDelta(const G4double y_edge, const G4double y_delta) {
200 return SetYEdgeDelta(this->GetEffectiveDefaultUnit(), y_edge, y_delta);
201 }
202
203 BoxBuilderPtr BoxBuilder::SetZEdgeDelta(const G4double z_edge, const G4double z_delta) {
204 return SetZEdgeDelta(this->GetEffectiveDefaultUnit(), z_edge, z_delta);
205 }
206
207 BoxBuilderPtr BoxBuilder::SetInternalOffset(const G4double x, const G4double y,
208 const G4double z) {
209 return SetInternalOffset(this->GetEffectiveDefaultUnit(), x, y, z);
210 }
211
212 // These overloads handle the unit conversion and then delegate to the "Dimensioned" methods.
213 BoxBuilderPtr BoxBuilder::SetXSize(const G4double unit, const G4double x_size) {
214 return SetXSizeDimensioned(x_size * unit);
215 }
216
217 BoxBuilderPtr BoxBuilder::SetYSize(const G4double unit, const G4double y_size) {
218 return SetYSizeDimensioned(y_size * unit);
219 }
220
221 BoxBuilderPtr BoxBuilder::SetZSize(const G4double unit, const G4double z_size) {
222 return SetZSizeDimensioned(z_size * unit);
223 }
224
225 // These methods calculate the size and offset, apply the unit, and then delegate to the Dimensioned setters.
226 BoxBuilderPtr BoxBuilder::SetXEdges(const G4double unit, const G4double x_edge1,
227 const G4double x_edge2) {
228 G4double size = std::abs(x_edge2 - x_edge1);
229 G4double offset = (x_edge1 + x_edge2) / 2.0;
230 SetXSizeDimensioned(size * unit);
231 return SetInternalOffsetDimensioned(
232 offset * unit,
233 this->builder_configs_->internal_offset.y(),
234 this->builder_configs_->internal_offset.z()
235 );
236 }
237
238 BoxBuilderPtr BoxBuilder::SetYEdges(const G4double unit, const G4double y_edge1,
239 const G4double y_edge2) {
240 G4double size = std::abs(y_edge2 - y_edge1);
241 G4double offset = (y_edge1 + y_edge2) / 2.0;
242 SetYSizeDimensioned(size * unit);
243 return SetInternalOffsetDimensioned(
244 this->builder_configs_->internal_offset.x(),
245 offset * unit,
246 this->builder_configs_->internal_offset.z()
247 );
248 }
249
250 BoxBuilderPtr BoxBuilder::SetZEdges(const G4double unit, const G4double z_edge1,
251 const G4double z_edge2) {
252 G4double size = std::abs(z_edge2 - z_edge1);
253 G4double offset = (z_edge1 + z_edge2) / 2.0;
254 SetZSizeDimensioned(size * unit);
255 return SetInternalOffsetDimensioned(
256 this->builder_configs_->internal_offset.x(),
257 this->builder_configs_->internal_offset.y(),
258 offset * unit
259 );
260 }
261
262 // These methods calculate the size and offset from an edge and delta, apply the unit, and delegate.
263 BoxBuilderPtr BoxBuilder::SetXEdgeDelta(const G4double unit, const G4double x_edge,
264 const G4double x_delta) {
265 G4double size = std::abs(x_delta);
266 G4double offset = x_edge + x_delta / 2.0;
267 SetXSizeDimensioned(size * unit);
268 return SetInternalOffsetDimensioned(
269 offset * unit,
270 this->builder_configs_->internal_offset.y(),
271 this->builder_configs_->internal_offset.z()
272 );
273 }
274
275 BoxBuilderPtr BoxBuilder::SetYEdgeDelta(const G4double unit, const G4double y_edge,
276 const G4double y_delta) {
277 G4double size = std::abs(y_delta);
278 G4double offset = y_edge + y_delta / 2.0;
279 SetYSizeDimensioned(size * unit);
280 return SetInternalOffsetDimensioned(
281 this->builder_configs_->internal_offset.x(),
282 offset * unit,
283 this->builder_configs_->internal_offset.z()
284 );
285 }
286
287 BoxBuilderPtr BoxBuilder::SetZEdgeDelta(const G4double unit, const G4double z_edge,
288 const G4double z_delta) {
289 G4double size = std::abs(z_delta);
290 G4double offset = z_edge + z_delta / 2.0;
291 SetZSizeDimensioned(size * unit);
292 return SetInternalOffsetDimensioned(
293 this->builder_configs_->internal_offset.x(),
294 this->builder_configs_->internal_offset.y(),
295 offset * unit
296 );
297 }
298
299 BoxBuilderPtr BoxBuilder::SetInternalOffset(const G4double unit, const G4double x,
300 const G4double y, const G4double z) {
301 return SetInternalOffsetDimensioned(x * unit, y * unit, z * unit);
302 }
303
304 BoxBuilder::BoxBuilder(const G4String &name) {
305 this->builder_configs_->name = name;
306 }
307
308 //Private default copy ctor.
309 //This is used by clone methods of concrete classes
310 BoxBuilder::BoxBuilder(const BoxBuilder &other) : VolumeBuilder<BoxBuilder>(other),
311 // Call base class copy constructor
312 x_size_(other.x_size_),
313 y_size_(other.y_size_),
314 z_size_(other.z_size_) {
316 SetName(other.GetBuilderName());
317 builder_configs_->internal_offset = other.builder_configs_->internal_offset;
319 }
320
321 G4VSolid *BoxBuilder::SolidConstructor(const G4String &name) {
322 if (this->solid_ptr_.get() != nullptr) {
323 std::string error = "Error in BoxBuilder::SolidConstructor: A solid was already built\n"
324 "You can copy and rename the builder to reset it and build again.";
325 throw std::runtime_error(error);
326 }
327 G4cout << G4endl;
328 G4cout << "New BoxBuilder:" << GetBuilderName() // lie and use the final transformed name
329 << "x_size: " << x_size_ << " y_size: " << y_size_ << " z_size: " << z_size_ <<
330 G4endl;
331 G4cout << "Internal offset: " << this->builder_configs_->internal_offset << G4endl;
332 return new G4Box(name, x_size_ / 2.0, y_size_ / 2.0, z_size_ / 2.0);
333 }
334}
Builder class for simple Box solids.
BoxBuilderPtr SetXSize(G4double x_size)
G4VSolid * SolidConstructor(const G4String &name) override
The polymorphic Solid constructor.
BoxBuilderPtr SetZSize(G4double z_size)
BoxBuilderPtr SetInternalOffset(G4double x, G4double y, G4double z)
BoxBuilderPtr SetZEdgeDelta(G4double z_edge, G4double z_delta)
BoxBuilderPtr SetXEdgeDelta(G4double x_edge, G4double x_delta)
BoxBuilderPtr SetYEdgeDelta(G4double y_edge, G4double y_delta)
BoxBuilderPtr SetXEdges(G4double x_edge1, G4double x_edge2)
BoxBuilderPtr SetYEdges(G4double y_edge1, G4double y_edge2)
BoxBuilderPtr SetYSize(G4double y_size)
BoxBuilderPtr SetZEdges(G4double z_edge1, G4double z_edge2)
VolumeBuilder: Common functionality for volume builder classes.
DerivedPtr SetName(const G4String &name)
SetName Sets name used for solid and derived product names.
BoxBuilderPtr CreateCenteredBoxBuilder(const G4String &name, G4double x_full_size, G4double y_full_size, G4double z_full_size)
Create a Box solid.
BoxBuilderPtr CreateDeltasBoxBuilder(const G4String &name, G4double edge_x, G4double x_delta, G4double edge_y, G4double y_delta, G4double edge_z, G4double z_delta)
Create a Box solid.
Definition BoxBuilder.cc:57
BoxBuilderPtr CreateEdgesBoxBuilder(const G4String &name, G4double x_edge1, G4double x_edge2, G4double y_edge1, G4double y_edge2, G4double z_edge1, G4double z_edge2)
Create a Box solid from edge coordinates.
BoxBuilderPtr CreateBoxBuilder(const G4String &name)
Create an unconfigured Box Solid, for use with SetXEdges() etc... Uses the global default unit unless...
Definition BoxBuilder.cc:33
BoxBuilderPtr CreateZDeltaBoxBuilder(const G4String &name, G4double x_full_size, G4double y_full_size, G4double edge_z, G4double z_delta)
Create a Box solid.
Definition BoxBuilder.cc:83
G4double GetEffectiveDefaultUnit() const
Get the builder default unit or global if not set.