FreeFOAM The Cross-Platform CFD Toolkit
Hosted by SourceForge:
Get FreeFOAM at SourceForge.net.
            Fast, secure and Free Open Source software downloads

meshSearch.C

Go to the documentation of this file.
00001 /*---------------------------------------------------------------------------*\
00002   =========                 |
00003   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
00004    \\    /   O peration     |
00005     \\  /    A nd           | Copyright (C) 1991-2010 OpenCFD Ltd.
00006      \\/     M anipulation  |
00007 -------------------------------------------------------------------------------
00008 License
00009     This file is part of OpenFOAM.
00010 
00011     OpenFOAM is free software: you can redistribute it and/or modify it
00012     under the terms of the GNU General Public License as published by
00013     the Free Software Foundation, either version 3 of the License, or
00014     (at your option) any later version.
00015 
00016     OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
00017     ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00018     FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
00019     for more details.
00020 
00021     You should have received a copy of the GNU General Public License
00022     along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.
00023 
00024 \*---------------------------------------------------------------------------*/
00025 
00026 #include "meshSearch.H"
00027 #include <OpenFOAM/polyMesh.H>
00028 #include <meshTools/indexedOctree.H>
00029 #include <OpenFOAM/DynamicList.H>
00030 #include <OpenFOAM/demandDrivenData.H>
00031 #include <meshTools/treeDataCell.H>
00032 #include <meshTools/treeDataFace.H>
00033 #include <meshTools/treeDataPoint.H>
00034 
00035 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
00036 
00037 defineTypeNameAndDebug(Foam::meshSearch, 0);
00038 
00039 Foam::scalar Foam::meshSearch::tol_ = 1E-3;
00040 
00041 
00042 // * * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * //
00043 
00044 bool Foam::meshSearch::findNearer
00045 (
00046     const point& sample,
00047     const pointField& points,
00048     label& nearestI,
00049     scalar& nearestDistSqr
00050 )
00051 {
00052     bool nearer = false;
00053 
00054     forAll(points, pointI)
00055     {
00056         scalar distSqr = magSqr(points[pointI] - sample);
00057 
00058         if (distSqr < nearestDistSqr)
00059         {
00060             nearestDistSqr = distSqr;
00061             nearestI = pointI;
00062             nearer = true;
00063         }
00064     }
00065 
00066     return nearer;
00067 }
00068 
00069 
00070 bool Foam::meshSearch::findNearer
00071 (
00072     const point& sample,
00073     const pointField& points,
00074     const labelList& indices,
00075     label& nearestI,
00076     scalar& nearestDistSqr
00077 )
00078 {
00079     bool nearer = false;
00080 
00081     forAll(indices, i)
00082     {
00083         label pointI = indices[i];
00084 
00085         scalar distSqr = magSqr(points[pointI] - sample);
00086 
00087         if (distSqr < nearestDistSqr)
00088         {
00089             nearestDistSqr = distSqr;
00090             nearestI = pointI;
00091             nearer = true;
00092         }
00093     }
00094 
00095     return nearer;
00096 }
00097 
00098 
00099 // tree based searching
00100 Foam::label Foam::meshSearch::findNearestCellTree(const point& location) const
00101 {
00102     const indexedOctree<treeDataPoint>& tree = cellCentreTree();
00103 
00104     scalar span = tree.bb().mag();
00105     
00106     pointIndexHit info = tree.findNearest(location, Foam::sqr(span));
00107 
00108     if (!info.hit())
00109     {
00110         info = tree.findNearest(location, Foam::sqr(GREAT));
00111     }
00112     return info.index();
00113 }
00114 
00115 
00116 // linear searching
00117 Foam::label Foam::meshSearch::findNearestCellLinear(const point& location) const
00118 {
00119     const vectorField& centres = mesh_.cellCentres();
00120 
00121     label nearestIndex = 0;
00122     scalar minProximity = magSqr(centres[nearestIndex] - location);
00123 
00124     findNearer
00125     (
00126         location,
00127         centres,
00128         nearestIndex,
00129         minProximity
00130     );
00131 
00132     return nearestIndex;
00133 }
00134 
00135 
00136 // walking from seed
00137 Foam::label Foam::meshSearch::findNearestCellWalk
00138 (
00139     const point& location,
00140     const label seedCellI
00141 ) const
00142 {
00143     if (seedCellI < 0)
00144     {
00145         FatalErrorIn
00146         (
00147             "meshSearch::findNearestCellWalk(const point&, const label)"
00148         )   << "illegal seedCell:" << seedCellI << exit(FatalError);
00149     }
00150 
00151     // Walk in direction of face that decreases distance
00152 
00153     label curCellI = seedCellI;
00154     scalar distanceSqr = magSqr(mesh_.cellCentres()[curCellI] - location);
00155 
00156     bool closer;
00157 
00158     do
00159     {
00160         // Try neighbours of curCellI
00161         closer = findNearer
00162         (
00163             location,
00164             mesh_.cellCentres(),
00165             mesh_.cellCells()[curCellI],
00166             curCellI,
00167             distanceSqr
00168         );
00169     } while (closer);
00170 
00171     return curCellI;
00172 }
00173 
00174 
00175 // tree based searching
00176 Foam::label Foam::meshSearch::findNearestFaceTree(const point& location) const
00177 {
00178     // Search nearest cell centre.
00179     const indexedOctree<treeDataPoint>& tree = cellCentreTree();
00180 
00181     scalar span = tree.bb().mag();
00182 
00183     // Search with decent span
00184     pointIndexHit info = tree.findNearest(location, Foam::sqr(span));
00185 
00186     if (!info.hit())
00187     {
00188         // Search with desparate span
00189         info = tree.findNearest(location, Foam::sqr(GREAT));
00190     }
00191 
00192 
00193     // Now check any of the faces of the nearest cell
00194     const vectorField& centres = mesh_.faceCentres();
00195     const cell& ownFaces = mesh_.cells()[info.index()];
00196 
00197     label nearestFaceI = ownFaces[0];
00198     scalar minProximity = magSqr(centres[nearestFaceI] - location);
00199 
00200     findNearer
00201     (
00202         location,
00203         centres,
00204         ownFaces,
00205         nearestFaceI,
00206         minProximity
00207     );
00208 
00209     return nearestFaceI;
00210 }
00211 
00212 
00213 // linear searching
00214 Foam::label Foam::meshSearch::findNearestFaceLinear(const point& location) const
00215 {
00216     const vectorField& centres = mesh_.faceCentres();
00217 
00218     label nearestFaceI = 0;
00219     scalar minProximity = magSqr(centres[nearestFaceI] - location);
00220 
00221     findNearer
00222     (
00223         location,
00224         centres,
00225         nearestFaceI,
00226         minProximity
00227     );
00228 
00229     return nearestFaceI;
00230 }
00231 
00232 
00233 // walking from seed
00234 Foam::label Foam::meshSearch::findNearestFaceWalk
00235 (
00236     const point& location,
00237     const label seedFaceI
00238 ) const
00239 {
00240     if (seedFaceI < 0)
00241     {
00242         FatalErrorIn
00243         (
00244             "meshSearch::findNearestFaceWalk(const point&, const label)"
00245         )   << "illegal seedFace:" << seedFaceI << exit(FatalError);
00246     }
00247 
00248     const vectorField& centres = mesh_.faceCentres();
00249 
00250 
00251     // Walk in direction of face that decreases distance
00252 
00253     label curFaceI = seedFaceI;
00254     scalar distanceSqr = magSqr(centres[curFaceI] - location);
00255 
00256     while (true)
00257     {
00258         label betterFaceI = curFaceI;
00259 
00260         findNearer
00261         (
00262             location,
00263             centres,
00264             mesh_.cells()[mesh_.faceOwner()[curFaceI]],
00265             betterFaceI,
00266             distanceSqr
00267         );
00268 
00269         if (mesh_.isInternalFace(curFaceI))
00270         {
00271             findNearer
00272             (
00273                 location,
00274                 centres,
00275                 mesh_.cells()[mesh_.faceNeighbour()[curFaceI]],
00276                 betterFaceI,
00277                 distanceSqr
00278             );
00279         }
00280 
00281         if (betterFaceI == curFaceI)
00282         {
00283             break;
00284         }
00285 
00286         curFaceI = betterFaceI;
00287     }
00288 
00289     return curFaceI;
00290 }
00291 
00292 
00293 Foam::label Foam::meshSearch::findCellLinear(const point& location) const
00294 {
00295     bool cellFound = false;
00296     label n = 0;
00297 
00298     label cellI = -1;
00299 
00300     while ((!cellFound) && (n < mesh_.nCells()))
00301     {
00302         if (pointInCell(location, n))
00303         {
00304             cellFound = true;
00305             cellI = n;
00306         }
00307         else
00308         {
00309             n++;
00310         }
00311     }
00312     if (cellFound)
00313     {
00314         return cellI;
00315     }
00316     else
00317     {
00318         return -1;
00319     }
00320 }
00321 
00322 
00323 Foam::label Foam::meshSearch::findNearestBoundaryFaceWalk
00324 (
00325     const point& location,
00326     const label seedFaceI
00327 ) const
00328 {
00329     if (seedFaceI < 0)
00330     {
00331         FatalErrorIn
00332         (
00333             "meshSearch::findNearestBoundaryFaceWalk"
00334             "(const point&, const label)"
00335         )   << "illegal seedFace:" << seedFaceI << exit(FatalError);
00336     }
00337 
00338     // Start off from seedFaceI
00339 
00340     label curFaceI = seedFaceI;
00341 
00342     const face& f =  mesh_.faces()[curFaceI];
00343 
00344     scalar minDist = f.nearestPoint
00345     (
00346         location,
00347         mesh_.points()
00348     ).distance();
00349 
00350     bool closer;
00351 
00352     do
00353     {
00354         closer = false;
00355 
00356         // Search through all neighbouring boundary faces by going
00357         // across edges
00358 
00359         label lastFaceI = curFaceI;
00360 
00361         const labelList& myEdges = mesh_.faceEdges()[curFaceI];
00362 
00363         forAll (myEdges, myEdgeI)
00364         {
00365             const labelList& neighbours = mesh_.edgeFaces()[myEdges[myEdgeI]];
00366 
00367             // Check any face which uses edge, is boundary face and
00368             // is not curFaceI itself.
00369 
00370             forAll(neighbours, nI)
00371             {
00372                 label faceI = neighbours[nI];
00373 
00374                 if
00375                 (
00376                     (faceI >= mesh_.nInternalFaces())
00377                  && (faceI != lastFaceI)
00378                 )
00379                 {
00380                     const face& f =  mesh_.faces()[faceI];
00381 
00382                     pointHit curHit = f.nearestPoint
00383                     (
00384                         location,
00385                         mesh_.points()
00386                     );
00387 
00388                     // If the face is closer, reset current face and distance
00389                     if (curHit.distance() < minDist)
00390                     {
00391                         minDist = curHit.distance();
00392                         curFaceI = faceI;
00393                         closer = true;  // a closer neighbour has been found
00394                     }
00395                 }
00396             }
00397         }
00398     } while (closer);
00399 
00400     return curFaceI;
00401 }
00402 
00403 
00404 Foam::vector Foam::meshSearch::offset
00405 (
00406     const point& bPoint,
00407     const label bFaceI,
00408     const vector& dir
00409 ) const
00410 {
00411     // Get the neighbouring cell
00412     label ownerCellI = mesh_.faceOwner()[bFaceI];
00413 
00414     const point& c = mesh_.cellCentres()[ownerCellI];
00415 
00416     // Typical dimension: distance from point on face to cell centre
00417     scalar typDim = mag(c - bPoint);
00418 
00419     return tol_*typDim*dir;
00420 }
00421 
00422 
00423 // * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
00424 
00425 // Construct from components
00426 Foam::meshSearch::meshSearch(const polyMesh& mesh, const bool faceDecomp)
00427 :
00428     mesh_(mesh),
00429     faceDecomp_(faceDecomp),
00430     cloud_(mesh_, IDLList<passiveParticle>()),
00431     boundaryTreePtr_(NULL),
00432     cellTreePtr_(NULL),
00433     cellCentreTreePtr_(NULL)
00434 {}
00435 
00436 
00437 // * * * * * * * * * * * * * * * * Destructor  * * * * * * * * * * * * * * * //
00438 
00439 Foam::meshSearch::~meshSearch()
00440 {
00441     clearOut();
00442 }
00443 
00444 
00445 // * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
00446 
00447 const Foam::indexedOctree<Foam::treeDataFace>& Foam::meshSearch::boundaryTree()
00448  const
00449 {
00450     if (!boundaryTreePtr_)
00451     {
00452         //
00453         // Construct tree
00454         //
00455 
00456         // all boundary faces (not just walls)
00457         labelList bndFaces(mesh_.nFaces()-mesh_.nInternalFaces());
00458         forAll(bndFaces, i)
00459         {
00460             bndFaces[i] = mesh_.nInternalFaces() + i;
00461         }
00462 
00463         treeBoundBox overallBb(mesh_.points());
00464         Random rndGen(123456);
00465         overallBb = overallBb.extend(rndGen, 1E-4);
00466         overallBb.min() -= point(ROOTVSMALL, ROOTVSMALL, ROOTVSMALL);
00467         overallBb.max() += point(ROOTVSMALL, ROOTVSMALL, ROOTVSMALL);
00468 
00469         boundaryTreePtr_ = new indexedOctree<treeDataFace>
00470         (
00471             treeDataFace    // all information needed to search faces
00472             (
00473                 false,                      // do not cache bb
00474                 mesh_,
00475                 bndFaces                    // boundary faces only
00476             ),
00477             overallBb,                      // overall search domain
00478             8,                              // maxLevel
00479             10,                             // leafsize
00480             3.0                             // duplicity
00481         );
00482     }
00483 
00484     return *boundaryTreePtr_;
00485 }
00486 
00487 
00488 const Foam::indexedOctree<Foam::treeDataCell>& Foam::meshSearch::cellTree()
00489  const
00490 {
00491     if (!cellTreePtr_)
00492     {
00493         //
00494         // Construct tree
00495         //
00496 
00497         treeBoundBox overallBb(mesh_.points());
00498         Random rndGen(123456);
00499         overallBb = overallBb.extend(rndGen, 1E-4);
00500         overallBb.min() -= point(ROOTVSMALL, ROOTVSMALL, ROOTVSMALL);
00501         overallBb.max() += point(ROOTVSMALL, ROOTVSMALL, ROOTVSMALL);
00502 
00503         cellTreePtr_ = new indexedOctree<treeDataCell>
00504         (
00505             treeDataCell
00506             (
00507                 false,  // not cache bb
00508                 mesh_
00509             ),
00510             overallBb,  // overall search domain
00511             8,      // maxLevel
00512             10,     // leafsize
00513             3.0     // duplicity
00514         );
00515     }
00516 
00517     return *cellTreePtr_;
00518     
00519 }
00520 
00521 
00522 const Foam::indexedOctree<Foam::treeDataPoint>&
00523  Foam::meshSearch::cellCentreTree() const
00524 {
00525     if (!cellCentreTreePtr_)
00526     {
00527         //
00528         // Construct tree
00529         //
00530 
00531         treeBoundBox overallBb(mesh_.cellCentres());
00532         Random rndGen(123456);
00533         overallBb = overallBb.extend(rndGen, 1E-4);
00534         overallBb.min() -= point(ROOTVSMALL, ROOTVSMALL, ROOTVSMALL);
00535         overallBb.max() += point(ROOTVSMALL, ROOTVSMALL, ROOTVSMALL);
00536 
00537         cellCentreTreePtr_ = new indexedOctree<treeDataPoint>
00538         (
00539             treeDataPoint(mesh_.cellCentres()),
00540             overallBb,  // overall search domain
00541             10,         // max levels
00542             10.0,       // maximum ratio of cubes v.s. cells
00543             100.0       // max. duplicity; n/a since no bounding boxes.
00544         );
00545     }
00546 
00547     return *cellCentreTreePtr_;
00548 }
00549 
00550 
00551 // Is the point in the cell
00552 // Works by checking if there is a face inbetween the point and the cell
00553 // centre.
00554 // Check for internal uses proper face decomposition or just average normal.
00555 bool Foam::meshSearch::pointInCell(const point& p, label cellI) const
00556 {
00557     if (faceDecomp_)
00558     {
00559         const point& ctr = mesh_.cellCentres()[cellI];
00560 
00561         vector dir(p - ctr);
00562         scalar magDir = mag(dir);
00563 
00564         // Check if any faces are hit by ray from cell centre to p.
00565         // If none -> p is in cell.
00566         const labelList& cFaces = mesh_.cells()[cellI];
00567 
00568         // Make sure half_ray does not pick up any faces on the wrong
00569         // side of the ray.
00570         scalar oldTol = intersection::setPlanarTol(0.0);
00571 
00572         forAll(cFaces, i)
00573         {
00574             label faceI = cFaces[i];
00575 
00576             pointHit inter = mesh_.faces()[faceI].ray
00577             (
00578                 ctr,
00579                 dir,
00580                 mesh_.points(),
00581                 intersection::HALF_RAY,
00582                 intersection::VECTOR
00583             );
00584 
00585             if (inter.hit())
00586             {
00587                 scalar dist = inter.distance();
00588 
00589                 if (dist < magDir)
00590                 {
00591                     // Valid hit. Hit face so point is not in cell.
00592                     intersection::setPlanarTol(oldTol);
00593 
00594                     return false;
00595                 }
00596             }
00597         }
00598 
00599         intersection::setPlanarTol(oldTol);
00600 
00601         // No face inbetween point and cell centre so point is inside.
00602         return true;
00603     }
00604     else
00605     {
00606         const labelList& f = mesh_.cells()[cellI];
00607         const labelList& owner = mesh_.faceOwner();
00608         const vectorField& cf = mesh_.faceCentres();
00609         const vectorField& Sf = mesh_.faceAreas();
00610 
00611         forAll(f, facei)
00612         {
00613             label nFace = f[facei];
00614             vector proj = p - cf[nFace];
00615             vector normal = Sf[nFace];
00616             if (owner[nFace] == cellI)
00617             {
00618                 if ((normal & proj) > 0)
00619                 {
00620                     return false;
00621                 }
00622             }
00623             else
00624             {
00625                 if ((normal & proj) < 0)
00626                 {
00627                     return false;
00628                 }
00629             }
00630         }
00631 
00632         return true;
00633     }
00634 }
00635 
00636 
00637 Foam::label Foam::meshSearch::findNearestCell
00638 (
00639     const point& location,
00640     const label seedCellI,
00641     const bool useTreeSearch
00642 ) const
00643 {
00644     if (seedCellI == -1)
00645     {
00646         if (useTreeSearch)
00647         {
00648             return findNearestCellTree(location);
00649         }
00650         else
00651         {
00652             return findNearestCellLinear(location);
00653         }
00654     }
00655     else
00656     {
00657         return findNearestCellWalk(location, seedCellI);
00658     }
00659 }
00660 
00661 
00662 Foam::label Foam::meshSearch::findNearestFace
00663 (
00664     const point& location,
00665     const label seedFaceI,
00666     const bool useTreeSearch
00667 ) const
00668 {
00669     if (seedFaceI == -1)
00670     {
00671         if (useTreeSearch)
00672         {
00673             return findNearestFaceTree(location);
00674         }
00675         else
00676         {
00677             return findNearestFaceLinear(location);
00678         }
00679     }
00680     else
00681     {
00682         return findNearestFaceWalk(location, seedFaceI);
00683     }
00684 }
00685 
00686 
00687 Foam::label Foam::meshSearch::findCell
00688 (
00689     const point& location,
00690     const label seedCellI,
00691     const bool useTreeSearch
00692 ) const
00693 {
00694     // Find the nearest cell centre to this location
00695     label nearCellI = findNearestCell(location, seedCellI, useTreeSearch);
00696 
00697     if (debug)
00698     {
00699         Pout<< "findCell : nearCellI:" << nearCellI
00700             << " ctr:" << mesh_.cellCentres()[nearCellI]
00701             << endl;
00702     }
00703 
00704     if (pointInCell(location, nearCellI))
00705     {
00706         return nearCellI;
00707     }
00708     else
00709     {
00710         if (useTreeSearch)
00711         {
00712             // Start searching from cell centre of nearCell
00713             point curPoint = mesh_.cellCentres()[nearCellI];
00714 
00715             vector edgeVec = location - curPoint;
00716             edgeVec /= mag(edgeVec);
00717 
00718             do
00719             {
00720                 // Walk neighbours (using tracking) to get closer
00721                 passiveParticle tracker(cloud_, curPoint, nearCellI);
00722 
00723                 if (debug)
00724                 {
00725                     Pout<< "findCell : tracked from curPoint:" << curPoint
00726                         << " nearCellI:" << nearCellI;
00727                 }
00728 
00729                 tracker.track(location);
00730 
00731                 if (debug)
00732                 {
00733                     Pout<< " to " << tracker.position()
00734                         << " need:" << location
00735                         << " onB:" << tracker.onBoundary()
00736                         << " cell:" << tracker.cell()
00737                         << " face:" << tracker.face() << endl;
00738                 }
00739 
00740                 if (!tracker.onBoundary())
00741                 {
00742                     // stopped not on boundary -> reached location
00743                     return tracker.cell();
00744                 }
00745 
00746                 // stopped on boundary face. Compare positions
00747                 scalar typDim = sqrt(mag(mesh_.faceAreas()[tracker.face()]));
00748 
00749                 if ((mag(tracker.position() - location)/typDim) < SMALL)
00750                 {
00751                     return tracker.cell();
00752                 }
00753 
00754                 // tracking stopped at boundary. Find next boundary
00755                 // intersection from current point (shifted out a little bit)
00756                 // in the direction of the destination
00757 
00758                 curPoint =
00759                     tracker.position()
00760                   + offset(tracker.position(), tracker.face(), edgeVec);
00761 
00762                 if (debug)
00763                 {
00764                     Pout<< "Searching for next boundary from curPoint:"
00765                         << curPoint
00766                         << " to location:" << location  << endl;
00767                 }
00768                 pointIndexHit curHit = intersection(curPoint, location);
00769                 if (debug)
00770                 {
00771                     Pout<< "Returned from line search with ";
00772                     curHit.write(Pout);
00773                     Pout<< endl;
00774                 }
00775 
00776                 if (!curHit.hit())
00777                 {
00778                     return -1;
00779                 }
00780                 else
00781                 {
00782                     nearCellI = mesh_.faceOwner()[curHit.index()];
00783                     curPoint =
00784                         curHit.hitPoint() 
00785                       + offset(curHit.hitPoint(), curHit.index(), edgeVec);
00786                 }
00787             }
00788             while(true);
00789         }
00790         else
00791         {
00792              return findCellLinear(location);
00793         }
00794     }
00795     return -1;
00796 }
00797 
00798 
00799 Foam::label Foam::meshSearch::findNearestBoundaryFace
00800 (
00801     const point& location,
00802     const label seedFaceI,
00803     const bool useTreeSearch
00804 ) const
00805 {
00806     if (seedFaceI == -1)
00807     {
00808         if (useTreeSearch)
00809         {
00810             const indexedOctree<treeDataFace>& tree =  boundaryTree();
00811 
00812             scalar span = tree.bb().mag();
00813 
00814             pointIndexHit info = boundaryTree().findNearest
00815             (
00816                 location,
00817                 Foam::sqr(span)
00818             );
00819 
00820             if (!info.hit())
00821             {
00822                 info = boundaryTree().findNearest
00823                 (
00824                     location,
00825                     Foam::sqr(GREAT)
00826                 );
00827             }
00828 
00829             return tree.shapes().faceLabels()[info.index()];
00830         }
00831         else
00832         {
00833             scalar minDist = GREAT;
00834 
00835             label minFaceI = -1;
00836 
00837             for
00838             (
00839                 label faceI = mesh_.nInternalFaces();
00840                 faceI < mesh_.nFaces();
00841                 faceI++
00842             )
00843             {
00844                 const face& f =  mesh_.faces()[faceI];
00845 
00846                 pointHit curHit =
00847                     f.nearestPoint
00848                     (
00849                         location,
00850                         mesh_.points()
00851                     );
00852 
00853                 if (curHit.distance() < minDist)
00854                 {
00855                     minDist = curHit.distance();
00856                     minFaceI = faceI;
00857                 }
00858             }
00859             return minFaceI;
00860         }
00861     }
00862     else
00863     {
00864         return findNearestBoundaryFaceWalk(location, seedFaceI);
00865     }
00866 }
00867 
00868 
00869 Foam::pointIndexHit Foam::meshSearch::intersection
00870 (
00871     const point& pStart,
00872     const point& pEnd
00873 ) const
00874 {
00875     pointIndexHit curHit = boundaryTree().findLine(pStart, pEnd);
00876 
00877     if (curHit.hit())
00878     {
00879         // Change index into octreeData into face label
00880         curHit.setIndex(boundaryTree().shapes().faceLabels()[curHit.index()]);
00881     }
00882     return curHit;
00883 }
00884 
00885 
00886 Foam::List<Foam::pointIndexHit> Foam::meshSearch::intersections
00887 (
00888     const point& pStart,
00889     const point& pEnd
00890 ) const
00891 {
00892     DynamicList<pointIndexHit> hits;
00893 
00894     vector edgeVec = pEnd - pStart;
00895     edgeVec /= mag(edgeVec);
00896 
00897     point pt = pStart;
00898 
00899     pointIndexHit bHit;
00900     do
00901     {
00902         bHit = intersection(pt, pEnd);
00903 
00904         if (bHit.hit())
00905         {
00906             hits.append(bHit);
00907 
00908             const vector& area = mesh_.faceAreas()[bHit.index()];
00909 
00910             scalar typDim = Foam::sqrt(mag(area));
00911 
00912             if ((mag(bHit.hitPoint() - pEnd)/typDim) < SMALL)
00913             {
00914                 break;
00915             }
00916 
00917             // Restart from hitPoint shifted a little bit in the direction
00918             // of the destination
00919 
00920             pt =
00921                 bHit.hitPoint()
00922               + offset(bHit.hitPoint(), bHit.index(), edgeVec);
00923         }
00924 
00925     } while(bHit.hit());
00926 
00927 
00928     hits.shrink();
00929 
00930     return hits;
00931 }
00932 
00933 
00934 bool Foam::meshSearch::isInside(const point& p) const
00935 {
00936     return
00937         boundaryTree().getVolumeType(p)
00938      == indexedOctree<treeDataFace>::INSIDE;
00939 }
00940 
00941 
00942 // Delete all storage
00943 void Foam::meshSearch::clearOut()
00944 {
00945     deleteDemandDrivenData(boundaryTreePtr_);
00946     deleteDemandDrivenData(cellTreePtr_);
00947     deleteDemandDrivenData(cellCentreTreePtr_);
00948 }
00949 
00950 
00951 void Foam::meshSearch::correct()
00952 {
00953     clearOut();
00954 }
00955 
00956 
00957 // ************************ vim: set sw=4 sts=4 et: ************************ //
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines