File indexing completed on 2025-01-30 10:26:24
0001
0002
0003
0004 #ifndef VECGEOM_VOLUMES_TILE_H_
0005 #define VECGEOM_VOLUMES_TILE_H_
0006
0007 #include "VecGeom/base/Vector3D.h"
0008 #include "kernel/GenericKernels.h"
0009
0010 namespace vecgeom {
0011
0012 enum TileType { kTriangle = 3, kQuadrilateral = 4 };
0013
0014 VECGEOM_DEVICE_DECLARE_CONV_TEMPLATE_1v_1t(struct, Tile, size_t, typename);
0015
0016 inline namespace VECGEOM_IMPL_NAMESPACE {
0017
0018 template <size_t, typename>
0019 struct Tile;
0020
0021 template <typename T>
0022 using TriangleFacet = Tile<3, T>;
0023
0024 template <typename T>
0025 using QuadrilateralFacet = Tile<4, T>;
0026
0027
0028
0029
0030
0031
0032 template <size_t NVERT, typename T = double>
0033 struct Tile {
0034 size_t fNvert = 0;
0035 Vector3D<T> fVertices[NVERT];
0036 Vector3D<T> fSideVectors[NVERT];
0037 Vector3D<T> fNormal;
0038 Vector3D<T> fCenter;
0039 size_t fIndices[NVERT] = {0};
0040 T fSurfaceArea = 0;
0041 bool fConvex = false;
0042 T fDistance = 0;
0043
0044 VECCORE_ATT_HOST_DEVICE
0045 Tile() {}
0046
0047 VECCORE_ATT_HOST_DEVICE
0048 VECGEOM_FORCE_INLINE
0049 bool SetVertices(Vector3D<T> const &vtx0, Vector3D<T> const &vtx1, Vector3D<T> const &vtx2, size_t ind0 = 0,
0050 size_t ind1 = 0, size_t ind2 = 0)
0051 {
0052 assert(NVERT == 3);
0053 AddVertex(vtx0, ind0);
0054 AddVertex(vtx1, ind1);
0055 return AddVertex(vtx2, ind2);
0056 }
0057
0058 VECCORE_ATT_HOST_DEVICE
0059 VECGEOM_FORCE_INLINE
0060 bool SetVertices(Vector3D<T> const &vtx0, Vector3D<T> const &vtx1, Vector3D<T> const &vtx2, Vector3D<T> const &vtx3,
0061 size_t ind0 = 0, size_t ind1 = 0, size_t ind2 = 0, size_t ind3 = 0)
0062 {
0063 assert(NVERT == 4);
0064 AddVertex(vtx0, ind0);
0065 AddVertex(vtx1, ind1);
0066 AddVertex(vtx2, ind2);
0067 return AddVertex(vtx3, ind3);
0068 }
0069
0070 VECCORE_ATT_HOST_DEVICE
0071 VECGEOM_FORCE_INLINE
0072 bool AddVertex(Vector3D<T> const &vtx, size_t ind = 0)
0073 {
0074 fVertices[fNvert] = vtx;
0075 fIndices[fNvert] = ind;
0076 fNvert++;
0077 if (fNvert < NVERT) return true;
0078
0079
0080 size_t nvert = NVERT;
0081 for (size_t i = 0; i < NVERT; ++i) {
0082 const Vector3D<T> vi = fVertices[(i + 1) % NVERT] - fVertices[i];
0083 if (vi.Mag2() < kTolerance) {
0084 nvert--;
0085 }
0086 }
0087
0088 if (nvert < 3) {
0089 std::cout << "Tile degenerated: Length of sides of facet are too small." << std::endl;
0090 return false;
0091 }
0092
0093
0094
0095 bool degenerated = true;
0096 for (size_t i = 0; i < NVERT - 1; ++i) {
0097 Vector3D<T> e1 = fVertices[i + 1] - fVertices[i];
0098 if (e1.Mag2() < kTolerance) continue;
0099 for (size_t j = i + 1; j < NVERT; ++j) {
0100 Vector3D<T> e2 = fVertices[(j + 1) % NVERT] - fVertices[j];
0101 if (e2.Mag2() < kTolerance) continue;
0102 fNormal = e1.Cross(e2);
0103
0104 if (fNormal.Mag2() < kTolerance) continue;
0105 fNormal.Normalize();
0106 degenerated = false;
0107 break;
0108 }
0109 if (!degenerated) break;
0110 }
0111
0112 if (degenerated) {
0113 std::cout << "Tile degenerated 2: Length of sides of facet are too small." << std::endl;
0114 return false;
0115 }
0116
0117
0118 for (size_t i = 0; i < NVERT; ++i) {
0119 Vector3D<T> e1 = fVertices[(i + 1) % NVERT] - fVertices[i];
0120 if (e1.Mag2() < kTolerance) continue;
0121 fSideVectors[i] = fNormal.Cross(e1).Normalized();
0122 fDistance = -fNormal.Dot(fVertices[i]);
0123 for (size_t j = i + 1; j < i + NVERT; ++j) {
0124 Vector3D<T> e2 = fVertices[(j + 1) % NVERT] - fVertices[j % NVERT];
0125 if (e2.Mag2() < kTolerance)
0126 fSideVectors[j % NVERT] = fSideVectors[(j - 1) % NVERT];
0127 else
0128 fSideVectors[j % NVERT] = fNormal.Cross(e2).Normalized();
0129 }
0130 break;
0131 }
0132
0133
0134 fSurfaceArea = 0.;
0135 for (size_t i = 1; i < NVERT - 1; ++i) {
0136 Vector3D<T> e1 = fVertices[i] - fVertices[0];
0137 Vector3D<T> e2 = fVertices[i + 1] - fVertices[0];
0138 fSurfaceArea += 0.5 * (e1.Cross(e2)).Mag();
0139 }
0140 assert(fSurfaceArea > kTolerance * kTolerance);
0141
0142
0143 for (size_t i = 0; i < NVERT; ++i)
0144 fCenter += fVertices[i];
0145 fCenter /= NVERT;
0146 return true;
0147 }
0148
0149 VECCORE_ATT_HOST_DEVICE
0150 VECGEOM_FORCE_INLINE
0151 Vector3D<T> const &GetNormal() const { return fNormal; }
0152
0153 VECCORE_ATT_HOST_DEVICE
0154 VECGEOM_FORCE_INLINE
0155 size_t IsNeighbor(Tile<NVERT, T> const &other)
0156 {
0157
0158 size_t ncommon = 0;
0159 for (size_t ind1 = 0; ind1 < NVERT; ++ind1) {
0160 for (size_t ind2 = 0; ind2 < NVERT; ++ind2) {
0161 if (fIndices[ind1] == other.fIndices[ind2]) ncommon++;
0162 }
0163 }
0164 return ncommon;
0165 }
0166
0167 VECGEOM_FORCE_INLINE
0168 VECCORE_ATT_HOST_DEVICE
0169 bool Contains(Vector3D<T> const &point) const
0170 {
0171
0172 bool inside = true;
0173 for (size_t i = 0; i < NVERT; ++i) {
0174 T saf = (point - fVertices[i]).Dot(fSideVectors[i]);
0175 inside &= saf > -kTolerance;
0176 }
0177 return inside;
0178 }
0179
0180 VECGEOM_FORCE_INLINE
0181 VECCORE_ATT_HOST_DEVICE
0182 T DistPlane(Vector3D<T> const &point) const
0183 {
0184
0185
0186 return (point.Dot(fNormal) + fDistance);
0187 }
0188
0189 VECCORE_ATT_HOST_DEVICE
0190 T DistanceToIn(Vector3D<T> const &point, Vector3D<T> const &direction) const
0191 {
0192 T ndd = NonZero(direction.Dot(fNormal));
0193 T saf = DistPlane(point);
0194 bool valid = ndd < 0. && saf > -kTolerance;
0195 if (!valid) return InfinityLength<T>();
0196 T distance = -saf / ndd;
0197
0198 Vector3D<T> point_prop = point + distance * direction;
0199
0200 if (!Contains(point_prop)) return InfinityLength<T>();
0201 return distance;
0202 }
0203
0204 VECCORE_ATT_HOST_DEVICE
0205 Precision DistanceToOut(Vector3D<T> const &point, Vector3D<T> const &direction) const
0206 {
0207 T ndd = NonZero(direction.Dot(fNormal));
0208 T saf = DistPlane(point);
0209 bool valid = ndd > 0. && saf < kTolerance;
0210 if (!valid) return InfinityLength<T>();
0211 T distance = -saf / ndd;
0212
0213 Vector3D<T> point_prop = point + distance * direction;
0214
0215 if (!Contains(point_prop)) return InfinityLength<T>();
0216 return distance;
0217 }
0218
0219 template <bool ToIn>
0220 VECCORE_ATT_HOST_DEVICE
0221 T SafetySq(Vector3D<T> const &point) const
0222 {
0223 T safety = DistPlane(point);
0224
0225 Vector3D<T> intersection = point - safety * fNormal;
0226 bool withinBound = Contains(intersection);
0227 if (ToIn)
0228 withinBound &= safety > -kTolerance;
0229 else
0230 withinBound &= safety < kTolerance;
0231 safety *= safety;
0232 if (withinBound) return safety;
0233
0234 Vector3D<T> safety_outbound = InfinityLength<T>();
0235 for (size_t ivert = 0; ivert < NVERT; ++ivert) {
0236 safety_outbound[ivert] =
0237 DistanceToLineSegmentSquared<kScalar>(fVertices[ivert], fVertices[(ivert + 1) % NVERT], point);
0238 }
0239 return (safety_outbound.Min());
0240 }
0241 };
0242
0243 #ifndef VECCORE_CUDA
0244 std::ostream &operator<<(std::ostream &os, TriangleFacet<double> const &facet);
0245 std::ostream &operator<<(std::ostream &os, QuadrilateralFacet<double> const &facet);
0246 #endif
0247 }
0248 }
0249
0250 #endif