Reading a file in OFF format

A

Alexander Schmidt

Hi,

I am not very familiar with C++ programming, so before I do a dirty hack I
ask for a more elegant solution (but only the usage of STL is allowed, no
special libs).
So I need to read a file in OFF format and store the values read in some
file format, I suppose in arrays of floats or ints would be meaningful:

My general idea:

- Open the file
- Read line 1 and check if OFF file
- Read line 2 and store values for Nv and Nf (how to tokenize that ?
searching for spaces ? is there sth. like a StringTokenizer in C++ ?)
- Read the vertex table (again: I would tokenize through searching for
strings -is there a more elegant approach ?)
- Read the faces (same question as above)

Thanks for your help !

---

The OFF format can be described as:

We use a very simple ASCII format for representing polygonal meshes. It
consists of a short header, a table of vertex coordinates, and a table of
polygons (all triangles) stored as indices into the vertex table.
a.. header
The header includes the number of vertices Nv, the number of faces
(triangles) Nf, and the number of edges which is assumed to be always 0,
i.e., there is only a vertex and a face table.
OFF
Nv Nf 0



b.. vertex table
The vertex table stored the geometry information. It contains Nv lines
with x y z coordinates for every vertex, i.e.
x[0] y[0] z[0]
...
x[Nv-1] y[Nv-1] z[Nv-1]



c.. table of faces/triangles
This table contains the connectivity information stored in Nf lines. Every
line describes a face/polygon, the first number denotes the number of
vertices, it is assumed to be always 3, i.e. the the meshes consist of
triangles only! Then the following 3 numbers are indices into the vertex
table (starting with index 0), i.e.
3 i0[0] i1[0] i2[0]
...
3 i0[Nf-1] i1[Nf-1] i2[Nf-1]
 
A

Alexander Schmidt

Alexander Schmidt said:
Hi,

I am not very familiar with C++ programming, so before I do a dirty hack I
ask for a more elegant solution (but only the usage of STL is allowed, no
special libs).
So I need to read a file in OFF format and store the values read in some
file format, I suppose in arrays of floats or ints would be meaningful:

My general idea:

- Open the file
- Read line 1 and check if OFF file
- Read line 2 and store values for Nv and Nf (how to tokenize that ?
searching for spaces ? is there sth. like a StringTokenizer in C++ ?)
- Read the vertex table (again: I would tokenize through searching for
strings -is there a more elegant approach ?)
- Read the faces (same question as above)

Thanks for your help !

---

The OFF format can be described as:

We use a very simple ASCII format for representing polygonal meshes. It
consists of a short header, a table of vertex coordinates, and a table of
polygons (all triangles) stored as indices into the vertex table.
a.. header
The header includes the number of vertices Nv, the number of faces
(triangles) Nf, and the number of edges which is assumed to be always 0,
i.e., there is only a vertex and a face table.
OFF
Nv Nf 0



b.. vertex table
The vertex table stored the geometry information. It contains Nv lines
with x y z coordinates for every vertex, i.e.
x[0] y[0] z[0]
...
x[Nv-1] y[Nv-1] z[Nv-1]



c.. table of faces/triangles
This table contains the connectivity information stored in Nf lines. Every
line describes a face/polygon, the first number denotes the number of
vertices, it is assumed to be always 3, i.e. the the meshes consist of
triangles only! Then the following 3 numbers are indices into the vertex
table (starting with index 0), i.e.
3 i0[0] i1[0] i2[0]
...
3 i0[Nf-1] i1[Nf-1] i2[Nf-1]

This is my solution, if someone has comments how to improve, they're
welcome:

#include <stdlib.h>
#include <iostream>
#include <fstream>
#include <string>

using namespace std;

// Global declarations
int RETURN_OK = 0;
int RETURN_ERROR = 1;

int nv, nf;

struct vertex
{
float x;
float y;
float z;
};

struct facade
{
int v1;
int v2;
int v3;
};

vertex *vertices;
facade *facades;

// Parser
void parse(string filename)
{
// Container holding last line read
string readLine;
// Containers for delimiter positions
int delimiterPos_1, delimiterPos_2, delimiterPos_3, delimiterPos_4;

// Open file for reading
ifstream in(filename.c_str());

// Check if file is in OFF format
getline(in,readLine);
if (readLine != "OFF")
{
cout << "The file to read is not in OFF format." << endl;
return;
}

// Read values for Nv and Nf
getline(in,readLine);
delimiterPos_1 = readLine.find(" ", 0);
nv = atoi(readLine.substr(0,delimiterPos_1+1).c_str());
delimiterPos_2 = readLine.find(" ", delimiterPos_1);
nf = atoi(readLine.substr(delimiterPos_1,delimiterPos_2+1).c_str());

// Read the vertices
vertices = new vertex[nv];

for (int n=0; n<nv; n++)
{
getline(in,readLine);
delimiterPos_1 = readLine.find(" ", 0);
vertices[n].x = atof(readLine.substr(0,delimiterPos_1).c_str());
delimiterPos_2 = readLine.find(" ", delimiterPos_1+1);
vertices[n].y =
atof(readLine.substr(delimiterPos_1,delimiterPos_2).c_str());
delimiterPos_3 = readLine.find(" ", delimiterPos_2+1);
vertices[n].z =
atof(readLine.substr(delimiterPos_2,delimiterPos_3).c_str());

cout << vertices[n].x << "\t" << vertices[n].y << "\t" <<
vertices[n].z << "\t" << endl;
}

// Read the facades
facades = new facade[nf];

for (int n=0; n<nf; n++)
{
getline(in,readLine);
delimiterPos_1 = readLine.find(" ", 0);
delimiterPos_2 = readLine.find(" ", delimiterPos_1+1);
facades[n].v1 =
atoi(readLine.substr(delimiterPos_1,delimiterPos_2).c_str());
delimiterPos_3 = readLine.find(" ", delimiterPos_2+1);
facades[n].v2 =
atoi(readLine.substr(delimiterPos_2,delimiterPos_3).c_str());
delimiterPos_4 = readLine.find(" ", delimiterPos_3+1);
facades[n].v3 =
atoi(readLine.substr(delimiterPos_3,delimiterPos_4).c_str());

cout << facades[n].v1 << "\t" << facades[n].v2 << "\t" <<
facades[n].v3 << "\t" << endl;
}
}


