mirror of
https://develop.openfoam.com/Development/openfoam.git
synced 2025-11-28 03:28:01 +00:00
ENH: orient cut plane faces based on the (oriented) edge gradient
- Since the local edges are oriented according to the gradient, they can also be used to determine the correct face orientation. This generalizes the algorithm for future reuse.
This commit is contained in:
@ -56,6 +56,23 @@ namespace Foam
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Classify sides of plane (0=BACK, 1=ONPLANE, 2=FRONT) for each point
|
||||||
|
inline PackedList<2> classifySides(const plane& pln, const pointField& pts)
|
||||||
|
{
|
||||||
|
const label len = pts.size();
|
||||||
|
|
||||||
|
PackedList<2> output(len);
|
||||||
|
|
||||||
|
// From signed (-1,0,+1) to (0,1,2) for PackedList
|
||||||
|
for (label i=0; i < len; ++i)
|
||||||
|
{
|
||||||
|
output.set(i, unsigned(1 + pln.sign(pts[i], SMALL)));
|
||||||
|
}
|
||||||
|
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Check for face/plane intersection based on crossings
|
// Check for face/plane intersection based on crossings
|
||||||
// Took (-1,0,+1) from plane::sign and packed as (0,1,2).
|
// Took (-1,0,+1) from plane::sign and packed as (0,1,2).
|
||||||
// Now use for left shift to obtain (1,2,4).
|
// Now use for left shift to obtain (1,2,4).
|
||||||
@ -78,35 +95,11 @@ namespace Foam
|
|||||||
return (accum == 3 || accum >= 5);
|
return (accum == 3 || accum >= 5);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//- For hashing face point labels, which are pre-sorted.
|
|
||||||
typedef HashSet<labelList, labelList::Hash<>> labelListHashSet;
|
|
||||||
|
|
||||||
} // End namespace Foam
|
} // End namespace Foam
|
||||||
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
||||||
|
|
||||||
Foam::PackedList<2> Foam::cuttingPlane::classifySides
|
|
||||||
(
|
|
||||||
const plane& pln,
|
|
||||||
const pointField& pts
|
|
||||||
)
|
|
||||||
{
|
|
||||||
const label len = pts.size();
|
|
||||||
|
|
||||||
PackedList<2> output(len);
|
|
||||||
|
|
||||||
// From signed (-1,0,+1) to (0,1,2) for PackedList
|
|
||||||
for (label i=0; i < len; ++i)
|
|
||||||
{
|
|
||||||
output.set(i, unsigned(1 + pln.sign(pts[i], SMALL)));
|
|
||||||
}
|
|
||||||
|
|
||||||
return output;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Foam::label Foam::cuttingPlane::calcCellCuts
|
Foam::label Foam::cuttingPlane::calcCellCuts
|
||||||
(
|
(
|
||||||
const primitiveMesh& mesh,
|
const primitiveMesh& mesh,
|
||||||
@ -231,12 +224,18 @@ Foam::label Foam::cuttingPlane::calcCellCuts
|
|||||||
void Foam::cuttingPlane::walkCellCuts
|
void Foam::cuttingPlane::walkCellCuts
|
||||||
(
|
(
|
||||||
const primitiveMesh& mesh,
|
const primitiveMesh& mesh,
|
||||||
const PackedList<2>& sides,
|
|
||||||
const bitSet& cellCuts,
|
const bitSet& cellCuts,
|
||||||
|
const PackedList<2>& sides,
|
||||||
const bool triangulate,
|
const bool triangulate,
|
||||||
label nFaceCuts
|
label nFaceCuts
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
|
// Information required from the mesh
|
||||||
|
const faceList& faces = mesh.faces();
|
||||||
|
const cellList& cells = mesh.cells();
|
||||||
|
const pointField& points = mesh.points();
|
||||||
|
|
||||||
|
|
||||||
// Dynamic lists to handle triangulation and/or missed cuts etc
|
// Dynamic lists to handle triangulation and/or missed cuts etc
|
||||||
const label nCellCuts = cellCuts.count();
|
const label nCellCuts = cellCuts.count();
|
||||||
|
|
||||||
@ -250,12 +249,6 @@ void Foam::cuttingPlane::walkCellCuts
|
|||||||
nFaceCuts = 4*nCellCuts;
|
nFaceCuts = 4*nCellCuts;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Information required from the mesh
|
|
||||||
const faceList& faces = mesh.faces();
|
|
||||||
const cellList& cells = mesh.cells();
|
|
||||||
const pointField& points = mesh.points();
|
|
||||||
|
|
||||||
|
|
||||||
// Edge to pointId mapping
|
// Edge to pointId mapping
|
||||||
EdgeMap<label> handledEdges(4*nFaceCuts);
|
EdgeMap<label> handledEdges(4*nFaceCuts);
|
||||||
|
|
||||||
@ -273,8 +266,8 @@ void Foam::cuttingPlane::walkCellCuts
|
|||||||
// that "owns" the point.
|
// that "owns" the point.
|
||||||
Map<label> endPoints;
|
Map<label> endPoints;
|
||||||
|
|
||||||
// Hash of faces (face points) exactly on-plane
|
// Hash of faces (face points) that are exactly on a cell face
|
||||||
labelListHashSet onPlaneFaces;
|
HashSet<labelList, labelList::Hash<>> onCellFace;
|
||||||
|
|
||||||
|
|
||||||
// Failure handling
|
// Failure handling
|
||||||
@ -363,7 +356,6 @@ void Foam::cuttingPlane::walkCellCuts
|
|||||||
// Expected id for the cut point
|
// Expected id for the cut point
|
||||||
cutPointId = dynCutPoints.size();
|
cutPointId = dynCutPoints.size();
|
||||||
|
|
||||||
|
|
||||||
const point& p0 = points[e[0]];
|
const point& p0 = points[e[0]];
|
||||||
const point& p1 = points[e[1]];
|
const point& p1 = points[e[1]];
|
||||||
|
|
||||||
@ -429,16 +421,16 @@ void Foam::cuttingPlane::walkCellCuts
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Handling cuts between two cells (on-plane cuts)
|
// Handling cuts between two cells
|
||||||
// After the previous intersectEdgeOrient call, the edge is oriented
|
// After the previous intersectEdgeOrient call, the edge oriented
|
||||||
// to have 0-1 in the positive plane normal.
|
// according to the gradient.
|
||||||
// If we only ever cut at the same edge end we know that we have
|
// If we only ever cut at the same edge end we know that we have
|
||||||
// an on-plane cut.
|
// a cut coinciding with a cell face.
|
||||||
|
|
||||||
if (pointCutType == 1 || pointCutType == 2)
|
if (pointCutType == 1 || pointCutType == 2)
|
||||||
{
|
{
|
||||||
// Hash the face-points to avoid duplicate faces
|
// Hash the face-points to avoid duplicate faces
|
||||||
if (!onPlaneFaces.insert(HashTableOps::values(localEdges, true)))
|
if (!onCellFace.insert(HashTableOps::values(localEdges, true)))
|
||||||
{
|
{
|
||||||
DebugInfo
|
DebugInfo
|
||||||
<<"skip duplicate on-place cut for cell " << celli
|
<<"skip duplicate on-place cut for cell " << celli
|
||||||
@ -451,7 +443,12 @@ void Foam::cuttingPlane::walkCellCuts
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Start somewhere
|
// Start somewhere.
|
||||||
|
|
||||||
|
// Since the local edges are oriented according to the gradient,
|
||||||
|
// they can also be used to determine the correct face orientation.
|
||||||
|
|
||||||
|
const edge refEdge = localFaces.begin().key();
|
||||||
label nextFace = localFaces.begin().object()[0];
|
label nextFace = localFaces.begin().object()[0];
|
||||||
|
|
||||||
DebugInfo
|
DebugInfo
|
||||||
@ -471,6 +468,7 @@ void Foam::cuttingPlane::walkCellCuts
|
|||||||
DebugInfo
|
DebugInfo
|
||||||
<< "lookup " << nextFace << " in " << iter.object() << nl;
|
<< "lookup " << nextFace << " in " << iter.object() << nl;
|
||||||
|
|
||||||
|
// Find local index (0,1) or -1 on failure
|
||||||
const label got = iter.object().which(nextFace);
|
const label got = iter.object().which(nextFace);
|
||||||
|
|
||||||
if (got != -1)
|
if (got != -1)
|
||||||
@ -507,7 +505,7 @@ void Foam::cuttingPlane::walkCellCuts
|
|||||||
if (nTargetLoop != localFaceLoop.size())
|
if (nTargetLoop != localFaceLoop.size())
|
||||||
{
|
{
|
||||||
DebugInfo
|
DebugInfo
|
||||||
<<"Warn expected " << nTargetLoop << " but got "
|
<< "Warn expected " << nTargetLoop << " but got "
|
||||||
<< localFaceLoop.size() << endl;
|
<< localFaceLoop.size() << endl;
|
||||||
|
|
||||||
unwindWalk(celli);
|
unwindWalk(celli);
|
||||||
@ -520,9 +518,8 @@ void Foam::cuttingPlane::walkCellCuts
|
|||||||
|
|
||||||
face f(localFaceLoop);
|
face f(localFaceLoop);
|
||||||
|
|
||||||
// Action #3: orient face
|
// Orient face to point in the same direction as the edge gradient
|
||||||
// Orient face to point in the same direction as the plane normal
|
if ((f.areaNormal(dynCutPoints) & refEdge.vec(points)) < 0)
|
||||||
if ((f.areaNormal(dynCutPoints) & this->normal()) < 0)
|
|
||||||
{
|
{
|
||||||
f.flip();
|
f.flip();
|
||||||
}
|
}
|
||||||
@ -646,7 +643,7 @@ void Foam::cuttingPlane::performCut
|
|||||||
const label nFaceCuts = calcCellCuts(mesh, sides, cellCuts);
|
const label nFaceCuts = calcCellCuts(mesh, sides, cellCuts);
|
||||||
|
|
||||||
// Find closed loop from cell cuts
|
// Find closed loop from cell cuts
|
||||||
walkCellCuts(mesh, sides, cellCuts, triangulate, nFaceCuts);
|
walkCellCuts(mesh, cellCuts, sides, triangulate, nFaceCuts);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -77,14 +77,12 @@ class cuttingPlane
|
|||||||
|
|
||||||
// Private Member Functions
|
// Private Member Functions
|
||||||
|
|
||||||
//- Classify sides of plane (0=BACK, 1=ONPLANE, 2=FRONT) for each point
|
|
||||||
static PackedList<2> classifySides
|
|
||||||
(
|
|
||||||
const plane& pln,
|
|
||||||
const pointField& pts
|
|
||||||
);
|
|
||||||
|
|
||||||
//- Determine cut cells, possibly restricted to a list of cells
|
//- Determine cut cells, possibly restricted to a list of cells
|
||||||
|
//
|
||||||
|
// \param cellCuts [in,out] On input an empty set (ie, no restriction)
|
||||||
|
// or subsetted cells. On output, the cells cut according to the
|
||||||
|
// planeSides detection.
|
||||||
|
//
|
||||||
// \return number of faces cut
|
// \return number of faces cut
|
||||||
label calcCellCuts
|
label calcCellCuts
|
||||||
(
|
(
|
||||||
@ -94,11 +92,13 @@ class cuttingPlane
|
|||||||
);
|
);
|
||||||
|
|
||||||
//- Walk the cell cuts to create faces
|
//- Walk the cell cuts to create faces
|
||||||
|
//
|
||||||
|
// \param planeSides [in] Used to determine edge cuts
|
||||||
void walkCellCuts
|
void walkCellCuts
|
||||||
(
|
(
|
||||||
const primitiveMesh& mesh,
|
const primitiveMesh& mesh,
|
||||||
const PackedList<2>& planeSides,
|
|
||||||
const bitSet& cellCuts,
|
const bitSet& cellCuts,
|
||||||
|
const PackedList<2>& planeSides,
|
||||||
const bool triangulate,
|
const bool triangulate,
|
||||||
const label nFaceCuts = 0
|
const label nFaceCuts = 0
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user