Commit 1ae664e3 authored by Andrew Heather's avatar Andrew Heather
Browse files

ENH: Reinstated local tet-based intersection

parent 994b303a
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2012 OpenFOAM Foundation
\\/ M anipulation | Copyright (C) 2017 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
Class
Foam::tetPoints
Description
Tet storage. Null constructable (unfortunately tetrahedron<point, point>
is not)
SourceFiles
\*---------------------------------------------------------------------------*/
#ifndef tetPoints_H
#define tetPoints_H
#include "tetrahedron.H"
#include "FixedList.H"
#include "treeBoundBox.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
/*---------------------------------------------------------------------------*\
Class tetPoints Declaration
\*---------------------------------------------------------------------------*/
class tetPoints
:
public FixedList<point, 4>
{
public:
// Constructors
//- Construct null
inline tetPoints()
{}
//- Construct from four points
inline tetPoints
(
const point& a,
const point& b,
const point& c,
const point& d
)
{
operator[](0) = a;
operator[](1) = b;
operator[](2) = c;
operator[](3) = d;
}
// Member Functions
//- Return the tetrahedron
inline tetPointRef tet() const
{
return tetPointRef
(
operator[](0),
operator[](1),
operator[](2),
operator[](3)
);
}
//- Calculate the bounding box
inline treeBoundBox bounds() const
{
treeBoundBox bb(operator[](0));
for (label i = 1; i < size(); ++i)
{
bb.add(operator[](i));
}
return bb;
}
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //
......@@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2017 OpenFOAM Foundation
\\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation
\\/ M anipulation |
-------------------------------------------------------------------------------
License
......@@ -56,6 +56,8 @@ namespace Foam
class Istream;
class Ostream;
class tetPoints;
class plane;
// Forward declaration of friend functions and operators
......@@ -75,6 +77,8 @@ inline Ostream& operator<<
const tetrahedron<Point, PointRef>&
);
typedef tetrahedron<point, const point&> tetPointRef;
/*---------------------------------------------------------------------------*\
class tetrahedron Declaration
\*---------------------------------------------------------------------------*/
......@@ -82,12 +86,78 @@ inline Ostream& operator<<
template<class Point, class PointRef>
class tetrahedron
{
public:
// Public typedefs
//- Storage type for tets originating from intersecting tets.
// (can possibly be smaller than 200)
typedef FixedList<tetPoints, 200> tetIntersectionList;
// Classes for use in sliceWithPlane. What to do with decomposition
// of tet.
//- Dummy
class dummyOp
{
public:
inline void operator()(const tetPoints&);
};
//- Sum resulting volumes
class sumVolOp
{
public:
scalar vol_;
inline sumVolOp();
inline void operator()(const tetPoints&);
};
//- Store resulting tets
class storeOp
{
tetIntersectionList& tets_;
label& nTets_;
public:
inline storeOp(tetIntersectionList&, label&);
inline void operator()(const tetPoints&);
};
private:
// Private data
PointRef a_, b_, c_, d_;
inline static point planeIntersection
(
const FixedList<scalar, 4>&,
const tetPoints&,
const label,
const label
);
template<class TetOp>
inline static void decomposePrism
(
const FixedList<point, 6>& points,
TetOp& op
);
template<class AboveTetOp, class BelowTetOp>
inline static void tetSliceWithPlane
(
const plane& pl,
const tetPoints& tet,
AboveTetOp& aboveOp,
BelowTetOp& belowOp
);
public:
......@@ -170,10 +240,6 @@ public:
// uniform distribution
inline Point randomPoint(Random& rndGen) const;
//- Return a random point in the tetrahedron from a
// uniform distribution
inline Point randomPoint(cachedRandom& rndGen) const;
//- Calculate the point from the given barycentric coordinates.
inline Point barycentricToPoint(const barycentric& bary) const;
......@@ -195,6 +261,26 @@ public:
//- Return true if point is inside tetrahedron
inline bool inside(const point& pt) const;
//- Decompose tet into tets above and below plane
template<class AboveTetOp, class BelowTetOp>
inline void sliceWithPlane
(
const plane& pl,
AboveTetOp& aboveOp,
BelowTetOp& belowOp
) const;
//- Decompose tet into tets inside and outside other tet
inline void tetOverlap
(
const tetrahedron<Point, PointRef>& tetB,
tetIntersectionList& insideTets,
label& nInside,
tetIntersectionList& outsideTets,
label& nOutside
) const;
//- Return (min)containment sphere, i.e. the smallest sphere with
// all points inside. Returns pointHit with:
// - hit : if sphere is equal to circumsphere
......
......@@ -25,6 +25,7 @@ License
#include "triangle.H"
#include "IOstreams.H"
#include "tetPoints.H"
#include "plane.H"
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
......@@ -485,6 +486,548 @@ bool Foam::tetrahedron<Point, PointRef>::inside(const point& pt) const
}
template<class Point, class PointRef>
inline void Foam::tetrahedron<Point, PointRef>::dummyOp::operator()
(
const tetPoints&
)
{}
template<class Point, class PointRef>
inline Foam::tetrahedron<Point, PointRef>::sumVolOp::sumVolOp()
:
vol_(0.0)
{}
template<class Point, class PointRef>
inline void Foam::tetrahedron<Point, PointRef>::sumVolOp::operator()
(
const tetPoints& tet
)
{
vol_ += tet.tet().mag();
}
template<class Point, class PointRef>
inline Foam::tetrahedron<Point, PointRef>::storeOp::storeOp
(
tetIntersectionList& tets,
label& nTets
)
:
tets_(tets),
nTets_(nTets)
{}
template<class Point, class PointRef>
inline void Foam::tetrahedron<Point, PointRef>::storeOp::operator()
(
const tetPoints& tet
)
{
tets_[nTets_++] = tet;
}
template<class Point, class PointRef>
inline Foam::point Foam::tetrahedron<Point, PointRef>::planeIntersection
(
const FixedList<scalar, 4>& d,
const tetPoints& t,
const label negI,
const label posI
)
{
return
(d[posI]*t[negI] - d[negI]*t[posI])
/ (-d[negI]+d[posI]);
}
template<class Point, class PointRef>
template<class TetOp>
inline void Foam::tetrahedron<Point, PointRef>::decomposePrism
(
const FixedList<point, 6>& points,
TetOp& op
)
{
op(tetPoints(points[1], points[3], points[2], points[0]));
op(tetPoints(points[1], points[2], points[3], points[4]));
op(tetPoints(points[4], points[2], points[3], points[5]));
}
template<class Point, class PointRef>
template<class AboveTetOp, class BelowTetOp>
inline void Foam::tetrahedron<Point, PointRef>::tetSliceWithPlane
(
const plane& pl,
const tetPoints& tet,
AboveTetOp& aboveOp,
BelowTetOp& belowOp
)
{
// Distance to plane
FixedList<scalar, 4> d;
label nPos = 0;
forAll(tet, i)
{
d[i] = ((tet[i] - pl.refPoint()) & pl.normal());
if (d[i] > 0)
{
nPos++;
}
}
if (nPos == 4)
{
aboveOp(tet);
}
else if (nPos == 3)
{
// Sliced into below tet and above prism. Prism gets split into
// two tets.
// Find the below tet
label i0 = -1;
forAll(d, i)
{
if (d[i] <= 0)
{
i0 = i;
break;
}
}
label i1 = d.fcIndex(i0);
label i2 = d.fcIndex(i1);
label i3 = d.fcIndex(i2);
point p01(planeIntersection(d, tet, i0, i1));
point p02(planeIntersection(d, tet, i0, i2));
point p03(planeIntersection(d, tet, i0, i3));
// i0 = tetCell vertex 0: p01,p02,p03 outwards pointing triad
// ,, 1 : ,, inwards pointing triad
// ,, 2 : ,, outwards pointing triad
// ,, 3 : ,, inwards pointing triad
//Pout<< "Split 3pos tet " << tet << " d:" << d << " into" << nl;
if (i0 == 0 || i0 == 2)
{
tetPoints t(tet[i0], p01, p02, p03);
//Pout<< " belowtet:" << t << " around i0:" << i0 << endl;
//checkTet(t, "nPos 3, belowTet i0==0 or 2");
belowOp(t);
// Prism
FixedList<point, 6> p
(
{
tet[i1],
tet[i3],
tet[i2],
p01,
p03,
p02
}
);
//Pout<< " aboveprism:" << p << endl;
decomposePrism(p, aboveOp);
}
else
{
tetPoints t(p01, p02, p03, tet[i0]);
//Pout<< " belowtet:" << t << " around i0:" << i0 << endl;
//checkTet(t, "nPos 3, belowTet i0==1 or 3");
belowOp(t);
// Prism
FixedList<point, 6> p
(
{
tet[i3],
tet[i1],
tet[i2],
p03,
p01,
p02
}
);
//Pout<< " aboveprism:" << p << endl;
decomposePrism(p, aboveOp);
}
}
else if (nPos == 2)
{
// Tet cut into two prisms. Determine the positive one.
label pos0 = -1;
label pos1 = -1;
forAll(d, i)
{
if (d[i] > 0)
{
if (pos0 == -1)
{
pos0 = i;
}
else
{
pos1 = i;
}
}
}
//Pout<< "Split 2pos tet " << tet << " d:" << d
// << " around pos0:" << pos0 << " pos1:" << pos1
// << " neg0:" << neg0 << " neg1:" << neg1 << " into" << nl;
const edge posEdge(pos0, pos1);
if (posEdge == edge(0, 1))
{
point p02(planeIntersection(d, tet, 0, 2));
point p03(planeIntersection(d, tet, 0, 3));
point p12(planeIntersection(d, tet, 1, 2));
point p13(planeIntersection(d, tet, 1, 3));
// Split the resulting prism
{
FixedList<point, 6> p
(
{
tet[0],
p02,
p03,
tet[1],
p12,
p13
}
);
//Pout<< " 01 aboveprism:" << p << endl;
decomposePrism(p, aboveOp);
}
{
FixedList<point, 6> p
(
{
tet[2],
p02,
p12,
tet[3],
p03,
p13
}
);
//Pout<< " 01 belowprism:" << p << endl;
decomposePrism(p, belowOp);
}
}
else if (posEdge == edge(1, 2))
{
point p01(planeIntersection(d, tet, 0, 1));
point p13(planeIntersection(d, tet, 1, 3));
point p02(planeIntersection(d, tet, 0, 2));
point p23(planeIntersection(d, tet, 2, 3));
// Split the resulting prism
{
FixedList<point, 6> p
(
{
tet[1],
p01,
p13,
tet[2],
p02,
p23
}
);
//Pout<< " 12 aboveprism:" << p << endl;
decomposePrism(p, aboveOp);
}
{
FixedList<point, 6> p
(
{
tet[3],
p23,
p13,
tet[0],
p02,
p01
}
);
//Pout<< " 12 belowprism:" << p << endl;
decomposePrism(p, belowOp);
}
}
else if (posEdge == edge(2, 0))
{
point p01(planeIntersection(d, tet, 0, 1));
point p03(planeIntersection(d, tet, 0, 3));
point p12(planeIntersection(d, tet, 1, 2));
point p23(planeIntersection(d, tet, 2, 3));
// Split the resulting prism
{
FixedList<point, 6> p
(
{
tet[2],
p12,
p23,
tet[0],
p01,
p03
}
);
//Pout<< " 20 aboveprism:" << p << endl;
decomposePrism(p, aboveOp);
}
{
FixedList<point, 6> p
(
{
tet[1],
p12,
p01,
tet[3],
p23,
p03
}
);
//Pout<< " 20 belowprism:" << p << endl;
decomposePrism(p, belowOp);
}
}
else if (posEdge == edge(0, 3))
{
point p01(planeIntersection(d, tet, 0, 1));
point p02(planeIntersection(d, tet, 0, 2));