initial commit for version 1.6.x patch release
[OpenFOAM-1.6.x.git] / src / surfMesh / surfaceFormats / off / OFFsurfaceFormat.C
blobbb423f5dddcfea98fb292331492affbda5b3ff8d
1 /*---------------------------------------------------------------------------*\
2   =========                 |
3   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
4    \\    /   O peration     |
5     \\  /    A nd           | Copyright (C) 1991-2009 OpenCFD Ltd.
6      \\/     M anipulation  |
7 -------------------------------------------------------------------------------
8 License
9     This file is part of OpenFOAM.
11     OpenFOAM is free software; you can redistribute it and/or modify it
12     under the terms of the GNU General Public License as published by the
13     Free Software Foundation; either version 2 of the License, or (at your
14     option) any later version.
16     OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
17     ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18     FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
19     for more details.
21     You should have received a copy of the GNU General Public License
22     along with OpenFOAM; if not, write to the Free Software Foundation,
23     Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
25 \*---------------------------------------------------------------------------*/
27 #include "OFFsurfaceFormat.H"
28 #include "clock.H"
29 #include "IFstream.H"
30 #include "IStringStream.H"
31 #include "Ostream.H"
32 #include "OFstream.H"
34 // * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
36 template<class Face>
37 Foam::fileFormats::OFFsurfaceFormat<Face>::OFFsurfaceFormat
39     const fileName& filename
42     read(filename);
46 // * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
48 template<class Face>
49 bool Foam::fileFormats::OFFsurfaceFormat<Face>::read
51     const fileName& filename
54     const bool mustTriangulate = this->isTri();
55     this->clear();
57     IFstream is(filename);
58     if (!is.good())
59     {
60         FatalErrorIn
61         (
62             "fileFormats::OFFsurfaceFormat::read(const fileName&)"
63         )
64             << "Cannot read file " << filename
65             << exit(FatalError);
66     }
68     // Read header
69     string hdr = this->getLineNoComment(is);
70     if (hdr != "OFF")
71     {
72         FatalErrorIn
73         (
74             "fileFormats::OFFsurfaceFormat::read(const fileName&)"
75         )
76             << "OFF file " << filename << " does not start with 'OFF'"
77             << exit(FatalError);
78     }
81     // get dimensions
82     label nPoints, nElems, nEdges;
84     string line = this->getLineNoComment(is);
85     {
86         IStringStream lineStream(line);
87         lineStream >> nPoints >> nElems >> nEdges;
88     }
90     // Read points
91     pointField pointLst(nPoints);
92     forAll(pointLst, pointI)
93     {
94         scalar x, y, z;
95         line = this->getLineNoComment(is);
96         {
97             IStringStream lineStream(line);
98             lineStream >> x >> y >> z;
99         }
100         pointLst[pointI] = point(x, y, z);
101     }
103     // Read faces - ignore optional zone information
104     // use a DynamicList for possible on-the-fly triangulation
105     DynamicList<Face>  dynFaces(nElems);
107     for (label faceI = 0; faceI < nElems; ++faceI)
108     {
109         line = this->getLineNoComment(is);
111         {
112             IStringStream lineStream(line);
114             label nVerts;
115             lineStream >> nVerts;
117             List<label> verts(nVerts);
119             forAll(verts, vertI)
120             {
121                 lineStream >> verts[vertI];
122             }
124             UList<label>& f = static_cast<UList<label>&>(verts);
126             if (mustTriangulate && f.size() > 3)
127             {
128                 // simple face triangulation about f[0]
129                 // cannot use face::triangulation (points may be incomplete)
130                 for (label fp1 = 1; fp1 < f.size() - 1; fp1++)
131                 {
132                     label fp2 = f.fcIndex(fp1);
134                     dynFaces.append(triFace(f[0], f[fp1], f[fp2]));
135                 }
136             }
137             else
138             {
139                 dynFaces.append(Face(f));
140             }
141         }
142     }
144     // transfer to normal lists, no zone information
145     reset(pointLst.xfer(), dynFaces.xfer(), Xfer<surfZoneList>());
147     return true;
151 template<class Face>
152 void Foam::fileFormats::OFFsurfaceFormat<Face>::write
154     const fileName& filename,
155     const MeshedSurfaceProxy<Face>& surf
158     const pointField& pointLst = surf.points();
159     const List<Face>&  faceLst = surf.faces();
160     const List<label>& faceMap = surf.faceMap();
161     const List<surfZone>& zoneLst = surf.surfZones();
163     OFstream os(filename);
164     if (!os.good())
165     {
166         FatalErrorIn
167         (
168             "fileFormats::OFFsurfaceFormat::write"
169             "(const fileName&, const MeshedSurfaceProxy<Face>&)"
170         )
171             << "Cannot open file for writing " << filename
172             << exit(FatalError);
173     }
175     // Write header
176     os  << "OFF" << endl
177         << "# Geomview OFF file written " << clock::dateTime().c_str() << nl
178         << nl
179         << "# points : " << pointLst.size() << nl
180         << "# faces  : " << faceLst.size() << nl
181         << "# zones  : " << zoneLst.size() << nl;
183     // Print zone names as comment
184     forAll(zoneLst, zoneI)
185     {
186         os  << "#   " << zoneI << "  " << zoneLst[zoneI].name()
187             << "  (nFaces: " << zoneLst[zoneI].size() << ")" << nl;
188     }
190     os  << nl
191         << "# nPoints  nFaces  nEdges" << nl
192         << pointLst.size() << ' ' << faceLst.size() << ' ' << 0 << nl
193         << nl
194         << "# <points count=\"" << pointLst.size() << "\">" << endl;
196     // Write vertex coords
197     forAll(pointLst, ptI)
198     {
199         os  << pointLst[ptI].x() << ' '
200             << pointLst[ptI].y() << ' '
201             << pointLst[ptI].z() << " #" << ptI << endl;
202     }
204     os  << "# </points>" << nl
205         << nl
206         << "# <faces count=\"" << faceLst.size() << "\">" << endl;
208     label faceIndex = 0;
209     forAll(zoneLst, zoneI)
210     {
211         os << "# <zone name=\"" << zoneLst[zoneI].name() << "\">" << endl;
213         if (surf.useFaceMap())
214         {
215             forAll(zoneLst[zoneI], localFaceI)
216             {
217                 const Face& f = faceLst[faceMap[faceIndex++]];
219                 os << f.size();
220                 forAll(f, fp)
221                 {
222                     os << ' ' << f[fp];
223                 }
225                 // add optional zone information
226                 os << ' ' << zoneI << endl;
227             }
228         }
229         else
230         {
231             forAll(zoneLst[zoneI], localFaceI)
232             {
233                 const Face& f = faceLst[faceIndex++];
235                 os << f.size();
236                 forAll(f, fp)
237                 {
238                     os << ' ' << f[fp];
239                 }
241                 // add optional zone information
242                 os << ' ' << zoneI << endl;
243             }
244         }
245         os << "# </zone>" << endl;
246     }
247     os << "# </faces>" << endl;
251 // ************************************************************************* //