【问题标题】:What is the most efficiency way to import an .STL file in c++?在 C++ 中导入 .STL 文件的最有效方法是什么?
【发布时间】:2017-12-13 00:42:34
【问题描述】:

解析 .STL 文件最有效的策略是什么?

我的代码的一个关键部分是导入 .STL 文件(一种常见的 CAD 文件格式),这会限制整体性能。

这里总结了.STL文件格式-https://en.wikipedia.org/wiki/STL_(file_format)

此应用程序需要使用 ASCII 格式。

通用格式为:

solid name
    facet normal ni nj nk
        outer loop
            vertex v1x v1y v1z
            vertex v2x v2y v2z
            vertex v3x v3y v3z
        endloop
    endfacet
endsolid

但是,我注意到没有严格的格式要求。而且,导入功能必须进行最少的错误检查。我已经完成了一些性能测量(使用 chrono),对于 43,000 行文件给出了:

stl_import() - 1.177568 秒

解析循环 - 3.894250 s

解析循环:

cout << "Importing " << stl_path << "... ";
    auto file_vec = import_stl(stl_path);
    for (auto& l : file_vec) {
        trim(l);
        if (solid_state) {
            if (facet_state) {
                if (starts_with(l, "vertex")) {

                    //---------ADD FACE----------//

                    l.erase(0, 6);
                    trim(l);

                    vector<string> strs;
                    split(strs, l, is_any_of(" "));

                    point p = { stod(strs[0]), stod(strs[1]), stod(strs[2]) };
                    facet_points.push_back(p);

                    //---------------------------//
                }
                else {
                    if (starts_with(l, "endfacet")) {
                        facet_state = false;
                    }
                }
            }
            else {
                if (starts_with(l, "facet")) {
                    facet_state = true;
                    //assert(facet_points.size() == 0);

                    //---------------------------//
                    //   Normals can be ignored  //
                    //---------------------------//

                }
                if (starts_with(l, "endsolid")) {
                    solid_state = false;
                }
            }
        }
        else {
            if (starts_with(l, "solid")) {
                solid_state = true;
            }
        }

        if (facet_points.size() == 3) {
            triangle facet(facet_points[0], facet_points[1], facet_points[2]);
            stl_solid.add_facet(facet);
            facet_points.clear();

            //check normal
            facet.normal();
        }
    }

stl_import 函数是:

std::vector<std::string> import_stl(const std::string& file_path)
{
    std::ifstream infile(file_path);
    SkipBOM(infile);
    std::vector<std::string> file_vec;
    std::string line;
    while (std::getline(infile, line))
    {
        file_vec.push_back(line);
    }
    return file_vec;
}

我已经搜索了优化文件读取等的方法。并且,我发现使用 mmap 可以提高文件读取速度。

Fast textfile reading in c++

这个问题是询问 .STL 文件的最佳解析策略是什么?

【问题讨论】:

  • 最好的方法无疑是找到合适的库。与尝试加快对文件数据的读取访问速度相比,一个好的解析例程可能会产生更好的结果。
  • 我已经进行了这些修改,尽管它们不会影响性能。
  • 为什么要在解析之前导入整个文件?这样做会浪费大量内存,而且可能还会浪费一些时间。

标签: c++ string file parsing cad


【解决方案1】:

如果没有可用于衡量时间花费的数据,就很难确定什么能真正提高性能。一个已经完成这项工作的体面的图书馆可能是最简单的方法。但是,当前代码使用了一些可能很容易提高性能的方法。我发现了一些东西:

  1. 流库非常擅长跳过前导空格。您可能需要使用std::getline(infile &gt;&gt; std::ws, line)std::ws 操纵器跳过前导空格,而不是先读取空格然后将其剪掉。
  2. 而不是将starts_with() 与字符串文字一起使用,我宁愿将每一行读入一个“命令”和行尾,并将命令与std::string const 对象进行比较:而不是字符比较,这可能就足够了比较大小。
  3. 我宁愿重置一个合适的流(可能是一个std::istringstream,但要防止复制可能的自定义内存流)并直接从中读取,而不是将split()std::string 转换为空白处的std::vector&lt;std::string&gt;

    std::istringstream in; // declared outside the reading loop
    // ...
    point p;
    in.clear(); // get rid of potentially existing errors
    in.str(line);
    if (in >> p.x >> p.y >> p.z) {
        facet_points.push_back(p);
    }
    

    这种方法具有允许格式检查的额外优势:我总是不信任收到的任何输入,即使它来自受信任的来源。

  4. 如果您坚持使用调整字符序列和/或将其拆分为子序列,我强烈建议使用std::string_view(或者,如果此 C++17 类不可用,则使用类似的类)以避免移动角色。
  5. 假设文件很大,我建议不要将文件读入std::vector&lt;std::string&gt; 然后解析它。相反,我会动态解析文件:这样热内存会立即被重用,而不是将其移出缓存以供以后处理。可以避免以这种方式处理辅助流(参见上面的第 3 点)。为了防止过于复杂的阅读循环,我将嵌套部分拆分为适当的函数,并在结束标记处从它们返回。此外,我会为 point 之类的结构定义输入函数,以便从流中读取它们。
  6. 根据您正在使用的系统,您可能需要在读取文件之前调用 std::ios_base::sync_with_stdio(false):过去至少有一个常用的流实现可以从该调用中受益。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-09-15
    • 2014-09-10
    • 1970-01-01
    • 1970-01-01
    • 2011-12-30
    • 2013-04-28
    相关资源
    最近更新 更多