File indexing completed on 2026-04-17 08:35:35
0001 #ifndef VECGEOM_SURFACE_FRAMEMASKS_H
0002 #define VECGEOM_SURFACE_FRAMEMASKS_H
0003
0004 #ifndef SURF_ACCURATE_SAFETY
0005 #define SURF_ACCURATE_SAFETY 0
0006 #endif
0007
0008 #define WINDOW_ACCURATE_SAFETY SURF_ACCURATE_SAFETY
0009 #define QUAD_ACCURATE_SAFETY SURF_ACCURATE_SAFETY
0010
0011 #include <VecGeom/surfaces/mask/WindowMask.h>
0012 #include <VecGeom/surfaces/mask/RingMask.h>
0013 #include <VecGeom/surfaces/mask/ZPhiMask.h>
0014 #include <VecGeom/surfaces/mask/TriangleMask.h>
0015 #include <VecGeom/surfaces/mask/QuadrilateralMask.h>
0016
0017 namespace vgbrep {
0018
0019 namespace detail {
0020 template <typename Real_t>
0021 static void ConvertAngleToFrame1(Vector3D<Real_t> &sPhi, Vector3D<Real_t> &ePhi, TransformationMP<Real_t> const &trans)
0022 {
0023 bool flip = trans.Rotation(8) < 0.;
0024 auto trans_sPhi = trans.InverseTransformDirection(sPhi);
0025 auto trans_ePhi = trans.InverseTransformDirection(ePhi);
0026 sPhi = flip ? trans_ePhi : trans_sPhi;
0027 ePhi = flip ? trans_sPhi : trans_ePhi;
0028 }
0029 }
0030
0031
0032
0033
0034
0035 template <typename Real_t, typename FrameType1, typename FrameType2>
0036 struct FrameChecker {
0037
0038
0039
0040
0041
0042
0043 static bool IsEmbedding(FrameType1 const &f1, FrameType2 const &f2, TransformationMP<Real_t> const &trans)
0044 {
0045 VECGEOM_LOG(error) << "Frame embedding not implemented for " << typeid(FrameType1).name() << " - "
0046 << typeid(FrameType2).name();
0047 return false;
0048 }
0049
0050
0051
0052
0053
0054
0055 static bool AreDisjoint(FrameType1 const &f1, FrameType2 const &f2, TransformationMP<Real_t> const &trans)
0056 {
0057 VECGEOM_LOG(error) << "Frame disjoint check not implemented for " << typeid(FrameType1).name() << " - "
0058 << typeid(FrameType2).name();
0059 return false;
0060 }
0061
0062
0063
0064
0065
0066
0067 static FrameIntersect CheckFrames(FrameType1 const &f1, FrameType2 const &f2, TransformationMP<Real_t> const &trans)
0068 {
0069 if (FrameChecker<Real_t, FrameType1, FrameType2>::AreDisjoint(f1, f2, trans)) return FrameIntersect::kNoIntersect;
0070 auto intersect_type = FrameIntersect::kIntersect;
0071 if (FrameChecker<Real_t, FrameType1, FrameType2>::IsEmbedding(f1, f2, trans))
0072 intersect_type = FrameIntersect::kEmbedding;
0073 if (FrameChecker<Real_t, FrameType2, FrameType1>::IsEmbedding(f2, f1, trans.Inverse())) {
0074 if (intersect_type == FrameIntersect::kEmbedding)
0075 intersect_type = FrameIntersect::kEqual;
0076 else
0077 intersect_type = FrameIntersect::kEmbedded;
0078 }
0079 return intersect_type;
0080 }
0081 };
0082
0083 template <typename Real_t>
0084 struct FrameChecker<Real_t, RingMask<Real_t>, RingMask<Real_t>> {
0085 static bool IsEmbedding(RingMask<Real_t> const &frame1, RingMask<Real_t> const &frame2,
0086 TransformationMP<Real_t> const &trans)
0087 {
0088
0089 if (!trans.HasTranslation()) {
0090
0091 if (frame2.rangeR[0] < vecgeom::MakeMinusTolerant<true, Real_t>(frame1.rangeR[0]) ||
0092 frame2.rangeR[1] > vecgeom::MakePlusTolerant<true, Real_t>(frame1.rangeR[1]))
0093 return false;
0094
0095 if (frame1.isFullCirc) return true;
0096 if (frame2.isFullCirc) return false;
0097 Vector3D<Real_t> sPhi{frame2.vecSPhi[0], frame2.vecSPhi[1], 0};
0098 Vector3D<Real_t> ePhi{frame2.vecEPhi[0], frame2.vecEPhi[1], 0};
0099 detail::ConvertAngleToFrame1(sPhi, ePhi, trans);
0100 AngleInterval<Real_t> ang1(frame1.vecSPhi.Phi(), frame1.vecEPhi.Phi());
0101 AngleInterval<Real_t> ang2(sPhi.Phi(), ePhi.Phi());
0102 bool embedding = ang1.Intersect(ang2) == ang2;
0103 return embedding;
0104 }
0105
0106 Vector3D<Real_t> center;
0107 Real_t safety = frame1.SafetyInside(trans.InverseTransform(center));
0108 return frame2.rangeR[1] < vecgeom::MakePlusTolerant<true, Real_t>(safety);
0109 }
0110
0111 static bool AreDisjoint(RingMask<Real_t> const &frame1, RingMask<Real_t> const &frame2,
0112 TransformationMP<Real_t> const &trans)
0113 {
0114
0115 if (!trans.HasTranslation()) {
0116
0117 if (frame2.rangeR[0] > vecgeom::MakeMinusTolerant<true, Real_t>(frame1.rangeR[1]) ||
0118 frame1.rangeR[0] > vecgeom::MakeMinusTolerant<true, Real_t>(frame2.rangeR[1]))
0119 return true;
0120
0121 if (frame1.isFullCirc || frame2.isFullCirc) return false;
0122
0123 Vector3D<Real_t> sPhi{frame2.vecSPhi[0], frame2.vecSPhi[1], 0};
0124 Vector3D<Real_t> ePhi{frame2.vecEPhi[0], frame2.vecEPhi[1], 0};
0125 detail::ConvertAngleToFrame1(sPhi, ePhi, trans);
0126 AngleInterval<Real_t> ang1(frame1.vecSPhi.Phi(), frame1.vecEPhi.Phi());
0127 AngleInterval<Real_t> ang2(sPhi.Phi(), ePhi.Phi());
0128 bool disjoint = ang1.Intersect(ang2).IsNull();
0129 return disjoint;
0130 }
0131
0132
0133 auto dist = trans.Translation().Length();
0134 if (frame1.rangeR[1] + frame2.rangeR[1] < dist + vecgeom::kToleranceDist<Real_t> * dist) return true;
0135
0136 if (frame1.rangeR[0] - frame2.rangeR[1] > dist - vecgeom::kToleranceDist<Real_t> * dist ||
0137 frame2.rangeR[0] - frame1.rangeR[1] > dist - vecgeom::kToleranceDist<Real_t> * dist)
0138 return true;
0139
0140 return false;
0141 }
0142
0143 static FrameIntersect CheckFrames(RingMask<Real_t> const &f1, RingMask<Real_t> const &f2,
0144 TransformationMP<Real_t> const &trans)
0145 {
0146 if (AreDisjoint(f1, f2, trans)) return FrameIntersect::kNoIntersect;
0147 auto intersect_type = FrameIntersect::kIntersect;
0148 if (IsEmbedding(f1, f2, trans)) intersect_type = FrameIntersect::kEmbedding;
0149 if (IsEmbedding(f2, f1, trans.Inverse())) {
0150 if (intersect_type == FrameIntersect::kEmbedding)
0151 intersect_type = FrameIntersect::kEqual;
0152 else
0153 intersect_type = FrameIntersect::kEmbedded;
0154 }
0155 return intersect_type;
0156 }
0157 };
0158
0159 template <typename Real_t>
0160 struct FrameChecker<Real_t, RingMask<Real_t>, WindowMask<Real_t>> {
0161 static bool IsEmbedding(RingMask<Real_t> const &frame1, WindowMask<Real_t> const &frame2,
0162 TransformationMP<Real_t> const &trans)
0163 {
0164 Vector3D<Real_t> vlocal[4] = {{frame2.rangeU[0], frame2.rangeV[0], 0},
0165 {frame2.rangeU[0], frame2.rangeV[1], 0},
0166 {frame2.rangeU[1], frame2.rangeV[1], 0},
0167 {frame2.rangeU[1], frame2.rangeV[0], 0}};
0168
0169 Vector3D<Real_t> v[4];
0170
0171 for (auto i = 0; i < 4; ++i) {
0172 v[i] = trans.InverseTransform(vlocal[i]);
0173 if (!frame1.Inside(v[i])) return false;
0174 }
0175
0176 if (frame1.IsConvex()) return true;
0177
0178
0179 Segment2D<Real_t> seg1_phi1({frame1.rangeR[0] * frame1.vecSPhi}, {frame1.rangeR[1] * frame1.vecSPhi});
0180 Segment2D<Real_t> seg1_phi2({frame1.rangeR[0] * frame1.vecEPhi}, {frame1.rangeR[1] * frame1.vecEPhi});
0181 for (size_t i = 0; i < 4; ++i) {
0182 Segment2D<Real_t> seg2({v[i].x(), v[i].y()}, {v[(i + 1) % 4].x(), v[(i + 1) % 4].y()});
0183 if (frame1.HasRmin()) {
0184 auto embedded = seg2.Intersect(Circle2D<Real_t>{frame1.rangeR[0], {Real_t(0), Real_t{0}}});
0185 if (embedded == SegmentIntersect::kEmbedded || embedded == SegmentIntersect::kIntersect) return false;
0186 }
0187 if (!frame1.isFullCirc) {
0188 auto embedded = seg1_phi1.Intersect(seg2);
0189 if (embedded != SegmentIntersect::kNoIntersect && embedded != SegmentIntersect::kEmbedding) return false;
0190 embedded = seg1_phi2.Intersect(seg2);
0191 if (embedded != SegmentIntersect::kNoIntersect && embedded != SegmentIntersect::kEmbedding) return false;
0192 }
0193 }
0194 if (frame1.isFullCirc && frame1.HasRmin()) {
0195
0196 auto center = trans.Transform(Vector3D<Real_t>{});
0197 if (frame2.Inside(center)) return false;
0198 }
0199
0200 return true;
0201 }
0202
0203 static bool AreDisjoint(RingMask<Real_t> const &frame1, WindowMask<Real_t> const &frame2,
0204 TransformationMP<Real_t> const &trans)
0205 {
0206
0207 auto center = trans.Transform(Vector3D<Real_t>{});
0208 if (frame2.SafetyOutside(center) > frame1.rangeR[1] - vecgeom::kToleranceDist<Real_t> * frame1.rangeR[1])
0209 return true;
0210
0211
0212 center = trans.InverseTransform(Vector3D<Real_t>{});
0213 auto diag2 = frame2.GetHalfSize().Length2();
0214 auto safety = frame1.SafetyOutside(center);
0215 if (center.Length2() < frame1.rangeR[0] * frame1.rangeR[0] &&
0216 diag2 < safety * safety + vecgeom::kToleranceDistSquared<Real_t>)
0217 return true;
0218 return false;
0219 }
0220
0221 static FrameIntersect CheckFrames(RingMask<Real_t> const &f1, WindowMask<Real_t> const &f2,
0222 TransformationMP<Real_t> const &trans)
0223 {
0224 if (AreDisjoint(f1, f2, trans)) return FrameIntersect::kNoIntersect;
0225 auto intersect_type = FrameIntersect::kIntersect;
0226 if (IsEmbedding(f1, f2, trans)) intersect_type = FrameIntersect::kEmbedding;
0227 if (FrameChecker<Real_t, WindowMask<Real_t>, RingMask<Real_t>>::IsEmbedding(f2, f1, trans.Inverse())) {
0228 if (intersect_type == FrameIntersect::kEmbedding)
0229 intersect_type = FrameIntersect::kEqual;
0230 else
0231 intersect_type = FrameIntersect::kEmbedded;
0232 }
0233 return intersect_type;
0234 }
0235 };
0236
0237 template <typename Real_t>
0238 struct FrameChecker<Real_t, RingMask<Real_t>, TriangleMask<Real_t>> {
0239 static bool IsEmbedding(RingMask<Real_t> const &frame1, TriangleMask<Real_t> const &frame2,
0240 TransformationMP<Real_t> const &trans)
0241 {
0242 Vector3D<Real_t> vlocal[3] = {{frame2.p_[0].x(), frame2.p_[0].y(), 0},
0243 {frame2.p_[1].x(), frame2.p_[1].y(), 0},
0244 {frame2.p_[2].x(), frame2.p_[2].y(), 0}};
0245
0246 Vector3D<Real_t> v[3];
0247
0248 for (auto i = 0; i < 3; ++i) {
0249 v[i] = trans.InverseTransform(vlocal[i]);
0250 if (!frame1.Inside(v[i])) return false;
0251 }
0252
0253 if (frame1.IsConvex()) return true;
0254
0255
0256 for (size_t i = 0; i < 3; ++i) {
0257 Segment2D<Real_t> seg2({v[i].x(), v[i].y()}, {v[(i + 1) % 3].x(), v[(i + 1) % 3].y()});
0258 if (frame1.HasRmin()) {
0259 auto embedded = seg2.Intersect(Circle2D<Real_t>{frame1.rangeR[0], {Real_t(0), Real_t{0}}});
0260 if (embedded == SegmentIntersect::kEmbedded || embedded == SegmentIntersect::kIntersect) return false;
0261 }
0262 if (!frame1.isFullCirc) {
0263 Segment2D<Real_t> seg1_phi1({frame1.rangeR[0] * frame1.vecSPhi}, {frame1.rangeR[1] * frame1.vecSPhi});
0264 Segment2D<Real_t> seg1_phi2({frame1.rangeR[0] * frame1.vecEPhi}, {frame1.rangeR[1] * frame1.vecEPhi});
0265 auto embedded = seg1_phi1.Intersect(seg2);
0266 if (embedded != SegmentIntersect::kNoIntersect && embedded != SegmentIntersect::kEmbedding) return false;
0267 embedded = seg1_phi2.Intersect(seg2);
0268 if (embedded != SegmentIntersect::kNoIntersect && embedded != SegmentIntersect::kEmbedding) return false;
0269 }
0270 }
0271
0272 if (!frame1.isFullCirc) {
0273 auto center = trans.Transform(Vector3D<Real_t>{});
0274 if (frame2.Inside(center)) return false;
0275 }
0276
0277 return true;
0278 }
0279
0280 static bool AreDisjoint(RingMask<Real_t> const &frame1, TriangleMask<Real_t> const &frame2,
0281 TransformationMP<Real_t> const &trans)
0282 {
0283
0284 auto center = trans.Transform(Vector3D<Real_t>{});
0285 return (frame2.SafetyOutside(center) > frame1.rangeR[1] - vecgeom::kToleranceDist<Real_t> * frame1.rangeR[1]);
0286 }
0287
0288 static FrameIntersect CheckFrames(RingMask<Real_t> const &f1, TriangleMask<Real_t> const &f2,
0289 TransformationMP<Real_t> const &trans)
0290 {
0291 if (AreDisjoint(f1, f2, trans)) return FrameIntersect::kNoIntersect;
0292 auto intersect_type = FrameIntersect::kIntersect;
0293 if (IsEmbedding(f1, f2, trans)) intersect_type = FrameIntersect::kEmbedding;
0294 if (FrameChecker<Real_t, TriangleMask<Real_t>, RingMask<Real_t>>::IsEmbedding(f2, f1, trans.Inverse())) {
0295 if (intersect_type == FrameIntersect::kEmbedding)
0296 intersect_type = FrameIntersect::kEqual;
0297 else
0298 intersect_type = FrameIntersect::kEmbedded;
0299 }
0300 return intersect_type;
0301 }
0302 };
0303
0304 template <typename Real_t>
0305 struct FrameChecker<Real_t, RingMask<Real_t>, QuadrilateralMask<Real_t>> {
0306 static bool IsEmbedding(RingMask<Real_t> const &frame1, QuadrilateralMask<Real_t> const &frame2,
0307 TransformationMP<Real_t> const &trans)
0308 {
0309 Vector3D<Real_t> vlocal[4] = {{frame2.p_[0].x(), frame2.p_[0].y(), 0},
0310 {frame2.p_[1].x(), frame2.p_[1].y(), 0},
0311 {frame2.p_[2].x(), frame2.p_[2].y(), 0},
0312 {frame2.p_[3].x(), frame2.p_[3].y(), 0}};
0313
0314 Vector3D<Real_t> v[4];
0315
0316 for (auto i = 0; i < 4; ++i) {
0317 v[i] = trans.InverseTransform(vlocal[i]);
0318 if (!frame1.Inside(v[i])) return false;
0319 }
0320
0321 if (frame1.IsConvex()) return true;
0322
0323
0324 for (size_t i = 0; i < 4; ++i) {
0325 Segment2D<Real_t> seg2({v[i].x(), v[i].y()}, {v[(i + 1) % 4].x(), v[(i + 1) % 4].y()});
0326 if (frame1.HasRmin()) {
0327 auto embedded = seg2.Intersect(Circle2D<Real_t>{frame1.rangeR[0], {Real_t(0), Real_t{0}}});
0328 if (embedded == SegmentIntersect::kEmbedded || embedded == SegmentIntersect::kIntersect) return false;
0329 }
0330 if (!frame1.isFullCirc) {
0331 Segment2D<Real_t> seg1_phi1({frame1.rangeR[0] * frame1.vecSPhi}, {frame1.rangeR[1] * frame1.vecSPhi});
0332 Segment2D<Real_t> seg1_phi2({frame1.rangeR[0] * frame1.vecEPhi}, {frame1.rangeR[1] * frame1.vecEPhi});
0333 auto embedded = seg1_phi1.Intersect(seg2);
0334 if (embedded != SegmentIntersect::kNoIntersect && embedded != SegmentIntersect::kEmbedding) return false;
0335 embedded = seg1_phi2.Intersect(seg2);
0336 if (embedded != SegmentIntersect::kNoIntersect && embedded != SegmentIntersect::kEmbedding) return false;
0337 }
0338 }
0339
0340 auto center = trans.Transform(Vector3D<Real_t>{});
0341 if (frame2.Inside(center)) return false;
0342
0343 return true;
0344 }
0345
0346 static bool AreDisjoint(RingMask<Real_t> const &frame1, QuadrilateralMask<Real_t> const &frame2,
0347 TransformationMP<Real_t> const &trans)
0348 {
0349
0350 auto center = trans.Transform(Vector3D<Real_t>{});
0351 return (frame2.SafetyOutside(center) > frame1.rangeR[1] - vecgeom::kToleranceDist<Real_t> * frame1.rangeR[1]);
0352 }
0353
0354 static FrameIntersect CheckFrames(RingMask<Real_t> const &f1, QuadrilateralMask<Real_t> const &f2,
0355 TransformationMP<Real_t> const &trans)
0356 {
0357 if (AreDisjoint(f1, f2, trans)) return FrameIntersect::kNoIntersect;
0358 auto intersect_type = FrameIntersect::kIntersect;
0359 if (IsEmbedding(f1, f2, trans)) intersect_type = FrameIntersect::kEmbedding;
0360 if (FrameChecker<Real_t, QuadrilateralMask<Real_t>, RingMask<Real_t>>::IsEmbedding(f2, f1, trans.Inverse())) {
0361 if (intersect_type == FrameIntersect::kEmbedding)
0362 intersect_type = FrameIntersect::kEqual;
0363 else
0364 intersect_type = FrameIntersect::kEmbedded;
0365 }
0366 return intersect_type;
0367 }
0368 };
0369
0370 template <typename Real_t>
0371 struct FrameChecker<Real_t, ZPhiMask<Real_t>, ZPhiMask<Real_t>> {
0372 static bool IsEmbedding(ZPhiMask<Real_t> const &frame1, ZPhiMask<Real_t> const &frame2,
0373 TransformationMP<Real_t> const &trans)
0374 {
0375
0376 Vector3D<Real_t> zmin(0., 0., frame2.rangeZ[0]);
0377 Vector3D<Real_t> zmax(0., 0., frame2.rangeZ[1]);
0378
0379 zmin = trans.InverseTransform(zmin);
0380 zmax = trans.InverseTransform(zmax);
0381
0382
0383 if (zmin[2] < vecgeom::MakeMinusTolerant<true, Real_t>(frame1.rangeZ[0]) ||
0384 zmax[2] > vecgeom::MakePlusTolerant<true, Real_t>(frame1.rangeZ[1]))
0385 return false;
0386
0387
0388 if (frame1.isFullCirc) return true;
0389 if (frame2.isFullCirc) return false;
0390 Vector3D<Real_t> sPhi{frame2.vecSPhi[0], frame2.vecSPhi[1], 0};
0391 Vector3D<Real_t> ePhi{frame2.vecEPhi[0], frame2.vecEPhi[1], 0};
0392 detail::ConvertAngleToFrame1(sPhi, ePhi, trans);
0393 AngleInterval<Real_t> ang1(frame1.vecSPhi.Phi(), frame1.vecEPhi.Phi());
0394 AngleInterval<Real_t> ang2(sPhi.Phi(), ePhi.Phi());
0395 bool embedding = ang1.Intersect(ang2) == ang2;
0396 return embedding;
0397 }
0398
0399 static bool AreDisjoint(ZPhiMask<Real_t> const &frame1, ZPhiMask<Real_t> const &frame2,
0400 TransformationMP<Real_t> const &trans)
0401 {
0402
0403 Vector3D<Real_t> zmin(0., 0., frame2.rangeZ[0]);
0404 Vector3D<Real_t> zmax(0., 0., frame2.rangeZ[1]);
0405
0406 zmin = trans.InverseTransform(zmin);
0407 zmax = trans.InverseTransform(zmax);
0408
0409
0410 if (zmin[2] > vecgeom::MakeMinusTolerant<true, Real_t>(frame1.rangeZ[1]) ||
0411 zmax[2] < vecgeom::MakePlusTolerant<true, Real_t>(frame1.rangeZ[0]))
0412 return true;
0413
0414
0415 if (frame1.isFullCirc || frame2.isFullCirc) return false;
0416
0417 Vector3D<Real_t> sPhi{frame2.vecSPhi[0], frame2.vecSPhi[1], 0};
0418 Vector3D<Real_t> ePhi{frame2.vecEPhi[0], frame2.vecEPhi[1], 0};
0419 detail::ConvertAngleToFrame1(sPhi, ePhi, trans);
0420 AngleInterval<Real_t> ang1(frame1.vecSPhi.Phi(), frame1.vecEPhi.Phi());
0421 AngleInterval<Real_t> ang2(sPhi.Phi(), ePhi.Phi());
0422 bool disjoint = ang1.Intersect(ang2).IsNull();
0423 return disjoint;
0424 }
0425
0426 static FrameIntersect CheckFrames(ZPhiMask<Real_t> const &f1, ZPhiMask<Real_t> const &f2,
0427 TransformationMP<Real_t> const &trans)
0428 {
0429 if (AreDisjoint(f1, f2, trans)) return FrameIntersect::kNoIntersect;
0430 auto intersect_type = FrameIntersect::kIntersect;
0431 if (IsEmbedding(f1, f2, trans)) intersect_type = FrameIntersect::kEmbedding;
0432 if (IsEmbedding(f2, f1, trans.Inverse())) {
0433 if (intersect_type == FrameIntersect::kEmbedding)
0434 intersect_type = FrameIntersect::kEqual;
0435 else
0436 intersect_type = FrameIntersect::kEmbedded;
0437 }
0438 return intersect_type;
0439 }
0440 };
0441
0442 template <typename Real_t>
0443 struct FrameChecker<Real_t, WindowMask<Real_t>, RingMask<Real_t>> {
0444 static bool IsEmbedding(WindowMask<Real_t> const &frame1, RingMask<Real_t> const &frame2,
0445 TransformationMP<Real_t> const &trans)
0446 {
0447
0448
0449 Vector3D<Real_t> center;
0450 Real_t safety = frame1.SafetyInside(trans.InverseTransform(center));
0451 return safety > frame2.rangeR[1] - vecgeom::kToleranceDist<Real_t> * frame2.rangeR[1];
0452 }
0453
0454 static bool AreDisjoint(WindowMask<Real_t> const &frame1, RingMask<Real_t> const &frame2,
0455 TransformationMP<Real_t> const &trans)
0456 {
0457 return FrameChecker<Real_t, RingMask<Real_t>, WindowMask<Real_t>>::AreDisjoint(frame2, frame1, trans.Inverse());
0458 }
0459
0460 static FrameIntersect CheckFrames(WindowMask<Real_t> const &f1, RingMask<Real_t> const &f2,
0461 TransformationMP<Real_t> const &trans)
0462 {
0463 if (AreDisjoint(f1, f2, trans)) return FrameIntersect::kNoIntersect;
0464 auto intersect_type = FrameIntersect::kIntersect;
0465 if (IsEmbedding(f1, f2, trans)) intersect_type = FrameIntersect::kEmbedding;
0466 if (FrameChecker<Real_t, RingMask<Real_t>, WindowMask<Real_t>>::IsEmbedding(f2, f1, trans.Inverse())) {
0467 if (intersect_type == FrameIntersect::kEmbedding)
0468 intersect_type = FrameIntersect::kEqual;
0469 else
0470 intersect_type = FrameIntersect::kEmbedded;
0471 }
0472 return intersect_type;
0473 }
0474 };
0475
0476 template <typename Real_t>
0477 struct FrameChecker<Real_t, WindowMask<Real_t>, WindowMask<Real_t>> {
0478 static bool IsEmbedding(WindowMask<Real_t> const &frame1, WindowMask<Real_t> const &frame2,
0479 TransformationMP<Real_t> const &trans)
0480 {
0481
0482 Vector3D<Real_t> v[4] = {{frame2.rangeU[0], frame2.rangeV[0], 0},
0483 {frame2.rangeU[0], frame2.rangeV[1], 0},
0484 {frame2.rangeU[1], frame2.rangeV[1], 0},
0485 {frame2.rangeU[1], frame2.rangeV[0], 0}};
0486
0487 for (auto i = 0; i < 4; ++i) {
0488 if (!frame1.Inside(trans.InverseTransform(v[i]))) return false;
0489 }
0490 return true;
0491 }
0492
0493 static bool AreDisjoint(WindowMask<Real_t> const &frame1, WindowMask<Real_t> const &frame2,
0494 TransformationMP<Real_t> const &trans)
0495 {
0496
0497 Vector3D<Real_t> v1[4] = {{frame1.rangeU[0], frame1.rangeV[0], 0},
0498 {frame1.rangeU[0], frame1.rangeV[1], 0},
0499 {frame1.rangeU[1], frame1.rangeV[1], 0},
0500 {frame1.rangeU[1], frame1.rangeV[0], 0}};
0501 Vector3D<Real_t> v2[4] = {trans.InverseTransform(Vector3D<Real_t>(frame2.rangeU[0], frame2.rangeV[0], 0)),
0502 trans.InverseTransform(Vector3D<Real_t>(frame2.rangeU[0], frame2.rangeV[1], 0)),
0503 trans.InverseTransform(Vector3D<Real_t>(frame2.rangeU[1], frame2.rangeV[1], 0)),
0504 trans.InverseTransform(Vector3D<Real_t>(frame2.rangeU[1], frame2.rangeV[0], 0))};
0505 Polygon<Real_t, 4> poly1(v1);
0506 Polygon<Real_t, 4> poly2(v2);
0507 auto intersect = poly1.Intersect(poly2);
0508 if (intersect == FrameIntersect::kIntersect) return false;
0509
0510 auto center1 = poly1.GetCenter();
0511 auto center2 = poly2.GetCenter();
0512 if (frame1.Inside(Vector3D<Real_t>(center2[0], center2[1], 0)) ||
0513 frame2.Inside(trans.Transform(Vector3D<Real_t>(center1[0], center1[1], 0))))
0514 return false;
0515 return true;
0516 }
0517
0518 static FrameIntersect CheckFrames(WindowMask<Real_t> const &f1, WindowMask<Real_t> const &f2,
0519 TransformationMP<Real_t> const &trans)
0520 {
0521 if (AreDisjoint(f1, f2, trans)) return FrameIntersect::kNoIntersect;
0522 auto intersect_type = FrameIntersect::kIntersect;
0523 if (IsEmbedding(f1, f2, trans)) intersect_type = FrameIntersect::kEmbedding;
0524 if (IsEmbedding(f2, f1, trans.Inverse())) {
0525 if (intersect_type == FrameIntersect::kEmbedding)
0526 intersect_type = FrameIntersect::kEqual;
0527 else
0528 intersect_type = FrameIntersect::kEmbedded;
0529 }
0530 return intersect_type;
0531 }
0532 };
0533
0534 template <typename Real_t>
0535 struct FrameChecker<Real_t, WindowMask<Real_t>, TriangleMask<Real_t>> {
0536 static bool IsEmbedding(WindowMask<Real_t> const &frame1, TriangleMask<Real_t> const &frame2,
0537 TransformationMP<Real_t> const &trans)
0538 {
0539
0540 Vector3D<Real_t> v[3] = {{frame2.p_[0].x(), frame2.p_[0].y(), 0},
0541 {frame2.p_[1].x(), frame2.p_[1].y(), 0},
0542 {frame2.p_[2].x(), frame2.p_[2].y(), 0}};
0543 for (auto i = 0; i < 3; ++i) {
0544 if (!frame1.Inside(trans.InverseTransform(v[i]))) return false;
0545 }
0546 return true;
0547 }
0548
0549 static bool AreDisjoint(WindowMask<Real_t> const &frame1, TriangleMask<Real_t> const &frame2,
0550 TransformationMP<Real_t> const &trans)
0551 {
0552
0553 Vector3D<Real_t> v1[4] = {{frame1.rangeU[0], frame1.rangeV[0], 0},
0554 {frame1.rangeU[0], frame1.rangeV[1], 0},
0555 {frame1.rangeU[1], frame1.rangeV[1], 0},
0556 {frame1.rangeU[1], frame1.rangeV[0], 0}};
0557 Vector3D<Real_t> v2[3] = {trans.InverseTransform(Vector3D<Real_t>(frame2.p_[0].x(), frame2.p_[0].y(), 0)),
0558 trans.InverseTransform(Vector3D<Real_t>(frame2.p_[1].x(), frame2.p_[1].y(), 0)),
0559 trans.InverseTransform(Vector3D<Real_t>(frame2.p_[2].x(), frame2.p_[2].y(), 0))};
0560 Polygon<Real_t, 4> poly1(v1);
0561 Polygon<Real_t, 3> poly2(v2);
0562 auto intersect = poly1.Intersect(poly2);
0563 if (intersect == FrameIntersect::kIntersect) return false;
0564
0565 auto center1 = poly1.GetCenter();
0566 auto center2 = poly2.GetCenter();
0567 if (frame1.Inside(Vector3D<Real_t>(center2[0], center2[1], 0)) ||
0568 frame2.Inside(trans.Transform(Vector3D<Real_t>(center1[0], center1[1], 0))))
0569 return false;
0570 return true;
0571 }
0572
0573 static FrameIntersect CheckFrames(WindowMask<Real_t> const &f1, TriangleMask<Real_t> const &f2,
0574 TransformationMP<Real_t> const &trans)
0575 {
0576 if (AreDisjoint(f1, f2, trans)) return FrameIntersect::kNoIntersect;
0577 auto intersect_type = FrameIntersect::kIntersect;
0578 if (IsEmbedding(f1, f2, trans)) intersect_type = FrameIntersect::kEmbedding;
0579 if (FrameChecker<Real_t, TriangleMask<Real_t>, WindowMask<Real_t>>::IsEmbedding(f2, f1, trans.Inverse())) {
0580 if (intersect_type == FrameIntersect::kEmbedding)
0581 intersect_type = FrameIntersect::kEqual;
0582 else
0583 intersect_type = FrameIntersect::kEmbedded;
0584 }
0585 return intersect_type;
0586 }
0587 };
0588
0589 template <typename Real_t>
0590 struct FrameChecker<Real_t, WindowMask<Real_t>, QuadrilateralMask<Real_t>> {
0591 static bool IsEmbedding(WindowMask<Real_t> const &frame1, QuadrilateralMask<Real_t> const &frame2,
0592 TransformationMP<Real_t> const &trans)
0593 {
0594
0595 Vector3D<Real_t> v[4] = {{frame2.p_[0].x(), frame2.p_[0].y(), 0},
0596 {frame2.p_[1].x(), frame2.p_[1].y(), 0},
0597 {frame2.p_[2].x(), frame2.p_[2].y(), 0},
0598 {frame2.p_[3].x(), frame2.p_[3].y(), 0}};
0599 for (auto i = 0; i < 4; ++i) {
0600 if (!frame1.Inside(trans.InverseTransform(v[i]))) return false;
0601 }
0602 return true;
0603 }
0604
0605 static bool AreDisjoint(WindowMask<Real_t> const &frame1, QuadrilateralMask<Real_t> const &frame2,
0606 TransformationMP<Real_t> const &trans)
0607 {
0608
0609 Vector3D<Real_t> v1[4] = {{frame1.rangeU[0], frame1.rangeV[0], 0},
0610 {frame1.rangeU[0], frame1.rangeV[1], 0},
0611 {frame1.rangeU[1], frame1.rangeV[1], 0},
0612 {frame1.rangeU[1], frame1.rangeV[0], 0}};
0613 Vector3D<Real_t> v2[4] = {trans.InverseTransform(Vector3D<Real_t>(frame2.p_[0].x(), frame2.p_[0].y(), 0)),
0614 trans.InverseTransform(Vector3D<Real_t>(frame2.p_[1].x(), frame2.p_[1].y(), 0)),
0615 trans.InverseTransform(Vector3D<Real_t>(frame2.p_[2].x(), frame2.p_[2].y(), 0)),
0616 trans.InverseTransform(Vector3D<Real_t>(frame2.p_[3].x(), frame2.p_[3].y(), 0))};
0617 Polygon<Real_t, 4> poly1(v1);
0618 Polygon<Real_t, 4> poly2(v2);
0619 auto intersect = poly1.Intersect(poly2);
0620 if (intersect == FrameIntersect::kIntersect) return false;
0621
0622 auto center1 = poly1.GetCenter();
0623 auto center2 = poly2.GetCenter();
0624 if (frame1.Inside(Vector3D<Real_t>(center2[0], center2[1], 0)) ||
0625 frame2.Inside(trans.Transform(Vector3D<Real_t>(center1[0], center1[1], 0))))
0626 return false;
0627 return true;
0628 }
0629
0630 static FrameIntersect CheckFrames(WindowMask<Real_t> const &f1, QuadrilateralMask<Real_t> const &f2,
0631 TransformationMP<Real_t> const &trans)
0632 {
0633 if (AreDisjoint(f1, f2, trans)) return FrameIntersect::kNoIntersect;
0634 auto intersect_type = FrameIntersect::kIntersect;
0635 if (IsEmbedding(f1, f2, trans)) intersect_type = FrameIntersect::kEmbedding;
0636 if (FrameChecker<Real_t, QuadrilateralMask<Real_t>, WindowMask<Real_t>>::IsEmbedding(f2, f1, trans.Inverse())) {
0637 if (intersect_type == FrameIntersect::kEmbedding)
0638 intersect_type = FrameIntersect::kEqual;
0639 else
0640 intersect_type = FrameIntersect::kEmbedded;
0641 }
0642 return intersect_type;
0643 }
0644 };
0645
0646 template <typename Real_t>
0647 struct FrameChecker<Real_t, TriangleMask<Real_t>, RingMask<Real_t>> {
0648 static bool IsEmbedding(TriangleMask<Real_t> const &frame1, RingMask<Real_t> const &frame2,
0649 TransformationMP<Real_t> const &trans)
0650 {
0651
0652
0653 Vector3D<Real_t> center;
0654 Real_t safety = frame1.SafetyInside(trans.InverseTransform(center));
0655 return safety > frame2.rangeR[1] - vecgeom::kToleranceDist<Real_t> * frame2.rangeR[1];
0656 }
0657
0658 static bool AreDisjoint(TriangleMask<Real_t> const &frame1, RingMask<Real_t> const &frame2,
0659 TransformationMP<Real_t> const &trans)
0660 {
0661 return FrameChecker<Real_t, RingMask<Real_t>, TriangleMask<Real_t>>::AreDisjoint(frame2, frame1, trans.Inverse());
0662 }
0663
0664 static FrameIntersect CheckFrames(TriangleMask<Real_t> const &f1, RingMask<Real_t> const &f2,
0665 TransformationMP<Real_t> const &trans)
0666 {
0667 if (AreDisjoint(f1, f2, trans)) return FrameIntersect::kNoIntersect;
0668 auto intersect_type = FrameIntersect::kIntersect;
0669 if (IsEmbedding(f1, f2, trans)) intersect_type = FrameIntersect::kEmbedding;
0670 if (FrameChecker<Real_t, RingMask<Real_t>, TriangleMask<Real_t>>::IsEmbedding(f2, f1, trans.Inverse())) {
0671 if (intersect_type == FrameIntersect::kEmbedding)
0672 intersect_type = FrameIntersect::kEqual;
0673 else
0674 intersect_type = FrameIntersect::kEmbedded;
0675 }
0676 return intersect_type;
0677 }
0678 };
0679
0680 template <typename Real_t>
0681 struct FrameChecker<Real_t, TriangleMask<Real_t>, WindowMask<Real_t>> {
0682 static bool IsEmbedding(TriangleMask<Real_t> const &frame1, WindowMask<Real_t> const &frame2,
0683 TransformationMP<Real_t> const &trans)
0684 {
0685
0686 Vector3D<Real_t> v[4] = {{frame2.rangeU[0], frame2.rangeV[0], 0},
0687 {frame2.rangeU[0], frame2.rangeV[1], 0},
0688 {frame2.rangeU[1], frame2.rangeV[1], 0},
0689 {frame2.rangeU[1], frame2.rangeV[0], 0}};
0690
0691 for (auto i = 0; i < 4; ++i) {
0692 if (!frame1.Inside(trans.InverseTransform(v[i]))) return false;
0693 }
0694 return true;
0695 }
0696
0697 static bool AreDisjoint(TriangleMask<Real_t> const &frame1, WindowMask<Real_t> const &frame2,
0698 TransformationMP<Real_t> const &trans)
0699 {
0700 return FrameChecker<Real_t, WindowMask<Real_t>, TriangleMask<Real_t>>::AreDisjoint(frame2, frame1, trans.Inverse());
0701 }
0702
0703 static FrameIntersect CheckFrames(TriangleMask<Real_t> const &f1, WindowMask<Real_t> const &f2,
0704 TransformationMP<Real_t> const &trans)
0705 {
0706 if (AreDisjoint(f1, f2, trans)) return FrameIntersect::kNoIntersect;
0707 auto intersect_type = FrameIntersect::kIntersect;
0708 if (IsEmbedding(f1, f2, trans)) intersect_type = FrameIntersect::kEmbedding;
0709 if (FrameChecker<Real_t, WindowMask<Real_t>, TriangleMask<Real_t>>::IsEmbedding(f2, f1, trans.Inverse())) {
0710 if (intersect_type == FrameIntersect::kEmbedding)
0711 intersect_type = FrameIntersect::kEqual;
0712 else
0713 intersect_type = FrameIntersect::kEmbedded;
0714 }
0715 return intersect_type;
0716 }
0717 };
0718
0719 template <typename Real_t>
0720 struct FrameChecker<Real_t, TriangleMask<Real_t>, TriangleMask<Real_t>> {
0721 static bool IsEmbedding(TriangleMask<Real_t> const &frame1, TriangleMask<Real_t> const &frame2,
0722 TransformationMP<Real_t> const &trans)
0723 {
0724
0725 Vector3D<Real_t> v[3] = {{frame2.p_[0].x(), frame2.p_[0].y(), 0},
0726 {frame2.p_[1].x(), frame2.p_[1].y(), 0},
0727 {frame2.p_[2].x(), frame2.p_[2].y(), 0}};
0728 for (auto i = 0; i < 3; ++i) {
0729 if (!frame1.Inside(trans.InverseTransform(v[i]))) return false;
0730 }
0731 return true;
0732 }
0733
0734 static bool AreDisjoint(TriangleMask<Real_t> const &frame1, TriangleMask<Real_t> const &frame2,
0735 TransformationMP<Real_t> const &trans)
0736 {
0737
0738 Vector3D<Real_t> v1[3] = {{frame1.p_[0].x(), frame1.p_[0].y(), 0},
0739 {frame1.p_[1].x(), frame1.p_[1].y(), 0},
0740 {frame1.p_[2].x(), frame1.p_[2].y(), 0}};
0741 Vector3D<Real_t> v2[3] = {trans.InverseTransform(Vector3D<Real_t>(frame2.p_[0].x(), frame2.p_[0].y(), 0)),
0742 trans.InverseTransform(Vector3D<Real_t>(frame2.p_[1].x(), frame2.p_[1].y(), 0)),
0743 trans.InverseTransform(Vector3D<Real_t>(frame2.p_[2].x(), frame2.p_[2].y(), 0))};
0744 Polygon<Real_t, 3> poly1(v1);
0745 Polygon<Real_t, 3> poly2(v2);
0746 auto intersect = poly1.Intersect(poly2);
0747 if (intersect == FrameIntersect::kIntersect) return false;
0748
0749 auto center1 = poly1.GetCenter();
0750 auto center2 = poly2.GetCenter();
0751 if (frame1.Inside(Vector3D<Real_t>(center2[0], center2[1], 0)) ||
0752 frame2.Inside(trans.Transform(Vector3D<Real_t>(center1[0], center1[1], 0))))
0753 return false;
0754 return true;
0755 }
0756
0757 static FrameIntersect CheckFrames(TriangleMask<Real_t> const &f1, TriangleMask<Real_t> const &f2,
0758 TransformationMP<Real_t> const &trans)
0759 {
0760 if (AreDisjoint(f1, f2, trans)) return FrameIntersect::kNoIntersect;
0761 auto intersect_type = FrameIntersect::kIntersect;
0762 if (IsEmbedding(f1, f2, trans)) intersect_type = FrameIntersect::kEmbedding;
0763 if (IsEmbedding(f2, f1, trans.Inverse())) {
0764 if (intersect_type == FrameIntersect::kEmbedding)
0765 intersect_type = FrameIntersect::kEqual;
0766 else
0767 intersect_type = FrameIntersect::kEmbedded;
0768 }
0769 return intersect_type;
0770 }
0771 };
0772
0773 template <typename Real_t>
0774 struct FrameChecker<Real_t, TriangleMask<Real_t>, QuadrilateralMask<Real_t>> {
0775 static bool IsEmbedding(TriangleMask<Real_t> const &frame1, QuadrilateralMask<Real_t> const &frame2,
0776 TransformationMP<Real_t> const &trans)
0777 {
0778
0779 Vector3D<Real_t> v[4] = {{frame2.p_[0].x(), frame2.p_[0].y(), 0},
0780 {frame2.p_[1].x(), frame2.p_[1].y(), 0},
0781 {frame2.p_[2].x(), frame2.p_[2].y(), 0},
0782 {frame2.p_[3].x(), frame2.p_[3].y(), 0}};
0783 for (auto i = 0; i < 4; ++i) {
0784 if (!frame1.Inside(trans.InverseTransform(v[i]))) return false;
0785 }
0786 return true;
0787 }
0788
0789 static bool AreDisjoint(TriangleMask<Real_t> const &frame1, QuadrilateralMask<Real_t> const &frame2,
0790 TransformationMP<Real_t> const &trans)
0791 {
0792
0793 Vector3D<Real_t> v1[3] = {{frame1.p_[0].x(), frame1.p_[0].y(), 0},
0794 {frame1.p_[1].x(), frame1.p_[1].y(), 0},
0795 {frame1.p_[2].x(), frame1.p_[2].y(), 0}};
0796 Vector3D<Real_t> v2[4] = {trans.InverseTransform(Vector3D<Real_t>(frame2.p_[0].x(), frame2.p_[0].y(), 0)),
0797 trans.InverseTransform(Vector3D<Real_t>(frame2.p_[1].x(), frame2.p_[1].y(), 0)),
0798 trans.InverseTransform(Vector3D<Real_t>(frame2.p_[2].x(), frame2.p_[2].y(), 0)),
0799 trans.InverseTransform(Vector3D<Real_t>(frame2.p_[3].x(), frame2.p_[3].y(), 0))};
0800 Polygon<Real_t, 3> poly1(v1);
0801 Polygon<Real_t, 4> poly2(v2);
0802 auto intersect = poly1.Intersect(poly2);
0803 if (intersect == FrameIntersect::kIntersect) return false;
0804
0805 auto center1 = poly1.GetCenter();
0806 auto center2 = poly2.GetCenter();
0807 if (frame1.Inside(Vector3D<Real_t>(center2[0], center2[1], 0)) ||
0808 frame2.Inside(trans.Transform(Vector3D<Real_t>(center1[0], center1[1], 0))))
0809 return false;
0810 return true;
0811 }
0812
0813 static FrameIntersect CheckFrames(TriangleMask<Real_t> const &f1, QuadrilateralMask<Real_t> const &f2,
0814 TransformationMP<Real_t> const &trans)
0815 {
0816 if (AreDisjoint(f1, f2, trans)) return FrameIntersect::kNoIntersect;
0817 auto intersect_type = FrameIntersect::kIntersect;
0818 if (IsEmbedding(f1, f2, trans)) intersect_type = FrameIntersect::kEmbedding;
0819 if (FrameChecker<Real_t, QuadrilateralMask<Real_t>, TriangleMask<Real_t>>::IsEmbedding(f2, f1, trans.Inverse())) {
0820 if (intersect_type == FrameIntersect::kEmbedding)
0821 intersect_type = FrameIntersect::kEqual;
0822 else
0823 intersect_type = FrameIntersect::kEmbedded;
0824 }
0825 return intersect_type;
0826 }
0827 };
0828
0829 template <typename Real_t>
0830 struct FrameChecker<Real_t, QuadrilateralMask<Real_t>, RingMask<Real_t>> {
0831 static bool IsEmbedding(QuadrilateralMask<Real_t> const &frame1, RingMask<Real_t> const &frame2,
0832 TransformationMP<Real_t> const &trans)
0833 {
0834
0835
0836 Vector3D<Real_t> center;
0837 Real_t safety = frame1.SafetyInside(trans.InverseTransform(center));
0838 return safety > frame2.rangeR[1] - vecgeom::kToleranceDist<Real_t> * frame2.rangeR[1];
0839 }
0840
0841 static bool AreDisjoint(QuadrilateralMask<Real_t> const &frame1, RingMask<Real_t> const &frame2,
0842 TransformationMP<Real_t> const &trans)
0843 {
0844 return FrameChecker<Real_t, RingMask<Real_t>, QuadrilateralMask<Real_t>>::AreDisjoint(frame2, frame1,
0845 trans.Inverse());
0846 }
0847
0848 static FrameIntersect CheckFrames(QuadrilateralMask<Real_t> const &f1, RingMask<Real_t> const &f2,
0849 TransformationMP<Real_t> const &trans)
0850 {
0851 if (AreDisjoint(f1, f2, trans)) return FrameIntersect::kNoIntersect;
0852 auto intersect_type = FrameIntersect::kIntersect;
0853 if (IsEmbedding(f1, f2, trans)) intersect_type = FrameIntersect::kEmbedding;
0854 if (FrameChecker<Real_t, RingMask<Real_t>, QuadrilateralMask<Real_t>>::IsEmbedding(f2, f1, trans.Inverse())) {
0855 if (intersect_type == FrameIntersect::kEmbedding)
0856 intersect_type = FrameIntersect::kEqual;
0857 else
0858 intersect_type = FrameIntersect::kEmbedded;
0859 }
0860 return intersect_type;
0861 }
0862 };
0863
0864 template <typename Real_t>
0865 struct FrameChecker<Real_t, QuadrilateralMask<Real_t>, WindowMask<Real_t>> {
0866 static bool IsEmbedding(QuadrilateralMask<Real_t> const &frame1, WindowMask<Real_t> const &frame2,
0867 TransformationMP<Real_t> const &trans)
0868 {
0869
0870 Vector3D<Real_t> v[4] = {{frame2.rangeU[0], frame2.rangeV[0], 0},
0871 {frame2.rangeU[0], frame2.rangeV[1], 0},
0872 {frame2.rangeU[1], frame2.rangeV[1], 0},
0873 {frame2.rangeU[1], frame2.rangeV[0], 0}};
0874
0875 for (auto i = 0; i < 4; ++i) {
0876 if (!frame1.Inside(trans.InverseTransform(v[i]))) return false;
0877 }
0878 return true;
0879 }
0880
0881 static bool AreDisjoint(QuadrilateralMask<Real_t> const &frame1, WindowMask<Real_t> const &frame2,
0882 TransformationMP<Real_t> const &trans)
0883 {
0884 return FrameChecker<Real_t, WindowMask<Real_t>, QuadrilateralMask<Real_t>>::AreDisjoint(frame2, frame1,
0885 trans.Inverse());
0886 }
0887
0888 static FrameIntersect CheckFrames(QuadrilateralMask<Real_t> const &f1, WindowMask<Real_t> const &f2,
0889 TransformationMP<Real_t> const &trans)
0890 {
0891 if (AreDisjoint(f1, f2, trans)) return FrameIntersect::kNoIntersect;
0892 auto intersect_type = FrameIntersect::kIntersect;
0893 if (IsEmbedding(f1, f2, trans)) intersect_type = FrameIntersect::kEmbedding;
0894 if (FrameChecker<Real_t, WindowMask<Real_t>, QuadrilateralMask<Real_t>>::IsEmbedding(f2, f1, trans.Inverse())) {
0895 if (intersect_type == FrameIntersect::kEmbedding)
0896 intersect_type = FrameIntersect::kEqual;
0897 else
0898 intersect_type = FrameIntersect::kEmbedded;
0899 }
0900 return intersect_type;
0901 }
0902 };
0903
0904 template <typename Real_t>
0905 struct FrameChecker<Real_t, QuadrilateralMask<Real_t>, TriangleMask<Real_t>> {
0906 static bool IsEmbedding(QuadrilateralMask<Real_t> const &frame1, TriangleMask<Real_t> const &frame2,
0907 TransformationMP<Real_t> const &trans)
0908 {
0909
0910 Vector3D<Real_t> v[3] = {{frame2.p_[0].x(), frame2.p_[0].y(), 0},
0911 {frame2.p_[1].x(), frame2.p_[1].y(), 0},
0912 {frame2.p_[2].x(), frame2.p_[2].y(), 0}};
0913 for (auto i = 0; i < 3; ++i) {
0914 if (!frame1.Inside(trans.InverseTransform(v[i]))) return false;
0915 }
0916 return true;
0917 }
0918
0919 static bool AreDisjoint(QuadrilateralMask<Real_t> const &frame1, TriangleMask<Real_t> const &frame2,
0920 TransformationMP<Real_t> const &trans)
0921 {
0922 return FrameChecker<Real_t, TriangleMask<Real_t>, QuadrilateralMask<Real_t>>::AreDisjoint(frame2, frame1,
0923 trans.Inverse());
0924 }
0925
0926 static FrameIntersect CheckFrames(QuadrilateralMask<Real_t> const &f1, TriangleMask<Real_t> const &f2,
0927 TransformationMP<Real_t> const &trans)
0928 {
0929 if (AreDisjoint(f1, f2, trans)) return FrameIntersect::kNoIntersect;
0930 auto intersect_type = FrameIntersect::kIntersect;
0931 if (IsEmbedding(f1, f2, trans)) intersect_type = FrameIntersect::kEmbedding;
0932 if (FrameChecker<Real_t, TriangleMask<Real_t>, QuadrilateralMask<Real_t>>::IsEmbedding(f2, f1, trans.Inverse())) {
0933 if (intersect_type == FrameIntersect::kEmbedding)
0934 intersect_type = FrameIntersect::kEqual;
0935 else
0936 intersect_type = FrameIntersect::kEmbedded;
0937 }
0938 return intersect_type;
0939 }
0940 };
0941
0942 template <typename Real_t>
0943 struct FrameChecker<Real_t, QuadrilateralMask<Real_t>, QuadrilateralMask<Real_t>> {
0944 static bool IsEmbedding(QuadrilateralMask<Real_t> const &frame1, QuadrilateralMask<Real_t> const &frame2,
0945 TransformationMP<Real_t> const &trans)
0946 {
0947
0948 Vector3D<Real_t> v[4] = {{frame2.p_[0].x(), frame2.p_[0].y(), 0},
0949 {frame2.p_[1].x(), frame2.p_[1].y(), 0},
0950 {frame2.p_[2].x(), frame2.p_[2].y(), 0},
0951 {frame2.p_[3].x(), frame2.p_[3].y(), 0}};
0952 for (auto i = 0; i < 4; ++i) {
0953 if (!frame1.Inside(trans.InverseTransform(v[i]))) return false;
0954 }
0955 return true;
0956 }
0957
0958 static bool AreDisjoint(QuadrilateralMask<Real_t> const &frame1, QuadrilateralMask<Real_t> const &frame2,
0959 TransformationMP<Real_t> const &trans)
0960 {
0961
0962 Vector3D<Real_t> v1[4] = {{frame1.p_[0].x(), frame1.p_[0].y(), 0},
0963 {frame1.p_[1].x(), frame1.p_[1].y(), 0},
0964 {frame1.p_[2].x(), frame1.p_[2].y(), 0},
0965 {frame1.p_[3].x(), frame1.p_[3].y(), 0}};
0966 Vector3D<Real_t> v2[4] = {trans.InverseTransform(Vector3D<Real_t>(frame2.p_[0].x(), frame2.p_[0].y(), 0)),
0967 trans.InverseTransform(Vector3D<Real_t>(frame2.p_[1].x(), frame2.p_[1].y(), 0)),
0968 trans.InverseTransform(Vector3D<Real_t>(frame2.p_[2].x(), frame2.p_[2].y(), 0)),
0969 trans.InverseTransform(Vector3D<Real_t>(frame2.p_[3].x(), frame2.p_[3].y(), 0))};
0970 Polygon<Real_t, 4> poly1(v1);
0971 Polygon<Real_t, 4> poly2(v2);
0972 auto intersect = poly1.Intersect(poly2);
0973 if (intersect == FrameIntersect::kIntersect) return false;
0974
0975 auto center1 = poly1.GetCenter();
0976 auto center2 = poly2.GetCenter();
0977 if (frame1.Inside(Vector3D<Real_t>(center2[0], center2[1], 0)) ||
0978 frame2.Inside(trans.Transform(Vector3D<Real_t>(center1[0], center1[1], 0))))
0979 return false;
0980 return true;
0981 }
0982
0983 static FrameIntersect CheckFrames(QuadrilateralMask<Real_t> const &f1, QuadrilateralMask<Real_t> const &f2,
0984 TransformationMP<Real_t> const &trans)
0985 {
0986 if (AreDisjoint(f1, f2, trans)) return FrameIntersect::kNoIntersect;
0987 auto intersect_type = FrameIntersect::kIntersect;
0988 if (IsEmbedding(f1, f2, trans)) intersect_type = FrameIntersect::kEmbedding;
0989 if (IsEmbedding(f2, f1, trans.Inverse())) {
0990 if (intersect_type == FrameIntersect::kEmbedding)
0991 intersect_type = FrameIntersect::kEqual;
0992 else
0993 intersect_type = FrameIntersect::kEmbedded;
0994 }
0995 return intersect_type;
0996 }
0997 };
0998
0999
1000
1001 }
1002
1003 #endif