C++ 在c+;中导入.STL文件最有效的方法是什么+;?
解析.STL文件最有效的策略是什么 我的代码的一个关键部分是导入一个.STL文件(一种常见的CAD文件格式),这限制了整体性能 .STL文件格式总结如下: 此应用程序需要使用ASCII格式 通用格式为:C++ 在c+;中导入.STL文件最有效的方法是什么+;?,c++,string,file,parsing,cad,C++,String,File,Parsing,Cad,解析.STL文件最有效的策略是什么 我的代码的一个关键部分是导入一个.STL文件(一种常见的CAD文件格式),这限制了整体性能 .STL文件格式总结如下: 此应用程序需要使用ASCII格式 通用格式为: solid name facet normal ni nj nk outer loop vertex v1x v1y v1z vertex v2x v2y v2z vertex v3x v3y v3z
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),对于43000行文件,它给出:
stl_导入()-1.177568 s
解析循环-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();
}
}
cout如果没有可用于测量时间花在何处的数据,则很难确定实际改善性能的因素。一个已经做好这项工作的体面的图书馆可能是最简单的方法。然而,当前的代码使用了一些方法,这些方法可能很容易提高性能。我发现了一些东西:
streams库非常擅长跳过前导空格。您可能希望使用std::getline(infle>>std::ws,line)
:std::ws
操纵器跳过前导空格,而不是先读取空格,然后再修剪它们
std::string const
对象进行比较,而不是进行字符比较,比较大小可能就足够了std::string
转换成std::vector
,我宁愿重置一个合适的流(可能是std::istringstream
,但为了防止复制自定义内存流),并直接从中读取:
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);
}
这种方法还有一个额外的优点,就是允许进行格式检查:我总是不相信收到的任何输入,即使它来自可信的来源std::string_view
(或者,如果此C++17类不可用,则使用类似的类),以避免移动字符std::vector
,然后对其进行解析。相反,我会动态解析文件:这样热内存会立即被重用,而不是将其移出缓存进行后期处理。这种处理辅助流的方式(见上文第3点)可以避免。为了避免过于复杂的读取循环,我将嵌套的部分拆分为适当的函数,并在结束标记上从它们返回。此外,我还为point
等结构定义了输入函数,以便从流中简单地读取它们std::ios\u base::sync\u with\u stdio(false)
:以前至少有一种常用的streams实现,可以从该调用中获益毫无疑问,最好的办法是找到一个合适的图书馆。一个好的解析例程可能会比尝试加快对文件数据的读取速度产生更好的结果。我已经进行了这些编辑,尽管它们不会影响性能。为什么在解析之前要导入整个文件?你这样做浪费了很多内存,可能也浪费了一些时间。
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);
}