1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | cfMesh: A library for mesh generation
5 \\ / A nd | Author: Franjo Juretic (franjo.juretic@c-fields.com)
6 \\/ M anipulation | Copyright (C) Creative Fields, Ltd.
7 -------------------------------------------------------------------------------
9 This file is part of cfMesh.
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.
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
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/>.
26 \*---------------------------------------------------------------------------*/
28 #include "meshOctree.H"
30 #include "demandDrivenData.H"
31 #include "helperFunctions.H"
34 // #define DEBUGSearch
36 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
41 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
43 void meshOctree::findNearestSurfacePoint
47 label& nearestTriangle,
55 const label cLabel = findLeafContainingVertex(p);
59 sizeVec.x() = sizeVec.y() = sizeVec.z() = searchRange_;
63 const scalar s = 0.75 * leaves_[cLabel]->size(rootBox_);
64 sizeVec.x() = sizeVec.y() = sizeVec.z() = s;
67 //- find nearest surface vertex to the point p
70 DynList<const meshOctreeCube*, 256> neighbours;
76 boundBox bb(p - sizeVec, p + sizeVec);
79 findLeavesContainedInBox(bb, neighbours);
81 //- find nearest projection
82 forAll(neighbours, neiI)
84 if( !neighbours[neiI]->hasContainedElements() )
88 neighbours[neiI]->slotPtr()->containedTriangles_;
89 const constRow el = ct[neighbours[neiI]->containedElements()];
93 help::nearestPointOnTheTriangle(el[tI], surface_, p);
95 const scalar dSq = Foam::magSqr(p0 - p);
100 nearestTriangle = el[tI];
101 region = surface_[el[tI]].region();
110 } while( !found && (iterationI++ < 5) );
113 forAll(surface_, triI)
115 const point pp = help::nearestPointOnTheTriangle(triI, surface_, p);
117 if( distSq - magSqr(pp - p) > SMALL )
118 Pout << "Point " << p << " current nearest " << nearest
119 << " closer point " << pp << endl;
123 if( (!found || (region < 0)) && !Pstream::parRun() )
125 Warning << "Could not find a boundary region for vertex " << p << endl;
126 Warning << "Found " << found << " and region " << region << endl;
130 void meshOctree::findNearestSurfacePointInRegion
134 label& nearestTriangle,
139 const label cLabel = findLeafContainingVertex(p);
143 sizeVec.x() = sizeVec.y() = sizeVec.z() = searchRange_;
147 const scalar s = 0.75 * leaves_[cLabel]->size(rootBox_);
148 sizeVec.x() = sizeVec.y() = sizeVec.z() = s;
151 //- find nearest surface vertex to the point p
154 DynList<const meshOctreeCube*, 256> neighbours;
155 nearestTriangle = -1;
161 const boundBox bb(p - sizeVec, p + sizeVec);
164 findLeavesContainedInBox(bb, neighbours);
166 //- find nearest projection
167 forAll(neighbours, neiI)
169 if( !neighbours[neiI]->hasContainedElements() )
173 neighbours[neiI]->slotPtr()->containedTriangles_;
175 ct[neighbours[neiI]->containedElements()];
178 if( surface_[el[tI]].region() != region )
182 help::nearestPointOnTheTriangle(el[tI], surface_, p);
184 const scalar dSq = Foam::magSqr(p0 - p);
189 nearestTriangle = el[tI];
198 } while( !found && (iterationI++ < 5) );
200 if( (!found || (region < 0)) && !Pstream::parRun() )
201 Warning << "Could not find a boundary region for vertex " << p << endl;
204 bool meshOctree::findNearestEdgePoint
210 const DynList<label>& regions
213 //- find the estimate for the searching range
214 const label cLabel = findLeafContainingVertex(p);
218 sizeVec.x() = sizeVec.y() = sizeVec.z() = searchRange_;
222 const scalar s = 0.75 * leaves_[cLabel]->size(rootBox_);
223 sizeVec.x() = sizeVec.y() = sizeVec.z() = s;
226 DynList<const meshOctreeCube*, 256> neighbours;
228 const pointField& sp = surface_.points();
229 const edgeLongList& edges = surface_.edges();
230 const VRWGraph& edgeFaces = surface_.edgeFacets();
233 bool foundAnEdge(false);
241 boundBox bb(p - sizeVec, p + sizeVec);
244 findLeavesContainedInBox(bb, neighbours);
246 forAll(neighbours, neiI)
248 if( !neighbours[neiI]->hasContainedEdges() )
251 const VRWGraph& containedEdges =
252 neighbours[neiI]->slotPtr()->containedEdges_;
254 containedEdges[neighbours[neiI]->containedEdges()];
258 //- find if the edge is in correct patches
259 bool correctPatches(true);
261 forAllRow(edgeFaces, ce[eI], efI)
263 const label facetI = edgeFaces(ce[eI], efI);
265 if( !regions.contains(surface_[facetI].region()) )
267 correctPatches = false;
272 if( !correctPatches )
275 const point s = sp[edges[ce[eI]].start()];
276 const point e = sp[edges[ce[eI]].end()];
277 const point np = help::nearestPointOnTheEdgeExact(s, e, p);
278 const scalar dSq = Foam::magSqr(np - p);
284 nearestEdge = ce[eI];
293 } while( !foundAnEdge && (++iterationI < 5) );
298 bool meshOctree::findNearestPointToEdge
303 const FixedList<point, 2>& edgePoints,
304 const FixedList<label, 2>& edgePointRegions
307 const point c = 0.5 * (edgePoints[0] + edgePoints[1]);
308 const scalar dst = mag(edgePoints[0] - edgePoints[1]);
309 vector sizeVec(dst, dst, dst);
311 boundBox bb(c - 0.75 * sizeVec, c + 0.75 * sizeVec);
313 DynList<const meshOctreeCube*, 256> leavesInBox;
314 findLeavesContainedInBox(bb, leavesInBox);
316 const VRWGraph& edgeFaces = surface_.edgeFacets();
317 const pointField& points = surface_.points();
318 const edgeLongList& surfaceEdges = surface_.edges();
325 forAll(leavesInBox, leafI)
327 if( !leavesInBox[leafI]->hasContainedEdges() )
330 const VRWGraph& containedEdges =
331 leavesInBox[leafI]->slotPtr()->containedEdges_;
332 const constRow edges =
333 containedEdges[leavesInBox[leafI]->containedEdges()];
337 const constRow ef = edgeFaces[edges[eI]];
343 (surface_[ef[0]].region() == edgePointRegions[0]) &&
344 (surface_[ef[1]].region() == edgePointRegions[1])
347 (surface_[ef[1]].region() == edgePointRegions[0]) &&
348 (surface_[ef[0]].region() == edgePointRegions[1])
352 const edge& edg = surfaceEdges[edges[eI]];
354 point nearestOnEdge, nearestOnLine;
356 help::nearestEdgePointToTheLine
367 if( magSqr(nearestOnEdge - nearestOnLine) < distSq )
369 nearest = nearestOnEdge;
370 nearestEdge = edges[eI];
371 distSq = magSqr(nearestOnEdge - nearestOnLine);
382 bool meshOctree::findNearestCorner
388 const DynList<label>& patches
393 const label cLabel = findLeafContainingVertex(p);
397 sizeVec.x() = sizeVec.y() = sizeVec.z() = searchRange_;
401 const scalar s = 0.75 * leaves_[cLabel]->size(rootBox_);
402 sizeVec.x() = sizeVec.y() = sizeVec.z() = s;
405 //- find nearest surface vertex to the point p
408 DynList<const meshOctreeCube*, 256> neighbours;
410 const pointField& points = surface_.points();
411 const VRWGraph& pEdges = surface_.pointEdges();
412 const VRWGraph& eFacets = surface_.edgeFacets();
419 boundBox bb(p - sizeVec, p + sizeVec);
422 findLeavesContainedInBox(bb, neighbours);
423 labelHashSet checkedPoint;
425 //- find nearest projection
426 forAll(neighbours, neiI)
428 if( !neighbours[neiI]->hasContainedElements() )
432 neighbours[neiI]->slotPtr()->containedTriangles_;
433 const constRow el = ct[neighbours[neiI]->containedElements()];
436 const labelledTri& tri = surface_[el[tI]];
440 const label spI = tri[pI];
442 if( checkedPoint.found(spI) )
445 checkedPoint.insert(spI);
447 DynList<label> nodePatches;
450 forAllRow(pEdges, spI, i)
452 const label eI = pEdges(spI, i);
454 if( eFacets.sizeOfRow(eI) != 2 )
458 surface_[eFacets(eI, 0)].region() !=
459 surface_[eFacets(eI, 1)].region()
462 //- found an edge attached to this vertex
464 nodePatches.appendIfNotIn
466 surface_[eFacets(eI, 0)].region()
468 nodePatches.appendIfNotIn
470 surface_[eFacets(eI, 1)].region()
477 //- check if all required patches
478 //- are present at this corner
482 if( nodePatches.contains(patches[i]) )
486 if( nEdges >= patches.size() )
488 //- all patches are present, check the distance
489 const scalar dSq = Foam::magSqr(points[spI] - p);
495 nearest = points[spI];
507 } while( !found && (iterationI++ < 5) );
512 bool meshOctree::findNearestPointToPatches
517 const DynList<label>& patches,
521 if( patches.size() == 0 )
528 if( patches.size() == 2 )
531 found = findNearestEdgePoint(mapPoint, dSq, nse, p, patches);
533 else if( patches.size() > 2 )
536 found = findNearestCorner(mapPoint, dSq, nsp, p, patches);
539 point mapPointApprox(p);
544 point newP(vector::zero);
545 forAll(patches, patchI)
549 this->findNearestSurfacePointInRegion
561 newP /= patches.size();
562 if( Foam::magSqr(newP - mapPointApprox) < tol * dSq )
565 mapPointApprox = newP;
568 distSq = Foam::magSqr(mapPointApprox - p);
569 nearest = mapPointApprox;
571 if( found && (dSq < 1.5 * distSq) )
580 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
582 } // End namespace Foam
584 // ************************************************************************* //