File indexing completed on 2026-04-17 08:35:36
0001
0002 #ifndef VECGEOM_SURFACE_LOGICEVALUATOR_H
0003 #define VECGEOM_SURFACE_LOGICEVALUATOR_H
0004
0005 #include <VecGeom/surfaces/Model.h>
0006
0007 namespace vgbrep {
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017 template <typename Real_t>
0018 VECCORE_ATT_HOST_DEVICE bool EvaluateInside(vecgeom::Vector3D<Real_t> const &plocalVol, int volId,
0019 LogicExpression const &logic, SurfData<Real_t> const &surfdata,
0020 const int logic_id = vecgeom::kMaximumInt, const bool is_inside = 0)
0021 {
0022 auto test_bit = [](unsigned bset, int bit) { return (bset & (unsigned(1) << bit)) > 0; };
0023 auto set_bit = [](unsigned &bset, int bit) { bset |= unsigned(1) << bit; };
0024 auto reset_bit = [](unsigned &bset, int bit) { bset &= ~(unsigned(1) << bit); };
0025 auto swap_bit = [](unsigned &bset, int bit) { bset ^= unsigned(1) << bit; };
0026
0027 auto insideSurf = [&](int isurf, bool flip) {
0028
0029 auto itrans = surfdata.fLocalSurf[isurf].fTrans;
0030 Vector3D<Real_t> plocalSurf = itrans.Transform(plocalVol);
0031 auto const &unplaced = surfdata.fLocalSurf[isurf].fSurface;
0032 return unplaced.Inside(plocalSurf, surfdata, flip);
0033 };
0034 unsigned stack = 0;
0035 unsigned negate = 0;
0036 int depth = 0;
0037 bool result = false;
0038 unsigned i;
0039 for (i = 0; i < logic.size(); ++i) {
0040 switch (logic[i]) {
0041 case lplus:
0042 depth++;
0043 break;
0044 case lminus:
0045 result = test_bit(stack, depth);
0046 reset_bit(negate, depth--);
0047 result ^= test_bit(negate, depth);
0048 if (result)
0049 set_bit(stack, depth);
0050 else
0051 reset_bit(stack, depth);
0052 break;
0053 case lnot:
0054 swap_bit(negate, depth);
0055 break;
0056 case lor:
0057 if (test_bit(stack, depth))
0058 i = logic[i + 1] - 1;
0059 else
0060 i++;
0061 break;
0062 case land:
0063 if (!test_bit(stack, depth))
0064 i = logic[i + 1] - 1;
0065 else
0066 i++;
0067 break;
0068 default:
0069
0070 result = logic[i] == std::abs(logic_id) ? is_inside ^ bool(negate) : insideSurf(int(logic[i]), bool(negate));
0071 result ^= test_bit(negate, depth);
0072 reset_bit(negate, depth);
0073
0074 if (result)
0075 set_bit(stack, depth);
0076 else
0077 reset_bit(stack, depth);
0078 }
0079 }
0080 VECGEOM_ASSERT(depth == 0);
0081 return (stack & 1) > 0;
0082 }
0083
0084
0085
0086
0087
0088
0089
0090 template <typename Real_t>
0091 VECCORE_ATT_HOST_DEVICE Real_t EvaluateSafety(vecgeom::Vector3D<Real_t> const &plocalVol, int volId, bool exiting,
0092 LogicExpression const &logic, SurfData<Real_t> const &surfdata,
0093 Real_t safe_max = vecgeom::InfinityLength<Real_t>())
0094 {
0095 struct Safetyval {
0096 vecgeom::Vector3D<Real_t> onsurf;
0097 Real_t safety{0.};
0098 short int isurf{-1};
0099 char op{0};
0100
0101 VECCORE_ATT_HOST_DEVICE
0102 VECGEOM_FORCE_INLINE
0103 void Reset()
0104 {
0105 safety = 0.;
0106 isurf = -1;
0107 op = 0;
0108 }
0109
0110
0111 VECCORE_ATT_HOST_DEVICE
0112 VECGEOM_FORCE_INLINE
0113 void SwapReduction(const Safetyval &other)
0114 {
0115
0116 auto crt_op = op;
0117 op = 0;
0118
0119 if (other.isurf < 0) return;
0120 if (isurf < 0) {
0121 operator=(other);
0122 return;
0123 }
0124 VECGEOM_ASSERT(crt_op != 0);
0125
0126 if ((crt_op > 0) ^ (safety > other.safety)) {
0127
0128 safety = other.safety;
0129 onsurf = other.onsurf;
0130 isurf = other.isurf;
0131 }
0132 }
0133 };
0134
0135
0136 auto safetySurf = [&](Safetyval &safety_surf) {
0137
0138 auto trans = surfdata.fLocalSurf[safety_surf.isurf].fTrans;
0139 Vector3D<Real_t> local = trans.Transform(plocalVol);
0140 auto const &framedsurf = surfdata.fLocalSurf[safety_surf.isurf];
0141 bool flipped = framedsurf.fLogicId < 0;
0142 auto const &unplaced = framedsurf.fSurface;
0143 unplaced.Safety(local, flipped, surfdata, safety_surf.safety, safety_surf.onsurf);
0144 };
0145
0146 auto safetyFrame = [&](Safetyval &safety_surf) {
0147
0148 auto const &framedsurf = surfdata.fLocalSurf[safety_surf.isurf];
0149 bool valid = false;
0150 auto safety = framedsurf.fFrame.Safety(safety_surf.onsurf, safety_surf.safety, surfdata, valid);
0151 if (valid) safety_surf.safety = safety;
0152 };
0153
0154
0155
0156
0157
0158
0159
0160
0161
0162
0163
0164
0165
0166
0167
0168
0169
0170
0171
0172
0173
0174
0175
0176
0177 constexpr int kStackSize = 8;
0178 Safetyval cached_safety[kStackSize];
0179 Safetyval crt_safety;
0180
0181 int depth = 0;
0182 unsigned i;
0183 for (i = 0; i < logic.size(); ++i) {
0184 auto item = logic[i];
0185 if (item == lplus) {
0186
0187 cached_safety[depth++] = crt_safety;
0188 crt_safety.Reset();
0189 } else if (item == lminus) {
0190
0191 depth--;
0192 VECGEOM_ASSERT(depth >= 0);
0193 crt_safety.op = cached_safety[depth].op;
0194 crt_safety.SwapReduction(cached_safety[depth]);
0195 } else if (item == lnot) {
0196
0197 } else if (LogicExpression::is_operator_token(item)) {
0198 crt_safety.op = (item == land) ? 1 : -1;
0199 i++;
0200 } else {
0201
0202 Safetyval new_safety;
0203 new_safety.isurf = short(item);
0204 safetySurf(new_safety);
0205 crt_safety.SwapReduction(new_safety);
0206 }
0207 }
0208 VECGEOM_ASSERT(depth == 0);
0209 if (exiting) crt_safety.safety = -crt_safety.safety;
0210
0211 if (crt_safety.safety > 0. && crt_safety.safety <= safe_max) safetyFrame(crt_safety);
0212 return crt_safety.safety;
0213 }
0214
0215 }
0216 #endif