objToVTK.C
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration | Website: https://openfoam.org
5  \\ / A nd | Copyright (C) 2011-2018 OpenFOAM Foundation
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8 License
9  This file is part of OpenFOAM.
10 
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.
15 
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.
20 
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/>.
23 
24 Application
25  objToVTK
26 
27 Description
28  Read obj line (not surface!) file and convert into vtk.
29 
30 \*---------------------------------------------------------------------------*/
31 
32 #include "argList.H"
33 #include "OFstream.H"
34 #include <fstream>
35 #include <sstream>
36 #include "IStringStream.H"
37 #include "point.H"
38 #include "DynamicList.H"
39 
40 using namespace Foam;
41 
42 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
43 
44 string getLine(std::ifstream& is)
45 {
46  string line;
47  do
48  {
49  std::getline(is, line);
50  }
51  while (line.size() && line[0] == '#');
52 
53  return line;
54 }
55 
56 
57 // Read space-separated vertices (with optional '/' arguments)
58 labelList parseVertices(const string& line)
59 {
60  DynamicList<label> verts;
61 
62  // Assume 'l' is followed by space.
63  string::size_type endNum = 1;
64 
65  do
66  {
67  string::size_type startNum = line.find_first_not_of(' ', endNum);
68 
69  if (startNum == string::npos)
70  {
71  break;
72  }
73 
74  endNum = line.find(' ', startNum);
75 
76  string vertexSpec;
77  if (endNum != string::npos)
78  {
79  vertexSpec = line.substr(startNum, endNum-startNum);
80  }
81  else
82  {
83  vertexSpec = line.substr(startNum, line.size() - startNum);
84  }
85 
86  string::size_type slashPos = vertexSpec.find('/');
87 
88  label vertI = 0;
89  if (slashPos != string::npos)
90  {
91  IStringStream intStream(vertexSpec.substr(0, slashPos));
92 
93  intStream >> vertI;
94  }
95  else
96  {
97  IStringStream intStream(vertexSpec);
98 
99  intStream >> vertI;
100  }
101  verts.append(vertI - 1);
102  }
103  while (true);
104 
105  return verts.shrink();
106 }
107 
108 
109 
110 int main(int argc, char *argv[])
111 {
112  #include "removeCaseOptions.H"
113 
114  argList::validArgs.append("OBJ file");
115  argList::validArgs.append("output VTK file");
116  argList args(argc, argv);
117 
118  const fileName objName = args[1];
119  const fileName outName = args[2];
120 
121  std::ifstream OBJfile(objName.c_str());
122 
123  if (!OBJfile.good())
124  {
126  << "Cannot read file " << objName << exit(FatalError);
127  }
128 
129  // Points and lines
131  DynamicList<vector> pointNormals;
132  DynamicList<labelList> polyLines;
133  DynamicList<labelList> polygons;
134 
135  bool hasWarned = false;
136 
137  label lineNo = 0;
138  while (OBJfile.good())
139  {
140  string line = getLine(OBJfile);
141  lineNo++;
142 
143  // Read first word
144  IStringStream lineStream(line);
145  word cmd;
146  lineStream >> cmd;
147 
148  if (cmd == "v")
149  {
150  scalar x, y, z;
151 
152  lineStream >> x >> y >> z;
153 
154  points.append(point(x, y, z));
155  }
156  else if (cmd == "vn")
157  {
158  scalar x, y, z;
159 
160  lineStream >> x >> y >> z;
161 
162  pointNormals.append(vector(x, y, z));
163  }
164  else if (cmd == "l")
165  {
166  polyLines.append(parseVertices(line));
167  }
168  else if (cmd == "f")
169  {
170  polygons.append(parseVertices(line));
171  }
172  else if (cmd != "")
173  {
174  if (!hasWarned)
175  {
176  hasWarned = true;
177 
179  << "Unrecognized OBJ command " << cmd << nl
180  << "In line " << lineStream.str()
181  << " at linenumber " << lineNo << nl
182  << "Only recognized commands are 'v' and 'l'.\n"
183  << "If this is a surface command use surfaceConvert instead"
184  << " to convert to a file format that can be read by VTK"
185  << endl;
186  }
187  }
188  }
189 
190 
191  //
192  // Write as vtk 'polydata' file
193  //
194 
195 
196  OFstream outFile(outName);
197 
198  outFile
199  << "# vtk DataFile Version 2.0\n"
200  << objName << nl
201  << "ASCII\n"
202  << "DATASET POLYDATA\n"
203  << "POINTS " << points.size() << " float\n";
204 
205  forAll(points, i)
206  {
207  const point& pt = points[i];
208 
209  outFile << pt.x() << ' ' << pt.y() << ' ' << pt.z() << nl;
210  }
211 
212  outFile
213  << "VERTICES " << points.size() << ' ' << (2 * points.size()) << nl;
214 
215  forAll(points, i)
216  {
217  outFile << 1 << ' ' << i << nl;
218  }
219 
220  label nItems = 0;
221  forAll(polyLines, polyI)
222  {
223  nItems += polyLines[polyI].size() + 1;
224  }
225 
226  outFile
227  << "LINES " << polyLines.size() << ' ' << nItems << nl;
228 
229  forAll(polyLines, polyI)
230  {
231  const labelList& line = polyLines[polyI];
232 
233  outFile << line.size();
234 
235  forAll(line, i)
236  {
237  outFile << ' ' << line[i];
238  }
239  outFile << nl;
240  }
241 
242 
243  nItems = 0;
244  forAll(polygons, polyI)
245  {
246  nItems += polygons[polyI].size() + 1;
247  }
248 
249  outFile
250  << "POLYGONS " << polygons.size() << ' ' << nItems << nl;
251 
252  forAll(polygons, polyI)
253  {
254  const labelList& line = polygons[polyI];
255 
256  outFile << line.size();
257 
258  forAll(line, i)
259  {
260  outFile << ' ' << line[i];
261  }
262  outFile << nl;
263  }
264 
265 
266  outFile
267  << "POINT_DATA " << points.size() << nl
268  << "SCALARS pointID float 1\n"
269  << "LOOKUP_TABLE default\n";
270 
271  forAll(points, i)
272  {
273  outFile << i;
274 
275  if ((i % 10) == 1)
276  {
277  outFile << nl;
278  }
279  else
280  {
281  outFile << ' ';
282  }
283  }
284 
285  if (!pointNormals.empty())
286  {
287  outFile << nl << "NORMALS pointNormals float\n";
288 
289  forAll(pointNormals, i)
290  {
291  const vector& n = pointNormals[i];
292 
293  outFile << n.x() << ' ' << n.y() << ' ' << n.z() << nl;
294  }
295  }
296 
297  Info<< "End\n" << endl;
298 
299  return 0;
300 }
301 
302 
303 // ************************************************************************* //
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:434
bool empty() const
Return true if the UList is empty (ie, size() is zero)
Definition: UListI.H:313
intWM_LABEL_SIZE_t label
A label is an int32_t or int64_t as specified by the pre-processor macro WM_LABEL_SIZE.
Definition: label.H:59
A class for handling file names.
Definition: fileName.H:79
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:124
error FatalError
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:319
Output to file stream.
Definition: OFstream.H:82
void size(const label)
Override size to be inconsistent with allocated storage.
Definition: ListI.H:163
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:256
static SLList< string > validArgs
A list of valid (mandatory) arguments.
Definition: argList.H:153
const Cmpt & z() const
Definition: VectorI.H:87
Vector< scalar > vector
A scalar version of the templated Vector.
Definition: vector.H:49
const Cmpt & y() const
Definition: VectorI.H:81
scalar y
const pointField & points
A class for handling words, derived from string.
Definition: word.H:59
Extract command arguments and options from the supplied argc and argv parameters. ...
Definition: argList.H:102
DynamicList< T, SizeInc, SizeMult, SizeDiv > & append(const T &)
Append an element at the end of the list.
Definition: DynamicListI.H:296
graph_traits< Graph >::vertices_size_type size_type
Definition: SloanRenumber.C:73
const Cmpt & x() const
Definition: VectorI.H:75
DynamicList< T, SizeInc, SizeMult, SizeDiv > & shrink()
Shrink the allocated space to the number of elements used.
Definition: DynamicListI.H:252
static const char nl
Definition: Ostream.H:265
vector point
Point is a vector.
Definition: point.H:41
#define WarningInFunction
Report a warning using Foam::Warning.
Input from memory buffer stream.
Definition: IStringStream.H:49
messageStream Info
Foam::argList args(argc, argv)
Namespace for OpenFOAM.