reading binary file

I am trying to read an stl binary file using following code but just a few numbers of data are read correctly, the rest are either very large or small. the data look like 1e+161 or nan or 1e-38. I build the geometry in comsol and exported the stl binary file. To check whether the problem is coming from geometry or not, I converted the stl to off file and read the off file and the data were as expected. here is the code,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
 struct Triangle {
    float x1, y1, z1;
    float x2, y2, z2;
    float x3, y3, z3;
};

std::vector<Triangle> readSTL(std::string filename) {
    std::vector<Triangle> triangles;

    std::ifstream file(filename, std::ios::in | std::ios::binary);
    if (!file) {
        throw std::runtime_error("Failed to open file: " + filename);
    }

    char header[80];
    file.read(header, 80);

    uint32_t num_triangles;
    file.read(reinterpret_cast<char*>(&num_triangles), sizeof(num_triangles));

    for (uint32_t i = 0; i < num_triangles; i++) {
        // Read vertex coordinates
        float v1x, v1y, v1z, v2x, v2y, v2z, v3x, v3y, v3z;
        file.read(reinterpret_cast<char*>(&v1x), sizeof(float));
        file.read(reinterpret_cast<char*>(&v1y), sizeof(float));
        file.read(reinterpret_cast<char*>(&v1z), sizeof(float));
        file.read(reinterpret_cast<char*>(&v2x), sizeof(float));
        file.read(reinterpret_cast<char*>(&v2y), sizeof(float));
        file.read(reinterpret_cast<char*>(&v2z), sizeof(float));
        file.read(reinterpret_cast<char*>(&v3x), sizeof(float));
        file.read(reinterpret_cast<char*>(&v3y), sizeof(float));
        file.read(reinterpret_cast<char*>(&v3z), sizeof(float));

        uint16_t attr_byte_count;
        file.read(reinterpret_cast<char*>(&attr_byte_count), sizeof(attr_byte_count));

        // Create Triangle object
        Triangle t = { v1x, v1y, v1z, v2x, v2y, v2z, v3x, v3y, v3z };
        triangles.push_back(t);
    }

    file.close();

    for (const auto& t : triangles) {
        std::cout << "Triangle vertex coordinates: "
            << "(" << t.x1 << ", " << t.y1 << ", " << t.z1 << ") "
            << "(" << t.x2 << ", " << t.y2 << ", " << t.z2 << ") "
            << "(" << t.x3 << ", " << t.y3 << ", " << t.z3 << ")" << std::endl;
    }

    return triangles;
}
Last edited on
According to https://en.wikipedia.org/wiki/STL_(file_format) there is a normal vector you have to read out with every triangle.
Last edited on
@mbozzi thank you. that was the issue. but how skipping normals can cause the data become of such large or very small order. here is the code for future readers
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
std::vector<Triangle> readSTL(std::string filename) {
    std::vector<Triangle> triangles;

    std::ifstream file(filename, std::ios::in | std::ios::binary);
    if (!file) {
        throw std::runtime_error("Failed to open file: " + filename);
    }

    char header[80];
    file.read(header, 80);

    uint32_t num_triangles;
    file.read(reinterpret_cast<char*>(&num_triangles), sizeof(num_triangles));

    for (uint32_t i = 0; i < num_triangles; i++) {
        // Read normal vector
        float nx, ny, nz;
        file.read(reinterpret_cast<char*>(&nx), sizeof(float));
        file.read(reinterpret_cast<char*>(&ny), sizeof(float));
        file.read(reinterpret_cast<char*>(&nz), sizeof(float));

        // Read vertex coordinates
        float v1x, v1y, v1z, v2x, v2y, v2z, v3x, v3y, v3z;
        file.read(reinterpret_cast<char*>(&v1x), sizeof(float));
        file.read(reinterpret_cast<char*>(&v1y), sizeof(float));
        file.read(reinterpret_cast<char*>(&v1z), sizeof(float));
        file.read(reinterpret_cast<char*>(&v2x), sizeof(float));
        file.read(reinterpret_cast<char*>(&v2y), sizeof(float));
        file.read(reinterpret_cast<char*>(&v2z), sizeof(float));
        file.read(reinterpret_cast<char*>(&v3x), sizeof(float));
        file.read(reinterpret_cast<char*>(&v3y), sizeof(float));
        file.read(reinterpret_cast<char*>(&v3z), sizeof(float));

        uint16_t attr_byte_count;
        file.read(reinterpret_cast<char*>(&attr_byte_count), sizeof(attr_byte_count));

        // Create Triangle object
        Triangle t = { v1x, v1y, v1z, v2x, v2y, v2z, v3x, v3y, v3z };
        triangles.push_back(t);
    }

    file.close();

    for (const auto& t : triangles) {
        std::cout << "Triangle vertex coordinates: "
            << "(" << t.x1 << ", " << t.y1 << ", " << t.z1 << ") "
            << "(" << t.x2 << ", " << t.y2 << ", " << t.z2 << ") "
            << "(" << t.x3 << ", " << t.y3 << ", " << t.z3 << ")" << std::endl;
    }

    return triangles;
} 
It's because of that 2-byte chunk. Since you read out the 2-byte value too early, it actually got filled with half of a 4-byte float. After that your subsequent reads would start at the wrong location.
Last edited on
That's right. Thank you
Topic archived. No new replies allowed.