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#include "MaterialsHelpers.hh"
10/*
11
12 * VolumeMaker.hh
13 *
14 * Created on: Jun 19, 2024
15 * Author: D. S. Leonard
16 * Implicit or explicit misrepresentation authorship is not protected under any license.
17 * See RZBuilder.hh for main documentation.
18 *
19 *s
20
21 */
22//#define SHARED_WRAPPER DLG4::i_shared_ptr
23#include <vector>
24#include "i_shared_ptr.hh"
26
27
28// #define FIXME(msg) static_assert(false, "FIXME: " msg)
29
30//#include "DetectorConstruction_includes.hh"
32#include <G4Material.hh>
33#include "G4Colour.hh" // why? It's in above.
34#include "G4VPhysicalVolume.hh"
35#include "G4UnionSolid.hh"
36#include <G4ThreeVector.hh>
37#include <mutex>
38#include <memory>
39#include <unordered_map>
40#include "AssemblyCore.hh"
41
42//#include "VolumeBuilderCore.hh"
43
45
46 class VolumeBuilderCore;
47 template <typename U>
48 class VolumeBuilderBase;
49
60 template <typename U>
61 class VolumeBuilderBase: public ENABLE_SHARED_WRAPPER<U>, public ISolidBuilder
62 , public IVolumeBuilder {
66
67 // limit public(protected) API by using friendship.
68 // Much of this can't even be handledby protected.
69 // Specifically factories (normal) and the type-erasing pseudo-inheritance (StructureBuilder)
70 template <typename>
71 friend class VolumeBuilderBase;
72 friend class VolumeBuilderCore;
73 friend class AssemblyCore;
74 template <typename>
77 friend FromG4VSolid VB::CreateFromG4VSolid(G4VSolid *solid);
78 friend Assembly VB::CreateAssembly(G4String names);
79 friend class RZBuilderCore;
80 friend class BoxBuilderCore;
81 friend class FromG4VSolidCore;
82
83 public:
91 [[nodiscard]] G4VPhysicalVolume *GetPlacement() final;
92
102
103
113 this->MakePlacement();
114 auto clone = this->ForkForPlacement(); // default/preset options
115 return clone;
116 }
117
126 [[nodiscard]] G4LogicalVolume *GetLogicalVolume() final;
127
138 [[nodiscard]] G4VSolid *GetBaseSolid() final;
139
146 [[nodiscard]] G4VSolid *GetFinalSolid() final;
147
148
160 DerivedPtr MakeLogicalVolume(
161 const VBHelpers::G4MaterialPtrOrString &material = {}, G4String name = std::string());
162
168 DerivedPtr MakeSolid();
169
175 DerivedPtr SetName(const G4String &name);
176
197 DerivedPtr AddUnion(const VolumeBuilder &other,
198 const DLG4::VolumeBuilders::ThreeVecDimensioner &offset = {0, 0, 0, VB::Length::mm},
199 G4RotationMatrix *rotation = nullptr);
201 DerivedPtr AddSubtraction(const VolumeBuilder &other,
202 const DLG4::VolumeBuilders::ThreeVecDimensioner &offset = {0, 0, 0, VB::Length::mm},
203 G4RotationMatrix *rotation = nullptr);
205 DerivedPtr AddIntersection(const VolumeBuilder &other,
206 const DLG4::VolumeBuilders::ThreeVecDimensioner &offset = {0, 0, 0, VB::Length::mm},
207 G4RotationMatrix *rotation = nullptr);
221 DerivedPtr AddBoolean(
222 const VolumeBuilder &other,
223 bool is_subtraction = false,
224 bool is_intersection = false,
225 const DLG4::VolumeBuilders::ThreeVecDimensioner &offset = {0, 0, 0, VB::Length::mm},
226 G4RotationMatrix *rotation = nullptr
227 );
236 DerivedPtr SetMaterial(const VBHelpers::G4MaterialPtrOrString &material);
237
243 DerivedPtr SetColor(double r = 0.5, double g = 0.5, double b = 0.5, double alpha = 1.0);
244
251 DerivedPtr SetColor(const G4Colour &color);
252
259 DerivedPtr SetAlpha(G4double alpha);
260
266 DerivedPtr ForceSolid(bool x = true); // default if uncalled is false.
267
274 DerivedPtr SetVisibility(bool x = true);
275
276 // ... inside the VolumeBuilder class declaration ...
277
291 DerivedPtr SetLogicalVolume(G4LogicalVolume *logical_volume);
292
302 DerivedPtr SetBooleanName(const G4String &name);
303
311 DerivedPtr SetPhysRotation(const G4RotationMatrix &rot);
312
323 DerivedPtr StackPhysRotation(const G4RotationMatrix &stacked_rot);
324
341 DerivedPtr SetPhysOffset(const DLG4::VolumeBuilders::ThreeVecDimensioner &offset = {0, 0, 0, VB::Length::mm});
352 DerivedPtr StackPhysOffset(const DLG4::VolumeBuilders::ThreeVecDimensioner &offset = {0, 0, 0, VB::Length::mm});
353
368 DerivedPtr SetPhysTransform(const UnitlessG4Transform3D &new_transform);
375 DerivedPtr StackPhysTransform(const UnitlessG4Transform3D &new_transform);
376
387 G4Transform3D GetPhysTransform() const final {
388 return {placement_configs_->rotation, placement_configs_->translation};
389 }
390
391
398 DerivedPtr OverridePlacementName(const G4String &pName);
399
400
407 DerivedPtr SetCopyNo(G4int pCopyNo);
408
415 DerivedPtr SetSurfaceCheck(G4bool pSurfChk);
416
417
429 DerivedPtr SetMother(const VolumeBuilder &mother);
430
442 DerivedPtr SetAutoPlacementNaming(bool set);
443
444
455 DerivedPtr SetAutoCopyNo(bool set);
456
473 DerivedPtr ReflectZFinalSolid();
474
483 DerivedPtr ReflectZBaseSolid();
484
499 DerivedPtr ForkAndReset(const G4String &new_name) const;
500
510 DerivedPtr ForkForFinalSolid(const G4String &new_name);
511
512
525 DerivedPtr ForkForLogicalVolume(const G4String &new_name);
526
527
542 DerivedPtr ForkForPlacement(
543 std::optional<int> copy_no = std::nullopt
544 , const G4String &name_override = ""
545 , bool parent_name_was_set = false
546 // in assembly/hierarchies, name change derives through parent
547 );
548
565 DerivedPtr CopyPlacementConfigsFrom(const VolumeBuilder &other);
566
576 DerivedPtr CopyVolumeConfigsFrom(const VolumeBuilder &other);
577
595 DerivedPtr SetDefaultUnit(Length unit);
596
612 DerivedPtr AddTo(BuilderViewList &list) const;
613
621 DerivedPtr AddTo(StructureViewList &list) const;
622
630 DerivedPtr AddTo(Assembly &assembly) const;
631
636 ~VolumeBuilderBase() override;
637
638
639 G4String GetBuilderName() const;
640
641 protected:
643 G4VSolid *SolidConstructor(const G4String &name) override = 0;
644
645 // base implementation of non-fluent clone.
647
648 private:
649 //Methods with basically protected intent
650 // But for now, keep them private and require explicit friend access
651 // ctors only useable through explicitly granted (friendship) inheritance...
652
653 VolumeBuilder ToVolumeBuilder() const override;
654 StructureBuilder ToStructureView() const override;
655
657 DerivedPtr SetSolid(G4VSolid *solid);
658
659 DerivedPtr Clone() const {
660 // This call is NOT DIRECTLY polymorphic. It calls the VolumeBuilder base clone_impl().
661 // Internally THAT calls polymorphic clone to create the structure_ptr and recreate the view.
662 // We have to re-cast the result.
663 i_shared_ptr<IStructureBuilder> base_cloned_ptr = this->clone_impl();
664 return std::static_pointer_cast<U>(base_cloned_ptr);
665 }
666
667
668 template <typename T, typename std::enable_if_t<std::is_base_of_v<IStructureBuilder, T>,
669 int> = 0>
671
672 VolumeBuilderBase &operator=(const VolumeBuilderBase &other) = delete;
673 DerivedPtr MakeFinalSolid(G4String boolean_name = "");
675
676 VolumeBuilderBase(VolumeBuilderBase &&) noexcept = default;
677
678 G4VSolid *GetSolidPtr() const {
679 return this->solid_ptr_.get_mutable();
680 };
681
682 //Configs (re-linked by copy-ctors)
683 ONCE_MUTABLE Linkable<BuilderConfigs> builder_configs_{BuilderConfigs{}};
684 ONCE_MUTABLE Linkable<BooleanConfigs> boolean_configs_{BooleanConfigs{}};
685 ONCE_MUTABLE Linkable<VolumeConfigs> lv_configs_{VolumeConfigs{}};
686 ONCE_MUTABLE Linkable<PlacementConfigs> placement_configs_{PlacementConfigs{}};
687
688 //Products (sometimes copied by copy methods)
689 ONCE_MUTABLE Linkable<G4VSolid> solid_ptr_{}; // child can and should create the solid
690 ONCE_MUTABLE Linkable<G4VSolid> final_solid_ptr_{};
693
694
698 void StoreIStructurePtr(const IStructurePtr &istructure_ptr);
699
700 void StoreBuilderView(const VolumeBuilder &builder_view);
701
702
703 //Unsaved data, left out of configs to be reset on all copy operations.
704 bool explicit_copyno_set_ = false;
705 bool explicit_physical_copy_name_set_ = false;
706 G4String placement_name_override_ = ""; // Will be derived from boolean_name_ by default
707
708 void SetSolid_impl(G4VSolid *solid);
709 void SetLogicalVolume_impl(G4LogicalVolume *logical_volume);
710
711 //Some hard baked settings
712 // let's pretend like we'd ever care about resource management:
713 static constexpr bool has_ownership_{false}; // for future resource control
714 static constexpr bool enable_full_lazy_builds{true};
715 // Allows full chain lazy building. Off for now.
716
717 //Methods with truly private intent.
718
719 // Propagate transforms
720 void PropagateTransform();
721
722
723 void ApplyAttributes_();
724 G4String GetPlacementBaseName() const;
725
726 [[nodiscard]] G4String GetLogicVolName() const; // should this be pulic?
727
728 // these validators may trigger lazy build of buildable products needed for the build:
729 void ValidateForPVBuild(std::string const &site = std::string());
730 void ValidateForVolumeBuild(std::string const &site = std::string());
731 void ValidateForBooleanBuild(std::string const &site = std::string());
732 // These helper validators just check that the product isn't already made:
733 void ValidateSolidNotBuilt(const std::string &operation) const;
734 void ValidateBooleanNotBuilt(const std::string &operation) const;
735 void ValidateLogicalNotBuilt(const std::string &operation) const;
736 void ValidatePlacementNotBuilt(const std::string &operation) const;
737
738 // For Geant, we need things left persistent, but this is a poor way even for this hack:
739 static void make_persistent(const std::shared_ptr<void> &obj);
740
741 G4ThreeVector ProvisionUnits(const DLG4::VolumeBuilders::ThreeVecDimensioner &vec) const;
742
743 // Private static helper
744 // method(s) used by the instance methods
745
746 static void NoNameCheck(const std::string &name, const std::string &site) {
747 if (name.empty()) {
748 throw std::runtime_error("Error in " + site + " ,"
749 "for builder named: " + name + "\n"
750 " Must provide a new name");
751 }
752 }
753 };
754} // namespace VolumeBuilder
755
756
757//The implementation:
758#include "VolumeBuilderBase.hpp"
759#endif
760
761/* TODO
762 * Need more derived classes for boxes and stuff!
763 * [] Propagate validators into all config methods.
764 * [] Validators needed in RZBuilder still.
765 * [] review make_persistent vs no-op deleters, and add upfront protection. make_persistent may need templating.
766 * [] use self-owned shared_ptr trick (intentional cycle) instead of make_peristent.
767 * [] A fill and copy would great.
768 * [] Structure builder lacks recursive clone of placement_configs_.children
769
770FromG4VSolid (rename?-> SolidAdapterBuilder)
771Bonus
772*
773* [] consider adding overlap check option to command line for easier use.
774* */
#define SET_LINK_TYPE
Definition Linkable.hh:63
#define ONCE_MUTABLE
A 3D vector that manages unit policy for parameter passing If constructed with a unit,...
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.".
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 MakeLogicalVolume(const VBHelpers::G4MaterialPtrOrString &material={}, G4String name=std::string())
Basically never needed now.
DerivedPtr MakePlacement()
Make a placed physical volume.
DerivedPtr StackPhysRotation(const G4RotationMatrix &stacked_rot)
Like SetPhysRotation but stacks with previous transformations in order applied.
DerivedPtr StackPhysOffset(const DLG4::VolumeBuilders::ThreeVecDimensioner &offset={0, 0, 0, VB::Length::mm})
Like SetPhysOffset but stacks with previous transformations in order applied.
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 DLG4::VolumeBuilders::ThreeVecDimensioner &offset={0, 0, 0, VB::Length::mm}, G4RotationMatrix *rotation=nullptr)
Add a boolean operation.
DerivedPtr SetMaterial(const VBHelpers::G4MaterialPtrOrString &material)
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 DLG4::VolumeBuilders::ThreeVecDimensioner &offset={0, 0, 0, VB::Length::mm})
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.
DerivedPtr SetDefaultUnit(Length unit)
Set the per-Builder default unit for all later non-factory offsets.
Length GetEffectiveDefaultUnit() const
Get the builder default unit or global if not set.
DerivedPtr AddSubtraction(const VolumeBuilder &other, const DLG4::VolumeBuilders::ThreeVecDimensioner &offset={0, 0, 0, VB::Length::mm}, 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 DLG4::VolumeBuilders::ThreeVecDimensioner &offset={0, 0, 0, VB::Length::mm}, G4RotationMatrix *rotation=nullptr)
Define combination another volume with present one, This does NOT immediately trigger a build on a pa...
DerivedPtr AddUnion(const VolumeBuilder &other, const DLG4::VolumeBuilders::ThreeVecDimensioner &offset={0, 0, 0, VB::Length::mm}, 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