mergePoints.C
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration |
5  \\ / A nd | www.openfoam.com
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8  Copyright (C) 2011-2016 OpenFOAM Foundation
9  Copyright (C) 2017-2019 OpenCFD Ltd.
10 -------------------------------------------------------------------------------
11 License
12  This file is part of OpenFOAM.
13 
14  OpenFOAM is free software: you can redistribute it and/or modify it
15  under the terms of the GNU General Public License as published by
16  the Free Software Foundation, either version 3 of the License, or
17  (at your option) any later version.
18 
19  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
20  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
21  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22  for more details.
23 
24  You should have received a copy of the GNU General Public License
25  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
26 
27 \*---------------------------------------------------------------------------*/
28 
29 #include "ListOps.H"
30 #include "point.H"
31 #include "Field.H"
32 
33 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
34 
35 template<class PointList>
36 Foam::label Foam::mergePoints
37 (
38  const PointList& points,
39  const scalar mergeTol,
40  const bool verbose,
41  labelList& pointMap,
42  typename PointList::const_reference origin
43 )
44 {
45  typedef typename PointList::value_type point_type;
46 
47  const label nPoints = points.size();
48 
49  // Create an old to new point mapping array
50  pointMap.resize_nocopy(nPoints);
51  pointMap = -1;
52 
53  if (!nPoints)
54  {
55  return 0;
56  }
57 
58  point_type compareOrigin = origin;
59  if (origin == point_type::max)
60  {
61  // Use average of input points to define a comparison origin.
62  // Same as sum(points)/nPoints, but handles different list types
63  compareOrigin = points[0];
64  for (label pointi=1; pointi < nPoints; ++pointi)
65  {
66  compareOrigin += points[pointi];
67  }
68  compareOrigin /= nPoints;
69  }
70 
71  // We're comparing distance squared to origin first.
72  // Say if starting from two close points:
73  // x, y, z
74  // x+mergeTol, y+mergeTol, z+mergeTol
75  // Then the magSqr of both will be
76  // x^2+y^2+z^2
77  // x^2+y^2+z^2 + 2*mergeTol*(x+z+y) + mergeTol^2*...
78  // so the difference will be 2*mergeTol*(x+y+z)
79 
80  const scalar mergeTolSqr = Foam::sqr(mergeTol);
81 
82  // Sort points by magSqr
83  List<scalar> magSqrDist(nPoints);
84  forAll(points, pointi)
85  {
86  magSqrDist[pointi] = magSqr(points[pointi] - compareOrigin);
87  }
88  labelList order(Foam::sortedOrder(magSqrDist));
89 
90 
91  Field<scalar> sortedTol(nPoints);
92  forAll(order, sortI)
93  {
94  const point_type& pt = points[order[sortI]];
95 
96  // Use scalar precision
97  sortedTol[sortI] =
98  2*mergeTol*
99  (
100  mag(scalar(pt.x() - compareOrigin.x()))
101  + mag(scalar(pt.y() - compareOrigin.y()))
102  + mag(scalar(pt.z() - compareOrigin.z()))
103  );
104  }
105 
106  label newPointi = 0;
107 
108  // Handle 0th point separately (is always unique)
109  label pointi = order[0];
110  pointMap[pointi] = newPointi++;
111 
112  for (label sortI = 1; sortI < order.size(); ++sortI)
113  {
114  // Get original point index
115  const label pointi = order[sortI];
116  const scalar mag2 = magSqrDist[order[sortI]];
117 
118  // Convert to scalar precision
119  // NOTE: not yet using point_type template parameter
120  const point pt
121  (
122  scalar(points[pointi].x()),
123  scalar(points[pointi].y()),
124  scalar(points[pointi].z())
125  );
126 
127 
128  // Compare to previous points to find equal one.
129  label equalPointi = -1;
130 
131  for
132  (
133  label prevSortI = sortI - 1;
134  prevSortI >= 0
135  && (mag(magSqrDist[order[prevSortI]] - mag2) <= sortedTol[sortI]);
136  --prevSortI
137  )
138  {
139  const label prevPointi = order[prevSortI];
140 
141  // Convert to scalar precision
142  // NOTE: not yet using point_type template parameter
143  const point prevPt
144  (
145  scalar(points[prevPointi].x()),
146  scalar(points[prevPointi].y()),
147  scalar(points[prevPointi].z())
148  );
149 
150  if (magSqr(pt - prevPt) <= mergeTolSqr)
151  {
152  // Found match.
153  equalPointi = prevPointi;
154 
155  break;
156  }
157  }
158 
159 
160  if (equalPointi != -1)
161  {
162  // Same coordinate as equalPointi. Map to same new point.
163  pointMap[pointi] = pointMap[equalPointi];
164 
165  if (verbose)
166  {
167  Pout<< "Foam::mergePoints : Merging points "
168  << pointi << " and " << equalPointi
169  << " with coordinates:" << points[pointi]
170  << " and " << points[equalPointi]
171  << endl;
172  }
173  }
174  else
175  {
176  // Differs. Store new point.
177  pointMap[pointi] = newPointi++;
178  }
179  }
180 
181  if (verbose)
182  {
183  Pout<< "Foam::mergePoints : "
184  << newPointi << " of " << points.size() << " unique points"
185  << endl;
186  }
187 
188  return newPointi;
189 }
190 
191 
192 template<class PointList>
194 (
195  const PointList& points,
196  const scalar mergeTol,
197  const bool verbose,
198  labelList& pointMap,
200  typename PointList::const_reference origin
201 )
202 {
203  const label nUnique = mergePoints
204  (
205  points,
206  mergeTol,
207  verbose,
208  pointMap,
209  origin
210  );
211 
212  newPoints.setSize(nUnique);
213  forAll(pointMap, pointi)
214  {
215  newPoints[pointMap[pointi]] = points[pointi];
216  }
217 
218  return (nUnique != points.size());
219 }
220 
221 
222 // ************************************************************************* //
Foam::labelList
List< label > labelList
A List of labels.
Definition: List.H:67
point.H
Foam::endl
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:369
Foam::Pout
prefixOSstream Pout
OSstream wrapped stdout (std::cout) with parallel prefix.
forAll
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:296
Foam::magSqr
dimensioned< typename typeOfMag< Type >::type > magSqr(const dimensioned< Type > &dt)
nPoints
label nPoints
Definition: gmvOutputHeader.H:2
Foam::List::setSize
void setSize(const label n)
Alias for resize()
Definition: List.H:222
Field.H
Foam::max
label max(const labelHashSet &set, label maxValue=labelMin)
Find the max value in labelHashSet, optionally limited by second argument.
Definition: hashSets.C:47
newPointi
label newPointi
Definition: readKivaGrid.H:496
Foam::mergePoints
label mergePoints(const PointList &points, const scalar mergeTol, const bool verbose, labelList &pointMap, typename PointList::const_reference origin=PointList::value_type::zero)
Sorts and merges points. All points closer than/equal mergeTol get merged.
Foam::sqr
dimensionedSymmTensor sqr(const dimensionedVector &dv)
Definition: dimensionedSymmTensor.C:51
Foam::List< label >
Foam::mag
dimensioned< typename typeOfMag< Type >::type > mag(const dimensioned< Type > &dt)
points
const pointField & points
Definition: gmvOutputHeader.H:1
x
x
Definition: LISASMDCalcMethod2.H:52
ListOps.H
Various functions to operate on Lists.
Foam::sortedOrder
labelList sortedOrder(const UList< T > &input)
Return the (stable) sort order for the list.
Foam::point
vector point
Point is a vector.
Definition: point.H:43
y
scalar y
Definition: LISASMDCalcMethod1.H:14