13#ifndef DUMUX_GEOMETRY_INTERSECTION_HH 
   14#define DUMUX_GEOMETRY_INTERSECTION_HH 
   18#include <dune/common/exceptions.hh> 
   19#include <dune/common/promotiontraits.hh> 
   20#include <dune/geometry/multilineargeometry.hh> 
   21#include <dune/geometry/referenceelements.hh> 
   32template<
class ct, 
int dw>
 
   36    using Point = Dune::FieldVector<ctype, dw>;
 
 
   44template<
class ct, 
int dw>
 
   48    using Point = Dune::FieldVector<ctype, dw>;
 
 
   57template<
class ct, 
int dw>
 
   61    using Point = Dune::FieldVector<ctype, dw>;
 
 
   70template<
class ct, 
int dw>
 
   74    using Point = Dune::FieldVector<ctype, dw>;
 
 
   83template<
class Geometry1, 
class Geometry2>
 
   86    static constexpr int dimworld = Geometry1::coorddimension;
 
   87    static constexpr int isDim = std::min( 
int(Geometry1::mydimension), 
int(Geometry2::mydimension) );
 
   88    static_assert(dimworld == int(Geometry2::coorddimension),
 
   89                  "Geometries must have the same coordinate dimension!");
 
   90    static_assert(int(Geometry1::mydimension) <= 3 && int(Geometry2::mydimension) <= 3,
 
   91                  "Geometries must have dimension 3 or less.");
 
   92    using ctype = 
typename Dune::PromotionTraits<typename Geometry1::ctype, typename Geometry2::ctype>::PromotedType;
 
   94    using DefaultPolicies = std::tuple<PointPolicy<ctype, dimworld>,
 
   99    using type = std::tuple_element_t<isDim, DefaultPolicies>;
 
 
  103template<
class Geometry1, 
class Geometry2>
 
 
  123template< 
class Geo1, 
class Geo2, 
class ctype,
 
  124          class GetFacetCornerIndices, 
class ComputeNormalFunction >
 
  126                                ctype& tfirst, ctype& tlast,
 
  127                                const GetFacetCornerIndices& getFacetCornerIndices,
 
  128                                const ComputeNormalFunction& computeNormal)
 
  130    static_assert(int(Geo2::mydimension) == 1, 
"Geometry2 must be a segment");
 
  131    static_assert(int(Geo1::mydimension) > int(Geo2::mydimension),
 
  132                  "Dimension of Geometry1 must be higher than that of Geometry2");
 
  134    const auto a = geo2.corner(0);
 
  135    const auto b = geo2.corner(1);
 
  136    const auto d = b - a;
 
  144    const auto facets = getFacetCornerIndices(geo1);
 
  145    for (
const auto& f : facets)
 
  147        const auto n = computeNormal(f);
 
  149        const auto c0 = geo1.corner(f[0]);
 
  150        const ctype denom = n*d;
 
  151        const ctype dist = n*(a-c0);
 
  154        const auto edge1 = geo1.corner(f[1]) - geo1.corner(f[0]);
 
  155        const ctype eps = baseEps*edge1.two_norm();
 
  160        if (abs(denom) < eps)
 
  167            const ctype t = -dist / denom;
 
  183            if (tfirst > tlast - baseEps)
 
 
  201<
class Geometry1, 
class Geometry2,
 
  203 int dimworld = Geometry1::coorddimension,
 
  204 int dim1 = Geometry1::mydimension,
 
  205 int dim2 = Geometry2::mydimension>
 
  208    static constexpr int dimWorld = Policy::dimWorld;
 
  211    using ctype = 
typename Policy::ctype;
 
  212    using Point = 
typename Policy::Point;
 
  218        static_assert(dimworld == Geometry2::coorddimension, 
"Can only intersect geometries of same coordinate dimension");
 
  219        DUNE_THROW(Dune::NotImplemented, 
"Geometry intersection detection with intersection computation not implemented for dimworld = " 
  220                                          << dimworld << 
", dim1 = " << dim1 << 
", dim2 = " << dim2);
 
 
 
  228template <
class Geometry1, 
class Geometry2, 
class Policy>
 
  231    enum { dimworld = 2 };
 
  236    static constexpr typename Policy::ctype eps_ = 1.5e-7;
 
  239    using ctype = 
typename Policy::ctype;
 
  240    using Point = 
typename Policy::Point;
 
  249    template<
class P = Policy, std::enable_if_t<P::dimIntersection == 0, 
int> = 0>
 
  252        static_assert(int(dimworld) == int(Geometry2::coorddimension), 
"Can only collide geometries of same coordinate dimension");
 
  254        const auto v1 = geo1.corner(1) - geo1.corner(0);
 
  255        const auto v2 = geo2.corner(1) - geo2.corner(0);
 
  256        const auto ac = geo2.corner(0) - geo1.corner(0);
 
  258        auto n2 = 
Point({-1.0*v2[1], v2[0]});
 
  262        const auto dist12 = n2*ac;
 
  268        const auto v1Norm2 = v1.two_norm2();
 
  269        const auto eps = eps_*sqrt(v1Norm2);
 
  270        const auto eps2 = eps_*v1Norm2;
 
  272        const auto sp = n2*v1;
 
  275            if (abs(dist12) > eps)
 
  281                if ( ac.two_norm2() < eps2 )
 
  284                if ( (geo2.corner(1) - geo1.corner(1)).two_norm2() < eps2 )
 
  289                if ( (geo2.corner(1) - geo1.corner(0)).two_norm2() < eps2 )
 
  292                if ( (geo2.corner(0) - geo1.corner(1)).two_norm2() < eps2 )
 
  301        const auto t1 = dist12 / sp;
 
  304        if (t1 < -1.0*eps_ || t1 > 1.0 + eps_)
 
  308        auto isPoint = geo1.global(t1);
 
  311        const auto c = geo2.corner(0);
 
  312        const auto d = geo2.corner(1);
 
  314        using std::min; 
using std::max;
 
  315        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]) });
 
 
  332    template<
