Adding faceCollapseMode enum to control mode. Fixing logic error,

returning validCollapse as the status of the faceCollapse was wrong,
it didn't necessarily mean the face was collapsed.

Adding mpre filtering controls to cvContol and using them in the
filtering functions.

Removing minimumEdgeLength(const point& pt) - not needed, always using
the stored vertex size.
This commit is contained in:
graham
2010-01-08 16:40:04 +00:00
parent 7800ceac99
commit d598afbd90
7 changed files with 233 additions and 178 deletions

View File

@ -93,6 +93,15 @@ public:
rmFine // Rebuild the conformation with fine tolerances (slower)
};
enum faceCollapseMode
{
fcmNone, // Do not collapse face
fcmEdge, // Collapse face to a single edge
fcmPoint, // Collapse face to a point
fcmDeferredMultiEdge // Collapse face to several edges
};
private:
// Private data
@ -214,9 +223,6 @@ private:
//- Return the local maximum surface protrusion distance
inline scalar maxSurfaceProtrusion(const point& pt) const;
//- Return the local minimum allowed dual edge length
inline scalar minimumEdgeLength(const point& pt) const;
//- Return the required alignment directions at the given location
tensor requiredAlignment(const point& pt) const;
@ -504,7 +510,7 @@ private:
//- Collapse a face to an edge, updating the point and point
//- map. Returns a bool of success or failure.
bool collapseFaceToEdge
bool collapseFace
(
const face& f,
pointField& pts,

View File

@ -76,8 +76,6 @@ void Foam::conformalVoronoiMesh::calcDualMesh
}
}
// Dual face filtering
// Indexing Delaunay cells, which are the dual vertices
label dualVertI = 0;
@ -386,7 +384,7 @@ Foam::label Foam::conformalVoronoiMesh::mergeCloseDualVertices
{
label nPtsMerged = 0;
scalar closenessTolerance = 1e-6;
scalar closenessTolerance = cvMeshControls().mergeClosenessCoeff();
for
(
@ -512,7 +510,10 @@ Foam::label Foam::conformalVoronoiMesh::smoothSurfaceDualFaces
{
label nCollapsedFaces = 0;
const scalar cosPerpendicularToleranceAngle = cos(degToRad(80));
const scalar cosPerpendicularToleranceAngle = cos
(
degToRad(cvMeshControls().surfaceStepFaceAngle())
);
for
(
@ -579,7 +580,16 @@ Foam::label Foam::conformalVoronoiMesh::smoothSurfaceDualFaces
vector faceNormal = dualFace.normal(pts);
faceNormal /= mag(faceNormal);
if (mag(faceNormal) < VSMALL)
{
// If the face is essentially zero area, then force it
// to be collapsed by making the dot product result -1
faceNormal = -surfaceNormal;
}
else
{
faceNormal /= mag(faceNormal);
}
if ((faceNormal & surfaceNormal) < cosPerpendicularToleranceAngle)
{
@ -591,7 +601,7 @@ Foam::label Foam::conformalVoronoiMesh::smoothSurfaceDualFaces
if
(
collapseFaceToEdge
collapseFace
(
dualFace,
pts,
@ -642,7 +652,7 @@ Foam::label Foam::conformalVoronoiMesh::collapseFaces
{
label nCollapsedFaces = 0;
scalar collapseSizeLimitCoeff = cvMeshControls().minimumEdgeLengthCoeff();
scalar collapseSizeLimitCoeff = cvMeshControls().filterSizeCoeff();
for
(
@ -687,7 +697,7 @@ Foam::label Foam::conformalVoronoiMesh::collapseFaces
if
(
collapseFaceToEdge
collapseFace
(
dualFace,
pts,
@ -706,7 +716,7 @@ Foam::label Foam::conformalVoronoiMesh::collapseFaces
}
bool Foam::conformalVoronoiMesh::collapseFaceToEdge
bool Foam::conformalVoronoiMesh::collapseFace
(
const face& f,
pointField& pts,
@ -715,7 +725,7 @@ bool Foam::conformalVoronoiMesh::collapseFaceToEdge
scalar collapseSizeLimitCoeff
) const
{
scalar guardFraction = 0.3;
bool limitToQuadsOrTris = true;
const vector fC = f.centre(pts);
@ -730,58 +740,28 @@ bool Foam::conformalVoronoiMesh::collapseFaceToEdge
// eigenvector corresponding to the smaller of the two remaining
// eigenvalues is the dominant axis in a high aspect ratio face.
// Normalise inertia tensor to remove problems with small values
scalar magJ = mag(J);
scalar detJ = SMALL;
if (magJ > VSMALL)
{
// Normalise inertia tensor to remove problems with small values
J /= mag(J);
// J /= cmptMax(J);
// J /= max(eigenValues(J).x(), SMALL);
}
else
{
WarningIn
(
"Foam::conformalVoronoiMesh::collapseFaceToEdge"
"("
"const face& f,"
"pointField& pts,"
"Map<label>& dualPtIndexMap"
") const"
)
<< "Inertia tensor magnitude too small, not collapsing." << nl
<< J << nl << "mag = " << magJ
<< endl;
// Output face and collapse axis for visualisation
// Calculating determinant, including stabilisation for zero or
// small negative values
forAll(f, fPtI)
{
meshTools::writeOBJ(Info, pts[f[fPtI]]);
}
Info<< "f";
forAll(f, fPtI)
{
Info << " " << fPtI + 1;
}
Info<< nl << endl;
return false;
detJ = max(det(J), SMALL);
}
vector collapseAxis = vector::zero;
scalar aspectRatio = 1;
// Calculating determinant, including stabilisation for zero or
// small negative values
scalar detJ = max(det(J), SMALL);
if (detJ < 1e-5)
{
const edgeList& eds = f.edges();
@ -839,7 +819,7 @@ bool Foam::conformalVoronoiMesh::collapseFaceToEdge
{
WarningIn
(
"Foam::conformalVoronoiMesh::collapseFaceToEdge"
"Foam::conformalVoronoiMesh::collapseFace"
"("
"const face& f,"
"pointField& pts,"
@ -849,33 +829,6 @@ bool Foam::conformalVoronoiMesh::collapseFaceToEdge
<< "No collapse axis found for face, not collapsing."
<< endl;
// // Output face and collapse axis for visualisation
// Info<< nl << "# Aspect ratio = " << aspectRatio << nl
// << "# collapseAxis = " << collapseAxis << nl
// << "# eigenvalues = " << eVals << endl;
// scalar scale = 2.0*mag(fC - pts[f[0]]);
// meshTools::writeOBJ(Info, fC);
// meshTools::writeOBJ(Info, fC + scale*collapseAxis);
// Info<< "f 1 2" << endl;
// forAll(f, fPtI)
// {
// meshTools::writeOBJ(Info, pts[f[fPtI]]);
// }
// Info<< "f";
// forAll(f, fPtI)
// {
// Info << " " << fPtI + 3;
// }
// Info<< nl << endl;
return false;
}
@ -913,44 +866,6 @@ bool Foam::conformalVoronoiMesh::collapseFaceToEdge
d += dShift;
// // Output face and collapse axis for visualisation
// Info<< "# Aspect ratio = " << aspectRatio << nl
// << "# determinant = " << detJ << nl
// << "# collapseAxis = " << collapseAxis << nl
// // << "# eigenvalues = " << eVals
// << endl;
// scalar scale = 2.0*mag(fC - pts[f[0]]);
// meshTools::writeOBJ(Info, fC);
// meshTools::writeOBJ(Info, fC + scale*collapseAxis);
// Info<< "f 1 2" << endl;
// forAll(f, fPtI)
// {
// meshTools::writeOBJ(Info, pts[f[fPtI]]);
// }
// Info<< "f";
// forAll(f, fPtI)
// {
// Info << " " << fPtI + 3;
// }
// Info<< nl << "# " << d << endl;
// Info<< "# " << d.first() << " " << d.last() << endl;
// forAll(d, dI)
// {
// meshTools::writeOBJ(Info, fC + (d[dI] - dShift)*collapseAxis);
// }
// Info<< endl;
// Form two lists, one for each half of the set of points
// projected along the collapse axis.
@ -989,7 +904,7 @@ bool Foam::conformalVoronoiMesh::collapseFaceToEdge
{
WarningIn
(
"Foam::conformalVoronoiMesh::collapseFaceToEdge"
"Foam::conformalVoronoiMesh::collapseFace"
"("
"const face& f,"
"pointField& pts,"
@ -1000,20 +915,58 @@ bool Foam::conformalVoronoiMesh::collapseFaceToEdge
<< endl;
}
bool validCollapse = false;
faceCollapseMode mode = fcmNone;
if
(
(dNeg.last() < guardFraction*dNeg.first())
&& (dPos.first() > guardFraction*dPos.last())
&& (fA < aspectRatio*sqr(targetFaceSize*collapseSizeLimitCoeff))
&& f.size() <= 4
(fA < aspectRatio*sqr(targetFaceSize*collapseSizeLimitCoeff))
&& (limitToQuadsOrTris && f.size() <= 4)
)
{
validCollapse = true;
scalar guardFraction = cvMeshControls().edgeCollapseGuardFraction();
cvMeshControls().maxCollapseFaceToPointSideLengthCoeff();
if
(
(dNeg.last() < guardFraction*dNeg.first())
&& (dPos.first() > guardFraction*dPos.last())
)
{
mode = fcmEdge;
}
else if
(
(d.last() - d.first())
< targetFaceSize
*cvMeshControls().maxCollapseFaceToPointSideLengthCoeff()
)
{
// If the face can't be collapsed to an edge, and it has a
// small enough span, collapse it to a point.
mode = fcmPoint;
}
// else (what to check? anything?)
// {
// // Alternatively, do not topologically collapse face, but push
// // all points onto a line, so that the face area is zero and
// // either:
// // + do not create it when dualising. This may damage the edge
// // addressing of the mesh;
// // + split the face into two (or more?) edges later,
// // sacrificing topological consistency with the Delaunay.
// // Note: The fcmDeferredMultiEdge collapse must be performed at
// // the polyMesh stage as this type of collapse can't be performed
// // and still maintain topological dual consistency with the
// // Delaunay structure
// mode = fcmDeferredMultiEdge;
// }
}
if (validCollapse)
if (mode == fcmEdge)
{
// Arbitrarily choosing the most distant point as the index to
// collapse to.
@ -1036,43 +989,60 @@ bool Foam::conformalVoronoiMesh::collapseFaceToEdge
pts[collapseToPtI] = collapseAxis*(sum(dPos)/dPos.size() - dShift) + fC;
}
else
else if (mode == fcmPoint)
{
// If the face can't be collapsed to a line, and it is small
// and low aspect ratio enough, collapse it to a point.
// Arbitrarily choosing the first point as the index to
// collapse to. Collapse to the face centre.
if
(
(d.last() - d.first()) < targetFaceSize*0.35
&& fA < aspectRatio*sqr(targetFaceSize*collapseSizeLimitCoeff)
&& f.size() <= 4
)
label collapseToPtI = facePts.first();
forAll(facePts, fPtI)
{
// Arbitrarily choosing the first point as the index to
// collapse to. Collapse to the face center.
label collapseToPtI = facePts.first();
forAll(facePts, fPtI)
{
dualPtIndexMap.insert(facePts[fPtI], collapseToPtI);
}
pts[collapseToPtI] = fC;
validCollapse = true;
dualPtIndexMap.insert(facePts[fPtI], collapseToPtI);
}
// Alternatively, do not topologically collapse face, but push
// all points onto a line, so that the face area is zero and
// either:
// + do not create it when dualising. This may damage the edge
// addressing of the mesh;
// + split the face into two (or more?) edges later, sacrificing
// topological consistency with the Delaunay.
pts[collapseToPtI] = fC;
}
return validCollapse;
// // Output face and collapse axis for visualisation
// Info<< "# Aspect ratio = " << aspectRatio << nl
// << "# determinant = " << detJ << nl
// << "# collapseAxis = " << collapseAxis << nl
// // << "# eigenvalues = " << eVals
// << endl;
// scalar scale = 2.0*mag(fC - pts[f[0]]);
// meshTools::writeOBJ(Info, fC);
// meshTools::writeOBJ(Info, fC + scale*collapseAxis);
// Info<< "f 1 2" << endl;
// forAll(f, fPtI)
// {
// meshTools::writeOBJ(Info, pts[f[fPtI]]);
// }
// Info<< "f";
// forAll(f, fPtI)
// {
// Info << " " << fPtI + 3;
// }
// Info<< nl << "# " << d << endl;
// Info<< "# " << d.first() << " " << d.last() << endl;
// forAll(d, dI)
// {
// meshTools::writeOBJ(Info, fC + (d[dI] - dShift)*collapseAxis);
// }
// Info<< endl;
return (mode != fcmNone);
}
@ -1149,12 +1119,12 @@ Foam::label Foam::conformalVoronoiMesh::checkPolyMeshQuality
wrongFaces
);
forAllConstIter(labelHashSet, wrongFaces, iter)
{
label faceI = iter.key();
// forAllConstIter(labelHashSet, wrongFaces, iter)
// {
// label faceI = iter.key();
Info<< faceI << " " << pMesh.faces()[faceI] << endl;
}
// Info<< faceI << " " << pMesh.faces()[faceI] << endl;
// }
return wrongFaces.size();

View File

@ -44,6 +44,7 @@ void Foam::conformalVoronoiMesh::conformToSurface()
}
}
Foam::conformalVoronoiMesh::reconformationMode
Foam::conformalVoronoiMesh::reconformationControl() const
{
@ -69,6 +70,7 @@ Foam::conformalVoronoiMesh::reconformationControl() const
return rmNone;
}
void Foam::conformalVoronoiMesh::buildSurfaceConformation
(
reconformationMode reconfMode

View File

@ -223,15 +223,6 @@ inline Foam::scalar Foam::conformalVoronoiMesh::maxSurfaceProtrusion
}
inline Foam::scalar Foam::conformalVoronoiMesh::minimumEdgeLength
(
const point& pt
) const
{
return targetCellSize(pt)*cvMeshControls().minimumEdgeLengthCoeff();
}
inline Foam::label Foam::conformalVoronoiMesh::insertPoint
(
const point& p,

View File

@ -147,11 +147,30 @@ Foam::cvControls::cvControls
const dictionary& filteringDict(cvMeshDict_.subDict("polyMeshFiltering"));
minimumEdgeLengthCoeff_ = readScalar
filterSizeCoeff_ = readScalar
(
filteringDict.lookup("minimumEdgeLengthCoeff")
filteringDict.lookup("filterSizeCoeff")
);
mergeClosenessCoeff_ = readScalar
(
filteringDict.lookup("mergeClosenessCoeff")
);
surfaceStepFaceAngle_ = readScalar
(
filteringDict.lookup("surfaceStepFaceAngle")
);
edgeCollapseGuardFraction_ = readScalar
(
filteringDict.lookup("edgeCollapseGuardFraction")
);
maxCollapseFaceToPointSideLengthCoeff_ = readScalar
(
filteringDict.lookup("maxCollapseFaceToPointSideLengthCoeff")
);
}

View File

@ -147,9 +147,35 @@ class cvControls
// polyMesh filtering controls
//- Minimum edge length allowed in the polyMesh, anything shorter will
// be filtered - fraction of the local target cell size
scalar minimumEdgeLengthCoeff_;
//- Upper limit on how close two dual vertices can be before
// being merged, fraction of the local target cell size
scalar mergeClosenessCoeff_;
//- The maximum allowed angle between a boundary face normal
// and the local surface normal before face will be
// aggressively collapsed
scalar surfaceStepFaceAngle_;
//- Defining how close to the midpoint (M) of the projected
// vertices line a projected vertex (X) can be before making
// an edge collapse invalid
//
// X---X-g----------------M----X-----------g----X--X
//
// Only allow a collapse if all projected vertices are
// outwith edgeCollapseGuardFraction (g) of the distance form
// the face centre to the furthest vertex in the considered
// direction
scalar edgeCollapseGuardFraction_;
//- The maximum allowed length of the longest edge of a face
// to enable a face to be collapsed to a point, fraction of
// the local target cell size
scalar maxCollapseFaceToPointSideLengthCoeff_;
//- Upper limit on the size of faces to be filtered from,
// fraction of the local target cell size
scalar filterSizeCoeff_;
// Private Member Functions
@ -238,8 +264,20 @@ public:
//- Return removalDistCoeff
inline scalar removalDistCoeff() const;
//- Return the minimumEdgeLengthCoeff
inline scalar minimumEdgeLengthCoeff() const;
//- Return the filterSizeCoeff
inline scalar filterSizeCoeff() const;
//- Return the mergeClosenessCoeff
inline scalar mergeClosenessCoeff() const;
//- Return the surfaceStepFaceAngle
inline scalar surfaceStepFaceAngle() const;
//- Return the edgeCollapseGuardFraction
inline scalar edgeCollapseGuardFraction() const;
//- Return the maxCollapseFaceToPointSideLengthCoeff
inline scalar maxCollapseFaceToPointSideLengthCoeff() const;
};

View File

@ -115,30 +115,59 @@ inline Foam::scalar Foam::cvControls::cosAlignmentAcceptanceAngle() const
return cosAlignmentAcceptanceAngle_;
}
inline Foam::scalar Foam::cvControls::insertionDistCoeff() const
{
return insertionDistCoeff_;
}
inline Foam::scalar Foam::cvControls::faceAreaRatioCoeff() const
{
return faceAreaRatioCoeff_;
}
inline Foam::scalar Foam::cvControls::cosInsertionAcceptanceAngle() const
{
return cosInsertionAcceptanceAngle_;
}
inline Foam::scalar Foam::cvControls::removalDistCoeff() const
{
return removalDistCoeff_;
}
inline Foam::scalar Foam::cvControls::minimumEdgeLengthCoeff() const
inline Foam::scalar Foam::cvControls::filterSizeCoeff() const
{
return minimumEdgeLengthCoeff_;
return filterSizeCoeff_;
}
inline Foam::scalar Foam::cvControls::mergeClosenessCoeff() const
{
return mergeClosenessCoeff_;
}
inline Foam::scalar Foam::cvControls::surfaceStepFaceAngle() const
{
return surfaceStepFaceAngle_;
}
inline Foam::scalar Foam::cvControls::edgeCollapseGuardFraction() const
{
return edgeCollapseGuardFraction_;
}
inline Foam::scalar
Foam::cvControls::maxCollapseFaceToPointSideLengthCoeff() const
{
return maxCollapseFaceToPointSideLengthCoeff_;
}
// ************************************************************************* //