ENH: autoLayerDriver: better layering information message
[OpenFOAM-2.0.x.git] / src / OpenFOAM / meshes / primitiveMesh / PrimitivePatch / PrimitivePatchProjectPoints.C
blob2c0115a96cf2e70af230af4630346f338f2de7f6
1 /*---------------------------------------------------------------------------*\
2   =========                 |
3   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
4    \\    /   O peration     |
5     \\  /    A nd           | Copyright (C) 2011 OpenFOAM Foundation
6      \\/     M anipulation  |
7 -------------------------------------------------------------------------------
8 License
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
13     the Free Software Foundation, either version 3 of the License, or
14     (at your 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
19     for more details.
21     You should have received a copy of the GNU General Public License
22     along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.
24 Description
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 \*---------------------------------------------------------------------------*/
30 #include "boolList.H"
31 #include "PointHit.H"
32 #include "objectHit.H"
33 #include "bandCompression.H"
35 // * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
37 template
39     class Face,
40     template<class> class FaceList,
41     class PointField,
42     class PointType
44 template <class ToPatch>
45 Foam::List<Foam::objectHit>
46 Foam::PrimitivePatch<Face, FaceList, PointField, PointType>::
47 projectPoints
49     const ToPatch& targetPatch,
50     const Field<PointType>& projectionDirection,
51     const intersection::algorithm alg,
52     const intersection::direction dir
53 ) const
55     // The current patch is slave, i.e. it is being projected onto the target
57     if (projectionDirection.size() != nPoints())
58     {
59         FatalErrorIn
60         (
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()
68             << abort(FatalError);
69     }
71     const labelList& slavePointOrder = localPointOrder();
73     const labelList& slaveMeshPoints = meshPoints();
75     // Result
76     List<objectHit> result(nPoints());
78     const labelListList& masterFaceFaces = targetPatch.faceFaces();
80     const ToPatch& masterFaces = targetPatch;
82     const Field<PointType>& masterPoints = targetPatch.points();
84     // Estimate face centre of target side
85     Field<PointType> masterFaceCentres(targetPatch.size());
87     forAll(masterFaceCentres, faceI)
88     {
89         masterFaceCentres[faceI] =
90             average(masterFaces[faceI].points(masterPoints));
91     }
93     // Algorithm:
94     // Loop through all points of the slave side. For every point find the
95     // radius for the current contact face. If the contact point falls inside
96     // the face and the radius is smaller than for all neighbouring faces,
97     // the contact is found. If not, visit the neighbour closest to the
98     // calculated contact point. If a single master face is visited more than
99     // twice, initiate n-squared search.
101     label curFace = 0;
102     label nNSquaredSearches = 0;
104     forAll(slavePointOrder, pointI)
105     {
106         // Pick up slave point and direction
107         const label curLocalPointLabel = slavePointOrder[pointI];
109         const PointType& curPoint =
110             points_[slaveMeshPoints[curLocalPointLabel]];
112         const PointType& curProjectionDir =
113             projectionDirection[curLocalPointLabel];
115         bool closer;
117         boolList visitedTargetFace(targetPatch.size(), false);
118         bool doNSquaredSearch = false;
120         bool foundEligible = false;
122         scalar sqrDistance = GREAT;
124         // Force the full search for the first point to ensure good
125         // starting face
126         if (pointI == 0)
127         {
128             doNSquaredSearch = true;
129         }
130         else
131         {
132             do
133             {
134                 closer = false;
135                 doNSquaredSearch = false;
137                 // Calculate intersection with curFace
138                 PointHit<PointType> curHit =
139                     masterFaces[curFace].ray
140                     (
141                         curPoint,
142                         curProjectionDir,
143                         masterPoints,
144                         alg,
145                         dir
146                     );
148                 visitedTargetFace[curFace] = true;
150                 if (curHit.hit())
151                 {
152                     result[curLocalPointLabel] = objectHit(true, curFace);
154                     break;
155                 }
156                 else
157                 {
158                     // If a new miss is eligible, it is closer than
159                     // any previous eligible miss (due to surface walk)
161                     // Only grab the miss if it is eligible
162                     if (curHit.eligibleMiss())
163                     {
164                         foundEligible = true;
165                         result[curLocalPointLabel] = objectHit(false, curFace);
166                     }
168                     // Find the next likely face for intersection
170                     // Calculate the miss point on the plane of the
171                     // face.  This is cooked (illogical!) for fastest
172                     // surface walk.
173                     //
174                     PointType missPlanePoint =
175                         curPoint + curProjectionDir*curHit.distance();
177                     const labelList& masterNbrs = masterFaceFaces[curFace];
179                     sqrDistance =
180                         magSqr(missPlanePoint - masterFaceCentres[curFace]);
182                     forAll(masterNbrs, nbrI)
183                     {
184                         if
185                         (
186                             magSqr
187                             (
188                                 missPlanePoint
189                               - masterFaceCentres[masterNbrs[nbrI]]
190                             )
191                          <= sqrDistance
192                         )
193                         {
194                             closer = true;
195                             curFace = masterNbrs[nbrI];
196                         }
197                     }
199                     if (visitedTargetFace[curFace])
200                     {
201                         // This face has already been visited.
202                         // Execute n-squared search
203                         doNSquaredSearch = true;
204                         break;
205                     }
206                 }
208                 if (debug) Info<< ".";
209             } while (closer);
210         }
212         if
213         (
214             doNSquaredSearch || !foundEligible
215         )
216         {
217             nNSquaredSearches++;
219             if (debug)
220             {
221                 Info<< "p " << curLocalPointLabel << ": ";
222             }
224             result[curLocalPointLabel] = objectHit(false, -1);
225             scalar minDistance = GREAT;
227             forAll(masterFaces, faceI)
228             {
229                 PointHit<PointType> curHit =
230                     masterFaces[faceI].ray
231                     (
232                         curPoint,
233                         curProjectionDir,
234                         masterPoints,
235                         alg,
236                         dir
237                     );
239                 if (curHit.hit())
240                 {
241                     result[curLocalPointLabel] = objectHit(true, faceI);
242                     curFace = faceI;
244                     break;
245                 }
246                 else if (curHit.eligibleMiss())
247                 {
248                     // Calculate min distance
249                     scalar missDist =
250                         Foam::mag(curHit.missPoint() - curPoint);
252                     if (missDist < minDistance)
253                     {
254                         minDistance = missDist;
256                         result[curLocalPointLabel] = objectHit(false, faceI);
257                         curFace = faceI;
258                     }
259                 }
260             }
262             if (debug)
263             {
264                 Info<< result[curLocalPointLabel] << nl;
265             }
266         }
267         else
268         {
269             if (debug) Info<< "x";
270         }
271     }
273     if (debug)
274     {
275         Info<< nl << "Executed " << nNSquaredSearches
276             << " n-squared searches out of total of "
277             << nPoints() << endl;
278     }
280     return result;
284 template
286     class Face,
287     template<class> class FaceList,
288     class PointField,
289     class PointType
291 template <class ToPatch>
292 Foam::List<Foam::objectHit>
293 Foam::PrimitivePatch<Face, FaceList, PointField, PointType>::
294 projectFaceCentres
296     const ToPatch& targetPatch,
297     const Field<PointType>& projectionDirection,
298     const intersection::algorithm alg,
299     const intersection::direction dir
300 ) const
302     // The current patch is slave, i.e. it is being projected onto the target
304     if (projectionDirection.size() != this->size())
305     {
306         FatalErrorIn
307         (
308             "labelList PrimitivePatch<Face, FaceList, PointField, PointType>::"
309             "projectFaceCentres(const PrimitivePatch& "
310             ", const Field<PointType>&) const"
311         )   << "Projection direction field does not correspond to patch faces."
312             << endl << "Size: " << projectionDirection.size()
313             << " Number of points: " << this->size()
314             << abort(FatalError);
315     }
317     labelList slaveFaceOrder = bandCompression(faceFaces());
319     // calculate master face centres
320     Field<PointType> masterFaceCentres(targetPatch.size());
322     const labelListList& masterFaceFaces = targetPatch.faceFaces();
324     const ToPatch& masterFaces = targetPatch;
326     const typename ToPatch::PointFieldType& masterPoints = targetPatch.points();
328     forAll(masterFaceCentres, faceI)
329     {
330         masterFaceCentres[faceI] =
331             masterFaces[faceI].centre(masterPoints);
332     }
334     // Result
335     List<objectHit> result(this->size());
337     const PrimitivePatch<Face, FaceList, PointField, PointType>& slaveFaces =
338         *this;
340     const PointField& slaveGlobalPoints = points();
342     // Algorithm:
343     // Loop through all points of the slave side. For every point find the
344     // radius for the current contact face. If the contact point falls inside
345     // the face and the radius is smaller than for all neighbouring faces,
346     // the contact is found. If not, visit the neighbour closest to the
347     // calculated contact point. If a single master face is visited more than
348     // twice, initiate n-squared search.
350     label curFace = 0;
351     label nNSquaredSearches = 0;
353     forAll(slaveFaceOrder, faceI)
354     {
355         // pick up slave point and direction
356         const label curLocalFaceLabel = slaveFaceOrder[faceI];
358         const point& curFaceCentre =
359             slaveFaces[curLocalFaceLabel].centre(slaveGlobalPoints);
361         const vector& curProjectionDir =
362             projectionDirection[curLocalFaceLabel];
364         bool closer;
366         boolList visitedTargetFace(targetPatch.size(), false);
367         bool doNSquaredSearch = false;
369         bool foundEligible = false;
371         scalar sqrDistance = GREAT;
373         // Force the full search for the first point to ensure good
374         // starting face
375         if (faceI == 0)
376         {
377             doNSquaredSearch = true;
378         }
379         else
380         {
381             do
382             {
383                 closer = false;
384                 doNSquaredSearch = false;
386                 // Calculate intersection with curFace
387                 PointHit<PointType> curHit =
388                     masterFaces[curFace].ray
389                     (
390                         curFaceCentre,
391                         curProjectionDir,
392                         masterPoints,
393                         alg,
394                         dir
395                     );
397                 visitedTargetFace[curFace] = true;
399                 if (curHit.hit())
400                 {
401                     result[curLocalFaceLabel] = objectHit(true, curFace);
403                     break;
404                 }
405                 else
406                 {
407                     // If a new miss is eligible, it is closer than
408                     // any previous eligible miss (due to surface walk)
410                     // Only grab the miss if it is eligible
411                     if (curHit.eligibleMiss())
412                     {
413                         foundEligible = true;
414                         result[curLocalFaceLabel] = objectHit(false, curFace);
415                     }
417                     // Find the next likely face for intersection
419                     // Calculate the miss point.  This is
420                     // cooked (illogical!) for fastest surface walk.
421                     //
422                     PointType missPlanePoint =
423                         curFaceCentre + curProjectionDir*curHit.distance();
425                     sqrDistance =
426                         magSqr(missPlanePoint - masterFaceCentres[curFace]);
428                     const labelList& masterNbrs = masterFaceFaces[curFace];
430                     forAll(masterNbrs, nbrI)
431                     {
432                         if
433                         (
434                             magSqr
435                             (
436                                 missPlanePoint
437                               - masterFaceCentres[masterNbrs[nbrI]]
438                             )
439                          <= sqrDistance
440                         )
441                         {
442                             closer = true;
443                             curFace = masterNbrs[nbrI];
444                         }
445                     }
447                     if (visitedTargetFace[curFace])
448                     {
449                         // This face has already been visited.
450                         // Execute n-squared search
451                         doNSquaredSearch = true;
452                         break;
453                     }
454                 }
456                 if (debug) Info<< ".";
457             } while (closer);
458         }
460         if (doNSquaredSearch || !foundEligible)
461         {
462             nNSquaredSearches++;
464             if (debug)
465             {
466                 Info<< "p " << curLocalFaceLabel << ": ";
467             }
469             result[curLocalFaceLabel] = objectHit(false, -1);
470             scalar minDistance = GREAT;
472             forAll(masterFaces, faceI)
473             {
474                 PointHit<PointType> curHit =
475                     masterFaces[faceI].ray
476                     (
477                         curFaceCentre,
478                         curProjectionDir,
479                         masterPoints,
480                         alg,
481                         dir
482                     );
484                 if (curHit.hit())
485                 {
486                     result[curLocalFaceLabel] = objectHit(true, faceI);
487                     curFace = faceI;
489                     break;
490                 }
491                 else if (curHit.eligibleMiss())
492                 {
493                     // Calculate min distance
494                     scalar missDist =
495                         Foam::mag(curHit.missPoint() - curFaceCentre);
497                     if (missDist < minDistance)
498                     {
499                         minDistance = missDist;
501                         result[curLocalFaceLabel] = objectHit(false, faceI);
502                         curFace = faceI;
503                     }
504                 }
505             }
507             if (debug)
508             {
509                 Info<< result[curLocalFaceLabel] << nl;
510             }
511         }
512         else
513         {
514             if (debug) Info<< "x";
515         }
516     }
518     if (debug)
519     {
520         Info<< nl << "Executed " << nNSquaredSearches
521             << " n-squared searches out of total of "
522             << this->size() << endl;
523     }
525     return result;
529 // ************************************************************************* //