meshOctreeFindNearestSurfacePoint.C
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | cfMesh: A library for mesh generation
4  \\ / O peration |
5  \\ / A nd | Author: Franjo Juretic (franjo.juretic@c-fields.com)
6  \\/ M anipulation | Copyright (C) Creative Fields, Ltd.
7 -------------------------------------------------------------------------------
8 License
9  This file is part of cfMesh.
10 
11  cfMesh is free software; you can redistribute it and/or modify it
12  under the terms of the GNU General Public License as published by the
13  Free Software Foundation; either version 3 of the License, or (at your
14  option) any later version.
15 
16  cfMesh is distributed in the hope that it will be useful, but WITHOUT
17  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
19  for more details.
20 
21  You should have received a copy of the GNU General Public License
22  along with cfMesh. If not, see <http://www.gnu.org/licenses/>.
23 
24 Description
25 
26 \*---------------------------------------------------------------------------*/
27 
28 #include "meshOctree.H"
29 #include "triSurf.H"
30 #include "demandDrivenData.H"
31 #include "helperFunctions.H"
32 #include "HashSet.H"
33 
34 // #define DEBUGSearch
35 
36 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
37 
38 namespace Foam
39 {
40 
41 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
42 
44 (
45  point& nearest,
46  scalar& distSq,
47  label& nearestTriangle,
48  label& region,
49  const point& p
50 ) const
51 {
52  region = -1;
53  nearestTriangle = 1;
54 
55  const label cLabel = findLeafContainingVertex(p);
56  vector sizeVec;
57  if( cLabel < 0 )
58  {
59  sizeVec.x() = sizeVec.y() = sizeVec.z() = searchRange_;
60  }
61  else
62  {
63  const scalar s = 0.75 * leaves_[cLabel]->size(rootBox_);
64  sizeVec.x() = sizeVec.y() = sizeVec.z() = s;
65  }
66 
67  //- find nearest surface vertex to the point p
68  bool found(false);
69  label iterationI(0);
71 
72  distSq = VGREAT;
73 
74  do
75  {
76  const boundBox bb(p - sizeVec, p + sizeVec);
77 
78  neighbours.clear();
79  findLeavesContainedInBox(bb, neighbours);
80 
81  //- find nearest projection
82  forAll(neighbours, neiI)
83  {
84  if( !neighbours[neiI]->hasContainedElements() )
85  continue;
86 
87  const VRWGraph& ct =
88  neighbours[neiI]->slotPtr()->containedTriangles_;
89  const constRow el = ct[neighbours[neiI]->containedElements()];
90  forAll(el, tI)
91  {
92  const point p0 =
93  help::nearestPointOnTheTriangle(el[tI], surface_, p);
94 
95  const scalar dSq = Foam::magSqr(p0 - p);
96  if( dSq < distSq )
97  {
98  distSq = dSq;
99  nearest = p0;
100  nearestTriangle = el[tI];
101  region = surface_[el[tI]].region();
102  found = true;
103  }
104  }
105  }
106 
107  if( !found )
108  sizeVec *= 2.0;
109 
110  } while( !found && (iterationI++ < 100) );
111 
112  # ifdef DEBUGSearch
113  forAll(surface_, triI)
114  {
115  const point pp = help::nearestPointOnTheTriangle(triI, surface_, p);
116 
117  if( distSq - magSqr(pp - p) > SMALL )
118  Pout << "Point " << p << " current nearest " << nearest
119  << " closer point " << pp << endl;
120  }
121  # endif
122 
123  if( (!found || (region < 0)) && !Pstream::parRun() )
124  {
125  Warning << "Could not find a boundary region for vertex " << p << endl;
126  Warning << "Found " << found << " and region " << region << endl;
127  }
128 }
129 
131 (
132  point& nearest,
133  scalar& distSq,
134  label& nearestTriangle,
135  const label region,
136  const point& p
137 ) const
138 {
139  if( region < 0 )
140  {
141  WarningIn
142  (
143  "void meshOctree::findNearestSurfacePointInRegion(point&, scalar&,"
144  "label&, const label, const point&) const"
145  ) << "Region " << region << " is not valid!" << endl;
146 
147  return;
148  }
149  const label cLabel = findLeafContainingVertex(p);
150  vector sizeVec;
151  if( cLabel < 0 )
152  {
153  sizeVec.x() = sizeVec.y() = sizeVec.z() = searchRange_;
154  }
155  else
156  {
157  const scalar s = 0.75 * leaves_[cLabel]->size(rootBox_);
158  sizeVec.x() = sizeVec.y() = sizeVec.z() = s;
159  }
160 
161  //- find nearest surface vertex to the point p
162  bool found(false);
163  label iterationI(0);
165  nearestTriangle = -1;
166 
167  distSq = VGREAT;
168 
169  do
170  {
171  const boundBox bb(p - sizeVec, p + sizeVec);
172 
173  neighbours.clear();
174  findLeavesContainedInBox(bb, neighbours);
175 
176  //- find nearest projection
177  forAll(neighbours, neiI)
178  {
179  if( !neighbours[neiI]->hasContainedElements() )
180  continue;
181 
182  const VRWGraph& ct =
183  neighbours[neiI]->slotPtr()->containedTriangles_;
184  const constRow el =
185  ct[neighbours[neiI]->containedElements()];
186  forAll(el, tI)
187  {
188  if( surface_[el[tI]].region() != region )
189  continue;
190 
191  const point p0 =
192  help::nearestPointOnTheTriangle(el[tI], surface_, p);
193 
194  const scalar dSq = Foam::magSqr(p0 - p);
195  if( dSq < distSq )
196  {
197  distSq = dSq;
198  nearest = p0;
199  nearestTriangle = el[tI];
200  found = true;
201  }
202  }
203  }
204 
205  if( !found )
206  sizeVec *= 2.0;
207 
208  } while( !found && (iterationI++ < 5) );
209 
210  if( (!found || (region < 0)) && !Pstream::parRun() )
211  Warning << "Could not find a boundary region for vertex " << p << endl;
212 }
213 
215 (
216  point& edgePoint,
217  scalar& distSq,
218  label& nearestEdge,
219  const point& p,
220  const DynList<label>& regions
221 ) const
222 {
223  //- find the estimate for the searching range
224  const label cLabel = findLeafContainingVertex(p);
225  vector sizeVec;
226  if( cLabel < 0 )
227  {
228  sizeVec.x() = sizeVec.y() = sizeVec.z() = searchRange_;
229  }
230  else
231  {
232  const scalar s = 0.75 * leaves_[cLabel]->size(rootBox_);
233  sizeVec.x() = sizeVec.y() = sizeVec.z() = s;
234  }
235 
237 
238  const pointField& sPoints = surface_.points();
239  const edgeLongList& edges = surface_.edges();
240  const VRWGraph& edgeFaces = surface_.edgeFacets();
241 
242  edgePoint = p;
243  bool foundAnEdge(false);
244  label iterationI(0);
245 
246  distSq = VGREAT;
247  nearestEdge = -1;
248 
249 // Info << "Finding nearest point for " << p << " size vec " << sizeVec << endl;
250 
251  do
252  {
253  const boundBox bb(p - sizeVec, p + sizeVec);
254 
255  neighbours.clear();
256  findLeavesContainedInBox(bb, neighbours);
257 
258 // Info << "Iteration " << iterationI << " nu found boxes "
259 // << neighbours.size() << endl;
260 
261  forAll(neighbours, neiI)
262  {
263  if( !neighbours[neiI]->hasContainedEdges() )
264  continue;
265 
266  const VRWGraph& containedEdges =
267  neighbours[neiI]->slotPtr()->containedEdges_;
268  const constRow ce =
269  containedEdges[neighbours[neiI]->containedEdges()];
270 
271 // Info << "Number of contained edges in box "
272 // << neighbours[neiI]->cubeLabel()
273 // << " are " << ce.size() << endl;
274 
275  forAll(ce, eI)
276  {
277  const label edgeI = ce[eI];
278 
279  //- find if the edge is in correct patches
280  bool correctPatches(true);
281 
282  forAllRow(edgeFaces, edgeI, efI)
283  {
284  const label facetI = edgeFaces(edgeI, efI);
285 
286  if( !regions.contains(surface_[facetI].region()) )
287  {
288  correctPatches = false;
289  break;
290  }
291  }
292 
293  if( !correctPatches )
294  continue;
295 
296  const edge& e = edges[edgeI];
297  const point& sp = sPoints[e.start()];
298  const point& ep = sPoints[e.end()];
299  const point np = help::nearestPointOnTheEdgeExact(sp, ep, p);
300  const scalar dSq = Foam::magSqr(np - p);
301 
302  if( dSq < distSq )
303  {
304  distSq = dSq;
305  edgePoint = np;
306  nearestEdge = ce[eI];
307  foundAnEdge = true;
308  }
309  }
310  }
311 
312  if( !foundAnEdge )
313  sizeVec *= 2.0;
314 
315  } while( !foundAnEdge && (++iterationI < 3) );
316 
317  return foundAnEdge;
318 }
319 
321 (
322  point& nearest,
323  scalar& distSq,
324  label& nearestEdge,
325  const FixedList<point, 2>& edgePoints,
326  const FixedList<label, 2>& edgePointRegions
327 ) const
328 {
329  const point c = 0.5 * (edgePoints[0] + edgePoints[1]);
330  const scalar dst = mag(edgePoints[0] - edgePoints[1]);
331  vector sizeVec(dst, dst, dst);
332 
333  boundBox bb(c - 0.75 * sizeVec, c + 0.75 * sizeVec);
334 
336  findLeavesContainedInBox(bb, leavesInBox);
337 
338  const VRWGraph& edgeFaces = surface_.edgeFacets();
339  const pointField& points = surface_.points();
340  const edgeLongList& surfaceEdges = surface_.edges();
341 
342  distSq = VGREAT;
343  nearestEdge = -1;
344 
345  bool found(false);
346 
347  forAll(leavesInBox, leafI)
348  {
349  if( !leavesInBox[leafI]->hasContainedEdges() )
350  continue;
351 
352  const VRWGraph& containedEdges =
353  leavesInBox[leafI]->slotPtr()->containedEdges_;
354  const constRow edges =
355  containedEdges[leavesInBox[leafI]->containedEdges()];
356 
357  forAll(edges, eI)
358  {
359  const constRow ef = edgeFaces[edges[eI]];
360  if( ef.size() != 2 )
361  continue;
362 
363  if(
364  (
365  (surface_[ef[0]].region() == edgePointRegions[0]) &&
366  (surface_[ef[1]].region() == edgePointRegions[1])
367  ) ||
368  (
369  (surface_[ef[1]].region() == edgePointRegions[0]) &&
370  (surface_[ef[0]].region() == edgePointRegions[1])
371  )
372  )
373  {
374  const edge& edg = surfaceEdges[edges[eI]];
375 
376  point nearestOnEdge, nearestOnLine;
377  if(
379  (
380  points[edg[0]],
381  points[edg[1]],
382  edgePoints[0],
383  edgePoints[1],
384  nearestOnEdge,
385  nearestOnLine
386  )
387  )
388  {
389  if( magSqr(nearestOnEdge - nearestOnLine) < distSq )
390  {
391  nearest = nearestOnEdge;
392  nearestEdge = edges[eI];
393  distSq = magSqr(nearestOnEdge - nearestOnLine);
394  found = true;
395  }
396  }
397  }
398  }
399  }
400 
401  return found;
402 }
403 
405 (
406  point& nearest,
407  scalar& distSq,
408  label& nearestPoint,
409  const point& p,
410  const DynList<label>& patches
411 ) const
412 {
413 
414 
415  const label cLabel = findLeafContainingVertex(p);
416  vector sizeVec;
417  if( cLabel < 0 )
418  {
419  sizeVec.x() = sizeVec.y() = sizeVec.z() = searchRange_;
420  }
421  else
422  {
423  const scalar s = 0.75 * leaves_[cLabel]->size(rootBox_);
424  sizeVec.x() = sizeVec.y() = sizeVec.z() = s;
425  }
426 
427  //- find nearest surface vertex to the point p
428  bool found(false);
429  label iterationI(0);
431 
432  const pointField& points = surface_.points();
433  const VRWGraph& pEdges = surface_.pointEdges();
434  const VRWGraph& eFacets = surface_.edgeFacets();
435 
436  distSq = VGREAT;
437  nearestPoint = -1;
438 
439  do
440  {
441  const boundBox bb(p - sizeVec, p + sizeVec);
442 
443  neighbours.clear();
444  findLeavesContainedInBox(bb, neighbours);
445  labelHashSet checkedPoint;
446 
447  //- find nearest projection
448  forAll(neighbours, neiI)
449  {
450  if( !neighbours[neiI]->hasContainedElements() )
451  continue;
452 
453  const VRWGraph& ct =
454  neighbours[neiI]->slotPtr()->containedTriangles_;
455  const constRow el = ct[neighbours[neiI]->containedElements()];
456  forAll(el, tI)
457  {
458  const labelledTri& tri = surface_[el[tI]];
459 
460  forAll(tri, pI)
461  {
462  const label spI = tri[pI];
463 
464  if( checkedPoint.found(spI) )
465  continue;
466 
467  checkedPoint.insert(spI);
468 
469  DynList<label> nodePatches;
470  label nEdges(0);
471 
472  forAllRow(pEdges, spI, i)
473  {
474  const label eI = pEdges(spI, i);
475 
476  if( eFacets.sizeOfRow(eI) != 2 )
477  break;
478 
479  if(
480  surface_[eFacets(eI, 0)].region() !=
481  surface_[eFacets(eI, 1)].region()
482  )
483  {
484  //- found an edge attached to this vertex
485  ++nEdges;
486  nodePatches.appendIfNotIn
487  (
488  surface_[eFacets(eI, 0)].region()
489  );
490  nodePatches.appendIfNotIn
491  (
492  surface_[eFacets(eI, 1)].region()
493  );
494  }
495  }
496 
497  if( nEdges > 2 )
498  {
499  //- check if all required patches
500  //- are present at this corner
501  nEdges = 0;
502  forAll(patches, i)
503  {
504  if( nodePatches.contains(patches[i]) )
505  ++nEdges;
506  }
507 
508  if( nEdges >= patches.size() )
509  {
510  //- all patches are present, check the distance
511  const scalar dSq = Foam::magSqr(points[spI] - p);
512 
513  if( dSq < distSq )
514  {
515  distSq = dSq;
516  found = true;
517  nearest = points[spI];
518  nearestPoint = spI;
519  }
520  }
521  }
522  }
523  }
524  }
525 
526  if( !found )
527  sizeVec *= 2.0;
528 
529  } while( !found && (iterationI++ < 3) );
530 
531  return found;
532 }
533 
535 (
536  point& nearest,
537  scalar& distSq,
538  const point& p,
539  const DynList<label>& patches,
540  const scalar tol
541 ) const
542 {
543  if( patches.size() == 0 )
544  return false;
545 
546  nearest = p;
547  scalar distSqApprox;
548  label iter(0);
549  while( iter++ < 40 )
550  {
551  point newP(vector::zero);
552  forAll(patches, patchI)
553  {
554  point np;
555  label nearestTri;
556  this->findNearestSurfacePointInRegion
557  (
558  np,
559  distSqApprox,
560  nearestTri,
561  patches[patchI],
562  nearest
563  );
564 
565  newP += np;
566  }
567 
568  newP /= patches.size();
569  distSq = magSqr(newP - p);
570 
571  if( Foam::magSqr(newP - nearest) < tol * distSq )
572  break;
573 
574  nearest = newP;
575  }
576 
577  return true;
578 }
579 
580 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
581 
582 } // End namespace Foam
583 
584 // ************************************************************************* //
triSurf.H
Foam::Vector< scalar >::zero
static const Vector zero
Definition: Vector.H:80
p
p
Definition: pEqn.H:62
forAll
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:406
demandDrivenData.H
Template functions to aid in the implementation of demand driven data.
Foam::meshOctree::findNearestSurfacePoint
void findNearestSurfacePoint(point &nearest, scalar &distSq, label &nearestTriangle, label &region, const point &p) const
find nearest surface point for vertex and its region
Definition: meshOctreeFindNearestSurfacePoint.C:44
Foam::help::nearestPointOnTheTriangle
point nearestPointOnTheTriangle(const triangle< point, point > &tri, const point &)
find the nearest point on the triangle to the given point
Definition: helperFunctionsGeometryQueriesI.H:475
Foam::Warning
messageStream Warning
Foam::UPstream::parRun
static bool & parRun()
Is this a parallel run?
Definition: UPstream.H:377
Foam::edge
An edge is a list of two point labels. The functionality it provides supports the discretisation on a...
Definition: edge.H:58
Foam::help::nearestEdgePointToTheLine
bool nearestEdgePointToTheLine(const point &edgePoint0, const point &edgePoint1, const point &lp0, const point &lp1, point &nearestOnEdge, point &nearestOnLine)
find the nearest points on the edge and the line
Definition: helperFunctionsGeometryQueriesI.H:417
Foam::meshOctree::findNearestPointToEdge
bool findNearestPointToEdge(point &nearest, scalar &distSq, label &nearestEdge, const FixedList< point, 2 > &edgePoints, const FixedList< label, 2 > &edgePointRegions) const
Definition: meshOctreeFindNearestSurfacePoint.C:321
Foam::endl
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:251
Foam::mag
dimensioned< scalar > mag(const dimensioned< Type > &)
Foam::HashSet< label, Hash< label > >
Foam::DynList::contains
bool contains(const T &e) const
check if the element is in the list (takes linear time)
Definition: DynListI.H:339
meshOctree.H
Foam::LongList< edge >
Foam::constRow
const typedef graphRow< const VRWGraph > constRow
Definition: graphRow.H:134
Foam::label
intWM_LABEL_SIZE_t label
A label is an int32_t or int64_t as specified by the pre-processor macro WM_LABEL_SIZE.
Definition: label.H:59
Foam::Field
Pre-declare SubField and related Field type.
Definition: Field.H:57
Foam::meshOctree::findNearestEdgePoint
bool findNearestEdgePoint(point &edgePoint, scalar &distSq, label &nearestEdge, const point &p, const DynList< label > &regions) const
find nearest feature-edges vertex to a given vertex
Definition: meshOctreeFindNearestSurfacePoint.C:215
Foam::meshOctree::findNearestPointToPatches
bool findNearestPointToPatches(point &nearest, scalar &distSq, const point &p, const DynList< label > &patches, const scalar tol=1e-4) const
find the nearest vertex to the given patches
Definition: meshOctreeFindNearestSurfacePoint.C:535
Foam::DynList::appendIfNotIn
void appendIfNotIn(const T &e)
Definition: DynListI.H:324
forAllRow
#define forAllRow(graph, rowI, index)
Definition: VRWGraph.H:277
Foam::help::nearestPointOnTheEdgeExact
point nearestPointOnTheEdgeExact(const point &edgePoint0, const point &edgePoint1, const point &p)
find the vertex on the edge nearest to the point p
Definition: helperFunctionsGeometryQueriesI.H:1633
HashSet.H
Foam::VRWGraph::sizeOfRow
label sizeOfRow(const label rowI) const
Returns the number of elements in the given row.
Definition: VRWGraphI.H:127
Foam::Vector::x
const Cmpt & x() const
Definition: VectorI.H:65
Foam::HashTable::found
bool found(const Key &) const
Return true if hashedEntry is found in table.
Definition: HashTable.C:109
Foam
Namespace for OpenFOAM.
Definition: combustionModel.C:30
Foam::Vector::z
const Cmpt & z() const
Definition: VectorI.H:77
Foam::e
const double e
Elementary charge.
Definition: doubleFloat.H:94
s
gmvFile<< "tracers "<< particles.size()<< nl;forAllConstIter(Cloud< passiveParticle >, particles, iter){ gmvFile<< iter().position().x()<< " ";}gmvFile<< nl;forAllConstIter(Cloud< passiveParticle >, particles, iter){ gmvFile<< iter().position().y()<< " ";}gmvFile<< nl;forAllConstIter(Cloud< passiveParticle >, particles, iter){ gmvFile<< iter().position().z()<< " ";}gmvFile<< nl;forAll(lagrangianScalarNames, i){ word name=lagrangianScalarNames[i];IOField< scalar > s(IOobject(name, runTime.timeName(), cloud::prefix, mesh, IOobject::MUST_READ, IOobject::NO_WRITE))
Foam::DynList
Definition: DynList.H:53
found
bool found
Definition: TABSMDCalcMethod2.H:32
Foam::Pout
prefixOSstream Pout(cout, "Pout")
Definition: IOstreams.H:53
helperFunctions.H
Foam::Vector< scalar >
Foam::FixedList
A 1D vector of objects of type <T> with a fixed size <Size>.
Definition: FixedList.H:53
points
const pointField & points
Definition: gmvOutputHeader.H:1
Foam::HashSet::insert
bool insert(const Key &key)
Insert a new entry.
Definition: HashSet.H:116
Foam::labelledTri
Triangle with additional region number.
Definition: labelledTri.H:49
Foam::boundBox
A bounding box defined in terms of the points at its extremities.
Definition: boundBox.H:55
Foam::constant::universal::c
const dimensionedScalar c
Speed of light in a vacuum.
patches
patches[0]
Definition: createSingleCellMesh.H:36
Foam::Vector::y
const Cmpt & y() const
Definition: VectorI.H:71
WarningIn
#define WarningIn(functionName)
Report a warning using Foam::Warning.
Definition: messageStream.H:254
Foam::meshOctree::findNearestCorner
bool findNearestCorner(point &nearest, scalar &distSq, label &nearestPoint, const point &p, const DynList< label > &patches) const
find nearest corner point
Definition: meshOctreeFindNearestSurfacePoint.C:405
Foam::meshOctree::findNearestSurfacePointInRegion
void findNearestSurfacePointInRegion(point &nearest, scalar &distSq, label &nearestTriangle, const label region, const point &p) const
find nearest surface point for vertex in a given region
Definition: meshOctreeFindNearestSurfacePoint.C:131
Foam::VRWGraph
Definition: VRWGraph.H:101
Foam::magSqr
dimensioned< scalar > magSqr(const dimensioned< Type > &)
Foam::DynList::clear
void clear()
Clear the list, i.e. set next free to zero.
Definition: DynListI.H:279