ENH: autoLayerDriver: better layering information message
[OpenFOAM-2.0.x.git] / src / surfMesh / surfaceFormats / off / OFFsurfaceFormat.C
blob8e753fad1642edfd4ebfc2c93b80d955617f82dd
1 /*---------------------------------------------------------------------------*\
2   =========                 |
3   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
4    \\    /   O peration     |
5     \\  /    A nd           | Copyright (C) 2011 OpenFOAM Foundation
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
13     the Free Software Foundation, either version 3 of the License, or
14     (at your 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, see <http://www.gnu.org/licenses/>.
24 \*---------------------------------------------------------------------------*/
26 #include "OFFsurfaceFormat.H"
27 #include "clock.H"
28 #include "IFstream.H"
29 #include "IStringStream.H"
30 #include "Ostream.H"
31 #include "OFstream.H"
33 // * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
35 template<class Face>
36 Foam::fileFormats::OFFsurfaceFormat<Face>::OFFsurfaceFormat
38     const fileName& filename
41     read(filename);
45 // * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
47 template<class Face>
48 bool Foam::fileFormats::OFFsurfaceFormat<Face>::read
50     const fileName& filename
53     const bool mustTriangulate = this->isTri();
54     this->clear();
56     IFstream is(filename);
57     if (!is.good())
58     {
59         FatalErrorIn
60         (
61             "fileFormats::OFFsurfaceFormat::read(const fileName&)"
62         )
63             << "Cannot read file " << filename
64             << exit(FatalError);
65     }
67     // Read header
68     string hdr = this->getLineNoComment(is);
69     if (hdr != "OFF")
70     {
71         FatalErrorIn
72         (
73             "fileFormats::OFFsurfaceFormat::read(const fileName&)"
74         )
75             << "OFF file " << filename << " does not start with 'OFF'"
76             << exit(FatalError);
77     }
80     // get dimensions
81     label nPoints, nElems, nEdges;
83     string line = this->getLineNoComment(is);
84     {
85         IStringStream lineStream(line);
86         lineStream >> nPoints >> nElems >> nEdges;
87     }
89     // Read points
90     pointField pointLst(nPoints);
91     forAll(pointLst, pointI)
92     {
93         scalar x, y, z;
94         line = this->getLineNoComment(is);
95         {
96             IStringStream lineStream(line);
97             lineStream >> x >> y >> z;
98         }
99         pointLst[pointI] = point(x, y, z);
100     }
102     // Read faces - ignore optional zone information
103     // use a DynamicList for possible on-the-fly triangulation
104     DynamicList<Face>  dynFaces(nElems);
106     for (label faceI = 0; faceI < nElems; ++faceI)
107     {
108         line = this->getLineNoComment(is);
110         {
111             IStringStream lineStream(line);
113             label nVerts;
114             lineStream >> nVerts;
116             List<label> verts(nVerts);
118             forAll(verts, vertI)
119             {
120                 lineStream >> verts[vertI];
121             }
123             labelUList& f = static_cast<labelUList&>(verts);
125             if (mustTriangulate && f.size() > 3)
126             {
127                 // simple face triangulation about f[0]
128                 // cannot use face::triangulation (points may be incomplete)
129                 for (label fp1 = 1; fp1 < f.size() - 1; fp1++)
130                 {
131                     label fp2 = f.fcIndex(fp1);
133                     dynFaces.append(triFace(f[0], f[fp1], f[fp2]));
134                 }
135             }
136             else
137             {
138                 dynFaces.append(Face(f));
139             }
140         }
141     }
143     // transfer to normal lists, no zone information
144     this->reset(pointLst.xfer(), dynFaces.xfer(), Xfer<surfZoneList>());
146     return true;
150 template<class Face>
151 void Foam::fileFormats::OFFsurfaceFormat<Face>::write
153     const fileName& filename,
154     const MeshedSurfaceProxy<Face>& surf
157     const pointField& pointLst = surf.points();
158     const List<Face>&  faceLst = surf.faces();
159     const List<label>& faceMap = surf.faceMap();
160     const List<surfZone>& zoneLst = surf.surfZones();
162     OFstream os(filename);
163     if (!os.good())
164     {
165         FatalErrorIn
166         (
167             "fileFormats::OFFsurfaceFormat::write"
168             "(const fileName&, const MeshedSurfaceProxy<Face>&)"
169         )
170             << "Cannot open file for writing " << filename
171             << exit(FatalError);
172     }
174     // Write header
175     os  << "OFF" << endl
176         << "# Geomview OFF file written " << clock::dateTime().c_str() << nl
177         << nl
178         << "# points : " << pointLst.size() << nl
179         << "# faces  : " << faceLst.size() << nl
180         << "# zones  : " << zoneLst.size() << nl;
182     // Print zone names as comment
183     forAll(zoneLst, zoneI)
184     {
185         os  << "#   " << zoneI << "  " << zoneLst[zoneI].name()
186             << "  (nFaces: " << zoneLst[zoneI].size() << ")" << nl;
187     }
189     os  << nl
190         << "# nPoints  nFaces  nEdges" << nl
191         << pointLst.size() << ' ' << faceLst.size() << ' ' << 0 << nl
192         << nl
193         << "# <points count=\"" << pointLst.size() << "\">" << endl;
195     // Write vertex coords
196     forAll(pointLst, ptI)
197     {
198         os  << pointLst[ptI].x() << ' '
199             << pointLst[ptI].y() << ' '
200             << pointLst[ptI].z() << " #" << ptI << endl;
201     }
203     os  << "# </points>" << nl
204         << nl
205         << "# <faces count=\"" << faceLst.size() << "\">" << endl;
207     label faceIndex = 0;
208     forAll(zoneLst, zoneI)
209     {
210         os << "# <zone name=\"" << zoneLst[zoneI].name() << "\">" << endl;
212         if (surf.useFaceMap())
213         {
214             forAll(zoneLst[zoneI], localFaceI)
215             {
216                 const Face& f = faceLst[faceMap[faceIndex++]];
218                 os << f.size();
219                 forAll(f, fp)
220                 {
221                     os << ' ' << f[fp];
222                 }
224                 // add optional zone information
225                 os << ' ' << zoneI << endl;
226             }
227         }
228         else
229         {
230             forAll(zoneLst[zoneI], localFaceI)
231             {
232                 const Face& f = faceLst[faceIndex++];
234                 os << f.size();
235                 forAll(f, fp)
236                 {
237                     os << ' ' << f[fp];
238                 }
240                 // add optional zone information
241                 os << ' ' << zoneI << endl;
242             }
243         }
244         os << "# </zone>" << endl;
245     }
246     os << "# </faces>" << endl;
250 // ************************************************************************* //