Reading a file in OFF format

Discussion in 'C++' started by Alexander Schmidt, Jul 10, 2004.

  1. 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]
     
    Alexander Schmidt, Jul 10, 2004
    #1
    1. Advertising

  2. "Alexander Schmidt" <> wrote in message
    news:...
    > 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;
    }
     
    Alexander Schmidt, Jul 10, 2004
    #2
    1. Advertising

  3. * Alexander Schmidt wrote:
    >
    > "Alexander Schmidt" <> wrote in message
    > news:...
    >> 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).


    I guess this is some kind of homework?

    >> 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++ ?)


    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 <sstream>

    > 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;

    > }


    --
    Robert Bauck Hamar
     
    Robert Bauck Hamar, Jul 10, 2004
    #3
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Steve
    Replies:
    0
    Views:
    479
    Steve
    Jan 31, 2006
  2. Wayne...
    Replies:
    15
    Views:
    793
    Toby Inkster
    Jul 23, 2004
  3. robert112
    Replies:
    1
    Views:
    478
    Juan T. Llibre
    Apr 26, 2007
  4. Randy Kramer
    Replies:
    2
    Views:
    430
    Randy Kramer
    Jan 12, 2007
  5. Wesley
    Replies:
    1
    Views:
    214
    Wesley
    Apr 15, 2014
Loading...

Share This Page