class P = Policy, std::enable_if_t<P::dimIntersection == 1, 
int> = 0>
 
  335        static_assert(int(dimworld) == int(Geometry2::coorddimension), 
"Can only collide geometries of same coordinate dimension");
 
  337        const auto& a = geo1.corner(0);
 
  338        const auto& b = geo1.corner(1);
 
  339        const auto ab = b - a;
 
  341        const auto& p = geo2.corner(0);
 
  342        const auto& q = geo2.corner(1);
 
  343        const auto pq = q - p;
 
  344        Dune::FieldVector<ctype, dimworld> n2{-pq[1], pq[0]};
 
  347        const auto abNorm2 = ab.two_norm2();
 
  348        const auto pqNorm2 = pq.two_norm2();
 
  349        const auto eps2 = eps_*max(abNorm2, pqNorm2);
 
  353        if (abs(n2*ab) > eps2)
 
  357        const auto ap = p - a;
 
  358        if (abs(ap*n2) > eps2)
 
  363        auto t2 = ab*(q - a);
 
  370        t1 = clamp(t1, 0.0, abNorm2);
 
  371        t2 = clamp(t2, 0.0, abNorm2);
 
  373        if (abs(t2-t1) < eps2)
 
 
 
  385template <
class Geometry1, 
class Geometry2, 
class Policy>
 
  388    enum { dimworld = 2 };
 
  393    using ctype = 
typename Policy::ctype;
 
  394    using Point = 
typename Policy::Point;
 
  398    static constexpr ctype eps_ = 1.5e-7; 
 
  408    template<
class P = Policy, std::enable_if_t<P::dimIntersection == 1, 
int> = 0>
 
  411        static_assert(int(dimworld) == int(Geometry2::coorddimension), 
"Can only collide geometries of same coordinate dimension");
 
  414        if (intersect_(geo1, geo2, tfirst, tlast))
 
 
  432    template<
class P = Policy, std::enable_if_t<P::dimIntersection == 0, 
int> = 0>
 
  435        static_assert(int(dimworld) == int(Geometry2::coorddimension), 
"Can only collide geometries of same coordinate dimension");
 
  438        if (!intersect_(geo1, geo2, tfirst, tlast))
 
  442            if ( tfirst > tlast - eps_ )
 
 
  456     static bool intersect_(
const Geometry1& geo1, 
const Geometry2& geo2, 
ctype& tfirst, 
ctype& tlast)
 
  459         auto getFacetCorners = [] (
const Geometry1& geo1)
 
  461             std::vector< std::array<int, 2> > facetCorners;
 
  462             switch (geo1.corners())
 
  465                     facetCorners = {{0, 2}, {3, 1}, {1, 0}, {2, 3}};
 
  468                     facetCorners = {{1, 0}, {0, 2}, {2, 1}};
 
  471                     DUNE_THROW(Dune::NotImplemented, 
"Collision of segment and geometry of type " 
  472                                    << geo1.type() << 
" with "<< geo1.corners() << 
" corners.");
 
  479         const auto center1 = geo1.center();
 
  480         auto computeNormal = [&geo1, ¢er1] (
const std::array<int, 2>& facetCorners)
 
  482             const auto c0 = geo1.corner(facetCorners[0]);
 
  483             const auto c1 = geo1.corner(facetCorners[1]);
 
  484             const auto edge = c1 - c0;
 
  486             Dune::FieldVector<ctype, dimworld> n({-1.0*edge[1], edge[0]});
 
  491             if ( n*(center1-c0) > 0.0 )
 
 
  505template <
class Geometry1, 
class Geometry2, 
class Policy>
 
  519    template<
class P = Policy>
 
 
  530template <
class Geometry1, 
class Geometry2, 
class Policy>
 
  533    enum { dimworld = 2 };
 
  538    using ctype = 
typename Policy::ctype;
 
  539    using Point = 
typename Policy::Point;
 
  543    static constexpr ctype eps_ = 1.5e-7; 
 
  558    template<
