diff --git a/applications/utilities/mesh/manipulation/polyDualMesh/meshDualiser.C b/applications/utilities/mesh/manipulation/polyDualMesh/meshDualiser.C index c512857b76..5fcf5d2f89 100644 --- a/applications/utilities/mesh/manipulation/polyDualMesh/meshDualiser.C +++ b/applications/utilities/mesh/manipulation/polyDualMesh/meshDualiser.C @@ -55,7 +55,7 @@ void Foam::meshDualiser::checkPolyTopoChange(const polyTopoChange& meshMod) } labelList oldToNew; - label nUnique = mergePoints + label nUnique = Foam::mergePoints ( points, 1e-6, @@ -223,7 +223,7 @@ Foam::label Foam::meshDualiser::addInternalFace pointField facePoints(meshMod.points(), newFace); labelList oldToNew; - label nUnique = mergePoints + label nUnique = Foam::mergePoints ( facePoints, 1e-6, diff --git a/src/OpenFOAM/meshes/meshTools/mergePoints.C b/src/OpenFOAM/meshes/meshTools/mergePoints.C index b5d6049755..56746484a8 100644 --- a/src/OpenFOAM/meshes/meshTools/mergePoints.C +++ b/src/OpenFOAM/meshes/meshTools/mergePoints.C @@ -6,7 +6,7 @@ \\/ M anipulation | ------------------------------------------------------------------------------- Copyright (C) 2011-2016 OpenFOAM Foundation - Copyright (C) 2017-2019 OpenCFD Ltd. + Copyright (C) 2017-2022 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -26,49 +26,47 @@ License \*---------------------------------------------------------------------------*/ -#include "ListOps.H" -#include "point.H" -#include "Field.H" +#include "ListOps.H" // sortedOrder, ListOps::identity -// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // +// * * * * * * * * * * * * * * * Implementation * * * * * * * * * * * * * * // -template -Foam::label Foam::mergePoints +template +Foam::label Foam::Detail::mergePoints ( const PointList& points, + const IndexerOp& indexer, + const label nSubPoints, + labelList& pointToUnique, + labelList& uniquePoints, const scalar mergeTol, - const bool verbose, - labelList& pointMap, - typename PointList::const_reference origin + const bool verbose ) { - typedef typename PointList::value_type point_type; + const label nTotPoints = points.size(); - const label nPoints = points.size(); - - // Create an old to new point mapping array - pointMap.resize_nocopy(nPoints); - pointMap = -1; - - if (!nPoints) + if (!nTotPoints || !nSubPoints) { - return 0; + // Nothing to do + pointToUnique = identity(nTotPoints); + uniquePoints = pointToUnique; + return 0; // No points removed } - point_type compareOrigin = origin; - if (origin == point_type::max) + // Properly size for old to new mapping array + pointToUnique.resize_nocopy(nTotPoints); + + + // Use the boundBox minimum as the reference point. This + // stretches distances with fewer collisions than a mid-point + // reference would. + + auto comparePoint(points[indexer(0)]); + for (label pointi = 1; pointi < nSubPoints; ++pointi) { - // Use average of input points to define a comparison origin. - // Same as sum(points)/nPoints, but handles different list types - compareOrigin = points[0]; - for (label pointi=1; pointi < nPoints; ++pointi) - { - compareOrigin += points[pointi]; - } - compareOrigin /= nPoints; + comparePoint = min(comparePoint, points[indexer(pointi)]); } - // We're comparing distance squared to origin first. + // We're comparing distance squared to reference point first. // Say if starting from two close points: // x, y, z // x+mergeTol, y+mergeTol, z+mergeTol @@ -77,156 +75,445 @@ Foam::label Foam::mergePoints // x^2+y^2+z^2 + 2*mergeTol*(x+z+y) + mergeTol^2*... // so the difference will be 2*mergeTol*(x+y+z) - const scalar mergeTolSqr = Foam::sqr(mergeTol); + const scalar mergeTolSqr(magSqr(mergeTol)); - // Sort points by magSqr - List magSqrDist(nPoints); - forAll(points, pointi) + // Use magSqr distance for the points sort order + List sqrDist(nSubPoints); + for (label pointi = 0; pointi < nSubPoints; ++pointi) { - magSqrDist[pointi] = magSqr(points[pointi] - compareOrigin); + const auto& p = points[indexer(pointi)]; + + sqrDist[pointi] = + ( + // Use scalar precision + magSqr(scalar(p.x() - comparePoint.x())) + + magSqr(scalar(p.y() - comparePoint.y())) + + magSqr(scalar(p.z() - comparePoint.z())) + ); } - labelList order(Foam::sortedOrder(magSqrDist)); + labelList order(Foam::sortedOrder(sqrDist)); - - Field sortedTol(nPoints); + List sortedTol(nSubPoints); forAll(order, sorti) { - const point_type& pt = points[order[sorti]]; + const auto& p = points[indexer(order[sorti])]; - // Use scalar precision sortedTol[sorti] = + ( 2*mergeTol* ( - mag(scalar(pt.x() - compareOrigin.x())) - + mag(scalar(pt.y() - compareOrigin.y())) - + mag(scalar(pt.z() - compareOrigin.z())) - ); + // Use scalar precision + mag(scalar(p.x() - comparePoint.x())) + + mag(scalar(p.y() - comparePoint.y())) + + mag(scalar(p.z() - comparePoint.z())) + ) + ); } - label newPointi = 0; - // Handle 0th point separately (is always unique) - label pointi = order[0]; - pointMap[pointi] = newPointi++; + // Bookkeeping parameters + // ~~~~~~~~~~~~~~~~~~~~~~ - /// if (verbose) - /// { - /// Pout<< "Foam::mergePoints : [0] Uniq point " << pointi << endl; - /// } + // Will only be working on a subset of the points + // Can use a slice of pointToUnique (full length not needed until later). + SubList