File indexing completed on 2026-05-19 08:25:20
0001 #ifndef UNPLACEDBOOLEANVOLUME_H_
0002 #define UNPLACEDBOOLEANVOLUME_H_
0003
0004 #include "VecGeom/base/Cuda.h"
0005 #include "VecGeom/base/Global.h"
0006 #include "VecGeom/base/AlignedBase.h"
0007 #include "VecGeom/base/Vector3D.h"
0008 #include "VecGeom/volumes/UnplacedVolume.h"
0009 #include "VecGeom/volumes/PlacedVolume.h"
0010 #include "VecGeom/volumes/BooleanStruct.h"
0011 #include "VecGeom/volumes/kernel/BooleanImplementation.h"
0012 #include "VecGeom/volumes/UnplacedVolumeImplHelper.h"
0013 #ifndef VECCORE_CUDA
0014 #include "VecGeom/volumes/UnplacedMultiUnion.h"
0015 #endif
0016
0017 #include <string>
0018
0019 namespace vecgeom {
0020
0021 VECGEOM_DEVICE_DECLARE_CONV_TEMPLATE_1v(class, UnplacedBooleanVolume, BooleanOperation, Arg1);
0022
0023 inline namespace VECGEOM_IMPL_NAMESPACE {
0024
0025 #ifndef VECCORE_CUDA
0026 namespace BooleanHelper {
0027
0028 VECCORE_ATT_HOST_DEVICE
0029 BooleanStruct const *GetBooleanStruct(VUnplacedVolume const *unplaced);
0030
0031 VECCORE_ATT_HOST_DEVICE
0032 size_t CountBooleanNodes(VUnplacedVolume const *unplaced, size_t &nunion, size_t &nintersection, size_t &nsubtraction);
0033
0034 UnplacedMultiUnion *Flatten(VUnplacedVolume const *unplaced, size_t min_unions = 3,
0035 Transformation3D const *trbase = nullptr, UnplacedMultiUnion *munion = nullptr);
0036 }
0037 #endif
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052 template <BooleanOperation Op>
0053 class UnplacedBooleanVolume : public UnplacedVolumeImplHelper<BooleanImplementation<Op>>, public AlignedBase {
0054
0055 public:
0056 BooleanStruct fBoolean;
0057 using UnplacedVolumeImplHelper<BooleanImplementation<Op>>::fGlobalConvexity;
0058
0059
0060 VECCORE_ATT_HOST_DEVICE
0061 UnplacedBooleanVolume(BooleanOperation op, VPlacedVolume const *left, VPlacedVolume const *right)
0062 : fBoolean(op, left, right)
0063 {
0064 fGlobalConvexity = false;
0065 VUnplacedVolume::ComputeBBox();
0066 #ifndef VECCORE_CUDA
0067 if (fBoolean.fLeftVolume->IsAssembly() || fBoolean.fRightVolume->IsAssembly()) {
0068 throw std::runtime_error("Trying to make boolean out of assembly which is not supported\n");
0069 }
0070 #endif
0071 }
0072
0073 VECCORE_ATT_HOST_DEVICE
0074 VECGEOM_FORCE_INLINE
0075 virtual bool IsBoolean() const override { return true; }
0076
0077 VECCORE_ATT_HOST_DEVICE
0078 virtual ESolidType GetType() const override { return ESolidType::boolean; }
0079
0080 #ifdef VECGEOM_CUDA_INTERFACE
0081 virtual size_t DeviceSizeOf() const override { return DevicePtr<cuda::UnplacedBooleanVolume<Op>>::SizeOf(); }
0082 virtual DevicePtr<cuda::VUnplacedVolume> CopyToGpu() const override;
0083 virtual DevicePtr<cuda::VUnplacedVolume> CopyToGpu(DevicePtr<cuda::VUnplacedVolume> const gpu_ptr) const override;
0084 #endif
0085
0086 VECCORE_ATT_HOST_DEVICE
0087 VECGEOM_FORCE_INLINE
0088 BooleanOperation GetOp() const { return fBoolean.fOp; }
0089
0090 VECCORE_ATT_HOST_DEVICE
0091 BooleanStruct const &GetStruct() const { return fBoolean; }
0092
0093 VECCORE_ATT_HOST_DEVICE
0094 bool Normal(Vector3D<Precision> const &point, Vector3D<Precision> &normal) const override;
0095
0096 Precision Capacity() const override
0097 {
0098 if (fBoolean.fCapacity < 0.) {
0099 fBoolean.fCapacity = VUnplacedVolume::EstimateCapacity(1000000);
0100 }
0101 return fBoolean.fCapacity;
0102 }
0103
0104 Precision SurfaceArea() const override
0105 {
0106 if (fBoolean.fSurfaceArea < 0.) {
0107 fBoolean.fSurfaceArea = VUnplacedVolume::EstimateSurfaceArea(1000000);
0108 }
0109 return fBoolean.fSurfaceArea;
0110 }
0111
0112 VECCORE_ATT_HOST_DEVICE
0113 void Extent(Vector3D<Precision> &aMin, Vector3D<Precision> &aMax) const override;
0114
0115 Vector3D<Precision> SamplePointOnSurface() const override;
0116
0117 std::string GetEntityType() const { return "BooleanVolume"; }
0118
0119 VECCORE_ATT_HOST_DEVICE
0120 virtual void Print() const override
0121 {
0122 #ifndef VECCORE_CUDA
0123 auto op = this->GetOp();
0124 const char *opname = (op == kUnion ? "Union" : (op == kIntersection ? "Intersection" : "Subtraction"));
0125 printf("UnplacedBooleanVol<%s>{fLeft=[%i]<%s>, fRight=[%i]<%s>}", opname, this->GetLeft()->id(),
0126 this->GetLeft()->GetName(), this->GetRight()->id(), this->GetRight()->GetName());
0127 #else
0128 printf("UnplacedBooleanVol<%i>{fLeft=[%i], fRight=[%i]}", this->GetOp(), this->GetLeft()->id(),
0129 this->GetRight()->id());
0130 #endif
0131 printf("\n\t----------------------------------------");
0132 printf("\n\tfLeft: [%i] ", this->GetLeft()->id());
0133 this->GetLeft()->GetUnplacedVolume()->Print();
0134 printf("\n\tfRight: [%i] ", this->GetRight()->id());
0135 this->GetRight()->GetUnplacedVolume()->Print();
0136 printf("\n\t----------------------------------------\n");
0137 }
0138
0139 virtual void Print(std::ostream &os) const override
0140 {
0141 #ifndef VECCORE_CUDA
0142 auto op = this->GetOp();
0143 os << "UnplacedBooleanVol<" << (op == kUnion ? "Union" : (op == kIntersection ? "Intersection" : "Subtraction"))
0144 << ">{fLeft=<" << this->GetLeft()->id() << ">, fRight=<" << this->GetRight()->id() << ">}\n";
0145 #endif
0146 os << "fLeft: [" << this->GetLeft()->id() << "] ";
0147 this->GetLeft()->GetUnplacedVolume()->Print(os);
0148 os << "fRight: [" << this->GetRight()->id() << "] ";
0149 this->GetRight()->GetUnplacedVolume()->Print(os);
0150 os << "\n";
0151 }
0152
0153 VECCORE_ATT_DEVICE
0154 static VPlacedVolume *Create(LogicalVolume const *const logical_volume, Transformation3D const *const transformation,
0155 #ifdef VECCORE_CUDA
0156 const int id, const int copy_no, const int child_id,
0157 #endif
0158 VPlacedVolume *const placement = NULL);
0159
0160 VECCORE_ATT_HOST_DEVICE
0161 VPlacedVolume const *GetLeft() const { return fBoolean.fLeftVolume; }
0162 VECCORE_ATT_HOST_DEVICE
0163 VPlacedVolume const *GetRight() const { return fBoolean.fRightVolume; }
0164
0165 #ifndef VECCORE_CUDA
0166
0167 VECCORE_ATT_HOST_DEVICE
0168 size_t CountNodes(size_t &nunion, size_t &nintersection, size_t &nsubtraction) const
0169 {
0170 return BooleanHelper::CountBooleanNodes(this, nunion, nintersection, nsubtraction);
0171 }
0172
0173
0174 UnplacedMultiUnion *Flatten(size_t min_unions = 1, Transformation3D const *trbase = nullptr,
0175 UnplacedMultiUnion *munion = nullptr)
0176 {
0177 return BooleanHelper::Flatten(this, min_unions, trbase, munion);
0178 }
0179 #endif
0180
0181 private:
0182 VECCORE_ATT_DEVICE
0183 virtual VPlacedVolume *SpecializedVolume(LogicalVolume const *const volume,
0184 Transformation3D const *const transformation,
0185 #ifdef VECCORE_CUDA
0186 const int id, const int copy_no, const int child_id,
0187 #endif
0188 VPlacedVolume *const placement = NULL) const override;
0189
0190 void SetLeft(VPlacedVolume const *pvol) { fBoolean.fLeftVolume = pvol; }
0191 void SetRight(VPlacedVolume const *pvol) { fBoolean.fRightVolume = pvol; }
0192
0193 friend class vecgeom::GeoManager;
0194 };
0195
0196 }
0197
0198 }
0199
0200 #endif