Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-04-17 08:35:33

0001 #ifndef VECGEOM_SURFACE_SOLIDCONVERTER_H_
0002 #define VECGEOM_SURFACE_SOLIDCONVERTER_H_
0003 
0004 #include <VecGeom/surfaces/Model.h>
0005 
0006 #include <VecGeom/surfaces/conv/BoxConverter.h>
0007 #include <VecGeom/surfaces/conv/TubeConverter.h>
0008 #include <VecGeom/surfaces/conv/CutTubeConverter.h>
0009 #include <VecGeom/surfaces/conv/EllipticalTubeConverter.h>
0010 #include <VecGeom/surfaces/conv/ParallelepipedConverter.h>
0011 #include <VecGeom/surfaces/conv/ConeConverter.h>
0012 #include <VecGeom/surfaces/conv/PolyconeConverter.h>
0013 #include <VecGeom/surfaces/conv/TorusConverter.h>
0014 #include <VecGeom/surfaces/conv/SExtrudedConverter.h>
0015 #include <VecGeom/surfaces/conv/TrdConverter.h>
0016 #include <VecGeom/surfaces/conv/TrapezoidConverter.h>
0017 #include <VecGeom/surfaces/conv/GenTrapConverter.h>
0018 #include <VecGeom/surfaces/conv/PolyhedronConverter.h>
0019 #include <VecGeom/surfaces/conv/BooleanConverter.h>
0020 #include <VecGeom/surfaces/conv/ScaledConverter.h>
0021 #include <VecGeom/surfaces/conv/TetConverter.h>
0022 #include <VecGeom/surfaces/conv/SphereConverter.h>
0023 #include <VecGeom/volumes/ScaledShape.h>
0024 
0025 namespace vgbrep {
0026 namespace conv {
0027 
0028 /// @brief Dispacher to different solid converters
0029 /// @tparam Real_t Precision type
0030 /// @param solid Unplaced solid to be converted
0031 /// @param volId Logical volume id
0032 /// @param localtrans Local transformation, used only for Boolean volumes
0033 /// @return Conversion success
0034 template <typename Real_t>
0035 bool CreateSolidSurfaces(vecgeom::VUnplacedVolume const *solid, int volId,
0036                          TransformationMP<Real_t> *localtrans = nullptr, bool intersection = false)
0037 {
0038   bool success{true};
0039   auto &cpudata     = CPUsurfData<Real_t>::Instance();
0040   auto const &shell = cpudata.fShells[volId];
0041   auto isurf_first  = shell.fSurfaces.size();
0042 
0043   auto createSurfacesLocal = [](vecgeom::VUnplacedVolume const *solid, int volId, bool intersection = false) {
0044     auto box = dynamic_cast<vecgeom::UnplacedBox const *>(solid);
0045     if (box) return conv::CreateBoxSurfaces<Real_t>(*box, volId, intersection);
0046 
0047     auto tube = dynamic_cast<vecgeom::UnplacedTube const *>(solid);
0048     if (tube) return conv::CreateTubeSurfaces<Real_t>(*tube, volId, intersection);
0049 
0050     auto etube = dynamic_cast<vecgeom::UnplacedEllipticalTube const *>(solid);
0051     if (etube) return conv::CreateEllipticalTubeSurfaces<Real_t>(*etube, volId, intersection);
0052 
0053     auto cuttube = dynamic_cast<vecgeom::UnplacedCutTube const *>(solid);
0054     if (cuttube) return conv::CreateTubeSurfaces<Real_t>(*cuttube, volId, intersection);
0055 
0056     auto para = dynamic_cast<vecgeom::UnplacedParallelepiped const *>(solid);
0057     if (para) return conv::CreateParallelepipedSurfaces<Real_t>(*para, volId, intersection);
0058 
0059     auto cone = dynamic_cast<vecgeom::UnplacedCone const *>(solid);
0060     if (cone) return conv::CreateConeSurfaces<Real_t>(*cone, volId, intersection);
0061 
0062     auto polycone = dynamic_cast<vecgeom::UnplacedPolycone const *>(solid);
0063     if (polycone) return conv::CreatePolyconeSurfaces<Real_t>(*polycone, volId, intersection);
0064 
0065     auto torus = dynamic_cast<vecgeom::UnplacedTorus2 const *>(solid);
0066     if (torus) return conv::CreateTorusSurfaces<Real_t>(*torus, volId, intersection);
0067 
0068     auto xtru = dynamic_cast<vecgeom::UnplacedSExtruVolume const *>(solid);
0069     if (xtru) return conv::CreateSExtrudedSurfaces<Real_t>(*xtru, volId, intersection);
0070 
0071     auto trd = dynamic_cast<vecgeom::UnplacedTrd const *>(solid);
0072     if (trd) return conv::CreateTrdSurfaces<Real_t>(*trd, volId, intersection);
0073 
0074     auto trap = dynamic_cast<vecgeom::UnplacedTrapezoid const *>(solid);
0075     if (trap) return conv::CreateTrapezoidSurfaces<Real_t>(*trap, volId, intersection);
0076 
0077     auto gentrap = dynamic_cast<vecgeom::UnplacedGenTrap const *>(solid);
0078     if (gentrap) return conv::CreateGenTrapSurfaces<Real_t>(*gentrap, volId);
0079 
0080     auto tet = dynamic_cast<vecgeom::UnplacedTet const *>(solid);
0081     if (tet) return conv::CreateTetSurfaces<Real_t>(*tet, volId, intersection);
0082 
0083     auto polyhedron = dynamic_cast<vecgeom::UnplacedPolyhedron const *>(solid);
0084     if (polyhedron) return conv::CreatePolyhedronSurfaces<Real_t>(*polyhedron, volId, intersection);
0085 
0086     auto scaled = dynamic_cast<vecgeom::UnplacedScaledShape const *>(solid);
0087     if (scaled) return conv::CreateScaledSurfaces<Real_t>(*scaled, volId, intersection);
0088 
0089     auto bstruct = vecgeom::BooleanHelper::GetBooleanStruct(solid);
0090     if (bstruct) return conv::CreateBooleanSurfaces<Real_t>(*bstruct, volId, intersection);
0091 
0092     auto sphere = dynamic_cast<vecgeom::UnplacedSphere const *>(solid);
0093     if (sphere) return conv::CreateSphereSurfaces<Real_t>(*sphere, volId, intersection);
0094 
0095     auto orb = dynamic_cast<vecgeom::UnplacedOrb const *>(solid);
0096     if (orb) return conv::CreateSphereSurfaces<Real_t>(*orb, volId, intersection);
0097 
0098     // Create a placeholder solid to allow execution to continue
0099     double capacity = solid->Capacity();
0100     VECGEOM_LOG(error) << "CreateSolidSurfaces: solid type not supported " << *solid << " replacing with sphere with equal capacity " << capacity;
0101     double radius = std::cbrt(capacity / (4.0 / 3.0 * 3.14159265358979323846));
0102     vecgeom::    UnplacedOrb temp_orb(radius);
0103     conv::CreateSphereSurfaces<Real_t>(temp_orb, volId, intersection);
0104 
0105     return false;
0106   };
0107 
0108   success = createSurfacesLocal(solid, volId, intersection);
0109 
0110   // If there is a local transformation, apply it to all surfaces
0111   if (success && localtrans) {
0112     auto isurf_last = shell.fSurfaces.size();
0113     for (size_t i = isurf_first; i < isurf_last; ++i) {
0114       auto &surf = cpudata.fLocalSurfaces[shell.fSurfaces[i]];
0115       TransformationMP<Real_t> trans(*localtrans);
0116       if (!surf.fTrans.IsIdentity()) {
0117         trans.MultiplyFromRight(surf.fTrans);
0118       }
0119       surf.fTrans = trans;
0120     }
0121   }
0122   return success;
0123 }
0124 
0125 /// @brief Converter for scaled solids
0126 /// @tparam Real_t Precision type
0127 /// @param scaled Scaled solid to be converted
0128 /// @param logical_id Id of the logical volume
0129 /// @return Conversion success
0130 template <typename Real_t>
0131 bool CreateScaledSurfaces(vecgeom::UnplacedScaledShape const &scaled, int logical_id, bool intersection)
0132 {
0133   auto const &vec_scale = scaled.GetScale().Scale();
0134   if (!ApproxEqualVector(vec_scale, vecgeom::Vector3D<vecgeom::Precision>{1, 1, -1})) {
0135     VECGEOM_LOG(error) << "UnplacedScaledShape having scale " << vec_scale << " not supported";
0136     return false;
0137   }
0138   auto success = CreateSolidSurfaces<Real_t>(scaled.UnscaledShape(), logical_id, /*localtrans=*/nullptr, intersection);
0139   // Reflect all framed surfaces held by the shell
0140   auto &cpudata     = CPUsurfData<Real_t>::Instance();
0141   auto const &shell = cpudata.fShells[logical_id];
0142   for (int lsurf_id : shell.fSurfaces) {
0143     FramedSurface<Precision, TransformationMP<Precision>> &lsurf = cpudata.fLocalSurfaces[lsurf_id];
0144     auto const &trans                                            = lsurf.fTrans;
0145     // Reflect the framed surface
0146     TransformationMP<Precision> scalez(0, 0, 0, 0, 0, 0, 1, 1, -1);
0147     TransformationMP<Precision> refl_trans = trans * scalez;
0148     lsurf.fTrans                           = refl_trans;
0149   }
0150   return success;
0151 }
0152 
0153 /// @brief Converter for Boolean solids
0154 /// @tparam Real_t Precision type
0155 /// @param bstruct Boolean structure to be converted
0156 /// @param logical_id Id of the logical volume
0157 /// @return Conversion success
0158 template <typename Real_t>
0159 bool CreateBooleanSurfaces(vecgeom::BooleanStruct const &bstruct, int logical_id, bool intersection)
0160 {
0161   TransformationMP<Real_t> trans;
0162   if (!AppendLogicTo<Real_t>(bstruct, trans, logical_id, intersection)) return false;
0163 
0164   auto &cpudata = CPUsurfData<Real_t>::Instance();
0165   // Finalize logic expression
0166   auto &crtlogic = cpudata.fShells[logical_id].fLogic;
0167   vgbrep::logichelper::LogicExpressionConstruct lc(crtlogic);
0168   lc.Simplify(crtlogic);
0169 
0170   // Assign logic id to each surface
0171   for (auto id : cpudata.fShells[logical_id].fSurfaces) {
0172     cpudata.fLocalSurfaces[id].fEmbedding = false;
0173     // Set the logic id for Boolean surfaces
0174     if (logichelper::is_negated(id, crtlogic))
0175       cpudata.fLocalSurfaces[id].fLogicId = -id;
0176     else
0177       cpudata.fLocalSurfaces[id].fLogicId = id;
0178   }
0179 
0180   vgbrep::logichelper::insert_jumps(crtlogic);
0181   cpudata.fShells[logical_id].fSimplified = true;
0182 
0183   return true;
0184 }
0185 
0186 template <typename Real_t>
0187 bool AppendLogicTo(vecgeom::BooleanStruct const &bstruct, TransformationMP<Real_t> const &trans, int logical_id,
0188                    bool intersection)
0189 {
0190   bool success  = true;
0191   auto &cpudata = CPUsurfData<Real_t>::Instance();
0192   auto &logic   = cpudata.fShells[logical_id].fLogic;
0193   intersection |= bstruct.fOp == vecgeom::kIntersection;
0194   // left node
0195   // open parenthesis
0196   logic.push_back(lplus);
0197   vecgeom::Transformation3DMP<Real_t> tr_left(trans);
0198   tr_left.MultiplyFromRight(*bstruct.fLeftVolume->GetTransformation());
0199   auto const unplaced_left = bstruct.fLeftVolume->GetUnplacedVolume();
0200   auto bstruct_left        = vecgeom::BooleanHelper::GetBooleanStruct(unplaced_left);
0201   if (bstruct_left)
0202     success = AppendLogicTo<Real_t>(*bstruct_left, tr_left, logical_id);
0203   else
0204     success = CreateSolidSurfaces<Real_t>(unplaced_left, logical_id, &tr_left, intersection);
0205   if (!success) return false;
0206   // close parenthesis
0207   logic.push_back(lminus);
0208 
0209   // operator
0210   switch (bstruct.fOp) {
0211   case vecgeom::kUnion:
0212     logic.push_back(lor);
0213     break;
0214   case vecgeom::kIntersection:
0215     logic.push_back(land);
0216     break;
0217   case vecgeom::kSubtraction:
0218     logic.push_back(land);
0219     logic.push_back(lnot);
0220     break;
0221   };
0222 
0223   // right node
0224   // open parenthesis
0225   logic.push_back(lplus);
0226   vecgeom::Transformation3DMP<Real_t> tr_right(trans);
0227   tr_right.MultiplyFromRight(*bstruct.fRightVolume->GetTransformation());
0228   auto const unplaced_right = bstruct.fRightVolume->GetUnplacedVolume();
0229   auto bstruct_right        = vecgeom::BooleanHelper::GetBooleanStruct(unplaced_right);
0230   if (bstruct_right)
0231     success = AppendLogicTo<Real_t>(*bstruct_right, tr_right, logical_id);
0232   else
0233     success = CreateSolidSurfaces<Real_t>(unplaced_right, logical_id, &tr_right, intersection);
0234   if (!success) return false;
0235   // close parenthesis
0236   logic.push_back(lminus);
0237   return true;
0238 }
0239 
0240 } // namespace conv
0241 } // namespace vgbrep
0242 #endif