1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | foam-extend: Open Source CFD
4 \\ / O peration | Version: 3.2
5 \\ / A nd | Web: http://www.foam-extend.org
6 \\/ M anipulation | For copyright notice see file Copyright
7 -------------------------------------------------------------------------------
9 This file is part of foam-extend.
11 foam-extend 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 foam-extend is distributed in the hope that it will be useful, but
17 WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 General Public License for more details.
21 You should have received a copy of the GNU General Public License
22 along with foam-extend. If not, see <http://www.gnu.org/licenses/>.
25 For every point on the patch find the closest face on the target side.
26 Return a target face label for each patch point
28 \*---------------------------------------------------------------------------*/
31 #include "PointHitTemplate.H"
32 #include "objectHit.H"
33 #include "bandCompression.H"
35 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
40 template<class> class FaceList,
44 template <class ToPatch>
45 Foam::List<Foam::objectHit>
46 Foam::PrimitivePatch<Face, FaceList, PointField, PointType>::
49 const ToPatch& targetPatch,
50 const Field<PointType>& projectionDirection,
51 const intersection::algorithm alg,
52 const intersection::direction dir
55 // The current patch is slave, i.e. it is being projected onto the target
57 if (projectionDirection.size() != nPoints())
61 "PrimitivePatch<Face, FaceList, PointField, PointType>::"
62 "projectPoints(const PrimitivePatch& "
63 ", const Field<PointType>&) const"
64 ) << "Projection direction field does not correspond to "
65 << "patch points." << endl
66 << "Size: " << projectionDirection.size()
67 << " Number of points: " << nPoints()
71 const labelList& slavePointOrder = localPointOrder();
73 const labelList& slaveMeshPoints = meshPoints();
76 List<objectHit> result(nPoints());
78 // If there are no faces in the master patch, return: all misses
79 if (targetPatch.size() == 0)
81 // Null-constructed object hit is a miss
85 const labelListList& masterFaceFaces = targetPatch.faceFaces();
87 const ToPatch& masterFaces = targetPatch;
89 const Field<PointType>& masterPoints = targetPatch.points();
91 // Estimate face centre of target side
92 Field<PointType> masterFaceCentres(targetPatch.size());
94 forAll (masterFaceCentres, faceI)
96 masterFaceCentres[faceI] =
97 average(masterFaces[faceI].points(masterPoints));
101 // Loop through all points of the slave side. For every point find the
102 // radius for the current contact face. If the contact point falls inside
103 // the face and the radius is smaller than for all neighbouring faces,
104 // the contact is found. If not, visit the neighbour closest to the
105 // calculated contact point. If a single master face is visited more than
106 // twice, initiate n-squared search.
110 Info<< "N-squared projection set for all points" << endl;
114 label nNSquaredSearches = 0;
116 forAll (slavePointOrder, pointI)
118 // Pick up slave point and direction
119 const label curLocalPointLabel = slavePointOrder[pointI];
121 const PointType& curPoint =
122 points_[slaveMeshPoints[curLocalPointLabel]];
124 const PointType& curProjectionDir =
125 projectionDirection[curLocalPointLabel];
129 boolList visitedTargetFace(targetPatch.size(), false);
130 bool doNSquaredSearch = false;
132 bool foundEligible = false;
134 scalar sqrDistance = GREAT;
136 // Force the full search for the first point to ensure good
140 doNSquaredSearch = true;
147 doNSquaredSearch = false;
149 // Calculate intersection with curFace
150 PointHit<PointType> curHit =
151 masterFaces[curFace].ray
160 visitedTargetFace[curFace] = true;
164 result[curLocalPointLabel] = objectHit(true, curFace);
170 // If a new miss is eligible, it is closer than
171 // any previous eligible miss (due to surface walk)
173 // Only grab the miss if it is eligible
174 if (curHit.eligibleMiss())
176 foundEligible = true;
177 result[curLocalPointLabel] = objectHit(false, curFace);
180 // Find the next likely face for intersection
182 // Calculate the miss point on the plane of the
183 // face. This is cooked (illogical!) for fastest
186 PointType missPlanePoint =
187 curPoint + curProjectionDir*curHit.distance();
189 const labelList& masterNbrs = masterFaceFaces[curFace];
192 magSqr(missPlanePoint - masterFaceCentres[curFace]);
194 forAll (masterNbrs, nbrI)
201 - masterFaceCentres[masterNbrs[nbrI]]
207 curFace = masterNbrs[nbrI];
211 if (visitedTargetFace[curFace])
213 // This face has already been visited.
214 // Execute n-squared search
215 doNSquaredSearch = true;
220 if (debug) Info<< ".";
224 if (doNSquaredSearch || !foundEligible)
230 Info<< "p " << curLocalPointLabel << ": ";
233 // Improved n-sqared search algorithm. HJ, 25/Nov/2006
234 result[curLocalPointLabel] = objectHit(false, -1);
235 scalar minMissDistance = GREAT;
236 scalar minHitDistance = GREAT;
237 bool hitFound = false;
239 forAll (masterFaces, faceI)
241 PointHit<PointType> curHit =
242 masterFaces[faceI].ray
253 // Calculate min distance
255 Foam::mag(curHit.hitPoint() - curPoint);
257 if (hitDist < minHitDistance)
259 result[curLocalPointLabel] = objectHit(true, faceI);
263 minHitDistance = hitDist;
266 else if (curHit.eligibleMiss() && !hitFound)
268 // Calculate min distance
270 Foam::mag(curHit.missPoint() - curPoint);
272 if (missDist < minMissDistance)
274 minMissDistance = missDist;
276 result[curLocalPointLabel] = objectHit(false, faceI);
284 Info<< result[curLocalPointLabel]
285 << " hit = " << minHitDistance
286 << " miss = " << minMissDistance << nl;
291 if (debug) Info<< "x";
297 Info<< nl << "Executed " << nNSquaredSearches
298 << " n-squared searches out of total of "
299 << nPoints() << endl;
309 template<class> class FaceList,
313 template <class ToPatch>
314 Foam::List<Foam::objectHit>
315 Foam::PrimitivePatch<Face, FaceList, PointField, PointType>::
318 const ToPatch& targetPatch,
319 const Field<PointType>& projectionDirection,
320 const intersection::algorithm alg,
321 const intersection::direction dir
324 // The current patch is slave, i.e. it is being projected onto the target
326 if (projectionDirection.size() != this->size())
330 "labelList PrimitivePatch<Face, FaceList, PointField, PointType>::"
331 "projectFaceCentres(const PrimitivePatch& "
332 ", const Field<PointType>&) const"
333 ) << "Projection direction field does not correspond to patch faces."
334 << endl << "Size: " << projectionDirection.size()
335 << " Number of points: " << this->size()
336 << abort(FatalError);
339 labelList slaveFaceOrder = bandCompression(faceFaces());
341 // calculate master face centres
342 Field<PointType> masterFaceCentres(targetPatch.size());
344 const labelListList& masterFaceFaces = targetPatch.faceFaces();
346 const ToPatch& masterFaces = targetPatch;
348 const Field<PointType>& masterPoints = targetPatch.points();
350 forAll (masterFaceCentres, faceI)
352 masterFaceCentres[faceI] =
353 masterFaces[faceI].centre(masterPoints);
357 List<objectHit> result(this->size());
359 // If there are no faces in the master patch, return: all misses
360 if (targetPatch.size() == 0)
362 // Null-constructed object hit is a miss
366 const PrimitivePatch<Face, FaceList, PointField>& slaveFaces = *this;
367 const vectorField& slaveGlobalPoints = points();
370 // Loop through all points of the slave side. For every point find the
371 // radius for the current contact face. If the contact point falls inside
372 // the face and the radius is smaller than for all neighbouring faces,
373 // the contact is found. If not, visit the neighbour closest to the
374 // calculated contact point. If a single master face is visited more than
375 // twice, initiate n-squared search.
378 label nNSquaredSearches = 0;
380 forAll (slaveFaceOrder, faceI)
382 // pick up slave point and direction
383 const label curLocalFaceLabel = slaveFaceOrder[faceI];
385 const point& curFaceCentre =
386 slaveFaces[curLocalFaceLabel].centre(slaveGlobalPoints);
388 const vector& curProjectionDir =
389 projectionDirection[curLocalFaceLabel];
393 boolList visitedTargetFace(targetPatch.size(), false);
394 bool doNSquaredSearch = false;
396 bool foundEligible = false;
398 scalar sqrDistance = GREAT;
400 // Force the full search for the first point to ensure good
402 if (faceI == 0 || nSquaredProjection_() > 0)
404 doNSquaredSearch = true;
411 doNSquaredSearch = false;
413 // Calculate intersection with curFace
414 PointHit<PointType> curHit =
415 masterFaces[curFace].ray
424 visitedTargetFace[curFace] = true;
428 result[curLocalFaceLabel] = objectHit(true, curFace);
434 // If a new miss is eligible, it is closer than
435 // any previous eligible miss (due to surface walk)
437 // Only grab the miss if it is eligible
438 if (curHit.eligibleMiss())
440 foundEligible = true;
441 result[curLocalFaceLabel] = objectHit(false, curFace);
444 // Find the next likely face for intersection
446 // Calculate the miss point. This is
447 // cooked (illogical!) for fastest surface walk.
449 PointType missPlanePoint =
450 curFaceCentre + curProjectionDir*curHit.distance();
453 magSqr(missPlanePoint - masterFaceCentres[curFace]);
455 const labelList& masterNbrs = masterFaceFaces[curFace];
457 forAll (masterNbrs, nbrI)
464 - masterFaceCentres[masterNbrs[nbrI]]
470 curFace = masterNbrs[nbrI];
474 if (visitedTargetFace[curFace])
476 // This face has already been visited.
477 // Execute n-squared search
478 doNSquaredSearch = true;
483 if (debug) Info<< ".";
487 if (doNSquaredSearch || !foundEligible)
493 Info<< "p " << curLocalFaceLabel << ": ";
496 // Improved n-sqared search algorithm. HJ, 25/Nov/2006
497 result[curLocalFaceLabel] = objectHit(false, -1);
498 scalar minMissDistance = GREAT;
499 scalar minHitDistance = GREAT;
500 bool hitFound = false;
502 forAll (masterFaces, faceI)
504 PointHit<PointType> curHit =
505 masterFaces[faceI].ray
516 // Calculate min distance
518 Foam::mag(curHit.hitPoint() - curFaceCentre);
520 if (hitDist < minHitDistance)
522 result[curLocalFaceLabel] = objectHit(true, faceI);
526 minHitDistance = hitDist;
529 else if (curHit.eligibleMiss() && !hitFound)
531 // Calculate min distance
533 Foam::mag(curHit.missPoint() - curFaceCentre);
535 if (missDist < minMissDistance)
537 minMissDistance = missDist;
539 result[curLocalFaceLabel] = objectHit(false, faceI);
547 Info << "r = " << result[curLocalFaceLabel] << nl;
552 if (debug) Info<< "x";
558 Info<< nl << "Executed " << nNSquaredSearches
559 << " n-squared searches out of total of "
560 << this->size() << endl;
567 // ************************************************************************* //