DLG4::VolumeBuilders
A fluent interface for Geant4 geometry definition.
Loading...
Searching...
No Matches
VolumeBuilder.hh
Go to the documentation of this file.
1#pragma once
2#ifndef VOLUMEBUILDER_HH
3#define VOLUMEBUILDER_HH
4#include <optional>
5#include "Linkable.hh"
6#include "IVolumeBuilder.hh"
7#include "ISolidBuilder.hh"
9/*
10
11 * VolumeMaker.hh
12 *
13 * Created on: Jun 19, 2024
14 * Author: D. S. Leonard
15 * Implicit or explicit misrepresentation authorship is not protected under any license.
16 * See RZBuilder.hh for main documentation.
17 *
18 *s
19
20 */
21//#define SHARED_WRAPPER DLG4::i_shared_ptr
22#include <vector>
23#include "i_shared_ptr.hh"
24#include <VolumeBuilderTypes.hh>
25
26
27// #define FIXME(msg) static_assert(false, "FIXME: " msg)
28
29//#include "DetectorConstruction_includes.hh"
31#include <G4Material.hh>
32#include "G4Colour.hh" // why? It's in above.
33#include "G4VPhysicalVolume.hh"
34#include "G4UnionSolid.hh"
35#include <G4ThreeVector.hh>
36#include <mutex>
37#include <memory>
38#include <unordered_map>
39//#include "VolumeBuilderReference.hh"
40
41namespace DLG4::VolumeBuilders {
42 class VolumeBuilderReference;
43 template <typename U>
44 class VolumeBuilder;
45
46
57 template <typename U>
58 class VolumeBuilder: public ENABLE_SHARED_WRAPPER<U>, public ISolidBuilder
59 , public IVolumeBuilder {
63
64 // limit public(protected) API by using friendship.
65 // Much of this can't even be handledby protected.
66 // Specifically factories (normal) and the type-erasing pseudo-inheritance (StructureBuilder)
67 template <typename>
68 friend class VolumeBuilder;
70 friend class Assembly;
71 template <typename>
72 friend class StructureBuilder;
74 friend FromG4VSolidPtr CreateFromG4VSolid(G4VSolid *solid);
75 friend AssemblyPtr CreateAssembly(G4String names);
76 friend class RZBuilder;
77 friend class BoxBuilder;
78 friend class FromG4VSolid;
79
80 public:
88 [[nodiscard]] G4VPhysicalVolume *GetPlacement() final;
89
99
100
110 this->MakePlacement();
111 auto clone = this->ForkForPlacement(); // default/preset options
112 return clone;
113 }
114
123 [[nodiscard]] G4LogicalVolume *GetLogicalVolume() final;
124
135 [[nodiscard]] G4VSolid *GetBaseSolid() final;
136
143 [[nodiscard]] G4VSolid *GetFinalSolid() final;
144
145
157 DerivedPtr MakeLogicalVolume(
158 G4Material *material = nullptr, G4String name = std::string());
159
165 DerivedPtr MakeSolid();
166
172 DerivedPtr SetName(const G4String &name);
173
194 DerivedPtr AddUnion(const BuilderView &other,
195 const Unit3Vec &offset = {CLHEP::mm, 0, 0, 0},
196 G4RotationMatrix *rotation = nullptr);
198 DerivedPtr AddSubtraction(const BuilderView &other,
199 const Unit3Vec &offset = {CLHEP::mm, 0, 0, 0},
200 G4RotationMatrix *rotation = nullptr);
202 DerivedPtr AddIntersection(const BuilderView &other,
203 const Unit3Vec &offset = {CLHEP::mm, 0, 0, 0},
204 G4RotationMatrix *rotation = nullptr);
218 DerivedPtr AddBoolean(
219 const BuilderView &other,
220 bool is_subtraction = false,
221 bool is_intersection = false,
222 const Unit3Vec &offset = {CLHEP::mm, 0, 0, 0},
223 G4RotationMatrix *rotation = nullptr
224 );
233 DerivedPtr SetMaterial(G4Material *material);
234
240 DerivedPtr SetColor(double r = 0.5, double g = 0.5, double b = 0.5, double alpha = 1.0);
241
248 DerivedPtr SetColor(const G4Colour &color);
249
256 DerivedPtr SetAlpha(G4double alpha);
257
263 DerivedPtr ForceSolid(bool x = true); // default if uncalled is false.
264
271 DerivedPtr SetVisibility(bool x = true);
272
273 // ... inside the VolumeBuilder class declaration ...
274
288 DerivedPtr SetLogicalVolume(G4LogicalVolume *logical_volume);
289
299 DerivedPtr SetBooleanName(const G4String &name);
300
308 DerivedPtr SetPhysRotation(const G4RotationMatrix &rot);
309
320 DerivedPtr StackPhysRotation(const G4RotationMatrix &stacked_rot);
321
338 DerivedPtr SetPhysOffset(const Unit3Vec &offset = {CLHEP::mm, 0, 0, 0});
349 DerivedPtr StackPhysOffset(const Unit3Vec &offset = {CLHEP::mm, 0, 0, 0});
350
364 DerivedPtr SetPhysTransform(const UnitlessG4Transform3D &new_transform);
371 DerivedPtr StackPhysTransform(const UnitlessG4Transform3D &new_transform);
372
383 G4Transform3D GetPhysTransform() const final {
384 return {placement_configs_->rotation, placement_configs_->translation};
385 }
386
387
394 DerivedPtr OverridePlacementName(const G4String &pName);
395
396
403 DerivedPtr SetCopyNo(G4int pCopyNo);
404
411 DerivedPtr SetSurfaceCheck(G4bool pSurfChk);
412
413
425 DerivedPtr SetMother(const BuilderView &mother);
426
438 DerivedPtr SetAutoPlacementNaming(bool set);
439
440
451 DerivedPtr SetAutoCopyNo(bool set);
452
468 DerivedPtr ReflectZFinalSolid();
469
478 DerivedPtr ReflectZBaseSolid();
479
494 virtual DerivedPtr ForkAndReset(const G4String &new_name) const;
495
505 DerivedPtr ForkForFinalSolid(const G4String &new_name);
506
507
520 DerivedPtr ForkForLogicalVolume(const G4String &new_name);
521
522
537 DerivedPtr ForkForPlacement(
538 std::optional<int> copy_no = std::nullopt
539 , const G4String &name_override = ""
540 , bool parent_name_was_set = false
541 // in assembly/hierarchies, name change derives through parent
542 );
543
560 DerivedPtr CopyPlacementConfigsFrom(const BuilderView &other);
561
571 DerivedPtr CopyVolumeConfigsFrom(const BuilderView &other);
572
590 DerivedPtr SetDefaultUnit(G4double unit);
591
597 G4double GetEffectiveDefaultUnit() const;
607 DerivedPtr AddTo(BuilderViewList &list) const;
608
616 DerivedPtr AddTo(StructureViewList &list) const;
617
625 DerivedPtr AddTo(AssemblyPtr &assembly) const;
626
631 ~VolumeBuilder() override;
632
633 BuilderView ToBuilderView() const override;
634
635 StructureView ToStructureView() const override;
636
637 G4String GetBuilderName() const;
638
639 protected:
641 G4VSolid *SolidConstructor(const G4String &name) override = 0;
642
643 // base implementation of non-fluent clone.
645
646 private:
647 //Methods with basically protected intent
648 // But for now, keep them private and require explicit friend access
649 // ctors only useable through explicitly granted (friendship) inheritance...
650
651
653 DerivedPtr SetSolid(G4VSolid *solid);
654
655 DerivedPtr Clone() const {
656 // This call is NOT DIRECTLY polymorphic. It calls the VolumeBuilder base clone_impl().
657 // Internally THAT calls polymorphic clone to create the structure_ptr and recreate the view.
658 // We have to re-cast the result.
659 i_shared_ptr<IStructureBuilder> base_cloned_ptr = this->clone_impl();
660 return std::static_pointer_cast<U>(base_cloned_ptr);
661 }
662
663
664 template <typename T, typename std::enable_if_t<std::is_base_of_v<IStructureBuilder, T>,
665 int> = 0>
667
668 VolumeBuilder &operator=(const VolumeBuilder &other) = delete;
669 DerivedPtr MakeFinalSolid(G4String boolean_name = "");
670 VolumeBuilder(const VolumeBuilder &other);
671
672 VolumeBuilder(VolumeBuilder &&) noexcept = default;
673
674 G4VSolid *GetSolidPtr() const {
675 return this->solid_ptr_.get_mutable();
676 };
677
678 //Configs (re-linked by copy-ctors)
679 ONCE_MUTABLE Linkable<BuilderConfigs> builder_configs_{BuilderConfigs{}};
680 ONCE_MUTABLE Linkable<BooleanConfigs> boolean_configs_{BooleanConfigs{}};
681 ONCE_MUTABLE Linkable<VolumeConfigs> lv_configs_{VolumeConfigs{}};
682 ONCE_MUTABLE Linkable<PlacementConfigs> placement_configs_{PlacementConfigs{}};
683
684 //Products (sometimes copied by copy methods)
685 ONCE_MUTABLE Linkable<G4VSolid> solid_ptr_{}; // child can and should create the solid
686 ONCE_MUTABLE Linkable<G4VSolid> final_solid_ptr_{};
687 ONCE_MUTABLE Linkable<G4LogicalVolume> logicvol_ptr_{};
688 ONCE_MUTABLE Linkable<G4VPhysicalVolume> placement_{};
689
690
694 void StoreIStructurePtr(const IStructurePtr &istructure_ptr);
695
696 void StoreBuilderView(const BuilderView &builder_view);
697
698
699 //Unsaved data, left out of configs to be reset on all copy operations.
700 bool explicit_copyno_set_ = false;
701 bool explicit_physical_copy_name_set_ = false;
702 G4String placement_name_override_ = ""; // Will be derived from boolean_name_ by default
703
704 void SetSolid_impl(G4VSolid *solid);
705 void SetLogicalVolume_impl(G4LogicalVolume *logical_volume);
706
707 //Some hard baked settings
708 // let's pretend like we'd ever care about resource management:
709 static constexpr bool has_ownership_{false}; // for future resource control
710 static constexpr bool enable_full_lazy_builds{true};
711 // Allows full chain lazy building. Off for now.
712
713 //Methods with truly private intent.
714
715 // Propagate transforms
716 void PropagateTransform();
717
718
719 void ApplyAttributes_();
720 G4String GetPlacementBaseName() const;
721
722 [[nodiscard]] G4String GetLogicVolName() const; // should this be pulic?
723
724 // these validators may trigger lazy build of buildable products needed for the build:
725 void ValidateForPVBuild(std::string const &site = std::string());
726 void ValidateForVolumeBuild(std::string const &site = std::string());
727 void ValidateForBooleanBuild(std::string const &site = std::string());
728 // These helper validators just check that the product isn't already made:
729 void ValidateSolidNotBuilt(const std::string &operation) const;
730 void ValidateBooleanNotBuilt(const std::string &operation) const;
731 void ValidateLogicalNotBuilt(const std::string &operation) const;
732 void ValidatePlacementNotBuilt(const std::string &operation) const;
733
734 // For Geant, we need things left persistent, but this is a poor way even for this hack:
735 static void make_persistent(const std::shared_ptr<void> &obj);
736
737 G4ThreeVector ProvisionUnits(const Unit3Vec &vec) const;
738
739 // Private static helper
740 // method(s) used by the instance methods
741
742 static void NoNameCheck(const std::string &name, const std::string &site) {
743 if (name.empty()) {
744 throw std::runtime_error("Error in " + site + " ,"
745 "for builder named: " + name + "\n"
746 " Must provide a new name");
747 }
748 }
749 };
750} // namespace VolumeBuilder
751
752
753//The implementation:
754#include "VolumeBuilder.hpp"
755#endif
756
757/* TODO
758 * Need more derived classes for boxes and stuff!
759 * [] Propagate validators into all config methods.
760 * [] Validators needed in RZBuilder still.
761 * [] review make_persistent vs no-op deleters, and add upfront protection. make_persistent may need templating.
762 * [] use self-owned shared_ptr trick (intentional cycle) instead of make_peristent.
763 * [] A fill and copy would great.
764
765FromG4VSolid (rename?-> SolidAdapterBuilder)
766Bonus
767*
768* [] consider adding overlap check option to command line for easier use.
769* */
#define SET_LINK_TYPE
Definition Linkable.hh:62
#define ONCE_MUTABLE
T * get_mutable() const
Definition Linkable.hh:287
A type-erased (data shared view) view of a builder or assembly, ie a "structure.".
Definition Assembly.hh:46
Builder class for simple Box solids.
A solid buider class that just wrap an existing G4VSolid.
Builder class for RZ mult-plane defined solids.
Definition RZBuilder.hh:132
A type-erased (data shared view) view of a builder or assembly, ie a "structure.".
A type-erased (data shared view) view of a builder or assembly, ie a "structure.".
A 3D vector that carries its own unit information.
A polymorphic, type-erased builder referencing any specialized builder.
VolumeBuilder: Common functionality for volume builder classes.
DerivedPtr ReflectZFinalSolid()
Configure final solid to be flipped in z.
friend AssemblyPtr CreateAssembly(G4String names)
Assembly of strucures, ie builders and/or other assemblies.
Definition Assembly.cc:25
BuilderView ToBuilderView() const override
~VolumeBuilder() override
Destructor Normally does not delete volume objects.
DerivedPtr SetName(const G4String &name)
SetName Sets name used for solid and derived product names.
SharedPtr< IStructureBuilder > clone_impl() const override
DerivedPtr StackPhysTransform(const UnitlessG4Transform3D &new_transform)
Like SetPhysTransform but stacks with previous transformations in order applied.
G4VSolid * SolidConstructor(const G4String &name) override=0
polymorphic access to solid construction
DerivedPtr MakePlacement()
Make a placed physical volume.
DerivedPtr AddTo(BuilderViewList &list) const
DerivedPtr MakeSolid()
Make the G4VSolid.
StructureView ToStructureView() const override
DerivedPtr StackPhysOffset(const Unit3Vec &offset={CLHEP::mm, 0, 0, 0})
Like SetPhysOffset but stacks with previous transformations in order applied.
DerivedPtr StackPhysRotation(const G4RotationMatrix &stacked_rot)
Like SetPhysRotation but stacks with previous transformations in order applied.
friend FromG4VSolidPtr CreateFromG4VSolid(G4VSolid *solid)
Constructor to make a builder from an Existing Geant solid.
DerivedPtr MakeLogicalVolume(G4Material *material=nullptr, G4String name=std::string())
Basically never needed now.
DerivedPtr ReflectZBaseSolid()
Configure base solid to be flipped BEFORE applying booleans.
A wrapper for std::shared_ptr that allows and facilitates many implicit(i) type conversions.
DerivedPtr CopyVolumeConfigsFrom(const BuilderView &other)
Copies the LogicalVolume configuration (material, VisAttributes, etc.) from another builder.
DerivedPtr CopyPlacementConfigsFrom(const BuilderView &other)
This may help if reusing placement configs for a different shape.
DerivedPtr ForkForLogicalVolume(const G4String &new_name)
Makes final solid (including booleans) if unbuilt and copies builder with products cleared for furthe...
virtual DerivedPtr ForkAndReset(const G4String &new_name) const
Copy a configured/unbuilt Builder, with a new name.
DerivedPtr ForkForFinalSolid(const G4String &new_name)
Calls MakeSolid() and copies builder with products cleared for further construction.
DerivedPtr ForkForPlacement(std::optional< int > copy_no=std::nullopt, const G4String &name_override="", bool parent_name_was_set=false)
Calls MakeLogicalVolume() and creates a new builder instance with a copy of all placement-related con...
DerivedPtr SetColor(double r=0.5, double g=0.5, double b=0.5, double alpha=1.0)
DerivedPtr SetVisibility(bool x=true)
DerivedPtr SetAlpha(G4double alpha)
DerivedPtr SetMaterial(G4Material *material)
DerivedPtr AddBoolean(const BuilderView &other, bool is_subtraction=false, bool is_intersection=false, const Unit3Vec &offset={CLHEP::mm, 0, 0, 0}, G4RotationMatrix *rotation=nullptr)
Add a boolean operation.
DerivedPtr SetAutoCopyNo(bool set)
Enable (disable for false) auto Physical Volume numbering, on by default.
DerivedPtr SetBooleanName(const G4String &name)
Pre-set base name for logical and physical volumes.
DerivedPtr SetLogicalVolume(G4LogicalVolume *logical_volume)
Directly Provide a Logical Volume Instead of using the builder.
DerivedPtr SetSurfaceCheck(G4bool pSurfChk)
Set the surface check flag for the placement.
DerivedPtr SetMother(const BuilderView &mother)
Set the mother volume with a builder, or G4VPhysicalVolume or G4VLogicalVolume through implicit conve...
DerivedPtr SetPhysOffset(const Unit3Vec &offset={CLHEP::mm, 0, 0, 0})
Set the translation vector for placement.
DerivedPtr SetPhysTransform(const UnitlessG4Transform3D &new_transform)
Set the G4Transform3D for placment The tranformation provided is meant to be UNITLESS unless you SetD...
DerivedPtr SetCopyNo(G4int pCopyNo)
Set the copy number for the placement.
DerivedPtr OverridePlacementName(const G4String &pName)
Set the placement name for the volume.
DerivedPtr SetPhysRotation(const G4RotationMatrix &rot)
Set the rotation matrix for placement.
DerivedPtr SetAutoPlacementNaming(bool set)
Enable auto Physical Volume naming.
G4Transform3D GetPhysTransform() const final
A helper to get the Physical Volume transform with units applied This is built from rotation and tran...
DerivedPtr PlaceAndFork()
An alias for MakePlacement and ForkForPlacement Used for one or many unaltered placments in sequence,...
G4VSolid * GetFinalSolid() final
Gets a complete final built Solid, including configured Boolean operaions if any.
G4LogicalVolume * GetLogicalVolume() final
Gets a built LogicalVolume, builds default if not built yet.
G4VPhysicalVolume * GetPlacement() final
Gets the (last) placed physical volume.
G4VSolid * GetBaseSolid() final
You probably want GetSolid() instead!!! This Gets a built Solid, BUT NOT final Boolean.
G4double GetEffectiveDefaultUnit() const
Get the builder default unit or global if not set.
DerivedPtr SetDefaultUnit(G4double unit)
Set the per-Builder default unit for all later non-factory offsets.
DerivedPtr AddSubtraction(const BuilderView &other, const Unit3Vec &offset={CLHEP::mm, 0, 0, 0}, G4RotationMatrix *rotation=nullptr)
Define combination another volume with present one, This does NOT immediately trigger a build on a pa...
DerivedPtr AddUnion(const BuilderView &other, const Unit3Vec &offset={CLHEP::mm, 0, 0, 0}, G4RotationMatrix *rotation=nullptr)
Define combination another volume with present one, This does NOT immediately trigger a build on a pa...
DerivedPtr AddIntersection(const BuilderView &other, const Unit3Vec &offset={CLHEP::mm, 0, 0, 0}, G4RotationMatrix *rotation=nullptr)
Define combination another volume with present one, This does NOT immediately trigger a build on a pa...
SharedPtr< VolumeBuilderReference > BuilderView
Common interface for all volume builder types.
SharedPtr< IStructureBuilder > IStructurePtr
True polymorphic class base view for all structures Mostly for internal use.
std::vector< StructureView > StructureViewList
a user type to hold many structures
G4Transform3D UnitlessG4Transform3D
std::vector< BuilderView > BuilderViewList
a user type to hold many builders