// Main
int main(int argc, char *argv[])
{
// Check input
if (argc != 2)
{
cout << "You have entered an incorrect number of command line
parameters. See README and try again." << endl;
return RETURN_ERROR;
}

// Read the filename
string filename = argv[1];

// Parse the file
parse(filename);

return RETURN_OK;
}
 
R

Robert Bauck Hamar

I guess this is some kind of homework?

The iostreams support formatted input. There is also an istringstream
which should do what you want, but you can just read in the tokens one
by one:
in >> lineRead >> nv >> nf ...

Some advice:
- Use C++ as C++ and not a better C. In particular: learn to use
classes.
- Try to avoid using new wherever possible. In your example you really
don't need more than one instance of vertex and facade. In a more
complex situation, you would, but then you could use the
vector template class from the stl.
- Don't write using namespace std;. The std namespace will probably
include new names in future revisions of C++.
- Always check input from sources you don't control.
- Don't create objects before you need them. This usually makes the
variable type apparent to a reader.
- Read books.
This is my solution, if someone has comments how to improve, they're
welcome:

#include <stdlib.h>
#include <iostream>
#include <fstream>
#include <string>

#include said:
using namespace std;

// Global declarations
int RETURN_OK = 0;
int RETURN_ERROR = 1;

You should use EXIT_SUCCESS and EXIT_FAILURE instead of these.
int nv, nf;

struct vertex
{
float x;
float y;
float z;
};

struct facade
{
int v1;
int v2;
int v3;
};

vertex *vertices;
facade *facades;

// Parser
void parse(string filename)
{
// Container holding last line read
string readLine;
// Containers for delimiter positions
int delimiterPos_1, delimiterPos_2, delimiterPos_3, delimiterPos_4;

// Open file for reading
ifstream in(filename.c_str());

// Check if file is in OFF format
getline(in,readLine);
if (readLine != "OFF")
{
cout << "The file to read is not in OFF format." << endl;
return;
}

// Read values for Nv and Nf
getline(in,readLine); /*
delimiterPos_1 = readLine.find(" ", 0);
nv = atoi(readLine.substr(0,delimiterPos_1+1).c_str());
delimiterPos_2 = readLine.find(" ", delimiterPos_1);
nf = atoi(readLine.substr(delimiterPos_1,delimiterPos_2+1).c_str());
*/
istringstream tokenizer(readLine);
tokenizer >> nv >> nf;
// Read the vertices
vertices = new vertex[nv];

for (int n=0; n<nv; n++)
{
getline(in,readLine);

tokenizer.str(readLine);
tokenizer >> ...
delimiterPos_1 = readLine.find(" ", 0);
vertices[n].x = atof(readLine.substr(0,delimiterPos_1).c_str());
delimiterPos_2 = readLine.find(" ", delimiterPos_1+1);
vertices[n].y =
atof(readLine.substr(delimiterPos_1,delimiterPos_2).c_str());
delimiterPos_3 = readLine.find(" ", delimiterPos_2+1);
vertices[n].z =
atof(readLine.substr(delimiterPos_2,delimiterPos_3).c_str());

cout << vertices[n].x << "\t" << vertices[n].y << "\t" <<
vertices[n].z << "\t" << endl;
}

// Read the facades
facades = new facade[nf];

for (int n=0; n<nf; n++)
{
getline(in,readLine);
delimiterPos_1 = readLine.find(" ", 0);
delimiterPos_2 = readLine.find(" ", delimiterPos_1+1);
facades[n].v1 =
atoi(readLine.substr(delimiterPos_1,delimiterPos_2).c_str());
delimiterPos_3 = readLine.find(" ", delimiterPos_2+1);
facades[n].v2 =
atoi(readLine.substr(delimiterPos_2,delimiterPos_3).c_str());
delimiterPos_4 = readLine.find(" ", delimiterPos_3+1);
facades[n].v3 =
atoi(readLine.substr(delimiterPos_3,delimiterPos_4).c_str());

cout << facades[n].v1 << "\t" << facades[n].v2 << "\t" <<
facades[n].v3 << "\t" << endl;
}

delete [] vertices;
delete [] facades;
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,768
Messages
2,569,574
Members
45,048
Latest member
verona

Latest Threads

Top