File indexing completed on 2026-04-17 08:35:35
0001 #ifndef VECGEOM_SURFACE_TRIANGLEMASK_H
0002 #define VECGEOM_SURFACE_TRIANGLEMASK_H
0003
0004 #include <VecGeom/surfaces/base/CommonTypes.h>
0005
0006 namespace vgbrep {
0007
0008
0009
0010 template <typename Real_t>
0011 struct TriangleMask {
0012 using value_type = Real_t;
0013 Point2D<Real_t> p_[3] = {Real_t(0)};
0014 Point2D<Real_t> n_[3] = {Real_t(0)};
0015
0016 TriangleMask() = default;
0017 template <typename Real_i>
0018 TriangleMask(Real_i x1, Real_i y1, Real_i x2, Real_i y2, Real_i x3, Real_i y3)
0019 {
0020 p_[0].Set(static_cast<Real_t>(x1), static_cast<Real_t>(y1));
0021 p_[1].Set(static_cast<Real_t>(x2), static_cast<Real_t>(y2));
0022 p_[2].Set(static_cast<Real_t>(x3), static_cast<Real_t>(y3));
0023
0024
0025 for (int i = 0; i < 3; ++i) {
0026 auto j = (i + 1) % 3;
0027 auto k = (i + 2) % 3;
0028 auto seg_ij = p_[j] - p_[i];
0029 auto seg_ik = p_[k] - p_[i];
0030 VECGEOM_ASSERT(seg_ij.Mag2() > vecgeom::kToleranceSquared);
0031
0032 n_[i].Set(seg_ij.y(), -seg_ij.x());
0033
0034 if (n_[i].Dot(seg_ik) > Real_t(0)) n_[i] *= Real_t(-1);
0035
0036 n_[i].Normalize();
0037 }
0038 }
0039 template <typename Real_i>
0040 TriangleMask(const TriangleMask<Real_i> &other)
0041 {
0042 for (int i = 0; i < 3; ++i) {
0043 p_[i] = Point2D<Real_t>(other.p_[i]);
0044 n_[i] = Point2D<Real_t>(other.n_[i]);
0045 }
0046 }
0047
0048
0049
0050
0051
0052 void Extent3D(Vector3D<Real_t> &aMin, Vector3D<Real_t> &aMax) const
0053 {
0054 aMin.Set(vecgeom::InfinityLength<Real_t>());
0055 aMax.Set(-vecgeom::InfinityLength<Real_t>());
0056 aMin.z() = aMax.z() = Real_t(0);
0057 for (int i = 0; i < 3; ++i) {
0058 aMin.x() = vecCore::math::Min(aMin.x(), p_[i].x());
0059 aMax.x() = vecCore::math::Max(aMax.x(), p_[i].x());
0060 aMin.y() = vecCore::math::Min(aMin.y(), p_[i].y());
0061 aMax.y() = vecCore::math::Max(aMax.y(), p_[i].y());
0062 }
0063 }
0064
0065
0066
0067 void GetExtent(WindowMask<Real_t> &window) const
0068 {
0069 window.rangeU.Set(p_[0].x());
0070 window.rangeV.Set(p_[0].y());
0071 for (int i = 0; i < 3; ++i) {
0072 window.rangeU.Set(vecCore::math::Min(window.rangeU[0], p_[i].x()),
0073 vecCore::math::Max(window.rangeU[1], p_[i].x()));
0074 window.rangeV.Set(vecCore::math::Min(window.rangeV[0], p_[i].y()),
0075 vecCore::math::Max(window.rangeV[1], p_[i].y()));
0076 }
0077 }
0078
0079
0080
0081
0082
0083
0084 VECCORE_ATT_HOST_DEVICE
0085 bool Inside(Vector3D<Real_t> const &local) const
0086 {
0087 Vector2D<Real_t> const local2D(local.x(), local.y());
0088 return (n_[0].Dot(local2D - p_[0]) < vecgeom::kToleranceStrict<Real_t> &&
0089 n_[1].Dot(local2D - p_[1]) < vecgeom::kToleranceStrict<Real_t> &&
0090 n_[2].Dot(local2D - p_[2]) < vecgeom::kToleranceStrict<Real_t>);
0091 }
0092
0093
0094
0095
0096 VECCORE_ATT_HOST_DEVICE
0097 Real_t Safety(Vector3D<Real_t> const &local, Real_t safetySurf, bool &valid) const
0098 {
0099 valid = true;
0100 Vector2D<Real_t> const local2D(local.x(), local.y());
0101 Real_t safety = safetySurf;
0102 bool withinBound[3];
0103 for (int i = 0; i < 3; ++i) {
0104 withinBound[i] = n_[i].Dot(local2D - p_[i]) <= 0;
0105 }
0106 if (withinBound[0] && withinBound[1] && withinBound[2]) return safetySurf;
0107
0108 Real_t dseg_squared = vecgeom::InfinityLength<Real_t>();
0109 for (int i = 0; i < 3; ++i) {
0110 if (!withinBound[i])
0111 dseg_squared = vecCore::math::Min(dseg_squared, DistanceToSegmentSquared(local2D, p_[i], p_[(i + 1) % 3]));
0112 }
0113 safety = vecCore::math::Sqrt(dseg_squared + safetySurf * safetySurf);
0114
0115 return safety;
0116 }
0117
0118
0119
0120
0121
0122 Real_t SafetyInside(Vector3D<Real_t> const &local) const
0123 {
0124 if (Inside(local) == false) return Real_t(0);
0125 Vector2D<Real_t> const local2D(local.x(), local.y());
0126 Real_t safety_squared = vecgeom::InfinityLength<Real_t>();
0127 for (int i = 0; i < 3; ++i) {
0128 safety_squared = vecCore::math::Min(safety_squared, DistanceToSegmentSquared(local2D, p_[i], p_[(i + 1) % 3]));
0129 }
0130 return vecCore::math::Sqrt(safety_squared);
0131 }
0132
0133
0134
0135
0136
0137 Real_t SafetyOutside(Vector3D<Real_t> const &local) const
0138 {
0139 if (Inside(local) == true) return Real_t(0);
0140 Vector2D<Real_t> const local2D(local.x(), local.y());
0141 Real_t safety_squared = vecgeom::InfinityLength<Real_t>();
0142 for (int i = 0; i < 3; ++i) {
0143 safety_squared = vecCore::math::Min(safety_squared, DistanceToSegmentSquared(local2D, p_[i], p_[(i + 1) % 3]));
0144 }
0145 return vecCore::math::Sqrt(safety_squared);
0146 }
0147 };
0148
0149 }
0150
0151 #endif