23#ifndef DUMUX_GEOMETRY_INTERSECTION_HH
24#define DUMUX_GEOMETRY_INTERSECTION_HH
28#include <dune/common/exceptions.hh>
29#include <dune/common/promotiontraits.hh>
30#include <dune/geometry/multilineargeometry.hh>
38namespace IntersectionPolicy {
41template<
class ct,
int dw>
45 using Point = Dune::FieldVector<ctype, dw>;
53template<
class ct,
int dw>
57 using Point = Dune::FieldVector<ctype, dw>;
66template<
class ct,
int dw>
70 using Point = Dune::FieldVector<ctype, dw>;
79template<
class ct,
int dw>
83 using Point = Dune::FieldVector<ctype, dw>;
92template<
class Geometry1,
class Geometry2>
95 static constexpr int dimworld = Geometry1::coorddimension;
96 static constexpr int isDim = std::min(
int(Geometry1::mydimension),
int(Geometry2::mydimension) );
97 static_assert(dimworld == int(Geometry2::coorddimension),
98 "Geometries must have the same coordinate dimension!");
99 static_assert(int(Geometry1::mydimension) <= 3 && int(Geometry2::mydimension) <= 3,
100 "Geometries must have dimension 3 or less.");
101 using ctype =
typename Dune::PromotionTraits<typename Geometry1::ctype, typename Geometry2::ctype>::PromotedType;
103 using DefaultPolicies = std::tuple<PointPolicy<ctype, dimworld>,
108 using type = std::tuple_element_t<isDim, DefaultPolicies>;
112template<
class Geometry1,
class Geometry2>
132template<
class Geo1,
class Geo2,
class ctype,
133 class GetFacetCornerIndices,
class ComputeNormalFunction >
135 ctype& tfirst, ctype& tlast,
136 const GetFacetCornerIndices& getFacetCornerIndices,
137 const ComputeNormalFunction& computeNormal)
139 static_assert(int(Geo2::mydimension) == 1,
"Geometry2 must be a segment");
140 static_assert(int(Geo1::mydimension) > int(Geo2::mydimension),
141 "Dimension of Geometry1 must be higher than that of Geometry2");
143 const auto a = geo2.corner(0);
144 const auto b = geo2.corner(1);
145 const auto d = b - a;
153 const auto facets = getFacetCornerIndices(geo1);
154 for (
const auto& f : facets)
156 const auto n = computeNormal(f);
158 const auto c0 = geo1.corner(f[0]);
159 const ctype denom = n*d;
160 const ctype dist = n*(a-c0);
163 const auto edge1 = geo1.corner(f[1]) - geo1.corner(f[0]);
164 const ctype eps = baseEps*edge1.two_norm();
169 if (abs(denom) < eps)
176 const ctype t = -dist / denom;
192 if (tfirst > tlast - baseEps)
210<
class Geometry1,
class Geometry2,
211 class Policy = IntersectionPolicy::DefaultPolicy<Geometry1, Geometry2>,
212 int dimworld = Geometry1::coorddimension,
213 int dim1 = Geometry1::mydimension,
214 int dim2 = Geometry2::mydimension>
217 static constexpr int dimWorld = Policy::dimWorld;
220 using ctype =
typename Policy::ctype;
221 using Point =
typename Policy::Point;
227 static_assert(dimworld == Geometry2::coorddimension,
"Can only intersect geometries of same coordinate dimension");
228 DUNE_THROW(Dune::NotImplemented,
"Geometry intersection detection with intersection computation not implemented for dimworld = "
229 << dimworld <<
", dim1 = " << dim1 <<
", dim2 = " << dim2);
237template <
class Geometry1,
class Geometry2,
class Policy>
240 enum { dimworld = 2 };
245 static constexpr typename Policy::ctype eps_ = 1.5e-7;
248 using ctype =
typename Policy::ctype;
249 using Point =
typename Policy::Point;
258 template<
class P = Policy, std::enable_if_t<P::dimIntersection == 0,
int> = 0>
261 static_assert(int(dimworld) == int(Geometry2::coorddimension),
"Can only collide geometries of same coordinate dimension");
263 const auto v1 = geo1.corner(1) - geo1.corner(0);
264 const auto v2 = geo2.corner(1) - geo2.corner(0);
265 const auto ac = geo2.corner(0) - geo1.corner(0);
267 auto n2 =
Point({-1.0*v2[1], v2[0]});
271 const auto dist12 = n2*ac;
277 const auto v1Norm2 = v1.two_norm2();
278 const auto eps = eps_*sqrt(v1Norm2);
279 const auto eps2 = eps_*v1Norm2;
281 const auto sp = n2*v1;
284 if (abs(dist12) > eps)
290 if ( ac.two_norm2() < eps2 )
293 if ( (geo2.corner(1) - geo1.corner(1)).two_norm2() < eps2 )
298 if ( (geo2.corner(1) - geo1.corner(0)).two_norm2() < eps2 )
301 if ( (geo2.corner(0) - geo1.corner(1)).two_norm2() < eps2 )
310 const auto t1 = dist12 / sp;
313 if (t1 < -1.0*eps_ || t1 > 1.0 + eps_)
317 auto isPoint = geo1.global(t1);
320 const auto c = geo2.corner(0);
321 const auto d = geo2.corner(1);
323 using std::min;
using std::max;
324 std::array<ctype, 4> bBox({ min(c[0], d[0]), min(c[1], d[1]), max(c[0], d[0]), max(c[1], d[1]) });
341 template<
class P = Policy, std::enable_if_t<P::dimIntersection == 1,
int> = 0>
344 static_assert(int(dimworld) == int(Geometry2::coorddimension),
"Can only collide geometries of same coordinate dimension");
346 const auto& a = geo1.corner(0);
347 const auto& b = geo1.corner(1);
348 const auto ab = b - a;
350 const auto& p = geo2.corner(0);
351 const auto& q = geo2.corner(1);
352 const auto pq = q - p;
353 Dune::FieldVector<ctype, dimworld> n2{-pq[1], pq[0]};
356 const auto abNorm2 = ab.two_norm2();
357 const auto pqNorm2 = pq.two_norm2();
358 const auto eps2 = eps_*max(abNorm2, pqNorm2);
362 if (abs(n2*ab) > eps2)
366 const auto ap = p - a;
367 if (abs(ap*n2) > eps2)
372 auto t2 = ab*(q - a);
379 t1 = clamp(t1, 0.0, abNorm2);
380 t2 = clamp(t2, 0.0, abNorm2);
382 if (abs(t2-t1) < eps2)
394template <
class Geometry1,
class Geometry2,
class Policy>
397 enum { dimworld = 2 };
402 using ctype =
typename Policy::ctype;
403 using Point =
typename Policy::Point;
407 static constexpr ctype eps_ = 1.5e-7;
417 template<
class P = Policy, std::enable_if_t<P::dimIntersection == 1,
int> = 0>
420 static_assert(int(dimworld) == int(Geometry2::coorddimension),
"Can only collide geometries of same coordinate dimension");
423 if (intersect_(geo1, geo2, tfirst, tlast))
441 template<
class P = Policy, std::enable_if_t<P::dimIntersection == 0,
int> = 0>
444 static_assert(int(dimworld) == int(Geometry2::coorddimension),
"Can only collide geometries of same coordinate dimension");
447 if (!intersect_(geo1, geo2, tfirst, tlast))
451 if ( tfirst > tlast - eps_ )
465 static bool intersect_(
const Geometry1& geo1,
const Geometry2& geo2,
ctype& tfirst,
ctype& tlast)
468 auto getFacetCorners = [] (
const Geometry1& geo1)
470 std::vector< std::array<int, 2> > facetCorners;
471 switch (geo1.corners())
474 facetCorners = {{0, 2}, {3, 1}, {1, 0}, {2, 3}};
477 facetCorners = {{1, 0}, {0, 2}, {2, 1}};
480 DUNE_THROW(Dune::NotImplemented,
"Collision of segment and geometry of type "
481 << geo1.type() <<
" with "<< geo1.corners() <<
" corners.");
488 const auto center1 = geo1.center();
489 auto computeNormal = [&geo1, ¢er1] (
const std::array<int, 2>& facetCorners)
491 const auto c0 = geo1.corner(facetCorners[0]);
492 const auto c1 = geo1.corner(facetCorners[1]);
493 const auto edge = c1 - c0;
495 Dune::FieldVector<ctype, dimworld> n({-1.0*edge[1], edge[0]});
500 if ( n*(center1-c0) > 0.0 )
514template <
class Geometry1,
class Geometry2,
class Policy>
528 template<
class P = Policy>
539template <
class Geometry1,
class Geometry2,
class Policy>
542 enum { dimworld = 2 };
547 using ctype =
typename Policy::ctype;
548 using Point =
typename Policy::Point;
552 static constexpr ctype eps_ = 1.5e-7;
567 template<
class P = Policy, std::enable_if_t<P::dimIntersection == 2,
int> = 0>
570 static_assert(int(dimworld) == int(Geometry2::coorddimension),
"Can only collide geometries of same coordinate dimension");
573 std::vector<Point> points; points.reserve(6);
576 for (
int i = 0; i < geo1.corners(); ++i)
578 points.emplace_back(geo1.corner(i));
580 const auto numPoints1 = points.size();
581 if (numPoints1 != geo1.corners())
584 for (
int i = 0; i < geo2.corners(); ++i)
586 points.emplace_back(geo2.corner(i));
591 if (points.size() - numPoints1 != geo2.corners())
593 const auto refElement1 = referenceElement(geo1);
594 const auto refElement2 = referenceElement(geo2);
597 using SegGeometry = Dune::MultiLinearGeometry<ctype, 1, dimworld>;
599 for (
int i = 0; i < refElement1.size(dim1-1); ++i)
601 const auto localEdgeGeom1 = refElement1.template geometry<dim1-1>(i);
603 std::vector<Point>( {geo1.global(localEdgeGeom1.corner(0)),
604 geo1.global(localEdgeGeom1.corner(1))} ));
606 for (
int j = 0; j < refElement2.size(dim2-1); ++j)
608 const auto localEdgeGeom2 = refElement2.template geometry<dim2-1>(j);
610 std::vector<Point>( {geo2.global(localEdgeGeom2.corner(0)),
611 geo2.global(localEdgeGeom2.corner(1))} ));
614 typename EdgeTest::Intersection edgeIntersection;
615 if (EdgeTest::intersection(edge1, edge2, edgeIntersection))
616 points.emplace_back(edgeIntersection);
626 const auto eps = (geo1.corner(0) - geo1.corner(1)).two_norm()*eps_;
627 std::sort(points.begin(), points.end(), [&eps](
const auto& a,
const auto& b) ->
bool
630 return (abs(a[0]-b[0]) > eps ? a[0] < b[0] : a[1] < b[1]);
633 auto removeIt = std::unique(points.begin(), points.end(), [&eps](
const auto& a,
const auto&b)
635 return (b-a).two_norm() < eps;
638 points.erase(removeIt, points.end());
641 if (points.size() < 3)
657 template<
class P = Policy, std::enable_if_t<P::dimIntersection == 1,
int> = 0>
660 static_assert(int(dimworld) == int(Geometry2::coorddimension),
"Can only collide geometries of same coordinate dimension");
661 DUNE_THROW(Dune::NotImplemented,
"Polygon-polygon intersection detection for segment-like intersections");
671 template<
class P = Policy, std::enable_if_t<P::dimIntersection == 0,
int> = 0>
674 static_assert(int(dimworld) == int(Geometry2::coorddimension),
"Can only collide geometries of same coordinate dimension");
675 DUNE_THROW(Dune::NotImplemented,
"Polygon-polygon intersection detection for touching points");
683template <
class Geometry1,
class Geometry2,
class Policy>
686 enum { dimworld = 3 };
691 using ctype =
typename Policy::ctype;
692 using Point =
typename Policy::Point;
696 static constexpr ctype eps_ = 1.5e-7;
710 template<
class P = Policy, std::enable_if_t<P::dimIntersection == 1,
int> = 0>
713 static_assert(int(dimworld) == int(Geometry2::coorddimension),
"Can only collide geometries of same coordinate dimension");
716 if (intersect_(geo1, geo2, tfirst, tlast))
738 template<
class P = Policy, std::enable_if_t<P::dimIntersection == 0,
int> = 0>
741 static_assert(int(dimworld) == int(Geometry2::coorddimension),
"Can only collide geometries of same coordinate dimension");
744 if (intersect_(geo1, geo2, tfirst, tlast))
748 if ( abs(tfirst - tlast) < eps_ )
762 static bool intersect_(
const Geometry1& geo1,
const Geometry2& geo2,
ctype& tfirst,
ctype& tlast)
765 auto getFacetCorners = [] (
const Geometry1& geo1)
767 std::vector< std::vector<int> > facetCorners;
769 switch (geo1.corners())
773 facetCorners = {{2, 0, 6, 4}, {1, 3, 5, 7}, {0, 1, 4, 5},
774 {3, 2, 7, 6}, {1, 0, 3, 2}, {4, 5, 6, 7}};
777 facetCorners = {{0, 2, 1}, {3, 4, 5}, {0, 1, 3, 4}, {0, 3, 2, 5}, {1, 2, 4, 5}};
780 facetCorners = {{0, 2, 1, 3}, {0, 1, 4}, {1, 3, 4}, {2, 4, 3}, {0, 4, 2}};
783 facetCorners = {{1, 0, 2}, {0, 1, 3}, {0, 3, 2}, {1, 2, 3}};
786 DUNE_THROW(Dune::NotImplemented,
"Collision of segment and geometry of type "
787 << geo1.type() <<
", "<< geo1.corners() <<
" corners.");
794 auto computeNormal = [&geo1] (
const std::vector<int>& facetCorners)
796 const auto v0 = geo1.corner(facetCorners[1]) - geo1.corner(facetCorners[0]);
797 const auto v1 = geo1.corner(facetCorners[2]) - geo1.corner(facetCorners[0]);
813template <
class Geometry1,
class Geometry2,
class Policy>
826 template<
class P = Policy>
837template <
class Geometry1,
class Geometry2,
class Policy>
840 enum { dimworld = 3 };
845 using ctype =
typename Policy::ctype;
846 using Point =
typename Policy::Point;
850 static constexpr ctype eps_ = 1.5e-7;
851 using ReferenceElementsGeo1 =
typename Dune::ReferenceElements<ctype, dim1>;
852 using ReferenceElementsGeo2 =
typename Dune::ReferenceElements<ctype, dim2>;
866 template<
class P = Policy, std::enable_if_t<P::dimIntersection == 2,
int> = 0>
869 static_assert(int(dimworld) == int(Geometry2::coorddimension),
"Can only collide geometries of same coordinate dimension");
872 const auto a1 = geo1.corner(1) - geo1.corner(0);
873 const auto b1 = geo1.corner(2) - geo1.corner(0);
876 const auto a2 = geo2.corner(1) - geo2.corner(0);
877 const auto b2 = geo2.corner(2) - geo2.corner(0);
881 const auto a1Norm2 = a1.two_norm2();
882 const auto b1Norm2 = b1.two_norm2();
885 const auto maxNorm2 = max(a1Norm2, b1Norm2);
886 const auto eps2 = maxNorm2*eps_;
894 auto d1 = geo2.corner(0) - geo1.corner(0);
895 if (d1.two_norm2() < eps2)
896 d1 = geo2.corner(1) - geo1.corner(0);
899 const auto maxNorm = sqrt(maxNorm2);
900 const auto eps3 = maxNorm*eps2;
902 if (abs(d1*n2) > eps3)
906 std::vector<Point> points; points.reserve(8);
909 for (
int i = 0; i < geo1.corners(); ++i)
911 points.emplace_back(geo1.corner(i));
913 const auto numPoints1 = points.size();
914 const bool resultIsGeo1 = numPoints1 == geo1.corners();
918 for (
int i = 0; i < geo2.corners(); ++i)
920 points.emplace_back(geo2.corner(i));
922 const bool resultIsGeo2 = (points.size() - numPoints1) == geo2.corners();
925 const auto referenceElement1 = ReferenceElementsGeo1::general(geo1.type());
926 const auto referenceElement2 = ReferenceElementsGeo2::general(geo2.type());
929 using SegGeometry = Dune::MultiLinearGeometry<ctype, 1, dimworld>;
931 for (
int i = 0; i < referenceElement1.size(dim1-1); ++i)
933 const auto localEdgeGeom1 = referenceElement1.template geometry<dim1-1>(i);
934 const auto edge1 = SegGeometry(
937 geo1.global(localEdgeGeom1.corner(0)),
938 geo1.global(localEdgeGeom1.corner(1))
942 for (
int j = 0; j < referenceElement2.size(dim2-1); ++j)
944 const auto localEdgeGeom2 = referenceElement2.template geometry<dim2-1>(j);
945 const auto edge2 = SegGeometry(
948 geo2.global(localEdgeGeom2.corner(0)),
949 geo2.global(localEdgeGeom2.corner(1))
954 typename EdgeTest::Intersection edgeIntersection;
955 if (EdgeTest::intersection(edge1, edge2, edgeIntersection))
956 points.emplace_back(edgeIntersection);
966 const auto eps = maxNorm*eps_;
967 std::sort(points.begin(), points.end(), [eps] (
const auto& a,
const auto& b) ->
bool
970 return (abs(a[0]-b[0]) > eps ? a[0] < b[0]
971 : (abs(a[1]-b[1]) > eps ? a[1] < b[1]
975 const auto squaredEps = eps*eps;
976 points.erase(std::unique(
977 points.begin(), points.end(),
978 [squaredEps] (
const auto& a,
const auto&b) { return (b-a).two_norm2() < squaredEps; }),
983 if (points.size() < 3)
999 template<
class P = Policy, std::enable_if_t<P::dimIntersection == 1,
int> = 0>
1002 static_assert(int(dimworld) == int(Geometry2::coorddimension),
"Can only collide geometries of same coordinate dimension");
1003 DUNE_THROW(Dune::NotImplemented,
"Polygon-polygon intersection detection for segment-like intersections");
1013 template<
class P = Policy, std::enable_if_t<P::dimIntersection == 0,
int> = 0>
1016 static_assert(int(dimworld) == int(Geometry2::coorddimension),
"Can only collide geometries of same coordinate dimension");
1017 DUNE_THROW(Dune::NotImplemented,
"Polygon-polygon intersection detection for touching points");
1025template <
class Geometry1,
class Geometry2,
class Policy>
1028 enum { dimworld = 3 };
1038 static constexpr ctype eps_ = 1.5e-7;
1055 template<
class P = Policy, std::enable_if_t<P::dimIntersection == 2,
int> = 0>
1058 static_assert(int(dimworld) == int(Geometry2::coorddimension),
"Can only collide geometries of same coordinate dimension");
1061 std::vector<Point> points; points.reserve(10);
1064 for (
int i = 0; i < geo1.corners(); ++i)
1066 points.emplace_back(geo1.corner(i));
1069 for (
int i = 0; i < geo2.corners(); ++i)
1071 points.emplace_back(geo2.corner(i));
1074 using PolyhedronFaceGeometry = Dune::MultiLinearGeometry<ctype, 2, dimworld>;
1075 using SegGeometry = Dune::MultiLinearGeometry<ctype, 1, dimworld>;
1077 const auto refElement1 = referenceElement(geo1);
1078 const auto refElement2 = referenceElement(geo2);
1084 for (
int i = 0; i < refElement1.size(dim1-1); ++i)
1086 const auto localEdgeGeom = refElement1.template geometry<dim1-1>(i);
1087 const auto p = geo1.global(localEdgeGeom.corner(0));
1088 const auto q = geo1.global(localEdgeGeom.corner(1));
1092 typename PolySegTest::Intersection polySegIntersection;
1093 if (PolySegTest::intersection(geo2, segGeo, polySegIntersection))
1094 points.emplace_back(std::move(polySegIntersection));
1098 for (
int i = 0; i < refElement1.size(1); ++i)
1100 const auto faceGeo = [&]()
1102 const auto localFaceGeo = refElement1.template geometry<1>(i);
1103 if (localFaceGeo.corners() == 4)
1105 const auto a = geo1.global(localFaceGeo.corner(0));
1106 const auto b = geo1.global(localFaceGeo.corner(1));
1107 const auto c = geo1.global(localFaceGeo.corner(2));
1108 const auto d = geo1.global(localFaceGeo.corner(3));
1110 return PolyhedronFaceGeometry(Dune::GeometryTypes::cube(2), std::vector<Point>{a, b, c, d});
1114 const auto a = geo1.global(localFaceGeo.corner(0));
1115 const auto b = geo1.global(localFaceGeo.corner(1));
1116 const auto c = geo1.global(localFaceGeo.corner(2));
1118 return PolyhedronFaceGeometry(Dune::GeometryTypes::simplex(2), std::vector<Point>{a, b, c});
1122 for (
int j = 0; j < refElement2.size(1); ++j)
1124 const auto localEdgeGeom = refElement2.template geometry<1>(j);
1125 const auto p = geo2.global(localEdgeGeom.corner(0));
1126 const auto q = geo2.global(localEdgeGeom.corner(1));
1131 typename PolySegTest::Intersection polySegIntersection;
1132 if (PolySegTest::intersection(faceGeo, segGeo, polySegIntersection))
1133 points.emplace_back(std::move(polySegIntersection));
1138 if (points.empty())
return false;
1141 const auto eps = (geo1.corner(0) - geo1.corner(1)).two_norm()*eps_;
1142 const auto notEqual = [eps] (
auto a,
auto b) {
using std::abs;
return abs(b-a) > eps; };
1143 std::sort(points.begin(), points.end(), [notEqual](
const auto& a,
const auto& b) ->
bool
1145 return (notEqual(a[0], b[0]) ? a[0] < b[0]
1146 : (notEqual(a[1], b[1]) ? a[1] < b[1]
1150 const auto squaredEps = eps*eps;
1151 points.erase(std::unique(
1152 points.begin(), points.end(),
1153 [squaredEps] (
const auto& a,
const auto&b) { return (b-a).two_norm2() < squaredEps; }),
1158 if (points.size() < 3)
return false;
1181 template<
class P = Policy, std::enable_if_t<P::dimIntersection != 2,
int> = 0>
1184 static_assert(int(dimworld) == int(Geometry2::coorddimension),
"Can only collide geometries of same coordinate dimension");
1185 DUNE_THROW(Dune::NotImplemented,
"Polyhedron-polygon intersection detection only implemented for polygon-like intersections");
1193template <
class Geometry1,
class Geometry2,
class Policy>
1206 template<
class P = Policy>
1217template <
class Geometry1,
class Geometry2,
class Policy>
1220 enum { dimworld = 3 };
1230 static constexpr ctype eps_ = 1.5e-7;
1244 template<
class P = Policy, std::enable_if_t<P::dimIntersection == 3,
int> = 0>
1248 int(dimworld) == int(Geometry2::coorddimension),
1249 "Can only collide geometries of same coordinate dimension"
1252 const auto refElement1 = referenceElement(geo1);
1253 const auto refElement2 = referenceElement(geo2);
1256 std::vector<Point> points;
1257 points.reserve(refElement1.size(2) + refElement2.size(2));
1260 const auto addPointIntersections = [&](
const auto& g1,
const auto& g2)
1262 for (
int i = 0; i < g1.corners(); ++i)
1264 points.emplace_back(c);
1267 addPointIntersections(geo1, geo2);
1268 addPointIntersections(geo2, geo1);
1271 using PolyhedronFaceGeometry = Dune::MultiLinearGeometry<ctype, 2, dimworld>;
1272 using SegGeometry = Dune::MultiLinearGeometry<ctype, 1, dimworld>;
1278 const auto addEdgeIntersections = [&](
const auto& g1,
const auto& g2,
const auto& ref1,
const auto& ref2)
1280 for (
int i = 0; i < ref1.size(1); ++i)
1282 const auto faceGeo = [&]()
1284 const auto localFaceGeo = ref1.template geometry<1>(i);
1285 if (localFaceGeo.corners() == 4)
1287 const auto a = g1.global(localFaceGeo.corner(0));
1288 const auto b = g1.global(localFaceGeo.corner(1));
1289 const auto c = g1.global(localFaceGeo.corner(2));
1290 const auto d = g1.global(localFaceGeo.corner(3));
1292 return PolyhedronFaceGeometry(
1293 Dune::GeometryTypes::cube(2), std::vector<Point>{a, b, c, d}
1298 const auto a = g1.global(localFaceGeo.corner(0));
1299 const auto b = g1.global(localFaceGeo.corner(1));
1300 const auto c = g1.global(localFaceGeo.corner(2));
1302 return PolyhedronFaceGeometry(
1303 Dune::GeometryTypes::simplex(2), std::vector<Point>{a, b, c}
1308 for (
int j = 0; j < ref2.size(2); ++j)
1310 const auto localEdgeGeom = ref2.template geometry<2>(j);
1311 const auto p = g2.global(localEdgeGeom.corner(0));
1312 const auto q = g2.global(localEdgeGeom.corner(1));
1317 typename PolySegTest::Intersection polySegIntersection;
1318 if (PolySegTest::intersection(faceGeo, segGeo, polySegIntersection))
1319 points.emplace_back(std::move(polySegIntersection));
1324 addEdgeIntersections(geo1, geo2, refElement1, refElement2);
1325 addEdgeIntersections(geo2, geo1, refElement2, refElement1);
1332 const auto norm = (geo1.corner(0) - geo1.corner(1)).two_norm();
1333 const auto eps = norm*eps_;
1334 const auto notEqual = [eps] (
auto a,
auto b) {
using std::abs;
return abs(b-a) > eps; };
1335 std::sort(points.begin(), points.end(), [notEqual](
const auto& a,
const auto& b) ->
bool
1337 return (notEqual(a[0], b[0]) ? a[0] < b[0]
1338 : (notEqual(a[1], b[1]) ? a[1] < b[1]
1342 const auto squaredEps = eps*eps;
1343 points.erase(std::unique(
1344 points.begin(), points.end(),
1345 [squaredEps] (
const auto& a,
const auto&b) { return (b-a).two_norm2() < squaredEps; }),
1350 if (points.size() < 4)
1354 const bool coplanar = [&]
1356 const auto p0 = points[0];
1360 const auto epsCoplanar =
normal.two_norm()*norm*eps_;
1361 for (
int i = 3; i < points.size(); ++i)
1363 const auto ad = points[i] - p0;
1365 if (abs(
normal*ad) > epsCoplanar)
1387 template<
class P = Policy, std::enable_if_t<P::dimIntersection != 3,
int> = 0>
1390 static_assert(int(dimworld) == int(Geometry2::coorddimension),
"Can only collide geometries of same coordinate dimension");
1391 DUNE_THROW(Dune::NotImplemented,
"Polyhedron-polygon intersection detection only implemented for polygon-like intersections");
1399template <
class Geometry1,
class Geometry2,
class Policy>
1402 enum { dimworld = 3 };
1412 static constexpr ctype eps_ = 1.5e-7;
1424 template<
class P = Policy, std::enable_if_t<P::dimIntersection == 1,
int> = 0>
1427 static_assert(int(dimworld) == int(Geometry2::coorddimension),
"Can only collide geometries of same coordinate dimension");
1429 ctype tfirst, tlast;
1430 if (intersect_(geo1, geo2, tfirst, tlast))
1450 template<
class P = Policy, std::enable_if_t<P::dimIntersection == 0,
int> = 0>
1453 static_assert(int(dimworld) == int(Geometry2::coorddimension),
"Can only collide geometries of same coordinate dimension");
1455 const auto p = geo2.corner(0);
1456 const auto q = geo2.corner(1);
1458 const auto a = geo1.corner(0);
1459 const auto b = geo1.corner(1);
1460 const auto c = geo1.corner(2);
1462 if (geo1.corners() == 3)
1463 return intersect_<Policy>(a, b, c, p, q, is);
1465 else if (geo1.corners() == 4)
1468 bool hasSegment1, hasSegment2;
1470 const auto d = geo1.corner(3);
1471 const bool intersects1 = intersect_<Policy>(a, b, d, p, q, is1, hasSegment1);
1472 const bool intersects2 = intersect_<Policy>(a, d, c, p, q, is2, hasSegment2);
1474 if (hasSegment1 || hasSegment2)
1477 if (intersects1) { is = is1;
return true; }
1478 if (intersects2) { is = is2;
return true; }
1484 DUNE_THROW(Dune::NotImplemented,
"Collision of segment and geometry of type "
1485 << geo1.type() <<
", "<< geo1.corners() <<
" corners.");
1492 template<
class P = Policy, std::enable_if_t<P::dimIntersection == 1,
int> = 0>
1493 static bool intersect_(
const Geometry1& geo1,
const Geometry2& geo2,
ctype& tfirst,
ctype& tlast)
1496 auto getFacetCorners = [] (
const Geometry1& geo1)
1498 std::vector< std::array<int, 2> > facetCorners;
1499 switch (geo1.corners())
1502 facetCorners = {{0, 2}, {3, 1}, {1, 0}, {2, 3}};
1505 facetCorners = {{1, 0}, {0, 2}, {2, 1}};
1508 DUNE_THROW(Dune::NotImplemented,
"Collision of segment and geometry of type "
1509 << geo1.type() <<
" with "<< geo1.corners() <<
" corners.");
1512 return facetCorners;
1515 const auto center1 = geo1.center();
1516 const auto normal1 =
crossProduct(geo1.corner(1) - geo1.corner(0),
1517 geo1.corner(2) - geo1.corner(0));
1520 auto computeNormal = [¢er1, &normal1, &geo1] (
const std::array<int, 2>& facetCorners)
1522 const auto c0 = geo1.corner(facetCorners[0]);
1523 const auto c1 = geo1.corner(facetCorners[1]);
1524 const auto edge = c1 - c0;
1526 Dune::FieldVector<ctype, dimworld> n =
crossProduct(edge, normal1);
1531 if ( n*(center1-c0) > 0.0 )
1543 template<
class P = Policy, std::enable_if_t<P::dimIntersection == 0,
int> = 0>
1544 static bool intersect_(
const Point& a,
const Point& b,
const Point& c,
1549 return intersect_(a, b, c, p, q, is, hasSegment);
1556 template<
class P = Policy, std::enable_if_t<P::dimIntersection == 0,
int> = 0>
1557 static bool intersect_(
const Point& a,
const Point& b,
const Point& c,
1561 hasSegmentIs =
false;
1563 const auto ab = b - a;
1564 const auto ac = c - a;
1565 const auto qp = p - q;
1572 const auto denom =
normal*qp;
1573 const auto abnorm2 = ab.two_norm2();
1574 const auto eps = eps_*abnorm2*qp.two_norm();
1576 if (abs(denom) < eps)
1578 const auto pa = a - p;
1579 const auto denom2 =
normal*pa;
1580 if (abs(denom2) > eps_*pa.two_norm()*abnorm2)
1585 using SegmentPolicy =
typename IntersectionPolicy::SegmentPolicy<ctype, dimworld>;
1586 using Triangle = Dune::AffineGeometry<ctype, 2, dimworld>;
1587 using Segment = Dune::AffineGeometry<ctype, 1, dimworld>;
1588 using SegmentIntersectionAlgorithm = GeometryIntersection<Triangle, Segment, SegmentPolicy>;
1589 using SegmentIntersectionType =
typename SegmentIntersectionAlgorithm::Intersection;
1590 SegmentIntersectionType segmentIs;
1592 Triangle triangle(Dune::GeometryTypes::simplex(2), std::array<Point, 3>({a, b, c}));
1593 Segment segment(Dune::GeometryTypes::simplex(1), std::array<Point, 2>({p, q}));
1594 if (SegmentIntersectionAlgorithm::intersection(triangle, segment, segmentIs))
1596 hasSegmentIs =
true;
1602 for (
const auto& ip : {p, q})
1618 const auto ap = p - a;
1619 const auto t = (ap*
normal)/denom;
1620 if (t < 0.0 - eps_)
return false;
1621 if (t > 1.0 + eps_)
return false;
1626 const auto v = (ac*e)/denom;
1627 if (v < -eps_ || v > 1.0 + eps_)
return false;
1628 const auto w = -(ab*e)/denom;
1629 if (w < -eps_ || v + w > 1.0 + eps_)
return false;
1633 const auto u = 1.0 - v - w;
1648template <
class Geometry1,
class Geometry2,
class Policy>
1661 template<
class P = Policy>
1672template <
class Geometry1,
class Geometry2,
class Policy>
1675 enum { dimworld = 3 };
1685 static constexpr ctype eps_ = 1.5e-7;
1694 template<
class P = Policy, std::enable_if_t<P::dimIntersection == 0,
int> = 0>
1697 static_assert(int(dimworld) == int(Geometry2::coorddimension),
"Can only collide geometries of same coordinate dimension");
1699 const auto v1 = geo1.corner(1) - geo1.corner(0);
1700 const auto v2 = geo2.corner(1) - geo2.corner(0);
1701 const auto ac = geo2.corner(0) - geo1.corner(0);
1703 const auto v1Norm2 = v1.two_norm2();
1704 const auto eps2 = eps_*v1Norm2;
1710 if ( n.two_norm2() < eps2*v1Norm2 )
1718 const auto sp = v1*v2;
1721 if ( ac.two_norm2() < eps2 )
1724 if ( (geo2.corner(1) - geo1.corner(1)).two_norm2() < eps2 )
1729 if ( (geo2.corner(1) - geo1.corner(0)).two_norm2() < eps2 )
1732 if ( (geo2.corner(0) - geo1.corner(1)).two_norm2() < eps2 )
1744 const auto t2 = - 1.0*(ac*v1Normal) / (v2*v1Normal);
1747 if (t2 < -1.0*eps_ || t2 > 1.0 + eps_)
1763 template<
class P = Policy, std::enable_if_t<P::dimIntersection == 1,
int> = 0>
1766 static_assert(int(dimworld) == int(Geometry2::coorddimension),
"Can only collide geometries of same coordinate dimension");
1768 const auto& a = geo1.corner(0);
1769 const auto& b = geo1.corner(1);
1770 const auto ab = b-a;
1772 const auto& p = geo2.corner(0);
1773 const auto& q = geo2.corner(1);
1774 const auto pq = q-p;
1776 const auto abNorm2 = ab.two_norm2();
1777 const auto pqNorm2 = pq.two_norm2();
1780 const auto eps2 = eps_*max(abNorm2, pqNorm2);
1787 const auto ap = (p-a);
1788 const auto aq = (q-a);
1806 tp = clamp(tp, 0.0, abNorm2);
1807 tq = clamp(tq, 0.0, abNorm2);
1809 if (abs(tp-tq) < eps2)
Define some often used mathematical functions.
Detect if a point intersects a geometry.
An axis-aligned bounding box volume hierarchy for dune grids.
A function to compute the convex hull of a point cloud.
bool intersectsPointGeometry(const Dune::FieldVector< ctype, dimworld > &point, const Geometry &g)
Find out whether a point is inside a three-dimensional geometry.
Definition: intersectspointgeometry.hh:38
Vector normal(const Vector &v)
Create a vector normal to the given one (v is expected to be non-zero)
Definition: normal.hh:36
bool intersectsPointSimplex(const Dune::FieldVector< ctype, dimworld > &point, const Dune::FieldVector< ctype, dimworld > &p0, const Dune::FieldVector< ctype, dimworld > &p1, const Dune::FieldVector< ctype, dimworld > &p2, const Dune::FieldVector< ctype, dimworld > &p3)
Find out whether a point is inside the tetrahedron (p0, p1, p2, p3) (dimworld is 3)
Definition: intersectspointsimplex.hh:36
bool computeSegmentIntersection(const Geo1 &geo1, const Geo2 &geo2, ctype baseEps, ctype &tfirst, ctype &tlast, const GetFacetCornerIndices &getFacetCornerIndices, const ComputeNormalFunction &computeNormal)
Algorithm to find segment-like intersections of a polygon/polyhedron with a segment....
Definition: geometryintersection.hh:134
Dune::FieldVector< Scalar, 3 > crossProduct(const Dune::FieldVector< Scalar, 3 > &vec1, const Dune::FieldVector< Scalar, 3 > &vec2)
Cross product of two vectors in three-dimensional Euclidean space.
Definition: math.hh:654
bool intersectsPointBoundingBox(const Dune::FieldVector< ctype, dimworld > &point, const ctype *b)
Check whether a point is intersectin a bounding box (dimworld == 3)
Definition: boundingboxtree.hh:304
typename DefaultPolicyChooser< Geometry1, Geometry2 >::type DefaultPolicy
Helper alias to define the default intersection policy.
Definition: geometryintersection.hh:113
constexpr Line line
Definition: couplingmanager1d3d_line.hh:43
Policy structure for point-like intersections.
Definition: geometryintersection.hh:43
static constexpr int dimIntersection
Definition: geometryintersection.hh:48
Point Intersection
Definition: geometryintersection.hh:49
ct ctype
Definition: geometryintersection.hh:44
Dune::FieldVector< ctype, dw > Point
Definition: geometryintersection.hh:45
static constexpr int dimWorld
Definition: geometryintersection.hh:47
Policy structure for segment-like intersections.
Definition: geometryintersection.hh:55
Segment Intersection
Definition: geometryintersection.hh:62
static constexpr int dimIntersection
Definition: geometryintersection.hh:61
Dune::FieldVector< ctype, dw > Point
Definition: geometryintersection.hh:57
static constexpr int dimWorld
Definition: geometryintersection.hh:60
std::array< Point, 2 > Segment
Definition: geometryintersection.hh:58
ct ctype
Definition: geometryintersection.hh:56
Policy structure for polygon-like intersections.
Definition: geometryintersection.hh:68
static constexpr int dimWorld
Definition: geometryintersection.hh:73
static constexpr int dimIntersection
Definition: geometryintersection.hh:74
ct ctype
Definition: geometryintersection.hh:69
Polygon Intersection
Definition: geometryintersection.hh:75
Dune::FieldVector< ctype, dw > Point
Definition: geometryintersection.hh:70
std::vector< Point > Polygon
Definition: geometryintersection.hh:71
Policy structure for polyhedron-like intersections.
Definition: geometryintersection.hh:81
std::vector< Point > Polyhedron
Definition: geometryintersection.hh:84
Dune::FieldVector< ctype, dw > Point
Definition: geometryintersection.hh:83
Polyhedron Intersection
Definition: geometryintersection.hh:88
static constexpr int dimIntersection
Definition: geometryintersection.hh:87
static constexpr int dimWorld
Definition: geometryintersection.hh:86
ct ctype
Definition: geometryintersection.hh:82
default policy chooser class
Definition: geometryintersection.hh:94
std::tuple_element_t< isDim, DefaultPolicies > type
Definition: geometryintersection.hh:108
A class for geometry collision detection and intersection calculation The class can be specialized fo...
Definition: geometryintersection.hh:216
typename Policy::ctype ctype
Definition: geometryintersection.hh:220
typename Policy::Intersection Intersection
Definition: geometryintersection.hh:222
static bool intersection(const Geometry1 &geo1, const Geometry2 &geo2, Intersection &intersection)
Determine if the two geometries intersect and compute the intersection geometry.
Definition: geometryintersection.hh:225
typename Policy::Point Point
Definition: geometryintersection.hh:221
typename Policy::Intersection Intersection
Definition: geometryintersection.hh:250
typename Policy::ctype ctype
Definition: geometryintersection.hh:248
typename Policy::Point Point
Definition: geometryintersection.hh:249
static bool intersection(const Geometry1 &geo1, const Geometry2 &geo2, Intersection &intersection)
Colliding two segments.
Definition: geometryintersection.hh:259
static bool intersection(const Geometry1 &geo1, const Geometry2 &geo2, Intersection &intersection)
Colliding segment and convex polygon.
Definition: geometryintersection.hh:418
typename Policy::ctype ctype
Definition: geometryintersection.hh:402
typename Policy::Intersection Intersection
Definition: geometryintersection.hh:404
static bool intersection(const Geometry1 &geo1, const Geometry2 &geo2, typename P::Intersection &intersection)
Colliding segment and convex polygon.
Definition: geometryintersection.hh:442
typename Policy::Point Point
Definition: geometryintersection.hh:403
static bool intersection(const Geometry1 &geo1, const Geometry2 &geo2, typename Base::Intersection &intersection)
Colliding segment and convex polygon.
Definition: geometryintersection.hh:529
typename Policy::Intersection Intersection
Definition: geometryintersection.hh:549
typename Policy::ctype ctype
Definition: geometryintersection.hh:547
static bool intersection(const Geometry1 &geo1, const Geometry2 &geo2, Intersection &intersection)
Colliding two polygons.
Definition: geometryintersection.hh:568
typename Policy::Point Point
Definition: geometryintersection.hh:548
typename Policy::Intersection Intersection
Definition: geometryintersection.hh:693
typename Policy::Point Point
Definition: geometryintersection.hh:692
typename Policy::ctype ctype
Definition: geometryintersection.hh:691
static bool intersection(const Geometry1 &geo1, const Geometry2 &geo2, Intersection &intersection)
Colliding segment and convex polyhedron.
Definition: geometryintersection.hh:711
static bool intersection(const Geometry1 &geo1, const Geometry2 &geo2, typename Base::Intersection &intersection)
Colliding segment and convex polyhedron.
Definition: geometryintersection.hh:827
typename Policy::Point Point
Definition: geometryintersection.hh:846
typename Policy::ctype ctype
Definition: geometryintersection.hh:845
typename Policy::Intersection Intersection
Definition: geometryintersection.hh:847
static bool intersection(const Geometry1 &geo1, const Geometry2 &geo2, Intersection &intersection)
Colliding two polygons.
Definition: geometryintersection.hh:867
typename Policy::Intersection Intersection
Definition: geometryintersection.hh:1035
static bool intersection(const Geometry1 &geo1, const Geometry2 &geo2, Intersection &intersection)
Colliding polygon and convex polyhedron.
Definition: geometryintersection.hh:1056
typename Policy::Point Point
Definition: geometryintersection.hh:1034
typename Policy::ctype ctype
Definition: geometryintersection.hh:1033
static bool intersection(const Geometry1 &geo1, const Geometry2 &geo2, typename Base::Intersection &intersection)
Colliding polygon and convex polyhedron.
Definition: geometryintersection.hh:1207
typename Policy::Point Point
Definition: geometryintersection.hh:1226
typename Policy::Intersection Intersection
Definition: geometryintersection.hh:1227
typename Policy::ctype ctype
Definition: geometryintersection.hh:1225
static bool intersection(const Geometry1 &geo1, const Geometry2 &geo2, Intersection &intersection)
Colliding two convex polyhedra.
Definition: geometryintersection.hh:1245
typename Policy::Intersection Intersection
Definition: geometryintersection.hh:1409
typename Policy::Point Point
Definition: geometryintersection.hh:1408
typename Policy::ctype ctype
Definition: geometryintersection.hh:1407
static bool intersection(const Geometry1 &geo1, const Geometry2 &geo2, Intersection &intersection)
Colliding segment and convex polyhedron.
Definition: geometryintersection.hh:1425
static bool intersection(const Geometry1 &geo1, const Geometry2 &geo2, Intersection &is)
Colliding segment and convex polyhedron.
Definition: geometryintersection.hh:1451
static bool intersection(const Geometry1 &geo1, const Geometry2 &geo2, typename Base::Intersection &intersection)
Colliding segment and convex polygon.
Definition: geometryintersection.hh:1662
typename Policy::Intersection Intersection
Definition: geometryintersection.hh:1682
typename Policy::Point Point
Definition: geometryintersection.hh:1681
static bool intersection(const Geometry1 &geo1, const Geometry2 &geo2, Intersection &intersection)
Colliding two segments.
Definition: geometryintersection.hh:1695
typename Policy::ctype ctype
Definition: geometryintersection.hh:1680