File indexing completed on 2026-04-17 08:35:36
0001 #ifndef VECGEOM_ARB4_IMPL_H
0002 #define VECGEOM_ARB4_IMPL_H
0003
0004 #include <VecGeom/surfaces/surf/SurfaceHelper.h>
0005 #include <VecGeom/surfaces/base/Equations.h>
0006
0007 namespace vgbrep {
0008
0009 template <typename Real_t>
0010 struct SurfaceHelper<SurfaceType::kArb4, Real_t> {
0011 Arb4Data<Real_t> const *fArb4Data{nullptr};
0012
0013 VECGEOM_FORCE_INLINE
0014 VECCORE_ATT_HOST_DEVICE
0015 SurfaceHelper(Arb4Data<Real_t> const &arbdata) { fArb4Data = &arbdata; }
0016
0017
0018
0019
0020 void Extent3D(Vector3D<Real_t> &aMin, Vector3D<Real_t> &aMax) const
0021 {
0022 Real_t dz = fArb4Data->halfH;
0023 aMin.Set(fArb4Data->verticesX[0], fArb4Data->verticesY[0], -dz);
0024 aMax = aMin;
0025 for (auto i = 0; i < 4; ++i) {
0026 aMin = vecCore::math::Min(aMin, Vector3D<Real_t>(fArb4Data->verticesX[i], fArb4Data->verticesY[i], -dz));
0027 aMax = vecCore::math::Max(aMax, Vector3D<Real_t>(fArb4Data->verticesX[i], fArb4Data->verticesY[i], -dz));
0028 aMin = vecCore::math::Min(aMin, Vector3D<Real_t>(fArb4Data->verticesX[i], fArb4Data->verticesY[i], dz));
0029 aMax = vecCore::math::Max(aMax, Vector3D<Real_t>(fArb4Data->verticesX[i], fArb4Data->verticesY[i], dz));
0030 }
0031 }
0032
0033 VECGEOM_FORCE_INLINE
0034 VECCORE_ATT_HOST_DEVICE
0035
0036
0037
0038
0039
0040 bool Inside(Vector3D<Real_t> const &point, bool flip, Real_t tol = vecgeom::kToleranceStrict<Real_t>)
0041 {
0042 Real_t dz = fArb4Data->halfH;
0043 Real_t dz_inv = fArb4Data->halfH_inv;
0044
0045
0046 Real_t cf = 0.5 * dz_inv * (dz - point.z());
0047
0048
0049 Real_t vertexX[2];
0050 Real_t vertexY[2];
0051
0052 for (int i = 0; i < 2; i++) {
0053
0054 vertexX[i] = fArb4Data->verticesX[i + 2] + cf * fArb4Data->connecting_compX[i];
0055 vertexY[i] = fArb4Data->verticesY[i + 2] + cf * fArb4Data->connecting_compY[i];
0056 }
0057
0058 Real_t dx = vertexX[1] - vertexX[0];
0059 Real_t dy = vertexY[1] - vertexY[0];
0060 Real_t px = point.x() - vertexX[0];
0061 Real_t py = point.y() - vertexY[0];
0062
0063 int sign = !flip ? -1 : 1;
0064 return (dx * py - dy * px) > sign * tol;
0065 }
0066
0067 VECGEOM_FORCE_INLINE
0068 VECCORE_ATT_HOST_DEVICE
0069
0070
0071
0072
0073
0074
0075 bool Intersect(Vector3D<Real_t> const &point, Vector3D<Real_t> const &dir, bool left_side, Real_t &distance,
0076 bool &two_solutions, Real_t &safety)
0077 {
0078
0079 using Vector3D = vecgeom::Vector3D<Real_t>;
0080
0081 Real_t dzp = point[2] + fArb4Data->halfH;
0082 Real_t dz_inv = fArb4Data->halfH_inv;
0083
0084
0085 Real_t xs1 = fArb4Data->verticesX[1] + fArb4Data->ftx1 * dzp;
0086 Real_t ys1 = fArb4Data->verticesY[1] + fArb4Data->fty1 * dzp;
0087 Real_t xs2 = fArb4Data->verticesX[0] + fArb4Data->ftx2 * dzp;
0088 Real_t ys2 = fArb4Data->verticesY[0] + fArb4Data->fty2 * dzp;
0089 Real_t dxs = xs2 - xs1;
0090 Real_t dys = ys2 - ys1;
0091
0092
0093 Real_t a = (fArb4Data->fDeltatx * dir[1] - fArb4Data->fDeltaty * dir[0] + fArb4Data->ft1crosst2 * dir[2]) * dir[2];
0094 Real_t b = dxs * dir[1] - dys * dir[0] +
0095 (fArb4Data->fDeltatx * point[1] - fArb4Data->fDeltaty * point[0] + fArb4Data->fty2 * xs1 -
0096 fArb4Data->fty1 * xs2 + fArb4Data->ftx1 * ys2 - fArb4Data->ftx2 * ys1) *
0097 dir[2];
0098 Real_t c = dxs * point[1] - dys * point[0] + xs1 * ys2 - xs2 * ys1;
0099
0100 QuadraticCoef<Real_t> coef;
0101 coef.phalf = Real_t(1.) * b / (Real_t(2.) * vecgeom::NonZero(a));
0102 coef.q = c / vecgeom::NonZero(a);
0103
0104 Real_t roots[2];
0105 int numroots;
0106 QuadraticSolver(coef, roots, numroots);
0107
0108
0109 for (auto i = 0; i < numroots; ++i) {
0110 if (roots[i] < -vecgeom::kTolerance) continue;
0111 distance = roots[i];
0112 Vector3D onsurf = point + distance * dir;
0113 if (Abs(onsurf.z()) > fArb4Data->halfH + vecgeom::kTolerance) continue;
0114
0115
0116
0117
0118 Real_t r = -1;
0119 Real_t rz = 0.5 * dz_inv * (onsurf[2] + fArb4Data->halfH);
0120 Real_t num = (onsurf.x() - fArb4Data->verticesX[1]) - rz * (fArb4Data->verticesX[3] - fArb4Data->verticesX[1]);
0121 Real_t denom =
0122 (fArb4Data->verticesX[0] - fArb4Data->verticesX[1]) +
0123 rz * (fArb4Data->verticesX[2] - fArb4Data->verticesX[0] - fArb4Data->verticesX[3] + fArb4Data->verticesX[1]);
0124 if (Abs(denom) > 1e-6) {
0125 r = num / vecgeom::NonZero(denom);
0126 if (!((r >= -vecgeom::kTolerance) && (r <= 1. + vecgeom::kTolerance))) continue;
0127 }
0128 num = (onsurf.y() - fArb4Data->verticesY[1]) - rz * (fArb4Data->verticesY[3] - fArb4Data->verticesY[1]);
0129 denom =
0130 (fArb4Data->verticesY[0] - fArb4Data->verticesY[1]) +
0131 rz * (fArb4Data->verticesY[2] - fArb4Data->verticesY[0] - fArb4Data->verticesY[3] + fArb4Data->verticesY[1]);
0132 if (Abs(denom) > 1e-6) r = num / vecgeom::NonZero(denom);
0133
0134
0135 if (!((r >= -vecgeom::kTolerance) && (r <= 1. + vecgeom::kTolerance))) continue;
0136 if (!((rz >= -vecgeom::kTolerance) && (rz <= 1. + vecgeom::kTolerance))) continue;
0137
0138
0139 Vector3D unorm = fArb4Data->fViCrossHi0 + rz * fArb4Data->fViCrossVj + r * fArb4Data->fHi1CrossHi0;
0140
0141 bool hit = left_side ^ (dir.Dot(unorm) < 0);
0142
0143 if (hit) {
0144 if (distance < -vecgeom::kTolerance) safety = Safety(point, left_side, distance, onsurf);
0145 return true;
0146 }
0147 }
0148 return false;
0149 }
0150
0151 VECGEOM_FORCE_INLINE
0152 VECCORE_ATT_HOST_DEVICE
0153
0154
0155
0156
0157
0158
0159 bool Safety(Vector3D<Real_t> const &point, bool left_side, Real_t &distance, Vector3D<Real_t> &onsurf) const
0160 {
0161
0162 Real_t dzp = fArb4Data->halfH + point[2];
0163
0164
0165 distance = (fabs(point[2]) > fArb4Data->halfH + vecgeom::kTolerance) ? fabs(point[2]) - fArb4Data->halfH : 0.;
0166
0167 #ifdef SURF_ACCURATE_SAFETY
0168 Real_t v_safety = vecgeom::InfinityLength<Real_t>();
0169 Real_t tmp = 0.;
0170 Vector3D<Real_t> vplane = {fArb4Data->verticesX[0], fArb4Data->verticesY[0], -fArb4Data->halfH};
0171 tmp = (point - vplane).Dot(fArb4Data->normal0);
0172 if (tmp > 0) v_safety = tmp;
0173
0174 vplane = {fArb4Data->verticesX[1], fArb4Data->verticesY[1], -fArb4Data->halfH};
0175 tmp = (point - vplane).Dot(fArb4Data->normal1);
0176 if (tmp > 0) v_safety = Min(v_safety, tmp);
0177
0178 vplane = {fArb4Data->verticesX[2], fArb4Data->verticesY[2], fArb4Data->halfH};
0179 tmp = (point - vplane).Dot(fArb4Data->normal2);
0180 if (tmp > 0) v_safety = Min(v_safety, tmp);
0181
0182 vplane = {fArb4Data->verticesX[3], fArb4Data->verticesY[3], -fArb4Data->halfH};
0183 tmp = (point - vplane).Dot(fArb4Data->normal3);
0184 if (tmp > 0) v_safety = Min(v_safety, tmp);
0185
0186 if (v_safety < vecgeom::InfinityLength<Real_t>()) {
0187 distance = Max(distance, v_safety);
0188 }
0189
0190 #endif
0191
0192 Real_t xs1 = fArb4Data->verticesX[1] + fArb4Data->ftx1 * dzp;
0193 Real_t ys1 = fArb4Data->verticesY[1] + fArb4Data->fty1 * dzp;
0194 Real_t xs2 = fArb4Data->verticesX[0] + fArb4Data->ftx2 * dzp;
0195 Real_t ys2 = fArb4Data->verticesY[0] + fArb4Data->fty2 * dzp;
0196 Real_t dxs = xs2 - xs1;
0197 Real_t dys = ys2 - ys1;
0198
0199 Real_t umin = 0.;
0200 Real_t safety = vecgeom::InfinityLength<Real_t>();
0201
0202 Real_t dx1 = 0.;
0203 Real_t dx2 = 0.;
0204 Real_t dy1 = 0.;
0205 Real_t dy2 = 0.;
0206
0207 Real_t dpx = point[0] - xs1;
0208 Real_t dpy = point[1] - ys1;
0209 Real_t lsq = dxs * dxs + dys * dys;
0210 Real_t u = (dpx * dxs + dpy * dys) / vecgeom::NonZero(lsq);
0211 if (u > 1 + vecgeom::kTolerance) {
0212 dpx = point[0] - xs2;
0213 dpy = point[1] - ys2;
0214 }
0215 if (u >= -vecgeom::kTolerance && u <= 1 + vecgeom::kTolerance) {
0216 dpx = dpx - u * dxs;
0217 dpy = dpy - u * dys;
0218 }
0219 Real_t ssq = dpx * dpx + dpy * dpy;
0220 if (ssq < safety) {
0221 dx1 = fArb4Data->verticesX[0] - fArb4Data->verticesX[1];
0222 dx2 = fArb4Data->verticesX[2] - fArb4Data->verticesX[3];
0223 dy1 = fArb4Data->verticesY[0] - fArb4Data->verticesY[1];
0224 dy2 = fArb4Data->verticesY[2] - fArb4Data->verticesY[3];
0225 umin = u;
0226 safety = ssq;
0227 }
0228 if (umin < -vecgeom::kTolerance || umin > 1 + vecgeom::kTolerance) umin = 0.;
0229 dxs = dx1 + umin * (dx2 - dx1);
0230 dys = dy1 + umin * (dy2 - dy1);
0231
0232 safety *= Real_t(1.) - Real_t(4.) * fArb4Data->halfH * fArb4Data->halfH /
0233 (dxs * dxs + dys * dys + Real_t(4.) * fArb4Data->halfH * fArb4Data->halfH);
0234 distance = Max(distance, Sqrt(safety));
0235
0236 return distance > -vecgeom::kToleranceDist<Real_t>;
0237 }
0238 };
0239
0240 }
0241
0242 #endif