File indexing completed on 2026-11-15 10:34:44
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 bool ContainsHalfSpace(VUnplacedVolume const *unplaced);
0032
0033 bool HasRootUnsupportedHalfSpaceUnion(VUnplacedVolume const *unplaced);
0034
0035 bool IsFiniteBody(VPlacedVolume const *placed);
0036
0037 bool IsFiniteBody(VUnplacedVolume const *unplaced);
0038
0039 VECCORE_ATT_HOST_DEVICE
0040 size_t CountBooleanNodes(VUnplacedVolume const *unplaced, size_t &nunion, size_t &nintersection, size_t &nsubtraction);
0041
0042 UnplacedMultiUnion *Flatten(VUnplacedVolume const *unplaced, size_t min_unions = 3,
0043 Transformation3D const *trbase = nullptr, UnplacedMultiUnion *munion = nullptr);
0044 }
0045 #endif
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060 template <BooleanOperation Op>
0061 class UnplacedBooleanVolume : public UnplacedVolumeImplHelper<BooleanImplementation<Op>>, public AlignedBase {
0062
0063 public:
0064 BooleanStruct fBoolean;
0065 using UnplacedVolumeImplHelper<BooleanImplementation<Op>>::fGlobalConvexity;
0066
0067
0068 VECCORE_ATT_HOST_DEVICE
0069 UnplacedBooleanVolume(BooleanOperation op, VPlacedVolume const *left, VPlacedVolume const *right
0070 #ifdef VECCORE_CUDA
0071 ,
0072 std::uint16_t leftScore = 1, std::uint16_t rightScore = 1, std::uint8_t identityMask = 0
0073 #endif
0074 )
0075 : fBoolean(op, left, right)
0076 {
0077 fGlobalConvexity = false;
0078 #ifndef VECCORE_CUDA
0079 VUnplacedVolume::ComputeBBox();
0080 if (fBoolean.fLeftVolume->IsAssembly() || fBoolean.fRightVolume->IsAssembly()) {
0081 throw std::runtime_error("Trying to make boolean out of assembly which is not supported\n");
0082 }
0083 #else
0084
0085
0086 fBoolean.fLeftScore = leftScore;
0087 fBoolean.fRightScore = rightScore;
0088 fBoolean.fIdentityMask = identityMask;
0089 VUnplacedVolume::ComputeBBox();
0090 #endif
0091 }
0092
0093 VECCORE_ATT_HOST_DEVICE
0094 VECGEOM_FORCE_INLINE
0095 virtual bool IsBoolean() const override { return true; }
0096
0097 VECCORE_ATT_HOST_DEVICE
0098 virtual ESolidType GetType() const override { return ESolidType::boolean; }
0099
0100 #ifdef VECGEOM_CUDA_INTERFACE
0101 virtual size_t DeviceSizeOf() const override { return DevicePtr<cuda::UnplacedBooleanVolume<Op>>::SizeOf(); }
0102 virtual DevicePtr<cuda::VUnplacedVolume> CopyToGpu() const override;
0103 virtual DevicePtr<cuda::VUnplacedVolume> CopyToGpu(DevicePtr<cuda::VUnplacedVolume> const gpu_ptr) const override;
0104 #endif
0105
0106 VECCORE_ATT_HOST_DEVICE
0107 VECGEOM_FORCE_INLINE
0108 BooleanOperation GetOp() const { return fBoolean.fOp; }
0109
0110 VECCORE_ATT_HOST_DEVICE
0111 BooleanStruct const &GetStruct() const { return fBoolean; }
0112
0113 VECCORE_ATT_HOST_DEVICE
0114 bool Normal(Vector3D<Precision> const &point, Vector3D<Precision> &normal) const override;
0115
0116 Precision Capacity() const override
0117 {
0118 if (fBoolean.fCapacity < 0.) {
0119 fBoolean.fCapacity = VUnplacedVolume::EstimateCapacity(1000000);
0120 }
0121 return fBoolean.fCapacity;
0122 }
0123
0124 Precision SurfaceArea() const override
0125 {
0126 if (fBoolean.fSurfaceArea < 0.) {
0127 fBoolean.fSurfaceArea = VUnplacedVolume::EstimateSurfaceArea(1000000);
0128 }
0129 return fBoolean.fSurfaceArea;
0130 }
0131
0132 VECCORE_ATT_HOST_DEVICE
0133 void Extent(Vector3D<Precision> &aMin, Vector3D<Precision> &aMax) const override;
0134
0135 #ifndef VECCORE_CUDA
0136
0137
0138
0139
0140
0141
0142
0143 bool CalculateClippedExtent(Axis axis, VoxelLimits const &limits, Transformation3D const &transform, Precision &min,
0144 Precision &max) const override;
0145 #endif
0146
0147 Vector3D<Precision> SamplePointOnSurface() const override;
0148
0149 std::string GetEntityType() const { return "BooleanVolume"; }
0150
0151 VECCORE_ATT_HOST_DEVICE
0152 virtual void Print() const override
0153 {
0154 #ifndef VECCORE_CUDA
0155 auto op = this->GetOp();
0156 const char *opname = (op == kUnion ? "Union" : (op == kIntersection ? "Intersection" : "Subtraction"));
0157 printf("UnplacedBooleanVol<%s>{fLeft=[%i]<%s>, fRight=[%i]<%s>}", opname, this->GetLeft()->id(),
0158 this->GetLeft()->GetName(), this->GetRight()->id(), this->GetRight()->GetName());
0159 #else
0160 printf("UnplacedBooleanVol<%i>{fLeft=[%i], fRight=[%i]}", this->GetOp(), this->GetLeft()->id(),
0161 this->GetRight()->id());
0162 #endif
0163 printf("\n\t----------------------------------------");
0164 printf("\n\tfLeft: [%i] ", this->GetLeft()->id());
0165 this->GetLeft()->GetUnplacedVolume()->Print();
0166 printf("\n\tfRight: [%i] ", this->GetRight()->id());
0167 this->GetRight()->GetUnplacedVolume()->Print();
0168 printf("\n\t----------------------------------------\n");
0169 }
0170
0171 virtual void Print(std::ostream &os) const override
0172 {
0173 #ifndef VECCORE_CUDA
0174 auto op = this->GetOp();
0175 os << "UnplacedBooleanVol<" << (op == kUnion ? "Union" : (op == kIntersection ? "Intersection" : "Subtraction"))
0176 << ">{fLeft=<" << this->GetLeft()->id() << ">, fRight=<" << this->GetRight()->id() << ">}\n";
0177 #endif
0178 os << "fLeft: [" << this->GetLeft()->id() << "] ";
0179 this->GetLeft()->GetUnplacedVolume()->Print(os);
0180 os << "fRight: [" << this->GetRight()->id() << "] ";
0181 this->GetRight()->GetUnplacedVolume()->Print(os);
0182 os << "\n";
0183 }
0184
0185 VECCORE_ATT_DEVICE
0186 static VPlacedVolume *Create(LogicalVolume const *const logical_volume, Transformation3D const *const transformation,
0187 #ifdef VECCORE_CUDA
0188 const int id, const int copy_no, const int child_id,
0189 #endif
0190 VPlacedVolume *const placement = NULL);
0191
0192 VECCORE_ATT_HOST_DEVICE
0193 VPlacedVolume const *GetLeft() const { return fBoolean.fLeftVolume; }
0194 VECCORE_ATT_HOST_DEVICE
0195 VPlacedVolume const *GetRight() const { return fBoolean.fRightVolume; }
0196
0197 #ifndef VECCORE_CUDA
0198
0199 VECCORE_ATT_HOST_DEVICE
0200 size_t CountNodes(size_t &nunion, size_t &nintersection, size_t &nsubtraction) const
0201 {
0202 return BooleanHelper::CountBooleanNodes(this, nunion, nintersection, nsubtraction);
0203 }
0204
0205
0206 UnplacedMultiUnion *Flatten(size_t min_unions = 1, Transformation3D const *trbase = nullptr,
0207 UnplacedMultiUnion *munion = nullptr)
0208 {
0209 return BooleanHelper::Flatten(this, min_unions, trbase, munion);
0210 }
0211 #endif
0212
0213 private:
0214 VECCORE_ATT_DEVICE
0215 virtual VPlacedVolume *SpecializedVolume(LogicalVolume const *const volume,
0216 Transformation3D const *const transformation,
0217 #ifdef VECCORE_CUDA
0218 const int id, const int copy_no, const int child_id,
0219 #endif
0220 VPlacedVolume *const placement = NULL) const override;
0221
0222 void SetLeft(VPlacedVolume const *pvol)
0223 {
0224 fBoolean.fLeftVolume = pvol;
0225 fBoolean.UpdatePlacementFlags();
0226 }
0227 void SetRight(VPlacedVolume const *pvol)
0228 {
0229 fBoolean.fRightVolume = pvol;
0230 fBoolean.UpdatePlacementFlags();
0231 }
0232
0233 friend class vecgeom::GeoManager;
0234 };
0235
0236 }
0237
0238 }
0239
0240 #endif