class P = Policy, std::enable_if_t<P::dimIntersection == 2, 
int> = 0>
 
  561        static_assert(int(dimworld) == int(Geometry2::coorddimension), 
"Can only collide geometries of same coordinate dimension");
 
  564        std::vector<Point> points; points.reserve(6);
 
  567        for (
int i = 0; i < geo1.corners(); ++i)
 
  569                points.emplace_back(geo1.corner(i));
 
  571        const auto numPoints1 = points.size();
 
  572        if (numPoints1 != geo1.corners())
 
  575            for (
int i = 0; i < geo2.corners(); ++i)
 
  577                    points.emplace_back(geo2.corner(i));
 
  582            if (points.size() - numPoints1 != geo2.corners())
 
  584                const auto refElement1 = referenceElement(geo1);
 
  585                const auto refElement2 = referenceElement(geo2);
 
  588                using SegGeometry = Dune::MultiLinearGeometry<ctype, 1, dimworld>;
 
  590                for (
int i = 0; i < refElement1.size(dim1-1); ++i)
 
  592                    const auto localEdgeGeom1 = refElement1.template geometry<dim1-1>(i);
 
  593                    const auto edge1 = SegGeometry( Dune::GeometryTypes::line,
 
  594                                                    std::vector<Point>( {geo1.global(localEdgeGeom1.corner(0)),
 
  595                                                                         geo1.global(localEdgeGeom1.corner(1))} ));
 
  597                    for (
int j = 0; j < refElement2.size(dim2-1); ++j)
 
  599                        const auto localEdgeGeom2 = refElement2.template geometry<dim2-1>(j);
 
  600                        const auto edge2 = SegGeometry( Dune::GeometryTypes::line,
 
  601                                                        std::vector<Point>( {geo2.global(localEdgeGeom2.corner(0)),
 
  602                                                                             geo2.global(localEdgeGeom2.corner(1))} ));
 
  605                        typename EdgeTest::Intersection edgeIntersection;
 
  606                        if (EdgeTest::intersection(edge1, edge2, edgeIntersection))
 
  607                            points.emplace_back(edgeIntersection);
 
  617        const auto eps = (geo1.corner(0) - geo1.corner(1)).two_norm()*eps_;
 
  618        std::sort(points.begin(), points.end(), [&eps](
const auto& a, 
const auto& b) -> 
bool 
  621            return (abs(a[0]-b[0]) > eps ? a[0] < b[0] : a[1] < b[1]);
 
  624        auto removeIt = std::unique(points.begin(), points.end(), [&eps](
const auto& a, 
const auto&b)
 
  626            return (b-a).two_norm() < eps;
 
  629        points.erase(removeIt, points.end());
 
  632        if (points.size() < 3)
 
 
  648    template<
class P = Policy, std::enable_if_t<P::dimIntersection == 1, 
int> = 0>
 
  651        static_assert(int(dimworld) == int(Geometry2::coorddimension), 
"Can only collide geometries of same coordinate dimension");
 
  652        DUNE_THROW(Dune::NotImplemented, 
"Polygon-polygon intersection detection for segment-like intersections");
 
 
  662    template<
class P = Policy, std::enable_if_t<P::dimIntersection == 0, 
int> = 0>
 
  665        static_assert(int(dimworld) == int(Geometry2::coorddimension), 
"Can only collide geometries of same coordinate dimension");
 
  666        DUNE_THROW(Dune::NotImplemented, 
"Polygon-polygon intersection detection for touching points");
 
 
 
  674template <
class Geometry1, 
class Geometry2, 
class Policy>
 
  677    enum { dimworld = 3 };
 
  682    using ctype = 
typename Policy::ctype;
 
  683    using Point = 
typename Policy::Point;
 
  687    static constexpr ctype eps_ = 1.5e-7; 
 
  701    template<
class P = Policy, std::enable_if_t<P::dimIntersection == 1, 
int> = 0>
 
  704        static_assert(int(dimworld) == int(Geometry2::coorddimension), 
"Can only collide geometries of same coordinate dimension");
 
  707        if (intersect_(geo1, geo2, tfirst, tlast))
 
 
  729    template<
class P = Policy, std::enable_if_t<P::dimIntersection == 0, 
int> = 0>
 
  732        static_assert(int(dimworld) == int(Geometry2::coorddimension), 
"Can only collide geometries of same coordinate dimension");
 
  735        if (intersect_(geo1, geo2, tfirst, tlast))
 
  739            if ( abs(tfirst - tlast) < eps_ )
 
 
  753     static bool intersect_(
const Geometry1& geo1, 
const Geometry2& geo2, 
ctype& tfirst, 
ctype& tlast)
 
  756         auto getFacetCorners = [] (
const Geometry1& geo1)
 
  758             std::vector< std::vector<int> > facetCorners;
 
  760             switch (geo1.corners())
 
  764                     facetCorners = {{2, 0, 6, 4}, {1, 3, 5, 7}, {0, 1, 4, 5},
 
  765                               {3, 2, 7, 6}, {1, 0, 3, 2}, {4, 5, 6, 7}};
 
  768                     facetCorners = {{0, 2, 1}, {3, 4, 5}, {0, 1, 3, 4}, {0, 3, 2, 5}, {1, 2, 4, 5}};
 
  771                     facetCorners = {{0, 2, 1, 3}, {0, 1, 4}, {1, 3, 4}, {2, 4, 3}, {0, 4, 2}};
 
  774                     facetCorners = {{1, 0, 2}, {0, 1, 3}, {0, 3, 2}, {1, 2, 3}};
 
  777                     DUNE_THROW(Dune::NotImplemented, 
"Collision of segment and geometry of type " 
  778                                    << geo1.type() << 
", "<< geo1.corners() << 
" corners.");
 
  785         auto computeNormal = [&geo1] (
const std::vector<int>& facetCorners)
 
  787             const auto v0 = geo1.corner(facetCorners[1]) - geo1.corner(facetCorners[0]);
 
  788             const auto v1 = geo1.corner(facetCorners[2]) - geo1.corner(facetCorners[0]);
 
 
  804template <
class Geometry1, 
class Geometry2, 
class Policy>
 
  817    template<
class P = Policy>
 
 
  828template <
class Geometry1, 
class Geometry2, 
class Policy>
 
  831    enum { dimworld = 3 };
 
  836    using ctype = 
typename Policy::ctype;
 
  837    using Point = 
typename Policy::Point;
 
  841    static constexpr ctype eps_ = 1.5e-7; 
 
  855    template<
class P = Policy, std::enable_if_t<P::dimIntersection == 2, 
int> = 0>
 
  858        static_assert(int(dimworld) == int(Geometry2::coorddimension), 
"Can only collide geometries of same coordinate dimension");
 
  861        const auto a1 = geo1.corner(1) - geo1.corner(0);
 
  862        const auto b1 = geo1.corner(2) - geo1.corner(0);
 
  865        const auto a2 = geo2.corner(1) - geo2.corner(0);
 
  866        const auto b2 = geo2.corner(2) - geo2.corner(0);
 
  870        const auto a1Norm2 = a1.two_norm2();
 
  871        const auto b1Norm2 = b1.two_norm2();
 
  874        const auto maxNorm2 = max(a1Norm2, b1Norm2);
 
  875        const auto eps2 = maxNorm2*eps_;
 
  883        auto d1 = geo2.corner(0) - geo1.corner(0);
 
  884        if (d1.two_norm2() < eps2)
 
  885            d1 = geo2.corner(1) - geo1.corner(0);
 
  888        const auto maxNorm = sqrt(maxNorm2);
 
  889        const auto eps3 = maxNorm*eps2;
 
  891        if (abs(d1*n2) > eps3)
 
  895        std::vector<Point> points; points.reserve(8);
 
  898        for (
int i = 0; i < geo1.corners(); ++i)
 
  900                points.emplace_back(geo1.corner(i));
 
  902        const auto numPoints1 = points.size();
 
  903        const bool resultIsGeo1 = numPoints1 == geo1.corners();
 
  907            for (
int i = 0; i < geo2.corners(); ++i)
 
  909                    points.emplace_back(geo2.corner(i));
 
  911            const bool resultIsGeo2 = (points.size() - numPoints1) == geo2.corners();
 
  914                const auto referenceElement1 = referenceElement(geo1);
 
  915                const auto referenceElement2 = referenceElement(geo2);
 
  918                using SegGeometry = Dune::MultiLinearGeometry<ctype, 1, dimworld>;
 
  920                for (
int i = 0; i < referenceElement1.size(dim1-1); ++i)
 
  922                    const auto localEdgeGeom1 = referenceElement1.template geometry<dim1-1>(i);
 
  923                    const auto edge1 = SegGeometry(
 
  924                        Dune::GeometryTypes::line,
 
  926                            geo1.global(localEdgeGeom1.corner(0)),
 
  927                            geo1.global(localEdgeGeom1.corner(1))
 
  931                    for (
int j = 0; j < referenceElement2.size(dim2-1); ++j)
 
  933                        const auto localEdgeGeom2 = referenceElement2.template geometry<dim2-1>(j);
 
  934                        const auto edge2 = SegGeometry(
 
  935                            Dune::GeometryTypes::line,
 
  937                                geo2.global(localEdgeGeom2.corner(0)),
 
  938                                geo2.global(localEdgeGeom2.corner(1))
 
  943                        typename EdgeTest::Intersection edgeIntersection;
 
  944                        if (EdgeTest::intersection(edge1, edge2, edgeIntersection))
 
  945                            points.emplace_back(edgeIntersection);
 
  955        const auto eps = maxNorm*eps_;
 
  956        std::sort(points.begin(), points.end(), [eps] (
const auto& a, 
const auto& b) -> 
bool 
  959            return (abs(a[0]-b[0]) > eps ? a[0] < b[0]
 
  960                                         : (abs(a[1]-b[1]) > eps ? a[1] < b[1]
 
  964        const auto squaredEps = eps*eps;
 
  965        points.erase(std::unique(
 
  966            points.begin(), points.end(),
 
  967            [squaredEps] (
const auto& a, 
const auto&b) { return (b-a).two_norm2() < squaredEps; }),
 
  972        if (points.size() < 3)
 
 
  988    template<
class P = Policy, std::enable_if_t<P::dimIntersection == 1, 
int> = 0>
 
  991        static_assert(int(dimworld) == int(Geometry2::coorddimension), 
"Can only collide geometries of same coordinate dimension");
 
  992        DUNE_THROW(Dune::NotImplemented, 
"Polygon-polygon intersection detection for segment-like intersections");
 
 
 1002    template<
class P = Policy, std::enable_if_t<P::dimIntersection == 0, 
int> = 0>
 
 1005        static_assert(int(dimworld) == int(Geometry2::coorddimension), 
"Can only collide geometries of same coordinate dimension");
 
 1006        DUNE_THROW(Dune::NotImplemented, 
"Polygon-polygon intersection detection for touching points");
 
 
 
 1014template <
class Geometry1, 
class Geometry2, 
class Policy>
 
 1017    enum { dimworld = 3 };
 
 1027    static constexpr ctype eps_ = 1.5e-7; 
 
 1044    template<
class P = Policy, std::enable_if_t<P::dimIntersection == 2, 
int> = 0>
 
 1047        static_assert(int(dimworld) == int(Geometry2::coorddimension), 
"Can only collide geometries of same coordinate dimension");
 
 1050        std::vector<Point> points; points.reserve(10);
 
 1053        for (
int i = 0; i < geo1.corners(); ++i)
 
 1055                points.emplace_back(geo1.corner(i));
 
 1058        for (
int i = 0; i < geo2.corners(); ++i)
 
 1060                points.emplace_back(geo2.corner(i));
 
 1063        using PolyhedronFaceGeometry = Dune::MultiLinearGeometry<ctype, 2, dimworld>;
 
 1064        using SegGeometry = Dune::MultiLinearGeometry<ctype, 1, dimworld>;
 
 1066        const auto refElement1 = referenceElement(geo1);
 
 1067        const auto refElement2 = referenceElement(geo2);
 
 1073        for (
int i = 0; i < refElement1.size(dim1-1); ++i)
 
 1075            const auto localEdgeGeom = refElement1.template geometry<dim1-1>(i);
 
 1076            const auto p = geo1.global(localEdgeGeom.corner(0));
 
 1077            const auto q = geo1.global(localEdgeGeom.corner(1));
 
 1078            const auto segGeo = SegGeometry(Dune::GeometryTypes::line, std::vector<Point>{p, q});
 
 1081            typename PolySegTest::Intersection polySegIntersection;
 
 1082            if (PolySegTest::intersection(geo2, segGeo, polySegIntersection))
 
 1083                points.emplace_back(std::move(polySegIntersection));
 
 1087        for (
int i = 0; i < refElement1.size(1); ++i)
 
 1089            const auto faceGeo = [&]()
 
 1091                const auto localFaceGeo = refElement1.template geometry<1>(i);
 
 1092                if (localFaceGeo.corners() == 4)
 
 1094                    const auto a = geo1.global(localFaceGeo.corner(0));
 
 1095                    const auto b = geo1.global(localFaceGeo.corner(1));
 
 1096                    const auto c = geo1.global(localFaceGeo.corner(2));
 
 1097                    const auto d = geo1.global(localFaceGeo.corner(3));
 
 1099                    return PolyhedronFaceGeometry(Dune::GeometryTypes::cube(2), std::vector<Point>{a, b, c, d});
 
 1103                    const auto a = geo1.global(localFaceGeo.corner(0));
 
 1104                    const auto b = geo1.global(localFaceGeo.corner(1));
 
 1105                    const auto c = geo1.global(localFaceGeo.corner(2));
 
 1107                    return PolyhedronFaceGeometry(Dune::GeometryTypes::simplex(2), std::vector<Point>{a, b, c});
 
 1111            for (
int j = 0; j < refElement2.size(1); ++j)
 
 1113                const auto localEdgeGeom = refElement2.template geometry<1>(j);
 
 1114                const auto p = geo2.global(localEdgeGeom.corner(0));
 
 1115                const auto q = geo2.global(localEdgeGeom.corner(1));
 
 1117                const auto segGeo = SegGeometry(Dune::GeometryTypes::line, std::vector<Point>{p, q});
 
 1120                typename PolySegTest::Intersection polySegIntersection;
 
 1121                if (PolySegTest::intersection(faceGeo, segGeo, polySegIntersection))
 
 1122                    points.emplace_back(std::move(polySegIntersection));
 
 1127        if (points.empty()) 
return false;
 
 1130        const auto eps = (geo1.corner(0) - geo1.corner(1)).two_norm()*eps_;
 
 1131        const auto notEqual = [eps] (
auto a, 
auto b) { 
using std::abs; 
return abs(b-a) > eps; };
 
 1132        std::sort(points.begin(), points.end(), [notEqual](
const auto& a, 
const auto& b) -> 
bool 
 1134            return (notEqual(a[0], b[0]) ? a[0] < b[0]
 
 1135                                         : (notEqual(a[1], b[1]) ? a[1] < b[1]
 
 1139        const auto squaredEps = eps*eps;
 
 1140        points.erase(std::unique(
 
 1141            points.begin(), points.end(),
 
 1142            [squaredEps] (
const auto& a, 
const auto&b) { return (b-a).two_norm2() < squaredEps; }),
 
 1147        if (points.size() < 3) 
return false;
 
 
 1170    template<
class P = Policy, std::enable_if_t<P::dimIntersection != 2, 
int> = 0>
 
 1173        static_assert(int(dimworld) == int(Geometry2::coorddimension), 
"Can only collide geometries of same coordinate dimension");
 
 1174        DUNE_THROW(Dune::NotImplemented, 
"Polyhedron-polygon intersection detection only implemented for polygon-like intersections");
 
 
 
 1182template <
class Geometry1, 
class Geometry2, 
class Policy>
 
 1195    template<
class P = Policy>
 
 
 1206template <
class Geometry1, 
class Geometry2, 
class Policy>
 
 1209    enum { dimworld = 3 };
 
 1219    static constexpr ctype eps_ = 1.5e-7; 
 
 1233    template<
class P = Policy, std::enable_if_t<P::dimIntersection == 3, 
int> = 0>
 
 1237            int(dimworld) == int(Geometry2::coorddimension),
 
 1238            "Can only collide geometries of same coordinate dimension" 
 1241        const auto refElement1 = referenceElement(geo1);
 
 1242        const auto refElement2 = referenceElement(geo2);
 
 1245        std::vector<Point> points;
 
 1246        points.reserve(refElement1.size(2) + refElement2.size(2));
 
 1249        const auto addPointIntersections = [&](
const auto& g1, 
const auto& g2)
 
 1251            for (
int i = 0; i < g1.corners(); ++i)
 
 1253                    points.emplace_back(c);
 
 1256        addPointIntersections(geo1, geo2);
 
 1257        addPointIntersections(geo2, geo1);
 
 1260        using PolyhedronFaceGeometry = Dune::MultiLinearGeometry<ctype, 2, dimworld>;
 
 1261        using SegGeometry = Dune::MultiLinearGeometry<ctype, 1, dimworld>;
 
 1267        const auto addEdgeIntersections = [&](
const auto& g1, 
const auto& g2, 
const auto& ref1, 
const auto& ref2)
 
 1269            for (
int i = 0; i < ref1.size(1); ++i)
 
 1271                const auto faceGeo = [&]()
 
 1273                    const auto localFaceGeo = ref1.template geometry<1>(i);
 
 1274                    if (localFaceGeo.corners() == 4)
 
 1276                        const auto a = g1.global(localFaceGeo.corner(0));
 
 1277                        const auto b = g1.global(localFaceGeo.corner(1));
 
 1278                        const auto c = g1.global(localFaceGeo.corner(2));
 
 1279                        const auto d = g1.global(localFaceGeo.corner(3));
 
 1281                        return PolyhedronFaceGeometry(
 
 1282                            Dune::GeometryTypes::cube(2), std::vector<Point>{a, b, c, d}
 
 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));
 
 1291                        return PolyhedronFaceGeometry(
 
 1292                            Dune::GeometryTypes::simplex(2), std::vector<Point>{a, b, c}
 
 1297                for (
int j = 0; j < ref2.size(2); ++j)
 
 1299                    const auto localEdgeGeom = ref2.template geometry<2>(j);
 
 1300                    const auto p = g2.global(localEdgeGeom.corner(0));
 
 1301                    const auto q = g2.global(localEdgeGeom.corner(1));
 
 1303                    const auto segGeo = SegGeometry(Dune::GeometryTypes::line, std::vector<Point>{p, q});
 
 1306                    typename PolySegTest::Intersection polySegIntersection;
 
 1307                    if (PolySegTest::intersection(faceGeo, segGeo, polySegIntersection))
 
 1308                        points.emplace_back(std::move(polySegIntersection));
 
 1313        addEdgeIntersections(geo1, geo2, refElement1, refElement2);
 
 1314        addEdgeIntersections(geo2, geo1, refElement2, refElement1);
 
 1321        const auto norm = (geo1.corner(0) - geo1.corner(1)).two_norm();
 
 1322        const auto eps = norm*eps_;
 
 1323        const auto notEqual = [eps] (
auto a, 
auto b) { 
using std::abs; 
return abs(b-a) > eps; };
 
 1324        std::sort(points.begin(), points.end(), [notEqual](
const auto& a, 
const auto& b) -> 
bool 
 1326            return (notEqual(a[0], b[0]) ? a[0] < b[0]
 
 1327                                         : (notEqual(a[1], b[1]) ? a[1] < b[1]
 
 1331        const auto squaredEps = eps*eps;
 
 1332        points.erase(std::unique(
 
 1333            points.begin(), points.end(),
 
 1334            [squaredEps] (
const auto& a, 
const auto&b) { return (b-a).two_norm2() < squaredEps; }),
 
 1339        if (points.size() < 4)
 
 1343        const bool coplanar = [&]
 
 1345            const auto p0 = points[0];
 
 1349            const auto epsCoplanar = 
normal.two_norm()*norm*eps_;
 
 1350            for (
int i = 3; i < points.size(); ++i)
 
 1352                const auto ad = points[i] - p0;
 
 1354                if (abs(
normal*ad) > epsCoplanar)
 
 
 1376    template<
class P = Policy, std::enable_if_t<P::dimIntersection != 3, 
int> = 0>
 
 1379        static_assert(int(dimworld) == int(Geometry2::coorddimension), 
"Can only collide geometries of same coordinate dimension");
 
 1380        DUNE_THROW(Dune::NotImplemented, 
"Polyhedron-polygon intersection detection only implemented for polygon-like intersections");
 
 
 
 1388template <
class Geometry1, 
class Geometry2, 
class Policy>
 
 1391    enum { dimworld = 3 };
 
 1401    static constexpr ctype eps_ = 1.5e-7; 
 
 1413    template<
class P = Policy, std::enable_if_t<P::dimIntersection == 1, 
int> = 0>
 
 1416        static_assert(int(dimworld) == int(Geometry2::coorddimension), 
"Can only collide geometries of same coordinate dimension");
 
 1418        ctype tfirst, tlast;
 
 1419        if (intersect_(geo1, geo2, tfirst, tlast))
 
 
 1439    template<
class P = Policy, std::enable_if_t<P::dimIntersection == 0, 
int> = 0>
 
 1442        static_assert(int(dimworld) == int(Geometry2::coorddimension), 
"Can only collide geometries of same coordinate dimension");
 
 1444        const auto p = geo2.corner(0);
 
 1445        const auto q = geo2.corner(1);
 
 1447        const auto a = geo1.corner(0);
 
 1448        const auto b = geo1.corner(1);
 
 1449        const auto c = geo1.corner(2);
 
 1451        if (geo1.corners() == 3)
 
 1452            return intersect_<Policy>(a, b, c, p, q, is);
 
 1454        else if (geo1.corners() == 4)
 
 1457            bool hasSegment1, hasSegment2;
 
 1459            const auto d = geo1.corner(3);
 
 1460            const bool intersects1 = intersect_<Policy>(a, b, d, p, q, is1, hasSegment1);
 
 1461            const bool intersects2 = intersect_<Policy>(a, d, c, p, q, is2, hasSegment2);
 
 1463            if (hasSegment1 || hasSegment2)
 
 1466            if (intersects1) { is = is1; 
return true; }
 
 1467            if (intersects2) { is = is2; 
return true; }
 
 1473            DUNE_THROW(Dune::NotImplemented, 
"Collision of segment and geometry of type " 
 1474                          << geo1.type() << 
", "<< geo1.corners() << 
" corners.");
 
 
 1481    template<
class P = Policy, std::enable_if_t<P::dimIntersection == 1, 
int> = 0>
 
 1482    static bool intersect_(
const Geometry1& geo1, 
const Geometry2& geo2, 
ctype& tfirst, 
ctype& tlast)
 
 1485        auto getFacetCorners = [] (
const Geometry1& geo1)
 
 1487            std::vector< std::array<int, 2> > facetCorners;
 
 1488            switch (geo1.corners())
 
 1491                    facetCorners = {{0, 2}, {3, 1}, {1, 0}, {2, 3}};
 
 1494                    facetCorners = {{1, 0}, {0, 2}, {2, 1}};
 
 1497                    DUNE_THROW(Dune::NotImplemented, 
"Collision of segment and geometry of type " 
 1498                                   << geo1.type() << 
" with "<< geo1.corners() << 
" corners.");
 
 1501            return facetCorners;
 
 1504        const auto center1 = geo1.center();
 
 1505        const auto normal1 = 
crossProduct(geo1.corner(1) - geo1.corner(0),
 
 1506                                          geo1.corner(2) - geo1.corner(0));
 
 1509        auto computeNormal = [¢er1, &normal1, &geo1] (
const std::array<int, 2>& facetCorners)
 
 1511            const auto c0 = geo1.corner(facetCorners[0]);
 
 1512            const auto c1 = geo1.corner(facetCorners[1]);
 
 1513            const auto edge = c1 - c0;
 
 1515            Dune::FieldVector<ctype, dimworld> n = 
crossProduct(edge, normal1);
 
 1520            if ( n*(center1-c0) > 0.0 )
 
 1532    template<
class P = Policy, std::enable_if_t<P::dimIntersection == 0, 
int> = 0>
 
 1533    static bool intersect_(
const Point& a, 
const Point& b, 
const Point& c,
 
 1538        return intersect_(a, b, c, p, q, is, hasSegment);
 
 1545    template<
class P = Policy, std::enable_if_t<P::dimIntersection == 0, 
int> = 0>
 
 1546    static bool intersect_(
const Point& a, 
const Point& b, 
const Point& c,
 
 1550        hasSegmentIs = 
false;
 
 1552        const auto ab = b - a;
 
 1553        const auto ac = c - a;
 
 1554        const auto qp = p - q;
 
 1561        const auto denom = 
normal*qp;
 
 1562        const auto abnorm2 = ab.two_norm2();
 
 1563        const auto eps = eps_*abnorm2*qp.two_norm();
 
 1565        if (abs(denom) < eps)
 
 1567            const auto pa = a - p;
 
 1568            const auto denom2 = 
normal*pa;
 
 1569            if (abs(denom2) > eps_*pa.two_norm()*abnorm2)
 
 1574            using SegmentPolicy = 
typename IntersectionPolicy::SegmentPolicy<ctype, dimworld>;
 
 1575            using Triangle = Dune::AffineGeometry<ctype, 2, dimworld>;
 
 1576            using Segment = Dune::AffineGeometry<ctype, 1, dimworld>;
 
 1577            using SegmentIntersectionAlgorithm = GeometryIntersection<Triangle, Segment, SegmentPolicy>;
 
 1578            using SegmentIntersectionType = 
typename SegmentIntersectionAlgorithm::Intersection;
 
 1579            SegmentIntersectionType segmentIs;
 
 1581            Triangle triangle(Dune::GeometryTypes::simplex(2), std::array<Point, 3>({a, b, c}));
 
 1582            Segment segment(Dune::GeometryTypes::simplex(1), std::array<Point, 2>({p, q}));
 
 1583            if (SegmentIntersectionAlgorithm::intersection(triangle, segment, segmentIs))
 
 1585                hasSegmentIs = 
true;
 
 1591            for (
const auto& ip : {p, q})
 
 1607        const auto ap = p - a;
 
 1608        const auto t = (ap*
normal)/denom;
 
 1609        if (t < 0.0 - eps_) 
return false;
 
 1610        if (t > 1.0 + eps_) 
return false;
 
 1615        const auto v = (ac*e)/denom;
 
 1616        if (v < -eps_ || v > 1.0 + eps_) 
return false;
 
 1617        const auto w = -(ab*e)/denom;
 
 1622        const auto u = 1.0 - v - 
w;
 
 
 1637template <
class Geometry1, 
class Geometry2, 
class Policy>
 
 1650    template<
class P = Policy>
 
 
 1661template <
class Geometry1, 
class Geometry2, 
class Policy>
 
 1664    enum { dimworld = 3 };
 
 1674    static constexpr ctype eps_ = 1.5e-7; 
 
 1683    template<
class P = Policy, std::enable_if_t<P::dimIntersection == 0, 
int> = 0>
 
 1686        static_assert(int(dimworld) == int(Geometry2::coorddimension), 
"Can only collide geometries of same coordinate dimension");
 
 1688        const auto v1 = geo1.corner(1) - geo1.corner(0);
 
 1689        const auto v2 = geo2.corner(1) - geo2.corner(0);
 
 1690        const auto ac = geo2.corner(0) - geo1.corner(0);
 
 1692        const auto v1Norm2 = v1.two_norm2();
 
 1693        const auto eps2 = eps_*v1Norm2;
 
 1699        if ( n.two_norm2() < eps2*v1Norm2 )
 
 1707            const auto sp = v1*v2;
 
 1710                if ( ac.two_norm2() < eps2 )
 
 1713                if ( (geo2.corner(1) - geo1.corner(1)).two_norm2() < eps2 )
 
 1718                if ( (geo2.corner(1) - geo1.corner(0)).two_norm2() < eps2 )
 
 1721                if ( (geo2.corner(0) - geo1.corner(1)).two_norm2() < eps2 )
 
 1733        const auto t2 = - 1.0*(ac*v1Normal) / (v2*v1Normal);
 
 1736        if (t2 < -1.0*eps_ || t2 > 1.0 + eps_)
 
 
 1752    template<
class P = Policy, std::enable_if_t<P::dimIntersection == 1, 
int> = 0>
 
 1755        static_assert(int(dimworld) == int(Geometry2::coorddimension), 
"Can only collide geometries of same coordinate dimension");
 
 1757        const auto& a = geo1.corner(0);
 
 1758        const auto& b = geo1.corner(1);
 
 1759        const auto ab = b-a;
 
 1761        const auto& p = geo2.corner(0);
 
 1762        const auto& q = geo2.corner(1);
 
 1763        const auto pq = q-p;
 
 1765        const auto abNorm2 = ab.two_norm2();
 
 1766        const auto pqNorm2 = pq.two_norm2();
 
 1769        const auto eps2 = eps_*max(abNorm2, pqNorm2);
 
 1776        const auto ap = (p-a);
 
 1777        const auto aq = (q-a);
 
 1795        tp = clamp(tp, 0.0, abNorm2);
 
 1796        tq = clamp(tq, 0.0, abNorm2);
 
 1798        if (abs(tp-tq) < eps2)
 
 
 
An axis-aligned bounding box volume hierarchy for dune grids.
typename Policy::Intersection Intersection
Definition geometryintersection.hh:241
typename Policy::ctype ctype
Definition geometryintersection.hh:239
typename Policy::Point Point
Definition geometryintersection.hh:240
static bool intersection(const Geometry1 &geo1, const Geometry2 &geo2, Intersection &intersection)
Colliding two segments.
Definition geometryintersection.hh:250
static bool intersection(const Geometry1 &geo1, const Geometry2 &geo2, typename Base::Intersection &intersection)
Colliding segment and convex polygon.
Definition geometryintersection.hh:520
static bool intersection(const Geometry1 &geo1, const Geometry2 &geo2, Intersection &intersection)
Colliding segment and convex polygon.
Definition geometryintersection.hh:409
typename Policy::ctype ctype
Definition geometryintersection.hh:393
typename Policy::Intersection Intersection
Definition geometryintersection.hh:395
static bool intersection(const Geometry1 &geo1, const Geometry2 &geo2, typename P::Intersection &intersection)
Colliding segment and convex polygon.
Definition geometryintersection.hh:433
typename Policy::Point Point
Definition geometryintersection.hh:394
typename Policy::Intersection Intersection
Definition geometryintersection.hh:540
typename Policy::ctype ctype
Definition geometryintersection.hh:538
static bool intersection(const Geometry1 &geo1, const Geometry2 &geo2, Intersection &intersection)
Colliding two polygons.
Definition geometryintersection.hh:559
typename Policy::Point Point
Definition geometryintersection.hh:539
typename Policy::Intersection Intersection
Definition geometryintersection.hh:1671
typename Policy::Point Point
Definition geometryintersection.hh:1670
static bool intersection(const Geometry1 &geo1, const Geometry2 &geo2, Intersection &intersection)
Colliding two segments.
Definition geometryintersection.hh:1684
typename Policy::ctype ctype
Definition geometryintersection.hh:1669
static bool intersection(const Geometry1 &geo1, const Geometry2 &geo2, typename Base::Intersection &intersection)
Colliding segment and convex polygon.
Definition geometryintersection.hh:1651
static bool intersection(const Geometry1 &geo1, const Geometry2 &geo2, typename Base::Intersection &intersection)
Colliding segment and convex polyhedron.
Definition geometryintersection.hh:818
typename Policy::Intersection Intersection
Definition geometryintersection.hh:1398
typename Policy::Point Point
Definition geometryintersection.hh:1397
typename Policy::ctype ctype
Definition geometryintersection.hh:1396
static bool intersection(const Geometry1 &geo1, const Geometry2 &geo2, Intersection &intersection)
Colliding segment and convex polyhedron.
Definition geometryintersection.hh:1414
static bool intersection(const Geometry1 &geo1, const Geometry2 &geo2, Intersection &is)
Colliding segment and convex polyhedron.
Definition geometryintersection.hh:1440
typename Policy::Point Point
Definition geometryintersection.hh:837
typename Policy::ctype ctype
Definition geometryintersection.hh:836
typename Policy::Intersection Intersection
Definition geometryintersection.hh:838
static bool intersection(const Geometry1 &geo1, const Geometry2 &geo2, Intersection &intersection)
Colliding two polygons.
Definition geometryintersection.hh:856
static bool intersection(const Geometry1 &geo1, const Geometry2 &geo2, typename Base::Intersection &intersection)
Colliding polygon and convex polyhedron.
Definition geometryintersection.hh:1196
typename Policy::Intersection Intersection
Definition geometryintersection.hh:684
typename Policy::Point Point
Definition geometryintersection.hh:683
typename Policy::ctype ctype
Definition geometryintersection.hh:682
static bool intersection(const Geometry1 &geo1, const Geometry2 &geo2, Intersection &intersection)
Colliding segment and convex polyhedron.
Definition geometryintersection.hh:702
typename Policy::Intersection Intersection
Definition geometryintersection.hh:1024
static bool intersection(const Geometry1 &geo1, const Geometry2 &geo2, Intersection &intersection)
Colliding polygon and convex polyhedron.
Definition geometryintersection.hh:1045
typename Policy::Point Point
Definition geometryintersection.hh:1023
typename Policy::ctype ctype
Definition geometryintersection.hh:1022
typename Policy::Point Point
Definition geometryintersection.hh:1215
typename Policy::Intersection Intersection
Definition geometryintersection.hh:1216
typename Policy::ctype ctype
Definition geometryintersection.hh:1214
static bool intersection(const Geometry1 &geo1, const Geometry2 &geo2, Intersection &intersection)
Colliding two convex polyhedra.
Definition geometryintersection.hh:1234
A class for geometry collision detection and intersection calculation The class can be specialized fo...
Definition geometryintersection.hh:207
typename Policy::ctype ctype
Definition geometryintersection.hh:211
typename Policy::Intersection Intersection
Definition geometryintersection.hh:213
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:216
typename Policy::Point Point
Definition geometryintersection.hh:212
default policy chooser class
Definition geometryintersection.hh:85
std::tuple_element_t< isDim, DefaultPolicies > type
Definition geometryintersection.hh:99
A function to compute the convex hull of a point cloud.
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:671
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:28
Vector normal(const Vector &v)
Create a vector normal to the given one (v is expected to be non-zero)
Definition normal.hh:26
std::vector< Dune::FieldVector< ctype, dimWorld > > grahamConvexHull(std::vector< Dune::FieldVector< ctype, dimWorld > > &points)
Compute the points making up the convex hull around the given set of unordered points.
Definition grahamconvexhull.hh:186
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:26
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:125
Detect if a point intersects a geometry.
Define some often used mathematical functions.
Distance implementation details.
Definition cvfelocalresidual.hh:25
Definition geometryintersection.hh:29
typename DefaultPolicyChooser< Geometry1, Geometry2 >::type DefaultPolicy
Helper alias to define the default intersection policy.
Definition geometryintersection.hh:104
const Scalar PengRobinsonMixture< Scalar, StaticParameters >::w
Definition pengrobinsonmixture.hh:140
const Scalar PengRobinsonMixture< Scalar, StaticParameters >::u
Definition pengrobinsonmixture.hh:138
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:305
Policy structure for point-like intersections.
Definition geometryintersection.hh:34
static constexpr int dimIntersection
Definition geometryintersection.hh:39
Point Intersection
Definition geometryintersection.hh:40
ct ctype
Definition geometryintersection.hh:35
Dune::FieldVector< ctype, dw > Point
Definition geometryintersection.hh:36
static constexpr int dimWorld
Definition geometryintersection.hh:38
Policy structure for polygon-like intersections.
Definition geometryintersection.hh:59
static constexpr int dimWorld
Definition geometryintersection.hh:64
static constexpr int dimIntersection
Definition geometryintersection.hh:65
ct ctype
Definition geometryintersection.hh:60
Polygon Intersection
Definition geometryintersection.hh:66
Dune::FieldVector< ctype, dw > Point
Definition geometryintersection.hh:61
std::vector< Point > Polygon
Definition geometryintersection.hh:62
Policy structure for polyhedron-like intersections.
Definition geometryintersection.hh:72
std::vector< Point > Polyhedron
Definition geometryintersection.hh:75
Dune::FieldVector< ctype, dw > Point
Definition geometryintersection.hh:74
Polyhedron Intersection
Definition geometryintersection.hh:79
static constexpr int dimIntersection
Definition geometryintersection.hh:78
static constexpr int dimWorld
Definition geometryintersection.hh:77
ct ctype
Definition geometryintersection.hh:73
Policy structure for segment-like intersections.
Definition geometryintersection.hh:46
Segment Intersection
Definition geometryintersection.hh:53
static constexpr int dimIntersection
Definition geometryintersection.hh:52
Dune::FieldVector< ctype, dw > Point
Definition geometryintersection.hh:48
static constexpr int dimWorld
Definition geometryintersection.hh:51
std::array< Point, 2 > Segment
Definition geometryintersection.hh:49
ct ctype
Definition geometryintersection.hh:47