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

surfaceFeatureExtract.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     surfaceFeatureExtract
00026 
00027 Description
00028     Extracts and writes surface features to file
00029 
00030 Usage
00031 
00032     - surfaceFeatureExtract [OPTIONS] <Foam surface file> <output set>
00033 
00034     @param <Foam surface file> \n
00035     @todo Detailed description of argument.
00036 
00037     @param <output set> \n
00038     @todo Detailed description of argument.
00039 
00040     @param -minLen \n
00041     Minimum cumulative length of feature.
00042 
00043     @param -includedAngle <included angle [0..180]>\n
00044     Construct set from included angle.
00045 
00046     @param -deleteBox <((x0 y0 z0)(x1 y1 z1))>\n
00047     Delete axis-aligned box.
00048 
00049     @param -minElem \n
00050     Minimum number of edges in feature.
00051 
00052     @param -subsetBox <((x0 y0 z0)(x1 y1 z1))>\n
00053     Extract all edges in axis-aligned box.
00054 
00055     @param -set <input feature set>\n
00056     Use existing set.
00057 
00058     @param -case <dir>\n
00059     Case directory.
00060 
00061     @param -help \n
00062     Display help message.
00063 
00064     @param -doc \n
00065     Display Doxygen API documentation page for this application.
00066 
00067     @param -srcDoc \n
00068     Display Doxygen source documentation page for this application.
00069 
00070 \*---------------------------------------------------------------------------*/
00071 
00072 #include <OpenFOAM/triangle.H>
00073 #include <triSurface/triSurface.H>
00074 #include <OpenFOAM/argList.H>
00075 #include <meshTools/surfaceFeatures.H>
00076 #include <meshTools/treeBoundBox.H>
00077 #include <meshTools/meshTools.H>
00078 #include <OpenFOAM/OFstream.H>
00079 
00080 using namespace Foam;
00081 
00082 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
00083 
00084 void dumpBox(const treeBoundBox& bb, const fileName& fName)
00085 {
00086     OFstream str(fName);
00087 
00088     Pout<< "Dumping bounding box " << bb << " as lines to obj file "
00089         << str.name() << endl;
00090 
00091 
00092     pointField boxPoints(bb.points());
00093 
00094     forAll(boxPoints, i)
00095     {
00096         meshTools::writeOBJ(str, boxPoints[i]);
00097     }
00098 
00099     forAll(treeBoundBox::edges, i)
00100     {
00101         const edge& e = treeBoundBox::edges[i];
00102 
00103         str<< "l " << e[0]+1 <<  ' ' << e[1]+1 << nl;
00104     }
00105 }
00106 
00107 
00108 // Deletes all edges inside/outside bounding box from set.
00109 void deleteBox
00110 (
00111     const triSurface& surf,
00112     const treeBoundBox& bb,
00113     const bool removeInside,
00114     List<surfaceFeatures::edgeStatus>& edgeStat
00115 )
00116 {
00117     forAll(edgeStat, edgeI)
00118     {
00119         const point eMid = surf.edges()[edgeI].centre(surf.localPoints());
00120 
00121         if
00122         (
00123             (removeInside && bb.contains(eMid))
00124          || (!removeInside && !bb.contains(eMid))
00125         )
00126         {
00127             edgeStat[edgeI] = surfaceFeatures::NONE;
00128         }
00129     }
00130 }
00131 
00132 
00133 // Main program:
00134 
00135 int main(int argc, char *argv[])
00136 {
00137     argList::noParallel();
00138 
00139     argList::validArgs.clear();
00140     argList::validArgs.append("surface");
00141     argList::validArgs.append("output set");
00142 
00143     argList::validOptions.insert("includedAngle", "included angle [0..180]");
00144     argList::validOptions.insert("set", "input feature set");
00145 
00146     argList::validOptions.insert("minLen", "cumulative length of feature");
00147     argList::validOptions.insert("minElem", "number of edges in feature");
00148     argList::validOptions.insert("subsetBox", "((x0 y0 z0)(x1 y1 z1))");
00149     argList::validOptions.insert("deleteBox", "((x0 y0 z0)(x1 y1 z1))");
00150     argList args(argc, argv);
00151 
00152     Pout<< "Feature line extraction is only valid on closed manifold surfaces."
00153         << endl;
00154 
00155 
00156     fileName surfFileName(args.additionalArgs()[0]);
00157     fileName outFileName(args.additionalArgs()[1]);
00158 
00159     Pout<< "Surface            : " << surfFileName << nl
00160         << "Output feature set : " << outFileName << nl
00161         << endl;
00162 
00163 
00164     // Read
00165     // ~~~~
00166 
00167     triSurface surf(surfFileName);
00168 
00169     Pout<< "Statistics:" << endl;
00170     surf.writeStats(Pout);
00171     Pout<< endl;
00172 
00173 
00174 
00175 
00176     // Either construct features from surface&featureangle or read set.
00177     // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
00178 
00179     surfaceFeatures set(surf);
00180 
00181     if (args.optionFound("set"))
00182     {
00183         fileName setName(args.option("set"));
00184 
00185         Pout<< "Reading existing feature set from file " << setName << endl;
00186 
00187         set = surfaceFeatures(surf, setName);
00188     }
00189     else if (args.optionFound("includedAngle"))
00190     {
00191         scalar includedAngle = args.optionRead<scalar>("includedAngle");
00192 
00193         Pout<< "Constructing feature set from included angle " << includedAngle
00194             << endl;
00195 
00196         set = surfaceFeatures(surf, includedAngle);
00197 
00198         Pout<< endl << "Writing initial features" << endl;
00199         set.write("initial.fSet");
00200         set.writeObj("initial");
00201     }
00202     else
00203     {
00204         FatalErrorIn(args.executable())
00205             << "No initial feature set. Provide either one"
00206             << " of -set (to read existing set)" << nl
00207             << " or -includedAngle (to new set construct from angle)"
00208             << exit(FatalError);
00209     }
00210 
00211 
00212     Pout<< nl
00213         << "Initial feature set:" << nl
00214         << "    feature points : " << set.featurePoints().size() << nl
00215         << "    feature edges  : " << set.featureEdges().size() << nl
00216         << "    of which" << nl
00217         << "        region edges   : " << set.nRegionEdges() << nl
00218         << "        external edges : " << set.nExternalEdges() << nl
00219         << "        internal edges : " << set.nInternalEdges() << nl
00220         << endl;
00221 
00222 
00223 
00224 
00225     // Trim set
00226     // ~~~~~~~~
00227 
00228     scalar minLen = -GREAT;
00229     if (args.optionReadIfPresent("minLen", minLen))
00230     {
00231         Pout<< "Removing features of length < " << minLen << endl;
00232     }
00233 
00234     label minElem = 0;
00235     if (args.optionReadIfPresent("minElem", minElem))
00236     {
00237         Pout<< "Removing features with number of edges < " << minElem << endl;
00238     }
00239 
00240     // Trim away small groups of features
00241     if (minLen > 0 || minLen > 0)
00242     {
00243         set.trimFeatures(minLen, minElem);
00244         Pout<< endl << "Removed small features" << endl;
00245     }
00246 
00247 
00248 
00249     // Subset
00250     // ~~~~~~
00251 
00252     // Convert to marked edges, points
00253     List<surfaceFeatures::edgeStatus> edgeStat(set.toStatus());
00254 
00255     if (args.optionFound("subsetBox"))
00256     {
00257         treeBoundBox bb(args.optionLookup("subsetBox")());
00258 
00259         Pout<< "Removing all edges outside bb " << bb << endl;
00260         dumpBox(bb, "subsetBox.obj");
00261 
00262         deleteBox
00263         (
00264             surf,
00265             bb,
00266             false,
00267             edgeStat
00268         );
00269     }
00270     else if (args.optionFound("deleteBox"))
00271     {
00272         treeBoundBox bb(args.optionLookup("deleteBox")());
00273 
00274         Pout<< "Removing all edges inside bb " << bb << endl;
00275         dumpBox(bb, "deleteBox.obj");
00276 
00277         deleteBox
00278         (
00279             surf,
00280             bb,
00281             true,
00282             edgeStat
00283         );
00284     }
00285 
00286     surfaceFeatures newSet(surf);
00287     newSet.setFromStatus(edgeStat);
00288 
00289     Pout<< endl << "Writing trimmed features to " << outFileName << endl;
00290     newSet.write(outFileName);
00291 
00292     Pout<< endl << "Writing edge objs." << endl;
00293     newSet.writeObj("final");
00294 
00295 
00296     Pout<< nl
00297         << "Final feature set:" << nl
00298         << "    feature points : " << newSet.featurePoints().size() << nl
00299         << "    feature edges  : " << newSet.featureEdges().size() << nl
00300         << "    of which" << nl
00301         << "        region edges   : " << newSet.nRegionEdges() << nl
00302         << "        external edges : " << newSet.nExternalEdges() << nl
00303         << "        internal edges : " << newSet.nInternalEdges() << nl
00304         << endl;
00305 
00306     Pout<< "End\n" << endl;
00307 
00308     return 0;
00309 }
00310 
00311 
00312 // ************************ vim: set sw=4 sts=4 et: ************************ //
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines