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
0029
0030
0031
0032
0033
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
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
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
0126
0127
0128
0129
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, nullptr, intersection);
0139
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
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
0154
0155
0156
0157
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
0166 auto &crtlogic = cpudata.fShells[logical_id].fLogic;
0167 vgbrep::logichelper::LogicExpressionConstruct lc(crtlogic);
0168 lc.Simplify(crtlogic);
0169
0170
0171 for (auto id : cpudata.fShells[logical_id].fSurfaces) {
0172 cpudata.fLocalSurfaces[id].fEmbedding = false;
0173
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
0195
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
0207 logic.push_back(lminus);
0208
0209
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
0224
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
0236 logic.push_back(lminus);
0237 return true;
0238 }
0239
0240 }
0241 }
0242 #endif