File indexing completed on 2026-09-09 09:27:33
0001
0002
0003
0004 #ifndef VECGEOM_VOLUMES_KERNEL_GENERICPOLYCONEIMPLEMENTATION_H_
0005 #define VECGEOM_VOLUMES_KERNEL_GENERICPOLYCONEIMPLEMENTATION_H_
0006
0007 #include "VecGeom/base/Vector3D.h"
0008 #include "VecGeom/volumes/GenericPolyconeStruct.h"
0009 #include "VecGeom/volumes/kernel/GenericKernels.h"
0010 #include <VecCore/VecCore>
0011 #include "VecGeom/volumes/kernel/CoaxialConesImplementation.h"
0012 #include "VecGeom/volumes/kernel/shapetypes/ConeTypes.h"
0013
0014 #include <cstdio>
0015
0016 namespace vecgeom {
0017
0018 VECGEOM_DEVICE_FORWARD_DECLARE(struct GenericPolyconeImplementation;);
0019 VECGEOM_DEVICE_DECLARE_CONV(struct, GenericPolyconeImplementation);
0020
0021 inline namespace VECGEOM_IMPL_NAMESPACE {
0022
0023 class PlacedGenericPolycone;
0024 template <typename T>
0025 struct GenericPolyconeStruct;
0026 class UnplacedGenericPolycone;
0027
0028 struct GenericPolyconeImplementation {
0029
0030 using PlacedShape_t = PlacedGenericPolycone;
0031 using UnplacedStruct_t = GenericPolyconeStruct<Precision>;
0032 using UnplacedVolume_t = UnplacedGenericPolycone;
0033
0034 template <typename Real_v, bool ForInside>
0035 VECGEOM_FORCE_INLINE VECCORE_ATT_HOST_DEVICE static void GenericKernelForASection(
0036 UnplacedStruct_t const &unplaced, int isect, Vector3D<Real_v> const &polyconePoint,
0037 typename vecCore::Mask_v<Real_v> &secFullyInside, typename vecCore::Mask_v<Real_v> &secFullyOutside)
0038 {
0039
0040 using namespace ConeTypes;
0041
0042 if (isect < 0) {
0043 secFullyInside = false;
0044 secFullyOutside = true;
0045 return;
0046 }
0047
0048 GenericPolyconeSection const &sec = unplaced.GetSection(isect);
0049 Vector3D<Precision> secLocalp = polyconePoint - Vector3D<Precision>(0, 0, sec.fShift);
0050 #ifdef POLYCONEDEBUG
0051 std::cerr << " isect=" << isect << "/" << unplaced.GetNSections() << " secLocalP=" << secLocalp
0052 << ", secShift=" << sec.fShift << " sec.fSolid=" << sec.fSolid << std::endl;
0053 if (sec.fSolid) sec.fSolid->Print();
0054 #endif
0055
0056 CoaxialConesImplementation::template GenericKernelForContainsAndInside<Real_v, typename vecCore::Mask_v<Real_v>,
0057 ForInside>(*sec.fCoaxialCones, secLocalp,
0058 secFullyInside, secFullyOutside);
0059 }
0060
0061 template <typename Real_v, typename Bool_v>
0062 VECGEOM_FORCE_INLINE VECCORE_ATT_HOST_DEVICE static void Contains(UnplacedStruct_t const &genericPolycone,
0063 Vector3D<Real_v> const &point, Bool_v &inside)
0064 {
0065 Bool_v unused(false), outside(false);
0066 GenericKernelForContainsAndInside<Real_v, Bool_v, false>(genericPolycone, point, unused, outside);
0067 inside = !outside;
0068 }
0069
0070
0071
0072 template <typename Real_v, typename Inside_t>
0073 VECGEOM_FORCE_INLINE VECCORE_ATT_HOST_DEVICE static void Inside(UnplacedStruct_t const &genericPolycone,
0074 Vector3D<Real_v> const &point, Inside_t &inside)
0075 {
0076
0077 using Bool_v = vecCore::Mask_v<Real_v>;
0078 using InsideBool_v = vecCore::Mask_v<Inside_t>;
0079 Bool_v completelyinside(false), completelyoutside(false);
0080 GenericKernelForContainsAndInside<Real_v, Bool_v, true>(genericPolycone, point, completelyinside,
0081 completelyoutside);
0082 inside = EInside::kSurface;
0083 vecCore::MaskedAssign(inside, (InsideBool_v)completelyoutside, Inside_t(EInside::kOutside));
0084 vecCore::MaskedAssign(inside, (InsideBool_v)completelyinside, Inside_t(EInside::kInside));
0085 }
0086
0087 template <typename Real_v, typename Bool_v, bool ForInside>
0088 VECGEOM_FORCE_INLINE VECCORE_ATT_HOST_DEVICE static void GenericKernelForContainsAndInside(
0089 UnplacedStruct_t const &unplaced, Vector3D<Real_v> const &localPoint, Bool_v &completelyInside,
0090 Bool_v &completelyOutside)
0091 {
0092
0093
0094
0095
0096
0097
0098
0099
0100
0101
0102 typedef Bool_v Bool_t;
0103
0104 int indexLow = unplaced.GetSectionIndex(localPoint.z() - kTolerance);
0105 int indexHigh = unplaced.GetSectionIndex(localPoint.z() + kTolerance);
0106 if (indexLow < 0 && indexHigh < 0) {
0107 completelyOutside = true;
0108 return;
0109 }
0110 if (indexLow < 0 && indexHigh == 0) {
0111
0112 GenericKernelForASection<Real_v, ForInside>(unplaced, 0, localPoint, completelyInside, completelyOutside);
0113 return;
0114 }
0115 if (indexHigh < 0 && indexLow == (unplaced.GetNSections() - 1)) {
0116
0117 GenericKernelForASection<Real_v, ForInside>(unplaced, (unplaced.GetNSections() - 1), localPoint, completelyInside,
0118 completelyOutside);
0119
0120 return;
0121 }
0122 if (indexLow >= 0 && indexHigh >= 0) {
0123 if (indexLow == indexHigh) {
0124
0125 GenericKernelForASection<Real_v, ForInside>(unplaced, indexLow, localPoint, completelyInside,
0126 completelyOutside);
0127
0128 return;
0129 } else {
0130
0131 Bool_t secInLow = false, secOutLow = false;
0132 Bool_t secInHigh = false, secOutHigh = false;
0133
0134 GenericPolyconeSection const §ionLow = unplaced.GetSection(indexLow);
0135 GenericPolyconeSection const §ionHigh = unplaced.GetSection(indexHigh);
0136
0137 Bool_t onRing(false);
0138 onRing |= (CoaxialConesImplementation::template IsOnRing<Real_v, false>(
0139 *sectionLow.fCoaxialCones, localPoint - Vector3D<Precision>(0, 0, sectionLow.fShift)) ||
0140 CoaxialConesImplementation::template IsOnRing<Real_v, true>(
0141 *sectionHigh.fCoaxialCones, localPoint - Vector3D<Precision>(0, 0, sectionHigh.fShift)));
0142
0143 GenericKernelForASection<Real_v, ForInside>(unplaced, indexLow, localPoint, secInLow, secOutLow);
0144 GenericKernelForASection<Real_v, ForInside>(unplaced, indexHigh, localPoint, secInHigh, secOutHigh);
0145 Bool_t surfLow = !secInLow && !secOutLow;
0146 Bool_t surfHigh = !secInHigh && !secOutHigh;
0147
0148 if (surfLow && surfHigh) {
0149 completelyInside = !onRing;
0150 return;
0151 } else {
0152
0153
0154
0155
0156
0157
0158 if (secOutLow && secOutHigh) {
0159 completelyOutside = true;
0160 return;
0161 }
0162 }
0163 }
0164 }
0165 }
0166
0167 template <typename Real_v>
0168 VECGEOM_FORCE_INLINE VECCORE_ATT_HOST_DEVICE static void DistanceToIn(UnplacedStruct_t const &polycone,
0169 Vector3D<Real_v> const &point,
0170 Vector3D<Real_v> const &direction,
0171 Real_v const &stepMax, Real_v &distance)
0172 {
0173
0174 Vector3D<Real_v> p = point;
0175 Vector3D<Real_v> v = direction;
0176
0177 #ifdef POLYCONEDEBUG
0178 std::cerr << "Polycone::DistToIn() (spot 1): point=" << point << ", dir=" << direction << ", localPoint=" << p
0179 << ", localDir=" << v << "\n";
0180 #endif
0181
0182
0183
0184 distance = kInfLength;
0185 int increment = (v.z() > 0) ? 1 : -1;
0186 if (std::fabs(v.z()) < kTolerance) increment = 0;
0187 int index = polycone.GetSectionIndex(p.z());
0188 if (index == -1) index = 0;
0189 if (index == -2) index = polycone.GetNSections() - 1;
0190
0191 do {
0192
0193 GenericPolyconeSection const &sec = polycone.GetSection(index);
0194
0195 #ifdef POLYCONEDEBUG
0196 std::cerr << "Polycone::DistToIn() (spot 2):"
0197 << " index=" << index << " NSec=" << polycone.GetNSections() << " &sec=" << &sec << " - secPars:"
0198 << " secOffset=" << sec.fShift << " Dz=" << sec.fSolid->GetDz() << " Rmin1=" << sec.fSolid->GetRmin1()
0199 << " Rmin2=" << sec.fSolid->GetRmin2() << " Rmax1=" << sec.fSolid->GetRmax1()
0200 << " Rmax2=" << sec.fSolid->GetRmax2() << " -- calling Cone::DistToIn()...\n";
0201 #endif
0202
0203 CoaxialConesImplementation::template DistanceToIn<Real_v>(
0204 *sec.fCoaxialCones, p - Vector3D<Precision>(0, 0, sec.fShift), v, stepMax, distance);
0205
0206 #ifdef POLYCONEDEBUG
0207 std::cerr << "Polycone::DistToIn() (spot 3):"
0208 << " distToIn() = " << distance << "\n";
0209 #endif
0210
0211 if (distance < kInfLength || !increment) break;
0212 index += increment;
0213 } while (index >= 0 && index < polycone.GetNSections());
0214 return;
0215 }
0216
0217 template <typename Real_v>
0218 VECGEOM_FORCE_INLINE VECCORE_ATT_HOST_DEVICE static void DistanceToOut(UnplacedStruct_t const &polycone,
0219 Vector3D<Real_v> const &point,
0220 Vector3D<Real_v> const &dir,
0221 Real_v const &stepMax, Real_v &distance)
0222 {
0223 distance = kInfLength;
0224 Vector3D<Real_v> pn = point;
0225 Precision dist = 0.;
0226 int increment = (dir.z() > 0) ? 1 : -1;
0227
0228
0229 if (polycone.GetNSections() == 1) {
0230 const GenericPolyconeSection §ion = polycone.GetSection(0);
0231
0232 CoaxialConesImplementation::template DistanceToOut<Real_v>(
0233 *section.fCoaxialCones, point - Vector3D<Precision>(0, 0, section.fShift), dir, stepMax, distance);
0234
0235 return;
0236 }
0237
0238 int indexLow = polycone.GetSectionIndex(point.z() - kTolerance);
0239 int indexHigh = polycone.GetSectionIndex(point.z() + kTolerance);
0240 int index = 0;
0241 if (indexLow < 0 && indexHigh < 0) {
0242 distance = -1;
0243 return;
0244 }
0245
0246 if (indexLow < 0 && indexHigh >= 0 && dir.z() < 0.) {
0247 index = indexHigh;
0248 const GenericPolyconeSection §ion = polycone.GetSection(index);
0249 CoaxialConesImplementation::template DistanceToOut<Real_v>(*section.fCoaxialCones, pn, dir, stepMax, dist);
0250 distance = dist;
0251 return;
0252 }
0253
0254 if (indexLow > 0 && indexHigh < 0 && dir.z() > 0.) {
0255 index = indexLow;
0256 const GenericPolyconeSection §ion = polycone.GetSection(index);
0257 CoaxialConesImplementation::template DistanceToOut<Real_v>(*section.fCoaxialCones, pn, dir, stepMax, dist);
0258 distance = dist;
0259 return;
0260 }
0261
0262 Inside_t inside;
0263 Precision totalDistance = 0.;
0264 int count = 0;
0265 do {
0266
0267 if (indexLow >= 0 && indexHigh >= 0) {
0268 count++;
0269 index = indexLow;
0270 const GenericPolyconeSection §ion = polycone.GetSection(index);
0271 pn.z() -= section.fShift;
0272 CoaxialConesImplementation::template Inside<Real_v>(*section.fCoaxialCones, pn, inside);
0273 if (inside == EInside::kOutside) {
0274 if (count == 1) {
0275 distance = -1;
0276 return;
0277 } else {
0278 distance = totalDistance;
0279 return;
0280 }
0281 } else {
0282 CoaxialConesImplementation::template DistanceToOut<Real_v>(*section.fCoaxialCones, pn, dir, stepMax, dist);
0283 if (dist < 0.) break;
0284 totalDistance += dist;
0285 pn += dir * dist;
0286 pn.z() += section.fShift;
0287 }
0288 indexLow += increment;
0289 indexHigh += increment;
0290 }
0291 } while (indexLow > -1 && indexLow < polycone.GetNSections());
0292 distance = totalDistance;
0293 return;
0294 }
0295
0296 template <typename Real_v>
0297 VECGEOM_FORCE_INLINE VECCORE_ATT_HOST_DEVICE static void SafetyToIn(UnplacedStruct_t const &polycone,
0298 Vector3D<Real_v> const &point, Real_v &safety)
0299 {
0300
0301 Vector3D<Real_v> p = point;
0302 int index = polycone.GetSectionIndex(p.z());
0303
0304 bool needZ = false;
0305 if (index < 0) {
0306 needZ = true;
0307 if (index == -1) index = 0;
0308 if (index == -2) index = polycone.GetNSections() - 1;
0309 }
0310 Precision minSafety = 0;
0311 GenericPolyconeSection const &sec = polycone.GetSection(index);
0312
0313 if (needZ) {
0314 CoaxialConesImplementation::template SafetyToIn<Real_v>(*sec.fCoaxialCones,
0315 p - Vector3D<Precision>(0, 0, sec.fShift), safety);
0316 } else
0317
0318 CoaxialConesImplementation::template SafetyToIn<Real_v>(*sec.fCoaxialCones,
0319 p - Vector3D<Precision>(0, 0, sec.fShift), safety);
0320
0321 if (safety < kTolerance) return;
0322 minSafety = safety;
0323 Precision zbase = polycone.fZs[index + 1];
0324
0325 for (int i = index + 1; i < polycone.GetNSections(); ++i) {
0326 Precision dz = polycone.fZs[i] - zbase;
0327 if (dz >= minSafety) break;
0328
0329 GenericPolyconeSection const § = polycone.GetSection(i);
0330 CoaxialConesImplementation::template SafetyToIn<Real_v>(*sect.fCoaxialCones,
0331 p - Vector3D<Precision>(0, 0, sect.fShift), safety);
0332 if (safety < minSafety) minSafety = safety;
0333 }
0334
0335
0336 if (index > 0) {
0337 zbase = polycone.fZs[index - 1];
0338 for (int i = index - 1; i >= 0; --i) {
0339 Precision dz = zbase - polycone.fZs[i];
0340 if (dz >= minSafety) break;
0341 GenericPolyconeSection const § = polycone.GetSection(i);
0342
0343 CoaxialConesImplementation::template SafetyToIn<Real_v>(*sect.fCoaxialCones,
0344 p - Vector3D<Precision>(0, 0, sect.fShift), safety);
0345
0346 if (safety < minSafety) minSafety = safety;
0347 }
0348 }
0349 safety = minSafety;
0350
0351 return;
0352 }
0353
0354 template <typename Real_v>
0355 VECGEOM_FORCE_INLINE VECCORE_ATT_HOST_DEVICE static void SafetyToOut(UnplacedStruct_t const &polycone,
0356 Vector3D<Real_v> const &point, Real_v &safety)
0357 {
0358 typedef typename vecCore::Mask_v<Real_v> Bool_v;
0359 Bool_v compIn(false), compOut(false);
0360 GenericKernelForContainsAndInside<Real_v, Bool_v, true>(polycone, point, compIn, compOut);
0361 if (compOut) {
0362 safety = -1;
0363 return;
0364 }
0365
0366 if (!compIn && !compOut) {
0367 safety = 0.;
0368 return;
0369 }
0370
0371 int index = polycone.GetSectionIndex(point.z());
0372 if (index < 0) {
0373 safety = -1;
0374 return;
0375 }
0376
0377 GenericPolyconeSection const &sec = polycone.GetSection(index);
0378
0379 Vector3D<Real_v> p = point - Vector3D<Precision>(0, 0, sec.fShift);
0380 CoaxialConesImplementation::template SafetyToOut<Real_v>(*sec.fCoaxialCones, p, safety);
0381
0382 Precision minSafety = safety;
0383 if (minSafety == kInfLength) {
0384 safety = 0.;
0385 return;
0386 }
0387 if (minSafety < kTolerance) {
0388 safety = 0.;
0389 return;
0390 }
0391
0392 Precision zbase = polycone.fZs[index + 1];
0393 for (int i = index + 1; i < polycone.GetNSections(); ++i) {
0394 Precision dz = polycone.fZs[i] - zbase;
0395 if (dz >= minSafety) break;
0396 GenericPolyconeSection const § = polycone.GetSection(i);
0397 p = point - Vector3D<Precision>(0, 0, sect.fShift);
0398
0399 CoaxialConesImplementation::template SafetyToIn<Real_v>(*sect.fCoaxialCones, p, safety);
0400
0401 if (safety < minSafety) minSafety = safety;
0402 }
0403
0404 if (index > 0) {
0405 zbase = polycone.fZs[index - 1];
0406 for (int i = index - 1; i >= 0; --i) {
0407 Precision dz = zbase - polycone.fZs[i];
0408 if (dz >= minSafety) break;
0409 GenericPolyconeSection const § = polycone.GetSection(i);
0410 p = point - Vector3D<Precision>(0, 0, sect.fShift);
0411
0412 CoaxialConesImplementation::template SafetyToIn<Real_v>(*sect.fCoaxialCones, p, safety);
0413
0414 if (safety < minSafety) minSafety = safety;
0415 }
0416 }
0417
0418 safety = minSafety;
0419 return;
0420 }
0421 };
0422 }
0423 }
0424
0425 #endif