diff --git a/src/mesh/conformalVoronoiMesh/conformalVoronoiMesh/conformalVoronoiMesh.C b/src/mesh/conformalVoronoiMesh/conformalVoronoiMesh/conformalVoronoiMesh.C index 9d2a73349c658b257b63aaf9224781ddbaecbb28..3c85a22075e8201b93f048a7cfebdc152475951c 100644 --- a/src/mesh/conformalVoronoiMesh/conformalVoronoiMesh/conformalVoronoiMesh.C +++ b/src/mesh/conformalVoronoiMesh/conformalVoronoiMesh/conformalVoronoiMesh.C @@ -2063,21 +2063,23 @@ void Foam::conformalVoronoiMesh::calcDualMesh // Assess close points to be merged - Info<< nl << " Merging close points" << endl; + { + Info<< nl << " Merging close points" << endl; - label nPtsMerged = 0; + label nPtsMerged = 0; - do - { - Map<label> dualPtIndexMap; + do + { + Map<label> dualPtIndexMap; - nPtsMerged = mergeCloseDualVertices(points, dualPtIndexMap); + nPtsMerged = mergeCloseDualVertices(points, dualPtIndexMap); - Info<< " Merged " << nPtsMerged << " points" << endl; + Info<< " Merged " << nPtsMerged << " points" << endl; - reindexDualVertices(dualPtIndexMap); + reindexDualVertices(dualPtIndexMap); - } while (nPtsMerged > 0); + } while (nPtsMerged > 0); + } // Smooth the surface of the mesh @@ -2091,13 +2093,32 @@ void Foam::conformalVoronoiMesh::calcDualMesh nSmoothedVertices = smoothSurfaceDualFaces(points, dualPtIndexMap); - Info<< " Smoothed " << nPtsMerged << " points (0 HARD CODED)" + Info<< " Smoothed " << nSmoothedVertices + << " points (0 HARD CODED)" << endl; reindexDualVertices(dualPtIndexMap); } while (nSmoothedVertices > 0); + { + Info<< nl << " Merging close points" << endl; + + label nPtsMerged = 0; + + do + { + Map<label> dualPtIndexMap; + + nPtsMerged = mergeCloseDualVertices(points, dualPtIndexMap); + + Info<< " Merged " << nPtsMerged << " points" << endl; + + reindexDualVertices(dualPtIndexMap); + + } while (nPtsMerged > 0); + } + // Assess faces for collapse Info<< nl << " Collapsing unnecessary faces" << endl; @@ -2387,7 +2408,7 @@ Foam::label Foam::conformalVoronoiMesh::mergeCloseDualVertices ( const pointField& pts, Map<label>& dualPtIndexMap -) +) const { label nPtsMerged = 0; @@ -2438,10 +2459,12 @@ Foam::label Foam::conformalVoronoiMesh::smoothSurfaceDualFaces ( pointField& pts, Map<label>& dualPtIndexMap -) +) const { label nSmoothedVertices = 0; + const scalar cosPerpendicularToleranceAngle = cos(degToRad(80)); + for ( Triangulation::Finite_edges_iterator eit = finite_edges_begin(); @@ -2477,29 +2500,59 @@ Foam::label Foam::conformalVoronoiMesh::smoothSurfaceDualFaces continue; } - forAll(dualFace, fPtI) + pointIndexHit surfHit; + label hitSurface; + + geometryToConformTo_.findSurfaceNearest + ( + dualFace.centre(pts), + cvMeshControls().spanSqr(), + surfHit, + hitSurface + ); + + vectorField norm(1); + + allGeometry_[hitSurface].getNormal + ( + List<pointIndexHit>(1, surfHit), + norm + ); + + const vector& surfaceNormal = norm[0]; + + vector faceNormal = dualFace.normal(pts); + + faceNormal /= mag(faceNormal); + + if ((faceNormal & surfaceNormal) < cosPerpendicularToleranceAngle) { - label ptI = dualFace[fPtI]; + collapseFaceToEdge(dualFace, pts, dualPtIndexMap); - point& pt = pts[ptI]; + // forAll(dualFace, fPtI) + // { + // label ptI = dualFace[fPtI]; - pointIndexHit surfHit; - label hitSurface; + // point& pt = pts[ptI]; - geometryToConformTo_.findSurfaceNearest - ( - pt, - cvMeshControls().spanSqr(), - surfHit, - hitSurface - ); + // pointIndexHit surfHit; + // label hitSurface; - if (surfHit.hit()) - { - pt = surfHit.hitPoint(); + // geometryToConformTo_.findSurfaceNearest + // ( + // pt, + // cvMeshControls().spanSqr(), + // surfHit, + // hitSurface + // ); - // dualPtIndexMap.insert(ptI, ptI); - } + // if (surfHit.hit()) + // { + // pt = surfHit.hitPoint(); + + // // dualPtIndexMap.insert(ptI, ptI); + // } + // } } } } @@ -2512,7 +2565,7 @@ Foam::label Foam::conformalVoronoiMesh::collapseFaces ( pointField& pts, Map<label>& dualPtIndexMap -) +) const { label nCollapsedFaces = 0; @@ -2750,6 +2803,115 @@ Foam::label Foam::conformalVoronoiMesh::collapseFaces } +void Foam::conformalVoronoiMesh::collapseFaceToEdge +( + const face& f, + pointField& pts, + Map<label>& dualPtIndexMap +) const +{ + const vector fC = f.centre(pts); + + const edgeList& faceEds = f.edges(); + + const scalar fArea = f.mag(pts); + + scalar averageQuality = 0.0; + + vector faceCollapseDirection = vector::zero; + + forAll(faceEds, edI) + { + const edge e = faceEds[edI]; + + triPointRef tri(pts[e.start()], pts[e.end()], fC); + + scalar triArea = tri.mag(); + + if (triArea < SMALL) + { + // Sliver triangle, do not consider + + continue; + } + + // 0.7697997 converts from a quality being 1 for an area ratio + // of an equilateral triangle (4*pi/(3*sqrt(3))) to the + // quality being 1 for an area ratio of a quarter of a square + // (pi), i.e. (4*pi/(3*sqrt(3)))/pi = 0.7697997 + + scalar triQuality = tri.quality()*0.7697997; + + // Weight the quality by the tri area + averageQuality += triQuality*triArea; + + // find the longest edge vector, and one of the other edges + // that isn't the longest + vector longestEdge = tri.b() - tri.a(); + vector otherEdge = tri.c() - tri.a(); + scalar longestEdgeMagSqr = magSqr(longestEdge); + + if (magSqr(tri.c() - tri.b()) > longestEdgeMagSqr) + { + longestEdge = tri.c() - tri.b(); + otherEdge = tri.a() - tri.b(); + longestEdgeMagSqr = magSqr(longestEdgeMagSqr); + } + + if (magSqr(tri.a() - tri.c()) > longestEdgeMagSqr) + { + longestEdge = tri.a() - tri.c(); + otherEdge = tri.b() - tri.c(); + longestEdgeMagSqr = magSqr(longestEdgeMagSqr); + } + + vector triCollapseDirection = + (otherEdge & longestEdge)*longestEdge/longestEdgeMagSqr + - otherEdge; + + triCollapseDirection /= mag(triCollapseDirection); + + // Add the triCollapseDirection so that it is constructive + + if + ( + magSqr(faceCollapseDirection + triCollapseDirection) + > magSqr(faceCollapseDirection) + ) + { + faceCollapseDirection += triCollapseDirection; + // faceCollapseDirection += triCollapseDirection/triQuality; + } + else + { + faceCollapseDirection -= triCollapseDirection; + // faceCollapseDirection -= triCollapseDirection/triQuality; + } + } + + faceCollapseDirection /= mag(faceCollapseDirection); + + averageQuality /= fArea; + + vector collapseAxis = (faceCollapseDirection ^ (f.normal(pts)/fArea)); + + Info<< nl << "# averageQuality " << averageQuality << endl; + + forAll(f, fPtI) + { + meshTools::writeOBJ(Info, pts[f[fPtI]]); + } + + collapseAxis *= 3.0*mag(pts[f[0]] - fC); + faceCollapseDirection *= 3.0*mag(pts[f[0]] - fC); + + meshTools::writeOBJ(Info, fC + faceCollapseDirection); + meshTools::writeOBJ(Info, fC - faceCollapseDirection); + meshTools::writeOBJ(Info, fC + collapseAxis); + meshTools::writeOBJ(Info, fC - collapseAxis); +} + + void Foam::conformalVoronoiMesh::reindexDualVertices ( const Map<label>& dualPtIndexMap diff --git a/src/mesh/conformalVoronoiMesh/conformalVoronoiMesh/conformalVoronoiMesh.H b/src/mesh/conformalVoronoiMesh/conformalVoronoiMesh/conformalVoronoiMesh.H index 2a3b0369b5a92757af505c5aecd4bacaa6aec631..783089034efbee81e95c7cad641921357445367a 100644 --- a/src/mesh/conformalVoronoiMesh/conformalVoronoiMesh/conformalVoronoiMesh.H +++ b/src/mesh/conformalVoronoiMesh/conformalVoronoiMesh/conformalVoronoiMesh.H @@ -468,7 +468,7 @@ private: ( const pointField& pts, Map<label>& dualPtIndexMap - ); + ) const; //- Smooth the dual vertices of the dual faces on the boundary // so that they conform to the surface and remove any @@ -477,7 +477,7 @@ private: ( pointField& pts, Map<label>& dualPtIndexMap - ); + ) const; //- Collapse a face to a point or an edge, modifying and // mapping the points, returns the true if the face was @@ -486,7 +486,15 @@ private: ( pointField& pts, Map<label>& dualPtIndexMap - ); + ) const; + + //- Collapse a face to an edge, updating the point and point map + void collapseFaceToEdge + ( + const face& f, + pointField& pts, + Map<label>& dualPtIndexMap + ) const; //- Re-index all of the the Delaunay cells void reindexDualVertices(const Map<label>& dualPtIndexMap);