File indexing completed on 2026-04-17 08:35:33
0001 #ifndef VECGEOM_SURFACE_POLYCONECONVERTER_H_
0002 #define VECGEOM_SURFACE_POLYCONECONVERTER_H_
0003
0004 #include <VecGeom/surfaces/conv/ConvHelper.h>
0005
0006 #include <VecGeom/volumes/Polycone.h>
0007
0008 namespace vgbrep {
0009 namespace conv {
0010
0011
0012
0013
0014
0015
0016 template <typename Real_t>
0017 bool CreatePolyconeSurfaces(vecgeom::UnplacedPolycone const &polycone, int logical_id, bool intersection = false)
0018 {
0019 using RingMask_t = RingMask<Real_t>;
0020 using ZPhiMask_t = ZPhiMask<Real_t>;
0021 using Vector3D = vecgeom::Vector3D<vecgeom::Precision>;
0022
0023 LogicExpressionCPU
0024 logic;
0025
0026 auto nSect = polycone.GetNSections();
0027 auto sphi = polycone.GetStartPhi();
0028 auto dphi = polycone.GetDeltaPhi();
0029 auto ephi = polycone.GetEndPhi();
0030 VECGEOM_ASSERT(dphi > vecgeom::kTolerance);
0031
0032 bool fullCirc = ApproxEqual(dphi, vecgeom::kTwoPi);
0033 bool smallerPi = dphi < (vecgeom::kPi - vecgeom::kTolerance);
0034
0035 int isurf;
0036 vecgeom::Precision surfdata[2];
0037
0038
0039 auto sphid = vecgeom::kRadToDeg * sphi;
0040 auto ephid = vecgeom::kRadToDeg * ephi;
0041
0042 vecgeom::Transformation3D transformation;
0043 std::vector<Vector3D> vert;
0044 auto csphi = std::cos(sphi);
0045 auto ssphi = std::sin(sphi);
0046 auto cephi = std::cos(ephi);
0047 auto sephi = std::sin(ephi);
0048
0049
0050 std::unique_ptr<vecgeom::Precision[]> zArray(new vecgeom::Precision[2 * nSect]);
0051 std::unique_ptr<vecgeom::Precision[]> rMinArray(new vecgeom::Precision[2 * nSect]);
0052 std::unique_ptr<vecgeom::Precision[]> rMaxArray(new vecgeom::Precision[2 * nSect]);
0053
0054 for (int i = 0; i < nSect; ++i) {
0055 rMinArray[2 * i] = polycone.GetRmin1AtSection(i);
0056 rMinArray[2 * i + 1] = polycone.GetRmin2AtSection(i);
0057 rMaxArray[2 * i] = polycone.GetRmax1AtSection(i);
0058 rMaxArray[2 * i + 1] = polycone.GetRmax2AtSection(i);
0059 }
0060
0061 zArray[0] = polycone.GetZAtPlane(0);
0062 for (int i = 1; i < nSect; ++i) {
0063 zArray[2 * i - 1] = polycone.GetZAtPlane(i);
0064 zArray[2 * i] = polycone.GetZAtPlane(i);
0065 }
0066 zArray[2 * nSect - 1] = polycone.GetZAtPlane(nSect);
0067
0068
0069 for (int i = 0; i < nSect; i++) {
0070 logic.push_back(lplus);
0071
0072 auto z1 = polycone.GetZAtPlane(i);
0073 auto z2 = polycone.GetZAtPlane(i + 1);
0074 auto rmin1 = polycone.GetRmin1AtSection(i);
0075 auto rmax1 = polycone.GetRmax1AtSection(i);
0076 auto rmin2 = polycone.GetRmin2AtSection(i);
0077 auto rmax2 = polycone.GetRmax2AtSection(i);
0078
0079 VECGEOM_ASSERT(rmax1 - rmin1 > -vecgeom::kTolerance);
0080 VECGEOM_ASSERT(rmax2 - rmin2 > -vecgeom::kTolerance);
0081
0082
0083
0084 if (rmax1 - rmin1 == vecgeom::kConeTolerance) rmax1 = rmin1 + vecgeom::kToleranceCone<Real_t>;
0085 if (rmax2 - rmin2 == vecgeom::kConeTolerance) rmax2 = rmin2 + vecgeom::kToleranceCone<Real_t>;
0086
0087
0088
0089
0090
0091
0092
0093 if (i > 0) {
0094 auto rmin_prev = polycone.GetRmin2AtSection(i - 1);
0095 auto rmax_prev = polycone.GetRmax2AtSection(i - 1);
0096
0097 bool has_inner_ring = rmin1 < rmin_prev - vecgeom::kTolerance;
0098 bool has_outer_ring = rmax1 > rmax_prev + vecgeom::kTolerance;
0099
0100 if (has_inner_ring) {
0101 isurf = builder::CreateLocalSurface<Real_t>(
0102 builder::CreateUnplacedSurface<Real_t>(SurfaceType::kPlanar),
0103 builder::CreateFrame<Real_t>(FrameType::kRing, RingMask_t{rmin1, rmin_prev, fullCirc, sphi, ephi}),
0104 vecgeom::Transformation3DMP<Precision>(0., 0., z1, 0., 180., -sphid - ephid));
0105 builder::GetSurface<Real_t>(isurf).fEmbedding = false;
0106 builder::AddSurfaceToShell<Real_t>(logical_id, isurf);
0107 if (intersection) builder::GetSurface<Real_t>(isurf).fSkipConvexity = true;
0108 logic.push_back(isurf);
0109 logic.push_back(land);
0110 }
0111 if (has_outer_ring) {
0112 isurf = builder::CreateLocalSurface<Real_t>(
0113 builder::CreateUnplacedSurface<Real_t>(SurfaceType::kPlanar),
0114 builder::CreateFrame<Real_t>(FrameType::kRing, RingMask_t{rmax_prev, rmax1, fullCirc, sphi, ephi}),
0115 vecgeom::Transformation3DMP<Precision>(0., 0., z1, 0., 180., -sphid - ephid));
0116 builder::GetSurface<Real_t>(isurf).fEmbedding = false;
0117 if (intersection) builder::GetSurface<Real_t>(isurf).fSkipConvexity = true;
0118 builder::AddSurfaceToShell<Real_t>(logical_id, isurf);
0119 logic.push_back(isurf);
0120 logic.push_back(land);
0121 }
0122
0123
0124 if (!has_inner_ring && !has_outer_ring) {
0125 isurf = builder::CreateLocalSurface<Real_t>(builder::CreateUnplacedSurface<Real_t>(SurfaceType::kPlanar),
0126 Frame{FrameType::kNoFrame},
0127 vecgeom::Transformation3DMP<Precision>(0., 0., z1, 0., 180., 0.));
0128 builder::AddSurfaceToShell<Real_t>(logical_id, isurf);
0129 if (intersection) builder::GetSurface<Real_t>(isurf).fSkipConvexity = true;
0130 logic.push_back(isurf);
0131 logic.push_back(land);
0132 }
0133 }
0134
0135 if (i < nSect - 1) {
0136 auto rmin_next = polycone.GetRmin1AtSection(i + 1);
0137 auto rmax_next = polycone.GetRmax1AtSection(i + 1);
0138
0139 bool has_inner_ring = rmin2 < rmin_next - vecgeom::kTolerance;
0140 bool has_outer_ring = rmax2 > rmax_next + vecgeom::kTolerance;
0141
0142 if (has_inner_ring) {
0143 isurf = builder::CreateLocalSurface<Real_t>(
0144 builder::CreateUnplacedSurface<Real_t>(SurfaceType::kPlanar),
0145 builder::CreateFrame<Real_t>(FrameType::kRing, RingMask_t{rmin2, rmin_next, fullCirc, sphi, ephi}),
0146 vecgeom::Transformation3DMP<Precision>(0., 0., z2, 0., 0., 0.));
0147 builder::AddSurfaceToShell<Real_t>(logical_id, isurf);
0148 if (intersection) builder::GetSurface<Real_t>(isurf).fSkipConvexity = true;
0149 builder::GetSurface<Real_t>(isurf).fEmbedding = false;
0150 logic.push_back(isurf);
0151 logic.push_back(land);
0152 }
0153 if (has_outer_ring) {
0154 isurf = builder::CreateLocalSurface<Real_t>(
0155 builder::CreateUnplacedSurface<Real_t>(SurfaceType::kPlanar),
0156 builder::CreateFrame<Real_t>(FrameType::kRing, RingMask_t{rmax_next, rmax2, fullCirc, sphi, ephi}),
0157 vecgeom::Transformation3DMP<Precision>(0., 0., z2, 0., 0., 0.));
0158 builder::AddSurfaceToShell<Real_t>(logical_id, isurf);
0159 if (intersection) builder::GetSurface<Real_t>(isurf).fSkipConvexity = true;
0160 builder::GetSurface<Real_t>(isurf).fEmbedding = false;
0161 logic.push_back(isurf);
0162 logic.push_back(land);
0163 }
0164
0165
0166 if (!has_inner_ring && !has_outer_ring) {
0167 isurf = builder::CreateLocalSurface<Real_t>(builder::CreateUnplacedSurface<Real_t>(SurfaceType::kPlanar),
0168 Frame{FrameType::kNoFrame},
0169 vecgeom::Transformation3DMP<Precision>(0., 0., z2, 0., 0., 0.));
0170 builder::AddSurfaceToShell<Real_t>(logical_id, isurf);
0171 if (intersection) builder::GetSurface<Real_t>(isurf).fSkipConvexity = true;
0172 logic.push_back(isurf);
0173 logic.push_back(land);
0174 }
0175 }
0176
0177
0178 if (i == 0) {
0179
0180 if (rmax1 - rmin1 > vecgeom::kTolerance) {
0181 isurf = builder::CreateLocalSurface<Real_t>(
0182 builder::CreateUnplacedSurface<Real_t>(SurfaceType::kPlanar),
0183 builder::CreateFrame<Real_t>(FrameType::kRing, RingMask_t{rmin1, rmax1, fullCirc, sphi, ephi}),
0184 vecgeom::Transformation3DMP<Precision>(0., 0., z1, 0., 180., -sphid - ephid));
0185 builder::AddSurfaceToShell<Real_t>(logical_id, isurf);
0186 builder::GetSurface<Real_t>(isurf).fEmbedding = false;
0187 if (intersection) builder::GetSurface<Real_t>(isurf).fSkipConvexity = true;
0188 logic.push_back(isurf);
0189 logic.push_back(land);
0190 }
0191 }
0192
0193
0194 if (i == nSect - 1) {
0195
0196 if (rmax1 - rmin1 > vecgeom::kTolerance) {
0197 isurf = builder::CreateLocalSurface<Real_t>(
0198 builder::CreateUnplacedSurface<Real_t>(SurfaceType::kPlanar),
0199 builder::CreateFrame<Real_t>(FrameType::kRing, RingMask_t{rmin2, rmax2, fullCirc, sphi, ephi}),
0200 vecgeom::Transformation3DMP<Precision>(0., 0., z2, 0., 0., 0.));
0201 builder::AddSurfaceToShell<Real_t>(logical_id, isurf);
0202 builder::GetSurface<Real_t>(isurf).fEmbedding = false;
0203 if (intersection) builder::GetSurface<Real_t>(isurf).fSkipConvexity = true;
0204 logic.push_back(isurf);
0205 logic.push_back(land);
0206 }
0207 }
0208
0209
0210 const Real_t z_shift = 0.5 * (z1 + z2);
0211
0212 if (rmin2 > vecgeom::kTolerance || rmin1 > vecgeom::kTolerance) {
0213 surfdata[0] = 0.5 * (rmin1 + rmin2);
0214 surfdata[1] = (rmin2 - rmin1) / (z2 - z1);
0215 auto stype = std::abs(surfdata[1]) > vecgeom::kTolerance ? SurfaceType::kConical : SurfaceType::kCylindrical;
0216 isurf = builder::CreateLocalSurface<Real_t>(
0217 builder::CreateUnplacedSurface<Real_t>(stype, surfdata, true),
0218 builder::CreateFrame<Real_t>(FrameType::kZPhi,
0219 ZPhiMask_t{z1 - z_shift, z2 - z_shift, fullCirc, rmin1, rmin2, sphi, ephi}),
0220 vecgeom::Transformation3DMP<Precision>(0., 0., z_shift, 0., 0., 0.));
0221 builder::AddSurfaceToShell<Real_t>(logical_id, isurf);
0222
0223 auto is_convex = IsConvexConcave<vecgeom::Precision>(2 * i, zArray, rMinArray, 1, 2 * nSect);
0224 if (!(is_convex)) builder::GetSurface<Real_t>(isurf).fEmbedding = false;
0225 if (intersection)
0226 builder::GetSurface<Real_t>(isurf).fSkipConvexity =
0227 true;
0228
0229 logic.push_back(isurf);
0230 logic.push_back(land);
0231 }
0232
0233 surfdata[0] = 0.5 * (rmax1 + rmax2);
0234 surfdata[1] = (rmax2 - rmax1) / (z2 - z1);
0235 auto stype = std::abs(surfdata[1]) > vecgeom::kTolerance ? SurfaceType::kConical : SurfaceType::kCylindrical;
0236 isurf = builder::CreateLocalSurface<Real_t>(
0237 builder::CreateUnplacedSurface<Real_t>(stype, surfdata),
0238 builder::CreateFrame<Real_t>(FrameType::kZPhi,
0239 ZPhiMask_t{z1 - z_shift, z2 - z_shift, fullCirc, rmax1, rmax2, sphi, ephi}),
0240 vecgeom::Transformation3DMP<Precision>(0., 0., z_shift, 0., 0., 0.));
0241 builder::AddSurfaceToShell<Real_t>(logical_id, isurf);
0242
0243 auto is_concave = IsConvexConcave<vecgeom::Precision>(2 * i, zArray, rMaxArray, 0, 2 * nSect);
0244 if (!(is_concave)) builder::GetSurface<Real_t>(isurf).fEmbedding = false;
0245 if (intersection) builder::GetSurface<Real_t>(isurf).fSkipConvexity = true;
0246 logic.push_back(isurf);
0247
0248 if (!fullCirc) {
0249
0250 std::vector<Vector3D> corners = {{rmin1 * csphi, rmin1 * ssphi, z1}, {rmax1 * csphi, rmax1 * ssphi, z1},
0251 {rmax2 * csphi, rmax2 * ssphi, z2}, {rmin2 * csphi, rmin2 * ssphi, z2},
0252 {rmax1 * cephi, rmax1 * sephi, z1}, {rmin1 * cephi, rmin1 * sephi, z1},
0253 {rmin2 * cephi, rmin2 * sephi, z2}, {rmax2 * cephi, rmax2 * sephi, z2}};
0254
0255
0256 vert = {corners[0], corners[1], corners[2], corners[3]};
0257 isurf = builder::CreateLocalSurfaceFromVertices<Real_t>(vert, logical_id);
0258 if (intersection) builder::GetSurface<Real_t>(isurf).fSkipConvexity = true;
0259 VECGEOM_ASSERT(isurf >= 0);
0260 builder::GetSurface<Real_t>(isurf).fEmbedding = false;
0261 logic.push_back(land);
0262 logic.push_back(lplus);
0263 logic.push_back(isurf);
0264
0265
0266 vert = {corners[4], corners[5], corners[6], corners[7]};
0267 isurf = builder::CreateLocalSurfaceFromVertices<Real_t>(vert, logical_id);
0268 if (intersection) builder::GetSurface<Real_t>(isurf).fSkipConvexity = true;
0269 VECGEOM_ASSERT(isurf >= 0);
0270 builder::GetSurface<Real_t>(isurf).fEmbedding = false;
0271 logic.push_back(smallerPi ? land : lor);
0272 logic.push_back(isurf);
0273 logic.push_back(lminus);
0274 }
0275
0276 logic.push_back(lminus);
0277 if (i < nSect - 1) logic.push_back(lor);
0278 }
0279 builder::AddLogicToShell<Real_t>(logical_id, logic);
0280
0281 return true;
0282 }
0283
0284 }
0285 }
0286 #endif