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

meshTriangulation.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 "meshTriangulation.H"
00027 #include <OpenFOAM/polyMesh.H>
00028 #include <triSurface/faceTriangulation.H>
00029 
00030 // * * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * //
00031 
00032 bool Foam::meshTriangulation::isInternalFace
00033 (
00034     const primitiveMesh& mesh,
00035     const boolList& includedCell,
00036     const label faceI
00037 )
00038 {
00039     if (mesh.isInternalFace(faceI))
00040     {
00041         label own = mesh.faceOwner()[faceI];
00042         label nei = mesh.faceNeighbour()[faceI];
00043 
00044         if (includedCell[own] && includedCell[nei])
00045         {
00046             // Neighbouring cell will get included in subset
00047             // as well so face is internal.
00048             return true;
00049         }
00050         else
00051         {
00052             return false;
00053         }
00054     }
00055     else
00056     {
00057         return false;
00058     }
00059 }
00060 
00061 
00062 void Foam::meshTriangulation::getFaces
00063 (
00064     const primitiveMesh& mesh,
00065     const boolList& includedCell,
00066     boolList& faceIsCut,
00067     label& nFaces,
00068     label& nInternalFaces
00069 )
00070 {    
00071     // All faces to be triangulated.     
00072     faceIsCut.setSize(mesh.nFaces());
00073     faceIsCut = false;
00074 
00075     nFaces = 0;
00076     nInternalFaces = 0;
00077     
00078     forAll(includedCell, cellI)
00079     {
00080         // Include faces of cut cells only.
00081         if (includedCell[cellI])
00082         {
00083             const labelList& cFaces = mesh.cells()[cellI];
00084 
00085             forAll(cFaces, i)
00086             {
00087                 label faceI = cFaces[i];
00088 
00089                 if (!faceIsCut[faceI])
00090                 {
00091                     // First visit of face.
00092                     nFaces++;
00093                     faceIsCut[faceI] = true;
00094 
00095                     // See if would become internal or external face
00096                     if (isInternalFace(mesh, includedCell, faceI))
00097                     {
00098                         nInternalFaces++;
00099                     }
00100                 }
00101             }
00102         }
00103     }
00104 
00105     Pout<< "Subset consists of " << nFaces << " faces out of " << mesh.nFaces()
00106         << " of which " << nInternalFaces << " are internal" << endl;
00107 }
00108 
00109 
00110 void Foam::meshTriangulation::insertTriangles
00111 (
00112     const triFaceList& faceTris,
00113     const label faceI,
00114     const label regionI,
00115     const bool reverse,
00116 
00117     List<labelledTri>& triangles,
00118     label& triI
00119 )
00120 {
00121     // Copy triangles. Optionally reverse them
00122     forAll(faceTris, i)
00123     {
00124         const triFace& f = faceTris[i];
00125 
00126         labelledTri& tri = triangles[triI];
00127 
00128         if (reverse)
00129         {
00130             tri[0] = f[0];
00131             tri[2] = f[1];
00132             tri[1] = f[2];
00133         }
00134         else
00135         {
00136             tri[0] = f[0];
00137             tri[1] = f[1];
00138             tri[2] = f[2];
00139         }
00140 
00141         tri.region() = regionI;
00142 
00143         faceMap_[triI] = faceI;
00144 
00145         triI++;
00146     }
00147 }
00148 
00149 
00150 // * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
00151 
00152 // Null constructor
00153 Foam::meshTriangulation::meshTriangulation()
00154 :
00155     triSurface(),
00156     nInternalFaces_(0),
00157     faceMap_()
00158 {}
00159 
00160 
00161 // Construct from faces of cells
00162 Foam::meshTriangulation::meshTriangulation
00163 (
00164     const polyMesh& mesh,
00165     const label internalFacesPatch,
00166     const boolList& includedCell,
00167     const bool faceCentreDecomposition
00168 )
00169 :
00170     triSurface(),
00171     nInternalFaces_(0),
00172     faceMap_()
00173 {
00174     const faceList& faces = mesh.faces();
00175     const pointField& points = mesh.points();
00176     const polyBoundaryMesh& patches = mesh.boundaryMesh();
00177 
00178     // All faces to be triangulated.     
00179     boolList faceIsCut;
00180     label nFaces, nInternalFaces;
00181 
00182     getFaces
00183     (
00184         mesh,
00185         includedCell,
00186         faceIsCut,
00187         nFaces,
00188         nInternalFaces
00189     );
00190 
00191 
00192     // Find upper limit for number of triangles
00193     // (can be less if triangulation fails)
00194     label nTotTri = 0;
00195 
00196     if (faceCentreDecomposition)
00197     {
00198         forAll(faceIsCut, faceI)
00199         {
00200             if (faceIsCut[faceI])
00201             {
00202                 nTotTri += faces[faceI].size();
00203             }
00204         }
00205     }
00206     else
00207     {
00208         forAll(faceIsCut, faceI)
00209         {
00210             if (faceIsCut[faceI])
00211             {
00212                 nTotTri += faces[faceI].nTriangles(points);
00213             }
00214         }
00215     }
00216     Pout<< "nTotTri : " << nTotTri << endl;
00217 
00218 
00219     // Storage for new and old points (only for faceCentre decomposition;
00220     // for triangulation uses only existing points)
00221     pointField newPoints;
00222 
00223     if (faceCentreDecomposition)
00224     {
00225         newPoints.setSize(mesh.nPoints() + faces.size());
00226         forAll(mesh.points(), pointI)
00227         {
00228             newPoints[pointI] = mesh.points()[pointI];
00229         }
00230         // Face centres
00231         forAll(faces, faceI)
00232         {
00233             newPoints[mesh.nPoints() + faceI] = mesh.faceCentres()[faceI];
00234         }
00235     }
00236 
00237     // Storage for all triangles
00238     List<labelledTri> triangles(nTotTri);
00239     faceMap_.setSize(nTotTri);
00240     label triI = 0;
00241 
00242 
00243     if (faceCentreDecomposition)
00244     {
00245         // Decomposition around face centre
00246         // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
00247 
00248         // Triangulate internal faces
00249         forAll(faceIsCut, faceI)
00250         {
00251             if (faceIsCut[faceI] && isInternalFace(mesh, includedCell, faceI))
00252             {
00253                 // Face was internal to the mesh and will be 'internal' to
00254                 // the surface.
00255 
00256                 // Triangulate face
00257                 const face& f = faces[faceI];
00258 
00259                 forAll(f, fp)
00260                 {
00261                     faceMap_[triI] = faceI;
00262 
00263                     triangles[triI++] =
00264                         labelledTri
00265                         (
00266                             f[fp],
00267                             f.nextLabel(fp),
00268                             mesh.nPoints() + faceI,     // face centre
00269                             internalFacesPatch
00270                         );
00271                 }
00272             }
00273         }
00274         nInternalFaces_ = triI;
00275 
00276 
00277         // Triangulate external faces
00278         forAll(faceIsCut, faceI)
00279         {
00280             if (faceIsCut[faceI] && !isInternalFace(mesh, includedCell, faceI))
00281             {
00282                 // Face will become outside of the surface.
00283 
00284                 label patchI = -1;
00285                 bool reverse = false;
00286 
00287                 if (mesh.isInternalFace(faceI))
00288                 {
00289                     patchI = internalFacesPatch;
00290 
00291                     // Check orientation. Check which side of the face gets
00292                     // included (note: only one side is).
00293                     if (includedCell[mesh.faceOwner()[faceI]])
00294                     {
00295                         reverse = false;
00296                     }
00297                     else
00298                     {
00299                         reverse = true;
00300                     }
00301                 }
00302                 else
00303                 {
00304                     // Face was already outside so orientation ok.
00305 
00306                     patchI = patches.whichPatch(faceI);
00307 
00308                     reverse = false;
00309                 }
00310 
00311 
00312                 // Triangulate face
00313                 const face& f = faces[faceI];
00314 
00315                 if (reverse)
00316                 {
00317                     forAll(f, fp)
00318                     {
00319                         faceMap_[triI] = faceI;
00320 
00321                         triangles[triI++] =
00322                             labelledTri
00323                             (
00324                                 f.nextLabel(fp),
00325                                 f[fp],
00326                                 mesh.nPoints() + faceI,     // face centre
00327                                 patchI
00328                             );
00329                     }
00330                 }
00331                 else
00332                 {
00333                     forAll(f, fp)
00334                     {
00335                         faceMap_[triI] = faceI;
00336 
00337                         triangles[triI++] =
00338                             labelledTri
00339                             (
00340                                 f[fp],
00341                                 f.nextLabel(fp),
00342                                 mesh.nPoints() + faceI,     // face centre
00343                                 patchI
00344                             );
00345                     }
00346                 }
00347             }
00348         }
00349     }
00350     else
00351     {
00352         // Triangulation using existing vertices
00353         // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
00354 
00355         // Triangulate internal faces
00356         forAll(faceIsCut, faceI)
00357         {
00358             if (faceIsCut[faceI] && isInternalFace(mesh, includedCell, faceI))
00359             {
00360                 // Face was internal to the mesh and will be 'internal' to
00361                 // the surface.
00362 
00363                 // Triangulate face. Fall back to naive triangulation if failed.
00364                 faceTriangulation faceTris(points, faces[faceI], true);
00365 
00366                 if (faceTris.empty())
00367                 {
00368                     WarningIn("meshTriangulation::meshTriangulation")
00369                         << "Could not find triangulation for face " << faceI
00370                         << " vertices " << faces[faceI] << " coords "
00371                         << IndirectList<point>(points, faces[faceI])() << endl;
00372                 }
00373                 else
00374                 {
00375                     // Copy triangles. Make them internalFacesPatch
00376                     insertTriangles
00377                     (
00378                         faceTris,
00379                         faceI,
00380                         internalFacesPatch,
00381                         false,                  // no reverse
00382 
00383                         triangles,
00384                         triI
00385                     );
00386                 }
00387             }
00388         }
00389         nInternalFaces_ = triI;
00390 
00391 
00392         // Triangulate external faces
00393         forAll(faceIsCut, faceI)
00394         {
00395             if (faceIsCut[faceI] && !isInternalFace(mesh, includedCell, faceI))
00396             {
00397                 // Face will become outside of the surface.
00398 
00399                 label patchI = -1;
00400                 bool reverse = false;
00401 
00402                 if (mesh.isInternalFace(faceI))
00403                 {
00404                     patchI = internalFacesPatch;
00405 
00406                     // Check orientation. Check which side of the face gets
00407                     // included (note: only one side is).
00408                     if (includedCell[mesh.faceOwner()[faceI]])
00409                     {
00410                         reverse = false;
00411                     }
00412                     else
00413                     {
00414                         reverse = true;
00415                     }
00416                 }
00417                 else
00418                 {
00419                     // Face was already outside so orientation ok.
00420 
00421                     patchI = patches.whichPatch(faceI);
00422 
00423                     reverse = false;
00424                 }
00425 
00426                 // Triangulate face
00427                 faceTriangulation faceTris(points, faces[faceI], true);
00428 
00429                 if (faceTris.empty())
00430                 {
00431                     WarningIn("meshTriangulation::meshTriangulation")
00432                         << "Could not find triangulation for face " << faceI
00433                         << " vertices " << faces[faceI] << " coords "
00434                         << IndirectList<point>(points, faces[faceI])() << endl;
00435                 }
00436                 else
00437                 {
00438                     // Copy triangles. Optionally reverse them
00439                     insertTriangles
00440                     (
00441                         faceTris,
00442                         faceI,
00443                         patchI,
00444                         reverse,    // whether to reverse
00445 
00446                         triangles,
00447                         triI
00448                     );
00449                 }
00450             }
00451         }
00452     }
00453 
00454     // Shrink if nessecary (because of invalid triangulations)
00455     triangles.setSize(triI);
00456     faceMap_.setSize(triI);
00457 
00458     Pout<< "nInternalFaces_:" << nInternalFaces_ << endl;
00459     Pout<< "triangles:" << triangles.size() << endl;
00460 
00461 
00462     geometricSurfacePatchList surfPatches(patches.size());
00463 
00464     forAll(patches, patchI)
00465     {
00466         surfPatches[patchI] =
00467             geometricSurfacePatch
00468             (
00469                 patches[patchI].physicalType(),
00470                 patches[patchI].name(),
00471                 patchI
00472             );
00473     }
00474 
00475     // Create globally numbered tri surface
00476     if (faceCentreDecomposition)
00477     {
00478         // Use newPoints (mesh points + face centres)
00479         triSurface globalSurf(triangles, surfPatches, newPoints);
00480 
00481         // Create locally numbered tri surface
00482         triSurface::operator=
00483         (
00484             triSurface
00485             (
00486                 globalSurf.localFaces(),
00487                 surfPatches,
00488                 globalSurf.localPoints()
00489             )
00490         );
00491     }
00492     else
00493     {
00494         // Use mesh points
00495         triSurface globalSurf(triangles, surfPatches, mesh.points());
00496 
00497         // Create locally numbered tri surface
00498         triSurface::operator=
00499         (
00500             triSurface
00501             (
00502                 globalSurf.localFaces(),
00503                 surfPatches,
00504                 globalSurf.localPoints()
00505             )
00506         );
00507     }
00508 }
00509 
00510 
00511 // ************************ vim: set sw=4 sts=4 et: ************************ //
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines