1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
5 \\ / A nd | Copyright held by original author
7 -------------------------------------------------------------------------------
9 This file is part of OpenFOAM.
11 OpenFOAM 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 2 of the License, or (at your
14 option) any later version.
16 OpenFOAM 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 OpenFOAM; if not, write to the Free Software Foundation,
23 Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
26 For every point on the patch find the closest face on the target side.
27 Return a target face label for each patch point
29 \*---------------------------------------------------------------------------*/
33 #include "objectHit.H"
34 #include "bandCompression.H"
36 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
41 template<class> class FaceList,
45 template <class ToPatch>
46 Foam::List<Foam::objectHit>
47 Foam::PrimitivePatch<Face, FaceList, PointField, PointType>::
50 const ToPatch& targetPatch,
51 const Field<PointType>& projectionDirection,
52 const intersection::algorithm alg,
53 const intersection::direction dir
56 // The current patch is slave, i.e. it is being projected onto the target
58 if (projectionDirection.size() != nPoints())
62 "PrimitivePatch<Face, FaceList, PointField, PointType>::"
63 "projectPoints(const PrimitivePatch& "
64 ", const Field<PointType>&) const"
65 ) << "Projection direction field does not correspond to "
66 << "patch points." << endl
67 << "Size: " << projectionDirection.size()
68 << " Number of points: " << nPoints()
72 const labelList& slavePointOrder = localPointOrder();
74 const labelList& slaveMeshPoints = meshPoints();
77 List<objectHit> result(nPoints());
79 // If there are no faces in the master patch, return: all misses
80 if (targetPatch.size() == 0)
82 // Null-constructed object hit is a miss
86 const labelListList& masterFaceFaces = targetPatch.faceFaces();
88 const ToPatch& masterFaces = targetPatch;
90 const Field<PointType>& masterPoints = targetPatch.points();
92 // Estimate face centre of target side
93 Field<PointType> masterFaceCentres(targetPatch.size());
95 forAll (masterFaceCentres, faceI)
97 masterFaceCentres[faceI] =
98 average(masterFaces[faceI].points(masterPoints));
102 // Loop through all points of the slave side. For every point find the
103 // radius for the current contact face. If the contact point falls inside
104 // the face and the radius is smaller than for all neighbouring faces,
105 // the contact is found. If not, visit the neighbour closest to the
106 // calculated contact point. If a single master face is visited more than
107 // twice, initiate n-squared search.
111 Info<< "N-squared projection set for all points" << endl;
115 label nNSquaredSearches = 0;
117 forAll (slavePointOrder, pointI)
119 // Pick up slave point and direction
120 const label curLocalPointLabel = slavePointOrder[pointI];
122 const PointType& curPoint =
123 points_[slaveMeshPoints[curLocalPointLabel]];
125 const PointType& curProjectionDir =
126 projectionDirection[curLocalPointLabel];
130 boolList visitedTargetFace(targetPatch.size(), false);
131 bool doNSquaredSearch = false;
133 bool foundEligible = false;
135 scalar sqrDistance = GREAT;
137 // Force the full search for the first point to ensure good
141 doNSquaredSearch = true;
148 doNSquaredSearch = false;
150 // Calculate intersection with curFace
151 PointHit<PointType> curHit =
152 masterFaces[curFace].ray
161 visitedTargetFace[curFace] = true;
165 result[curLocalPointLabel] = objectHit(true, curFace);
171 // If a new miss is eligible, it is closer than
172 // any previous eligible miss (due to surface walk)
174 // Only grab the miss if it is eligible
175 if (curHit.eligibleMiss())
177 foundEligible = true;
178 result[curLocalPointLabel] = objectHit(false, curFace);
181 // Find the next likely face for intersection
183 // Calculate the miss point on the plane of the
184 // face. This is cooked (illogical!) for fastest
187 PointType missPlanePoint =
188 curPoint + curProjectionDir*curHit.distance();
190 const labelList& masterNbrs = masterFaceFaces[curFace];
193 magSqr(missPlanePoint - masterFaceCentres[curFace]);
195 forAll (masterNbrs, nbrI)
202 - masterFaceCentres[masterNbrs[nbrI]]
208 curFace = masterNbrs[nbrI];
212 if (visitedTargetFace[curFace])
214 // This face has already been visited.
215 // Execute n-squared search
216 doNSquaredSearch = true;
221 if (debug) Info<< ".";
225 if (doNSquaredSearch || !foundEligible)
231 Info<< "p " << curLocalPointLabel << ": ";
234 // Improved n-sqared search algorithm. HJ, 25/Nov/2006
235 result[curLocalPointLabel] = objectHit(false, -1);
236 scalar minMissDistance = GREAT;
237 scalar minHitDistance = GREAT;
238 bool hitFound = false;
240 forAll (masterFaces, faceI)
242 PointHit<PointType> curHit =
243 masterFaces[faceI].ray
254 // Calculate min distance
256 Foam::mag(curHit.hitPoint() - curPoint);
258 if (hitDist < minHitDistance)
260 result[curLocalPointLabel] = objectHit(true, faceI);
264 minHitDistance = hitDist;
267 else if (curHit.eligibleMiss() && !hitFound)
269 // Calculate min distance
271 Foam::mag(curHit.missPoint() - curPoint);
273 if (missDist < minMissDistance)
275 minMissDistance = missDist;
277 result[curLocalPointLabel] = objectHit(false, faceI);
285 Info<< result[curLocalPointLabel]
286 << " hit = " << minHitDistance
287 << " miss = " << minMissDistance << nl;
292 if (debug) Info<< "x";
298 Info<< nl << "Executed " << nNSquaredSearches
299 << " n-squared searches out of total of "
300 << nPoints() << endl;
310 template<class> class FaceList,
314 template <class ToPatch>
315 Foam::List<Foam::objectHit>
316 Foam::PrimitivePatch<Face, FaceList, PointField, PointType>::
319 const ToPatch& targetPatch,
320 const Field<PointType>& projectionDirection,
321 const intersection::algorithm alg,
322 const intersection::direction dir
325 // The current patch is slave, i.e. it is being projected onto the target
327 if (projectionDirection.size() != this->size())
331 "labelList PrimitivePatch<Face, FaceList, PointField, PointType>::"
332 "projectFaceCentres(const PrimitivePatch& "
333 ", const Field<PointType>&) const"
334 ) << "Projection direction field does not correspond to patch faces."
335 << endl << "Size: " << projectionDirection.size()
336 << " Number of points: " << this->size()
337 << abort(FatalError);
340 labelList slaveFaceOrder = bandCompression(faceFaces());
342 // calculate master face centres
343 Field<PointType> masterFaceCentres(targetPatch.size());
345 const labelListList& masterFaceFaces = targetPatch.faceFaces();
347 const ToPatch& masterFaces = targetPatch;
349 const Field<PointType>& masterPoints = targetPatch.points();
351 forAll (masterFaceCentres, faceI)
353 masterFaceCentres[faceI] =
354 masterFaces[faceI].centre(masterPoints);
358 List<objectHit> result(this->size());
360 // If there are no faces in the master patch, return: all misses
361 if (targetPatch.size() == 0)
363 // Null-constructed object hit is a miss
367 const PrimitivePatch<Face, FaceList, PointField>& slaveFaces = *this;
368 const vectorField& slaveGlobalPoints = points();
371 // Loop through all points of the slave side. For every point find the
372 // radius for the current contact face. If the contact point falls inside
373 // the face and the radius is smaller than for all neighbouring faces,
374 // the contact is found. If not, visit the neighbour closest to the
375 // calculated contact point. If a single master face is visited more than
376 // twice, initiate n-squared search.
379 label nNSquaredSearches = 0;
381 forAll (slaveFaceOrder, faceI)
383 // pick up slave point and direction
384 const label curLocalFaceLabel = slaveFaceOrder[faceI];
386 const point& curFaceCentre =
387 slaveFaces[curLocalFaceLabel].centre(slaveGlobalPoints);
389 const vector& curProjectionDir =
390 projectionDirection[curLocalFaceLabel];
394 boolList visitedTargetFace(targetPatch.size(), false);
395 bool doNSquaredSearch = false;
397 bool foundEligible = false;
399 scalar sqrDistance = GREAT;
401 // Force the full search for the first point to ensure good
403 if (faceI == 0 || nSquaredProjection_)
405 doNSquaredSearch = true;
412 doNSquaredSearch = false;
414 // Calculate intersection with curFace
415 PointHit<PointType> curHit =
416 masterFaces[curFace].ray
425 visitedTargetFace[curFace] = true;
429 result[curLocalFaceLabel] = objectHit(true, curFace);
435 // If a new miss is eligible, it is closer than
436 // any previous eligible miss (due to surface walk)
438 // Only grab the miss if it is eligible
439 if (curHit.eligibleMiss())
441 foundEligible = true;
442 result[curLocalFaceLabel] = objectHit(false, curFace);
445 // Find the next likely face for intersection
447 // Calculate the miss point. This is
448 // cooked (illogical!) for fastest surface walk.
450 PointType missPlanePoint =
451 curFaceCentre + curProjectionDir*curHit.distance();
454 magSqr(missPlanePoint - masterFaceCentres[curFace]);
456 const labelList& masterNbrs = masterFaceFaces[curFace];
458 forAll (masterNbrs, nbrI)
465 - masterFaceCentres[masterNbrs[nbrI]]
471 curFace = masterNbrs[nbrI];
475 if (visitedTargetFace[curFace])
477 // This face has already been visited.
478 // Execute n-squared search
479 doNSquaredSearch = true;
484 if (debug) Info<< ".";
488 if (doNSquaredSearch || !foundEligible)
494 Info<< "p " << curLocalFaceLabel << ": ";
497 // Improved n-sqared search algorithm. HJ, 25/Nov/2006
498 result[curLocalFaceLabel] = objectHit(false, -1);
499 scalar minMissDistance = GREAT;
500 scalar minHitDistance = GREAT;
501 bool hitFound = false;
503 forAll (masterFaces, faceI)
505 PointHit<PointType> curHit =
506 masterFaces[faceI].ray
517 // Calculate min distance
519 Foam::mag(curHit.hitPoint() - curFaceCentre);
521 if (hitDist < minHitDistance)
523 result[curLocalFaceLabel] = objectHit(true, faceI);
527 minHitDistance = hitDist;
530 else if (curHit.eligibleMiss() && !hitFound)
532 // Calculate min distance
534 Foam::mag(curHit.missPoint() - curFaceCentre);
536 if (missDist < minMissDistance)
538 minMissDistance = missDist;
540 result[curLocalFaceLabel] = objectHit(false, faceI);
548 Info << "r = " << result[curLocalFaceLabel] << nl;
553 if (debug) Info<< "x";
559 Info<< nl << "Executed " << nNSquaredSearches
560 << " n-squared searches out of total of "
561 << this->size() << endl;
568 // ************************************************************************* //