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

surfaceCoarsen.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     surfaceCoarsen
00026 
00027 Description
00028     Surface coarsening using 'bunnylod'.
00029 
00030     Polygon Reduction Demo
00031     By Stan Melax (c) 1998
00032     mailto:melax@cs.ualberta.ca
00033     http://www.cs.ualberta.ca/~melax
00034 
00035 
00036 Usage
00037 
00038     - surfaceCoarsen [OPTIONS] <Foam surface file> <factor> <Foam output surface file>
00039 
00040     @param <Foam surface file> \n
00041     @todo Detailed description of argument.
00042 
00043     @param <factor> \n
00044     @todo Detailed description of argument.
00045 
00046     @param <Foam output surface file> \n
00047     @todo Detailed description of argument.
00048 
00049     @param -case <dir>\n
00050     Case directory.
00051 
00052     @param -help \n
00053     Display help message.
00054 
00055     @param -doc \n
00056     Display Doxygen API documentation page for this application.
00057 
00058     @param -srcDoc \n
00059     Display Doxygen source documentation page for this application.
00060 
00061 \*---------------------------------------------------------------------------*/
00062 
00063 #include <OpenFOAM/argList.H>
00064 #include <OpenFOAM/fileName.H>
00065 #include <triSurface/triSurface.H>
00066 #include <OpenFOAM/OFstream.H>
00067 #include <OpenFOAM/triFace.H>
00068 #include <OpenFOAM/triFaceList.H>
00069 
00070 // From bunnylod
00071 #include "bunnylod/progmesh.h"
00072 
00073 using namespace Foam;
00074 
00075 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
00076 
00077 int mapVertex(::List<int>& collapse_map, int a, int mx)
00078 {
00079     if (mx <= 0)
00080     {
00081         return 0;
00082     }
00083     while (a >= mx)
00084     {  
00085     a = collapse_map[a];
00086     }
00087     return a;
00088 }
00089 
00090 
00091 // Main program:
00092 
00093 int main(int argc, char *argv[])
00094 {
00095     argList::noParallel();
00096     argList::validArgs.clear();
00097     argList::validArgs.append("Foam surface file");
00098     argList::validArgs.append("reduction factor");
00099     argList::validArgs.append("Foam output file");
00100     argList args(argc, argv);
00101 
00102     fileName inFileName(args.additionalArgs()[0]);
00103 
00104     scalar reduction(readScalar(IStringStream(args.additionalArgs()[1])()));
00105 
00106     if (reduction <= 0 || reduction > 1)
00107     {
00108         FatalErrorIn(args.executable())
00109             << "Reduction factor " << reduction
00110             << " should be within 0..1" << endl
00111             << "(it is the reduction in number of vertices)"
00112             << exit(FatalError);
00113     }
00114 
00115     fileName outFileName(args.additionalArgs()[2]);
00116 
00117     Info<< "Input surface   :" << inFileName << endl
00118         << "Reduction factor:" << reduction << endl
00119         << "Output surface  :" << outFileName << endl << endl;
00120 
00121     const triSurface surf(inFileName);
00122 
00123     Info<< "Surface:" << endl;
00124     surf.writeStats(Info);
00125     Info<< endl;
00126 
00127 
00128     ::List< ::Vector> vert;     // global list of vertices
00129     ::List< ::tridata> tri;     // global list of triangles
00130 
00131 
00132     // Convert triSurface to progmesh format. Note: can use global point
00133     // numbering since surface read in from file.
00134     const pointField& pts = surf.points();
00135 
00136     forAll(pts, ptI)
00137     {
00138         const point& pt = pts[ptI];
00139 
00140         vert.Add( ::Vector(pt.x(), pt.y(), pt.z()));
00141     }
00142 
00143     forAll(surf, faceI)
00144     {
00145         const labelledTri& f = surf[faceI];
00146 
00147         tridata td;
00148         td.v[0]=f[0];
00149         td.v[1]=f[1];
00150         td.v[2]=f[2];
00151         tri.Add(td);
00152     }        
00153 
00154     ::List<int> collapse_map;   // to which neighbor each vertex collapses
00155     ::List<int> permutation;
00156 
00157     ::ProgressiveMesh(vert,tri,collapse_map,permutation);
00158 
00159     // rearrange the vertex list 
00160     ::List< ::Vector> temp_list;
00161     for(int i=0;i<vert.num;i++)
00162     {
00163         temp_list.Add(vert[i]);
00164     }
00165     for(int i=0;i<vert.num;i++)
00166     {
00167         vert[permutation[i]]=temp_list[i];
00168     }
00169 
00170     // update the changes in the entries in the triangle list
00171     for(int i=0;i<tri.num;i++)
00172     {
00173         for(int j=0;j<3;j++)
00174         {
00175             tri[i].v[j] = permutation[tri[i].v[j]];
00176         }
00177     }
00178 
00179     // Only get triangles with non-collapsed edges.
00180     int render_num = int(reduction * surf.nPoints());
00181 
00182     Info<< "Reducing to " << render_num << " vertices" << endl;
00183 
00184 
00185     // Storage for new surface.
00186     Foam::List<labelledTri> newTris(surf.size());
00187 
00188     label newI = 0;
00189 
00190     for (int i=0; i<tri.num; i++)
00191     {
00192         int p0 = mapVertex(collapse_map, tri[i].v[0], render_num);
00193         int p1 = mapVertex(collapse_map, tri[i].v[1], render_num);
00194         int p2 = mapVertex(collapse_map, tri[i].v[2], render_num);
00195 
00196         // note:  serious optimization opportunity here,
00197         //  by sorting the triangles the following "continue" 
00198         //  could have been made into a "break" statement.
00199         if (p0 == p1 || p1 == p2 || p2 == p0)
00200         {
00201             continue;
00202         }
00203 
00204         newTris[newI++] = labelledTri(p0, p1, p2, 0);
00205     }
00206     newTris.setSize(newI);
00207 
00208     // Convert vert into pointField.
00209     pointField newPoints(vert.num);
00210 
00211     for(int i=0; i<vert.num; i++)
00212     {
00213         const ::Vector & v = vert[i];
00214 
00215         newPoints[i] = point(v.x, v.y, v.z);
00216     }
00217 
00218     triSurface surf2(newTris, newPoints);
00219 
00220     triSurface outSurf
00221     (
00222         surf2.localFaces(),
00223         surf2.patches(),
00224         surf2.localPoints()
00225     );
00226 
00227     Info<< "Coarsened surface:" << endl;
00228     surf2.writeStats(Info);
00229     Info<< endl;
00230 
00231     Info<< "Writing to file " << outFileName << endl << endl;
00232 
00233     surf2.write(outFileName);
00234 
00235     Info << "End\n" << endl;
00236 
00237     return 0;
00238 }
00239 
00240 
00241 // ************************ vim: set sw=4 sts=4 et: ************************ //
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines