mirror of
https://github.com/OpenFOAM/OpenFOAM-6.git
synced 2025-12-08 06:57:46 +00:00
surfaceFeatureExtract: Refactor core functionality into core classes and libraries
This commit is contained in:
@ -231,18 +231,18 @@ int main(int argc, char *argv[])
|
||||
{
|
||||
treeBoundBox bb(subsetDict.lookup("insideBox")());
|
||||
|
||||
Info<< "Removing all edges outside bb " << bb << endl;
|
||||
dumpBox(bb, "subsetBox.obj");
|
||||
|
||||
Info<< "Removing all edges outside bb " << bb
|
||||
<< " see subsetBox.obj" << endl;
|
||||
bb.writeOBJ("subsetBox.obj");
|
||||
deleteBox(surf, bb, false, edgeStat);
|
||||
}
|
||||
else if (subsetDict.found("outsideBox"))
|
||||
{
|
||||
treeBoundBox bb(subsetDict.lookup("outsideBox")());
|
||||
|
||||
Info<< "Removing all edges inside bb " << bb << endl;
|
||||
dumpBox(bb, "deleteBox.obj");
|
||||
|
||||
Info<< "Removing all edges inside bb " << bb
|
||||
<< " see deleteBox.obj" << endl;
|
||||
bb.writeOBJ("deleteBox.obj");
|
||||
deleteBox(surf, bb, true, edgeStat);
|
||||
}
|
||||
|
||||
@ -432,16 +432,18 @@ int main(int argc, char *argv[])
|
||||
Info<< nl << "Extracting curvature of surface at the points."
|
||||
<< endl;
|
||||
|
||||
const vectorField pointNormals(surf.pointNormals2());
|
||||
triadField pointCoordSys = calcVertexCoordSys(surf, pointNormals);
|
||||
|
||||
triSurfacePointScalarField k = calcCurvature
|
||||
triSurfacePointScalarField k
|
||||
(
|
||||
sFeatFileName,
|
||||
runTime,
|
||||
IOobject
|
||||
(
|
||||
sFeatFileName + ".curvature",
|
||||
runTime.constant(),
|
||||
"triSurface",
|
||||
runTime
|
||||
),
|
||||
surf,
|
||||
pointNormals,
|
||||
pointCoordSys
|
||||
dimLength,
|
||||
surf.curvature()
|
||||
);
|
||||
|
||||
k.write();
|
||||
|
||||
@ -45,21 +45,6 @@ namespace Foam
|
||||
|
||||
point randomPointInPlane(const plane& p);
|
||||
|
||||
triadField calcVertexCoordSys
|
||||
(
|
||||
const triSurface& surf,
|
||||
const vectorField& pointNormals
|
||||
);
|
||||
|
||||
triSurfacePointScalarField calcCurvature
|
||||
(
|
||||
const word& name,
|
||||
const Time& runTime,
|
||||
const triSurface& surf,
|
||||
const vectorField& pointNormals,
|
||||
const triadField& pointCoordSys
|
||||
);
|
||||
|
||||
bool edgesConnected(const edge& e1, const edge& e2);
|
||||
|
||||
scalar calcProximityOfFeaturePoints
|
||||
@ -75,8 +60,6 @@ namespace Foam
|
||||
const scalar defaultCellSize
|
||||
);
|
||||
|
||||
void dumpBox(const treeBoundBox& bb, const fileName& fName);
|
||||
|
||||
//- Deletes all edges inside/outside bounding box from set.
|
||||
void deleteBox
|
||||
(
|
||||
|
||||
@ -28,11 +28,6 @@ Description
|
||||
Extracts and writes surface features to file. All but the basic feature
|
||||
extraction is WIP.
|
||||
|
||||
Curvature calculation is an implementation of the algorithm from:
|
||||
|
||||
"Estimating Curvatures and their Derivatives on Triangle Meshes"
|
||||
by S. Rusinkiewicz
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "surfaceFeatureExtract.H"
|
||||
@ -56,294 +51,6 @@ const Foam::scalar Foam::externalToleranceCosAngle
|
||||
);
|
||||
|
||||
|
||||
Foam::point Foam::randomPointInPlane(const plane& p)
|
||||
{
|
||||
// Perturb base point
|
||||
const point& refPt = p.refPoint();
|
||||
|
||||
// ax + by + cz + d = 0
|
||||
const FixedList<scalar, 4>& planeCoeffs = p.planeCoeffs();
|
||||
|
||||
const scalar perturbX = refPt.x() + 1e-3;
|
||||
const scalar perturbY = refPt.y() + 1e-3;
|
||||
const scalar perturbZ = refPt.z() + 1e-3;
|
||||
|
||||
if (mag(planeCoeffs[2]) < small)
|
||||
{
|
||||
if (mag(planeCoeffs[1]) < small)
|
||||
{
|
||||
const scalar x =
|
||||
-1.0
|
||||
*(
|
||||
planeCoeffs[3]
|
||||
+ planeCoeffs[1]*perturbY
|
||||
+ planeCoeffs[2]*perturbZ
|
||||
)/planeCoeffs[0];
|
||||
|
||||
return point
|
||||
(
|
||||
x,
|
||||
perturbY,
|
||||
perturbZ
|
||||
);
|
||||
}
|
||||
|
||||
const scalar y =
|
||||
-1.0
|
||||
*(
|
||||
planeCoeffs[3]
|
||||
+ planeCoeffs[0]*perturbX
|
||||
+ planeCoeffs[2]*perturbZ
|
||||
)/planeCoeffs[1];
|
||||
|
||||
return point
|
||||
(
|
||||
perturbX,
|
||||
y,
|
||||
perturbZ
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
const scalar z =
|
||||
-1.0
|
||||
*(
|
||||
planeCoeffs[3]
|
||||
+ planeCoeffs[0]*perturbX
|
||||
+ planeCoeffs[1]*perturbY
|
||||
)/planeCoeffs[2];
|
||||
|
||||
return point
|
||||
(
|
||||
perturbX,
|
||||
perturbY,
|
||||
z
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Foam::triadField Foam::calcVertexCoordSys
|
||||
(
|
||||
const triSurface& surf,
|
||||
const vectorField& pointNormals
|
||||
)
|
||||
{
|
||||
const pointField& points = surf.points();
|
||||
const Map<label>& meshPointMap = surf.meshPointMap();
|
||||
|
||||
triadField pointCoordSys(points.size());
|
||||
|
||||
forAll(points, pI)
|
||||
{
|
||||
const point& pt = points[pI];
|
||||
const vector& normal = pointNormals[meshPointMap[pI]];
|
||||
|
||||
if (mag(normal) < small)
|
||||
{
|
||||
pointCoordSys[meshPointMap[pI]] = triad::unset;
|
||||
continue;
|
||||
}
|
||||
|
||||
plane p(pt, normal);
|
||||
|
||||
// Pick random point in plane
|
||||
vector dir1 = pt - randomPointInPlane(p);
|
||||
dir1 /= mag(dir1);
|
||||
|
||||
vector dir2 = dir1 ^ normal;
|
||||
dir2 /= mag(dir2);
|
||||
|
||||
pointCoordSys[meshPointMap[pI]] = triad(dir1, dir2, normal);
|
||||
}
|
||||
|
||||
return pointCoordSys;
|
||||
}
|
||||
|
||||
|
||||
Foam::triSurfacePointScalarField Foam::calcCurvature
|
||||
(
|
||||
const word& name,
|
||||
const Time& runTime,
|
||||
const triSurface& surf,
|
||||
const vectorField& pointNormals,
|
||||
const triadField& pointCoordSys
|
||||
)
|
||||
{
|
||||
Info<< "Calculating face curvature" << endl;
|
||||
|
||||
const pointField& points = surf.points();
|
||||
const labelList& meshPoints = surf.meshPoints();
|
||||
const Map<label>& meshPointMap = surf.meshPointMap();
|
||||
|
||||
triSurfacePointScalarField curvaturePointField
|
||||
(
|
||||
IOobject
|
||||
(
|
||||
name + ".curvature",
|
||||
runTime.constant(),
|
||||
"triSurface",
|
||||
runTime,
|
||||
IOobject::NO_READ,
|
||||
IOobject::NO_WRITE
|
||||
),
|
||||
surf,
|
||||
dimLength,
|
||||
scalarField(points.size(), 0.0)
|
||||
);
|
||||
|
||||
List<symmTensor2D> pointFundamentalTensors
|
||||
(
|
||||
points.size(),
|
||||
symmTensor2D::zero
|
||||
);
|
||||
|
||||
scalarList accumulatedWeights(points.size(), 0.0);
|
||||
|
||||
forAll(surf, fi)
|
||||
{
|
||||
const triFace& f = surf[fi];
|
||||
const edgeList fEdges = f.edges();
|
||||
|
||||
// Calculate the edge vectors and the normal differences
|
||||
vectorField edgeVectors(f.size(), Zero);
|
||||
vectorField normalDifferences(f.size(), Zero);
|
||||
|
||||
forAll(fEdges, feI)
|
||||
{
|
||||
const edge& e = fEdges[feI];
|
||||
|
||||
edgeVectors[feI] = e.vec(points);
|
||||
normalDifferences[feI] =
|
||||
pointNormals[meshPointMap[e[0]]]
|
||||
- pointNormals[meshPointMap[e[1]]];
|
||||
}
|
||||
|
||||
// Set up a local coordinate system for the face
|
||||
const vector& e0 = edgeVectors[0];
|
||||
const vector eN = f.area(points);
|
||||
const vector e1 = (e0 ^ eN);
|
||||
|
||||
if (magSqr(eN) < rootVSmall)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
triad faceCoordSys(e0, e1, eN);
|
||||
faceCoordSys.normalize();
|
||||
|
||||
// Construct the matrix to solve
|
||||
scalarSymmetricSquareMatrix T(3, 0);
|
||||
scalarDiagonalMatrix Z(3, 0);
|
||||
|
||||
// Least Squares
|
||||
for (label i = 0; i < 3; ++i)
|
||||
{
|
||||
scalar x = edgeVectors[i] & faceCoordSys[0];
|
||||
scalar y = edgeVectors[i] & faceCoordSys[1];
|
||||
|
||||
T(0, 0) += sqr(x);
|
||||
T(1, 0) += x*y;
|
||||
T(1, 1) += sqr(x) + sqr(y);
|
||||
T(2, 1) += x*y;
|
||||
T(2, 2) += sqr(y);
|
||||
|
||||
scalar dndx = normalDifferences[i] & faceCoordSys[0];
|
||||
scalar dndy = normalDifferences[i] & faceCoordSys[1];
|
||||
|
||||
Z[0] += dndx*x;
|
||||
Z[1] += dndx*y + dndy*x;
|
||||
Z[2] += dndy*y;
|
||||
}
|
||||
|
||||
// Perform Cholesky decomposition and back substitution.
|
||||
// Decomposed matrix is in T and solution is in Z.
|
||||
LUsolve(T, Z);
|
||||
symmTensor2D secondFundamentalTensor(Z[0], Z[1], Z[2]);
|
||||
|
||||
// Loop over the face points adding the contribution of the face
|
||||
// curvature to the points.
|
||||
forAll(f, fpI)
|
||||
{
|
||||
const label patchPointIndex = meshPointMap[f[fpI]];
|
||||
|
||||
const triad& ptCoordSys = pointCoordSys[patchPointIndex];
|
||||
|
||||
if (!ptCoordSys.set())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Rotate faceCoordSys to ptCoordSys
|
||||
tensor rotTensor = rotationTensor(ptCoordSys[2], faceCoordSys[2]);
|
||||
triad rotatedFaceCoordSys = rotTensor & tensor(faceCoordSys);
|
||||
|
||||
// Project the face curvature onto the point plane
|
||||
|
||||
vector2D cmp1
|
||||
(
|
||||
ptCoordSys[0] & rotatedFaceCoordSys[0],
|
||||
ptCoordSys[0] & rotatedFaceCoordSys[1]
|
||||
);
|
||||
vector2D cmp2
|
||||
(
|
||||
ptCoordSys[1] & rotatedFaceCoordSys[0],
|
||||
ptCoordSys[1] & rotatedFaceCoordSys[1]
|
||||
);
|
||||
|
||||
tensor2D projTensor
|
||||
(
|
||||
cmp1,
|
||||
cmp2
|
||||
);
|
||||
|
||||
symmTensor2D projectedFundamentalTensor
|
||||
(
|
||||
projTensor.x() & (secondFundamentalTensor & projTensor.x()),
|
||||
projTensor.x() & (secondFundamentalTensor & projTensor.y()),
|
||||
projTensor.y() & (secondFundamentalTensor & projTensor.y())
|
||||
);
|
||||
|
||||
// Calculate weight
|
||||
// TODO: Voronoi area weighting
|
||||
const scalar weight = surf.pointNormalWeight
|
||||
(
|
||||
f,
|
||||
meshPoints[patchPointIndex],
|
||||
f.area(points),
|
||||
points
|
||||
);
|
||||
|
||||
// Sum contribution of face to this point
|
||||
pointFundamentalTensors[patchPointIndex] +=
|
||||
weight*projectedFundamentalTensor;
|
||||
|
||||
accumulatedWeights[patchPointIndex] += weight;
|
||||
}
|
||||
}
|
||||
|
||||
forAll(curvaturePointField, pI)
|
||||
{
|
||||
pointFundamentalTensors[pI] /= (accumulatedWeights[pI] + small);
|
||||
|
||||
vector2D principalCurvatures = eigenValues(pointFundamentalTensors[pI]);
|
||||
|
||||
//scalar curvature =
|
||||
// (principalCurvatures[0] + principalCurvatures[1])/2;
|
||||
scalar curvature = max
|
||||
(
|
||||
mag(principalCurvatures[0]),
|
||||
mag(principalCurvatures[1])
|
||||
);
|
||||
//scalar curvature = principalCurvatures[0]*principalCurvatures[1];
|
||||
|
||||
curvaturePointField[meshPoints[pI]] = curvature;
|
||||
}
|
||||
|
||||
return curvaturePointField;
|
||||
}
|
||||
|
||||
|
||||
bool Foam::edgesConnected(const edge& e1, const edge& e2)
|
||||
{
|
||||
if
|
||||
@ -455,30 +162,6 @@ Foam::scalar Foam::calcProximityOfFeatureEdges
|
||||
}
|
||||
|
||||
|
||||
void Foam::dumpBox(const treeBoundBox& bb, const fileName& fName)
|
||||
{
|
||||
OFstream str(fName);
|
||||
|
||||
Info<< "Dumping bounding box " << bb << " as lines to obj file "
|
||||
<< str.name() << endl;
|
||||
|
||||
|
||||
pointField boxPoints(bb.points());
|
||||
|
||||
forAll(boxPoints, i)
|
||||
{
|
||||
meshTools::writeOBJ(str, boxPoints[i]);
|
||||
}
|
||||
|
||||
forAll(treeBoundBox::edges, i)
|
||||
{
|
||||
const edge& e = treeBoundBox::edges[i];
|
||||
|
||||
str<< "l " << e[0]+1 << ' ' << e[1]+1 << nl;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Foam::deleteBox
|
||||
(
|
||||
const triSurface& surf,
|
||||
@ -809,24 +492,6 @@ Foam::surfaceFeatures::edgeStatus Foam::checkFlatRegionEdge
|
||||
}
|
||||
|
||||
|
||||
void Foam::extractCloseness
|
||||
(
|
||||
const fileName &sFeatFileName,
|
||||
const Time& runTime,
|
||||
const triSurface &surf,
|
||||
const bool writeVTK
|
||||
);
|
||||
|
||||
|
||||
void Foam::extractPointCloseness
|
||||
(
|
||||
const fileName &sFeatFileName,
|
||||
const Time& runTime,
|
||||
const triSurface &surf,
|
||||
const bool writeVTK
|
||||
);
|
||||
|
||||
|
||||
void Foam::writeStats(const extendedFeatureEdgeMesh& fem, Ostream& os)
|
||||
{
|
||||
os << " points : " << fem.points().size() << nl
|
||||
|
||||
Reference in New Issue
Block a user