Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. Reading floats from binary STL file with QDataStream

Reading floats from binary STL file with QDataStream

Scheduled Pinned Locked Moved General and Desktop
7 Posts 4 Posters 7.4k Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • A Offline
    A Offline
    albert86
    wrote on last edited by
    #1

    Hi all,

    I'm trying to read floats from an STL binary file (http://en.wikipedia.org/wiki/STL_(file_format)#Binary_STL).

    I'm having a strange problem taking the floats from the QDataStream. I've read that there is a known bug but I'm having a different problem. Once in a while it reads the wrong number (for example, if the 4-byte-float, as in IEEE 754 format, is supposed to be 35.56, it reads 1.231e+12). NOTE THAT MOST OF THE TIMES (99.5%) IT WORKS WELL.

    Here is the code:

    @ // Treat BINARY STL
    file->seek(0);
    QDataStream in(file);
    //in.setVersion(1);
    in.setByteOrder(QDataStream::LittleEndian);
    in.setFloatingPointPrecision(QDataStream::SinglePrecision);
    quint32 ntriangles;
    quint16 control_bytes;
    file->seek(80);
    in >> ntriangles;
    int triang_count = 0;
    double LIMIT_OUT = 2000;
    while (triang_count < ntriangles) {
    float nx, ny, nz, x1, x2, x3, y1, y2, y3, z1, z2, z3;
    file->seek(84+triang_count50+0+0);
    in >> nx;
    file->seek(84+triang_count
    50+0+4);
    in >> ny;
    file->seek(84+triang_count50+0+8);
    in >> nz;
    file->seek(84+triang_count
    50+12+0);
    in >> x1;
    file->seek(84+triang_count50+12+4);
    in >> y1;
    file->seek(84+triang_count
    50+12+8);
    in >> z1;
    file->seek(84+triang_count50+24+0);
    in >> x2;
    file->seek(84+triang_count
    50+24+4);
    in >> y2;
    file->seek(84+triang_count50+24+8);
    in >> z2;
    file->seek(84+triang_count
    50+36+0);
    in >> x3;
    file->seek(84+triang_count50+36+4);
    in >> y3;
    file->seek(84+triang_count
    50+36+8);
    in >> z3;
    file->seek(84+triang_count*50+48);
    in >> control_bytes;
    if (in.status() != QDataStream::Ok ){
    qDebug()<< (int) in.status();
    }
    //qDebug() << triangle_i;
    bool nook = false;
    nook = nook || ((fabs((double)x1)) > LIMIT_OUT);
    nook = nook || ((fabs((double)x2)) > LIMIT_OUT);
    nook = nook || ((fabs((double)x3)) > LIMIT_OUT);
    nook = nook || ((fabs((double)y1)) > LIMIT_OUT);
    nook = nook || ((fabs((double)y2)) > LIMIT_OUT);
    nook = nook || ((fabs((double)y3)) > LIMIT_OUT);
    nook = nook || ((fabs((double)z1)) > LIMIT_OUT);
    nook = nook || ((fabs((double)z2)) > LIMIT_OUT);
    nook = nook || ((fabs((double)z3)) > LIMIT_OUT);
    if (control_bytes == 0 && !nook){
    //DO TREATMENT
    }
    }
    @

    I've written the same code in Matlab, it works well and displays the STL geometry that it is supposed to display, I've also tried the versions of Qt 4.7.3, Qt 4.7.4 and Qt 4.8 beta in two different computers, the problem occurs in the same bytes in both computers for most versions (none works fine).

    At the end of every iteration, I check the status and it is always OK.

    Is there a better/different/more appropriate way to extract the floats according to IEEE 754?

    Thank you so much :)

    Albert

    1 Reply Last reply
    0
    • T Offline
      T Offline
      TheDestroyer
      wrote on last edited by
      #2

      Wouldn't be easier if you would use QFile? or simply fstream from standard C++?

      1 Reply Last reply
      0
      • G Offline
        G Offline
        goetz
        wrote on last edited by
        #3

        QDataStream is not sufficient to read data not written with a QDataStream.

        Additionally, I wouldn't bet a penny that manipulating the file position on the QFile object plays nicely with the data stream. I would expect troubles here.

        As TheDestroyer already mentioned, using QFile directly would be a more robust solution in your case.

        http://www.catb.org/~esr/faqs/smart-questions.html

        1 Reply Last reply
        0
        • A Offline
          A Offline
          albert86
          wrote on last edited by
          #4

          Thanks a lot for your replies :)

          I have also tried with QFile and memcpy. Like in this example :
          (file is a pointer to QFile, as in the previous example)

          @ while (triang_count < ntriangles) {
          file->seek(84+triang_count*50);
          float nxyz[12];
          QByteArray ba = file->read(50);
          memcpy(&nxyz, ba.constData(), 48);
          // code
          // ...
          // code
          triang_count = triang_count + 1;
          }@

          But I get the same wrong values at the same place.

          In this case I get the 12 floats of every triangle at once in the array nxyz (normal vector, p1, p2, p3; each has the components x, y, z). I see that this is much easier to work with, but I still get the wrong values.

          Thanks again for your help.

          1 Reply Last reply
          0
          • A Offline
            A Offline
            albert86
            wrote on last edited by
            #5

            Ok I got it! :D
            I was opening the file as text!! :$
            @file->open(QIODevice::ReadOnly))@

            I'm so clumsy... I've spent more than 4 hours here.

            Thanks for your help anyways.

            1 Reply Last reply
            1
            • A Offline
              A Offline
              andre
              wrote on last edited by
              #6

              [quote author="Volker" date="1329862180"]QDataStream is not sufficient to read data not written with a QDataStream.
              [/quote]
              Actually, it works quite nicely. QDataStream does not add or expect any special markers. Of course, its own internal types have (well defined) specific layouts in the stream, but that is not a concern for reading basic types like floats. The only thing you need to take into account is the endianness, but changing that is supported in the QDataStream API.

              1 Reply Last reply
              0
              • G Offline
                G Offline
                goetz
                wrote on last edited by
                #7

                Yes, that's true. Unfortunately I was convinced that QDataStream writes its version to the start of the stream. But that's not true.

                http://www.catb.org/~esr/faqs/smart-questions.html

                1 Reply Last reply
                0

                • Login

                • Login or register to search.
                • First post
                  Last post
                0
                • Categories
                • Recent
                • Tags
                • Popular
                • Users
                • Groups
                • Search
                • Get Qt Extensions
                • Unsolved