DLG4::VolumeBuilders
A fluent interface for Geant4 geometry definition.
Loading...
Searching...
No Matches
VolumeBuilderBase.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"
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 "AssemblyCore.hh"
40
41//#include "VolumeBuilderCore.hh"
42
44
45 class VolumeBuilderCore;
46 template <typename U>
47 class VolumeBuilderBase;
48
59 template <typename U>
60 class VolumeBuilderBase: public ENABLE_SHARED_WRAPPER<U>, public ISolidBuilder
61 , public IVolumeBuilder {
65
66 // limit public(protected) API by using friendship.
67 // Much of this can't even be handledby protected.
68 // Specifically factories (normal) and the type-erasing pseudo-inheritance (StructureBuilder)
69 template <typename>
70 friend class VolumeBuilderBase;
71 friend class VolumeBuilderCore;
72 friend class AssemblyCore;
73 template <typename>
76 friend FromG4VSolid VB::CreateFromG4VSolid(G4VSolid *solid);
77 friend Assembly VB::CreateAssembly(G4String names);
78 friend class RZBuilderCore;
79 friend class BoxBuilderCore;
80 friend class FromG4VSolidCore;
81
82 public:
90 [[nodiscard]] G4VPhysicalVolume *GetPlacement() final;
91
101
102
112 this->MakePlacement();
113 auto clone = this->ForkForPlacement(); // default/preset options
114 return clone;
115 }
116
125 [[nodiscard]] G4LogicalVolume *GetLogicalVolume() final;
126
137 [[nodiscard]] G4VSolid *GetBaseSolid() final;
138
145 [[nodiscard]] G4VSolid *GetFinalSolid() final;
146
147
159 DerivedPtr MakeLogicalVolume(
160 G4Material *material = nullptr, G4String name = std::string());
161
167 DerivedPtr MakeSolid();
168
174 DerivedPtr SetName(const G4String &name);
175
196 DerivedPtr AddUnion(const VolumeBuilder &other,
197 const Unit3Vec &offset = {CLHEP::mm, 0, 0, 0},
198 G4RotationMatrix *rotation = nullptr);
200 DerivedPtr AddSubtraction(const VolumeBuilder &other,
201 const Unit3Vec &offset = {CLHEP::mm, 0, 0, 0},
202 G4RotationMatrix *rotation = nullptr);
204 DerivedPtr AddIntersection(const VolumeBuilder &other,
205 const Unit3Vec &offset = {CLHEP::mm, 0, 0, 0},
206 G4RotationMatrix *rotation = nullptr);
220 DerivedPtr AddBoolean(
221 const VolumeBuilder &other,
222 bool is_subtraction = false,
223 bool is_intersection = false,
224 const Unit3Vec &offset = {CLHEP::mm, 0, 0, 0},
225 G4RotationMatrix *rotation = nullptr
226 );
235 DerivedPtr SetMaterial(G4Material *material);
236
242 DerivedPtr SetColor(double r = 0.5, double g = 0.5, double b = 0.5, double alpha = 1.0);
243
250 DerivedPtr SetColor(const G4Colour &color);
251
258 DerivedPtr SetAlpha(G4double alpha);
259
265 DerivedPtr ForceSolid(bool x = true); // default if uncalled is false.
266
273 DerivedPtr SetVisibility(bool x = true);
274
275 // ... inside the VolumeBuilder class declaration ...
276
290 DerivedPtr SetLogicalVolume(G4LogicalVolume *logical_volume);
291
301 DerivedPtr SetBooleanName(const G4String &name);
302
310 DerivedPtr SetPhysRotation(const G4RotationMatrix &rot);
311
322 DerivedPtr StackPhysRotation(const G4RotationMatrix &stacked_rot);
323
340 DerivedPtr SetPhysOffset(const Unit3Vec &offset = {CLHEP::mm, 0, 0, 0});
351 DerivedPtr StackPhysOffset(const Unit3Vec &offset = {CLHEP::mm, 0, 0, 0});
352
367 DerivedPtr SetPhysTransform(const UnitlessG4Transform3D &new_transform);
374 DerivedPtr StackPhysTransform(const UnitlessG4Transform3D &new_transform);
375
386 G4Transform3D GetPhysTransform() const final {
387 return {placement_configs_->rotation, placement_configs_->translation};
388 }
389
390
397 DerivedPtr OverridePlacementName(const G4String &pName);
398
399
406 DerivedPtr SetCopyNo(G4int pCopyNo);
407
414 DerivedPtr SetSurfaceCheck(G4bool pSurfChk);
415
416
428 DerivedPtr SetMother(const VolumeBuilder &mother);
429
441 DerivedPtr SetAutoPlacementNaming(bool set);
442
443
454 DerivedPtr SetAutoCopyNo(bool set);
455
472 DerivedPtr ReflectZFinalSolid();
473
482 DerivedPtr ReflectZBaseSolid();
483
498 DerivedPtr ForkAndReset(const G4String &new_name) const;
499
509 DerivedPtr ForkForFinalSolid(const G4String &new_name);
510
511
524 DerivedPtr ForkForLogicalVolume(const G4String &new_name);
525
526
541 DerivedPtr ForkForPlacement(
542 std::optional<int> copy_no = std::nullopt
543 , const G4String &name_override = ""
544 , bool parent_name_was_set = false
545 // in assembly/hierarchies, name change derives through parent
546 );
547
564 DerivedPtr CopyPlacementConfigsFrom(const VolumeBuilder &other);
565
575 DerivedPtr CopyVolumeConfigsFrom(const VolumeBuilder &other);
576
594 DerivedPtr SetDefaultUnit(G4double unit);
595
601 G4double GetEffectiveDefaultUnit() const;
611 DerivedPtr AddTo(BuilderViewList &list) const;
612
620 DerivedPtr AddTo(StructureViewList &list) const;
621
629 DerivedPtr AddTo(Assembly &assembly) const;
630
635 ~VolumeBuilderBase() override;
636
637
638 G4String GetBuilderName() const;
639
640 protected:
642 G4VSolid *SolidConstructor(const G4String &name) override = 0;
643
644 // base implementation of non-fluent clone.
646
647 private:
648 //Methods with basically protected intent
649 // But for now, keep them private and require explicit friend access
650 // ctors only useable through explicitly granted (friendship) inheritance...
651
652 VolumeBuilder ToVolumeBuilder() const override;
653 StructureBuilder ToStructureView() const override;
654
656 DerivedPtr SetSolid(G4VSolid *solid);
657
658 DerivedPtr Clone() const {
659 // This call is NOT DIRECTLY polymorphic. It calls the VolumeBuilder base clone_impl().
660 // Internally THAT calls polymorphic clone to create the structure_ptr and recreate the view.
661 // We have to re-cast the result.
662 i_shared_ptr<IStructureBuilder> base_cloned_ptr = this->clone_impl();
663 return std::static_pointer_cast<U>(base_cloned_ptr);
664 }
665
666
667 template <typename T, typename std::enable_if_t<std::is_base_of_v<IStructureBuilder, T>,
668 int> = 0>
670
671 VolumeBuilderBase &operator=(const VolumeBuilderBase &other) = delete;
672 DerivedPtr MakeFinalSolid(G4String boolean_name = "");
674
675 VolumeBuilderBase(VolumeBuilderBase &&) noexcept = default;
676
677 G4VSolid *GetSolidPtr() const {
678 return this->solid_ptr_.get_mutable();
679 };
680
681 //Configs (re-linked by copy-ctors)
682 ONCE_MUTABLE Linkable<BuilderConfigs> builder_configs_{BuilderConfigs{}};
683 ONCE_MUTABLE Linkable<BooleanConfigs> boolean_configs_{BooleanConfigs{}};
684 ONCE_MUTABLE Linkable<VolumeConfigs> lv_configs_{VolumeConfigs{}};
685 ONCE_MUTABLE Linkable<PlacementConfigs> placement_configs_{PlacementConfigs{}};
686
687 //Products (sometimes copied by copy methods)
688 ONCE_MUTABLE Linkable<G4VSolid> solid_ptr_{}; // child can and should create the solid
689 ONCE_MUTABLE Linkable<G4VSolid> final_solid_ptr_{};
692
693
697 void StoreIStructurePtr(const IStructurePtr &istructure_ptr);
698
699 void StoreBuilderView(const VolumeBuilder &builder_view);
700
701
702 //Unsaved data, left out of configs to be reset on all copy operations.
703 bool explicit_copyno_set_ = false;
704 bool explicit_physical_copy_name_set_ = false;
705 G4String placement_name_override_ = ""; // Will be derived from boolean_name_ by default
706
707 void SetSolid_impl(G4VSolid *solid);
708 void SetLogicalVolume_impl(G4LogicalVolume *logical_volume);
709
710 //Some hard baked settings
711 // let's pretend like we'd ever care about resource management:
712 static constexpr bool has_ownership_{false}; // for future resource control
713 static constexpr bool enable_full_lazy_builds{true};
714 // Allows full chain lazy building. Off for now.
715
716 //Methods with truly private intent.
717
718 // Propagate transforms
719 void PropagateTransform();
720
721
722 void ApplyAttributes_();
723 G4String GetPlacementBaseName() const;
724
725 [[nodiscard]] G4String GetLogicVolName() const; // should this be pulic?
726
727 // these validators may trigger lazy build of buildable products needed for the build:
728 void ValidateForPVBuild(std::string const &site = std::string());
729 void ValidateForVolumeBuild(std::string const &site = std::string());
730 void ValidateForBooleanBuild(std::string const &site = std::string());
731 // These helper validators just check that the product isn't already made:
732 void ValidateSolidNotBuilt(const std::string &operation) const;
733 void ValidateBooleanNotBuilt(const std::string &operation) const;
734 void ValidateLogicalNotBuilt(const std::string &operation) const;
735 void ValidatePlacementNotBuilt(const std::string &operation) const;
736
737 // For Geant, we need things left persistent, but this is a poor way even for this hack:
738 static void make_persistent(const std::shared_ptr<void> &obj);
739
740 G4ThreeVector ProvisionUnits(const Unit3Vec &vec) const;
741
742 // Private static helper
743 // method(s) used by the instance methods
744
745 static void NoNameCheck(const std::string &name, const std::string &site) {
746 if (name.empty()) {
747 throw std::runtime_error("Error in " + site + " ,"
748 "for builder named: " + name + "\n"
749 " Must provide a new name");
750 }
751 }
752 };
753} // namespace VolumeBuilder
754
755
756//The implementation:
757#include "VolumeBuilderBase.hpp"
758#endif
759
760/* TODO
761 * Need more derived classes for boxes and stuff!
762 * [] Propagate validators into all config methods.
763 * [] Validators needed in RZBuilder still.
764 * [] review make_persistent vs no-op deleters, and add upfront protection. make_persistent may need templating.
765 * [] use self-owned shared_ptr trick (intentional cycle) instead of make_peristent.
766 * [] A fill and copy would great.
767 * [] Structure builder lacks recursive clone of placement_configs_.children
768
769FromG4VSolid (rename?-> SolidAdapterBuilder)
770Bonus
771*
772* [] consider adding overlap check option to command line for easier use.
773* */
#define SET_LINK_TYPE
Definition Linkable.hh:62
#define ONCE_MUTABLE
A type-erased (data shared view) view of a builder or assembly, ie a "structure.".
Builder class for simple Box solids.
A solid buider class that just wrap an existing G4VSolid.
Builder class for RZ mult-plane defined solids.
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.
VolumeBuilder: Common functionality for volume builder classes.
~VolumeBuilderBase() override
Destructor Normally does not delete volume objects.
SharedPtr< IStructureBuilder > clone_impl() const override
G4VSolid * SolidConstructor(const G4String &name) override=0
polymorphic access to solid construction
DerivedPtr SetName(const G4String &name)
SetName Sets name used for solid and derived product names.
DerivedPtr StackPhysOffset(const Unit3Vec &offset={CLHEP::mm, 0, 0, 0})
Like SetPhysOffset but stacks with previous transformations in order applied.
DerivedPtr MakePlacement()
Make a placed physical volume.
DerivedPtr StackPhysRotation(const G4RotationMatrix &stacked_rot)
Like SetPhysRotation but stacks with previous transformations in order applied.
DerivedPtr MakeLogicalVolume(G4Material *material=nullptr, G4String name=std::string())
Basically never needed now.
DerivedPtr StackPhysTransform(const UnitlessG4Transform3D &new_transform)
Like SetPhysTransform but stacks with previous transformations in order applied.
A polymorphic, type-erased "view" of any specialized builder.
DerivedPtr CopyPlacementConfigsFrom(const VolumeBuilder &other)
This may help if reusing placement configs for a different shape.
DerivedPtr CopyVolumeConfigsFrom(const VolumeBuilder &other)
Copies the LogicalVolume configuration (material, VisAttributes, etc.) from another builder.
FromG4VSolid CreateFromG4VSolid(G4VSolid *solid)
Constructor to make a builder from an Existing Geant solid.
Assembly CreateAssembly(G4String name)
Assembly of strucures, ie builders and/or other assemblies.
DerivedPtr ForkForLogicalVolume(const G4String &new_name)
Makes final solid (including booleans) if unbuilt and copies builder with products cleared for furthe...
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 ForkForFinalSolid(const G4String &new_name)
Calls MakeSolid() and copies builder with products cleared for further construction.
DerivedPtr ForkAndReset(const G4String &new_name) const
Copy a configured/unbuilt Builder, with a new name.
DerivedPtr SetColor(double r=0.5, double g=0.5, double b=0.5, double alpha=1.0)
DerivedPtr AddBoolean(const VolumeBuilder &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 SetMother(const VolumeBuilder &mother)
Set the mother volume with a builder, or G4VPhysicalVolume or G4VLogicalVolume through implicit conve...
DerivedPtr SetSurfaceCheck(G4bool pSurfChk)
Set the surface check flag for the placement.
DerivedPtr SetAutoPlacementNaming(bool set)
Enable auto Physical Volume naming.
DerivedPtr SetBooleanName(const G4String &name)
Pre-set base name for logical and physical volumes.
DerivedPtr SetPhysTransform(const UnitlessG4Transform3D &new_transform)
Set the G4Transform3D for placment.
DerivedPtr SetLogicalVolume(G4LogicalVolume *logical_volume)
Directly Provide a Logical Volume Instead of using the builder.
DerivedPtr SetPhysRotation(const G4RotationMatrix &rot)
Set the rotation matrix for placement.
DerivedPtr SetPhysOffset(const Unit3Vec &offset={CLHEP::mm, 0, 0, 0})
Set the translation vector for placement.
DerivedPtr OverridePlacementName(const G4String &pName)
Set the placement name for the volume.
DerivedPtr SetCopyNo(G4int pCopyNo)
Set the copy number for the placement.
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,...
DerivedPtr SetAutoCopyNo(bool set)
Enable (disable for false) auto Physical Volume numbering, on by default.
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.
DerivedPtr ReflectZBaseSolid()
Configure base solid to be flipped BEFORE applying booleans.
DerivedPtr ReflectZFinalSolid()
Configure final solid to be flipped in z.
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 AddUnion(const VolumeBuilder &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 VolumeBuilder &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 AddSubtraction(const VolumeBuilder &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< VolumeBuilderCore > VolumeBuilder
SharedPtr< IStructureBuilder > IStructurePtr
True polymorphic class base view for all structures Mostly for internal use.
std::vector< VolumeBuilder > BuilderViewList
a user type to hold many builders
std::vector< StructureBuilder > StructureViewList
a user type to hold many structures