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

surfaceSubset.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 Application
00025     surfaceSubset
00026 
00027 Description
00028     A surface analysis tool which sub-sets the triSurface
00029     to choose only a part of interest.
00030 
00031     Based on subsetMesh.
00032 
00033 Usage
00034 
00035     - surfaceSubset [OPTIONS] <surfaceSubsetDic> <Foam surface file> <Foam output surface file>
00036 
00037     @param <surfaceSubsetDic> \n
00038     @todo Detailed description of argument.
00039 
00040     @param <Foam surface file> \n
00041     @todo Detailed description of argument.
00042 
00043     @param <Foam output surface file> \n
00044     @todo Detailed description of argument.
00045 
00046     @param -case <dir>\n
00047     Case directory.
00048 
00049     @param -help \n
00050     Display help message.
00051 
00052     @param -doc \n
00053     Display Doxygen API documentation page for this application.
00054 
00055     @param -srcDoc \n
00056     Display Doxygen source documentation page for this application.
00057 
00058 \*---------------------------------------------------------------------------*/
00059 
00060 #include <triSurface/triSurface.H>
00061 #include <OpenFOAM/argList.H>
00062 #include <OpenFOAM/OFstream.H>
00063 #include <OpenFOAM/IFstream.H>
00064 #include <OpenFOAM/Switch.H>
00065 #include <OpenFOAM/IOdictionary.H>
00066 #include <OpenFOAM/boundBox.H>
00067 #include <meshTools/indexedOctree.H>
00068 #include <meshTools/octree.H>
00069 #include <meshTools/treeDataTriSurface.H>
00070 #include <OpenFOAM/Random.H>
00071 
00072 using namespace Foam;
00073 
00074 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
00075 // Main program:
00076 
00077 int main(int argc, char *argv[])
00078 {
00079     argList::noParallel();
00080     argList::validArgs.clear();
00081     argList::validArgs.append("surfaceSubsetDict");
00082     argList::validArgs.append("surface file");
00083     argList::validArgs.append("output file");
00084     argList args(argc, argv);
00085 
00086     Info<< "Reading dictionary " << args.additionalArgs()[0] << " ..." << endl;
00087     IFstream dictFile(args.additionalArgs()[0]);
00088     dictionary meshSubsetDict(dictFile);
00089 
00090     Info<< "Reading surface " << args.additionalArgs()[1] << " ..." << endl;
00091     triSurface surf1(args.additionalArgs()[1]);
00092 
00093     Info<< "Original:" << endl;
00094     surf1.writeStats(Info);
00095     Info<< endl;
00096 
00097 
00098     labelList markedPoints
00099     (
00100         meshSubsetDict.lookup("localPoints")
00101     );
00102 
00103     labelList markedEdges
00104     (
00105         meshSubsetDict.lookup("edges")
00106     );
00107 
00108     labelList markedFaces
00109     (
00110         meshSubsetDict.lookup("faces")
00111     );
00112 
00113     pointField markedZone
00114     (
00115         meshSubsetDict.lookup("zone")
00116     );
00117 
00118     if (markedZone.size() && markedZone.size() != 2)
00119     {
00120         FatalErrorIn(args.executable())
00121             << "zone specification should be two points, min and max of "
00122             << "the boundingbox" << endl
00123             << "zone:" << markedZone
00124             << exit(FatalError);
00125     }
00126 
00127     Switch addFaceNeighbours
00128     (
00129         meshSubsetDict.lookup("addFaceNeighbours")
00130     );
00131 
00132     Switch invertSelection
00133     (
00134         meshSubsetDict.lookup("invertSelection")
00135     );
00136 
00137     // Mark the cells for the subset
00138 
00139     // Faces to subset
00140     boolList facesToSubset(surf1.size(), false);
00141 
00142 
00143     //
00144     // pick up faces connected to "localPoints"
00145     //
00146 
00147     if (markedPoints.size())
00148     {
00149         Info << "Found " << markedPoints.size() << " marked point(s)." << endl;
00150 
00151         // pick up cells sharing the point
00152 
00153         forAll (markedPoints, pointI)
00154         {
00155             if
00156             (
00157                 markedPoints[pointI] < 0
00158              || markedPoints[pointI] >= surf1.nPoints()
00159             )
00160             {
00161                 FatalErrorIn(args.executable())
00162                     << "localPoint label " << markedPoints[pointI]
00163                     << "out of range."
00164                     << " The mesh has got "
00165                     << surf1.nPoints() << " localPoints."
00166                     << exit(FatalError);
00167             }
00168 
00169             const labelList& curFaces =
00170                 surf1.pointFaces()[markedPoints[pointI]];
00171 
00172             forAll (curFaces, i)
00173             {
00174                 facesToSubset[curFaces[i]] =  true;
00175             }
00176         }
00177     }
00178 
00179 
00180 
00181     //
00182     // pick up faces connected to "edges"
00183     //
00184 
00185     if (markedEdges.size())
00186     {
00187         Info << "Found " << markedEdges.size() << " marked edge(s)." << endl;
00188 
00189         // pick up cells sharing the edge
00190 
00191         forAll (markedEdges, edgeI)
00192         {
00193             if
00194             (
00195                 markedEdges[edgeI] < 0
00196              || markedEdges[edgeI] >= surf1.nEdges()
00197             )
00198             {
00199                 FatalErrorIn(args.executable())
00200                     << "edge label " << markedEdges[edgeI]
00201                     << "out of range."
00202                     << " The mesh has got "
00203                     << surf1.nEdges() << " edges."
00204                     << exit(FatalError);
00205             }
00206 
00207             const labelList& curFaces = surf1.edgeFaces()[markedEdges[edgeI]];
00208 
00209             forAll (curFaces, i)
00210             {
00211                 facesToSubset[curFaces[i]] =  true;
00212             }
00213         }
00214     }
00215 
00216 
00217     //
00218     // pick up faces with centre inside "zone"
00219     //
00220 
00221     if (markedZone.size() == 2)
00222     {
00223         const point& min = markedZone[0];
00224         const point& max = markedZone[1];
00225 
00226         Info << "Using zone min:" << min << " max:" << max << endl;
00227 
00228         forAll(surf1, faceI)
00229         {
00230             const labelledTri& f = surf1[faceI];
00231             const point centre = f.centre(surf1.points());
00232 
00233             if
00234             (
00235                 (centre.x() >= min.x())
00236              && (centre.y() >= min.y())
00237              && (centre.z() >= min.z())
00238              && (centre.x() <= max.x())
00239              && (centre.y() <= max.y())
00240              && (centre.z() <= max.z())
00241             )
00242             {
00243                 facesToSubset[faceI] = true;
00244             }
00245         }
00246     }
00247 
00248 
00249     //
00250     // pick up faces on certain side of surface
00251     //
00252 
00253     if (meshSubsetDict.found("surface"))
00254     {
00255         const dictionary& surfDict = meshSubsetDict.subDict("surface");
00256 
00257         fileName surfName(surfDict.lookup("name"));
00258 
00259         Switch outside(surfDict.lookup("outside"));
00260 
00261         if (outside)
00262         {
00263             Info<< "Selecting all triangles with centre outside surface "
00264                 << surfName << endl;
00265         }
00266         else
00267         {
00268             Info<< "Selecting all triangles with centre inside surface "
00269                 << surfName << endl;
00270         }
00271 
00272         // Read surface to select on
00273         triSurface selectSurf(surfName);
00274 
00275         // bb of surface
00276         treeBoundBox bb(selectSurf.localPoints());
00277 
00278         // Radnom number generator
00279         Random rndGen(354543);
00280 
00281         // search engine
00282         indexedOctree<treeDataTriSurface> selectTree
00283         (
00284             treeDataTriSurface(selectSurf),
00285             bb.extend(rndGen, 1E-4),    // slightly randomize bb
00286             8,      // maxLevel
00287             10,     // leafsize
00288             3.0     // duplicity
00289         );
00290 
00291         // Check if face (centre) is in outside or inside.
00292         forAll(facesToSubset, faceI)
00293         {
00294             if (!facesToSubset[faceI])
00295             {
00296                 const point fc(surf1[faceI].centre(surf1.points()));
00297 
00298                 indexedOctree<treeDataTriSurface>::volumeType t =
00299                     selectTree.getVolumeType(fc);
00300 
00301                 if (t == indexedOctree<treeDataTriSurface>::INSIDE && !outside)
00302                 {
00303                     facesToSubset[faceI] = true;
00304                 }
00305                 else if
00306                 (
00307                     t == indexedOctree<treeDataTriSurface>::OUTSIDE
00308                  && outside
00309                 )
00310                 {
00311                     facesToSubset[faceI] = true;
00312                 }
00313             }
00314         }
00315     }
00316 
00317 
00318     //
00319     // pick up specified "faces"
00320     //
00321 
00322     // Number of additional faces picked up because of addFaceNeighbours
00323     label nFaceNeighbours = 0;
00324 
00325     if (markedFaces.size())
00326     {
00327         Info << "Found " << markedFaces.size() << " marked face(s)." << endl;
00328 
00329         // Check and mark faces to pick up
00330         forAll (markedFaces, faceI)
00331         {
00332             if
00333             (
00334                 markedFaces[faceI] < 0
00335              || markedFaces[faceI] >= surf1.size()
00336             )
00337             {
00338                 FatalErrorIn(args.executable())
00339                     << "Face label " << markedFaces[faceI] << "out of range."
00340                     << " The mesh has got "
00341                     << surf1.size() << " faces."
00342                     << exit(FatalError);
00343             }
00344 
00345             // Mark the face
00346             facesToSubset[markedFaces[faceI]] = true;
00347 
00348             // mark its neighbours if requested
00349             if (addFaceNeighbours)
00350             {
00351                 const labelList& curFaces =
00352                     surf1.faceFaces()[markedFaces[faceI]];
00353 
00354                 forAll (curFaces, i)
00355                 {
00356                     label faceI = curFaces[i];
00357 
00358                     if (!facesToSubset[faceI])
00359                     {
00360                         facesToSubset[faceI] =  true;
00361                         nFaceNeighbours++;
00362                     }
00363                 }
00364             }
00365         }
00366     }
00367 
00368     if (addFaceNeighbours)
00369     {
00370         Info<< "Added " << nFaceNeighbours
00371             << " faces because of addFaceNeighbours" << endl;
00372     }
00373 
00374 
00375     if (invertSelection)
00376     {
00377         Info<< "Inverting selection." << endl;
00378         boolList newFacesToSubset(facesToSubset.size());
00379 
00380         forAll(facesToSubset, i)
00381         {
00382             if (facesToSubset[i])
00383             {
00384                 newFacesToSubset[i] = false;
00385             }
00386             else
00387             {
00388                 newFacesToSubset[i] = true;
00389             }
00390         }
00391         facesToSubset.transfer(newFacesToSubset);
00392     }
00393 
00394 
00395     // Create subsetted surface
00396     labelList pointMap;
00397     labelList faceMap;
00398     triSurface surf2
00399     (
00400         surf1.subsetMesh(facesToSubset, pointMap, faceMap)
00401     );
00402 
00403     Info<< "Subset:" << endl;
00404     surf2.writeStats(Info);
00405     Info << endl;
00406 
00407     fileName outFileName(args.additionalArgs()[2]);
00408 
00409     Info << "Writing surface to " << outFileName << endl;
00410 
00411     surf2.write(outFileName);
00412 
00413     return 0;
00414 }
00415 
00416 
00417 // ************************ vim: set sw=4 sts=4 et: ************************ //
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines