2017-12-13 7 views
-5

.STLファイルを解析するための最も効率的な戦略は何ですか?C++で.STLファイルをインポートする最も効率的な方法は何ですか?

私のコードの重要な部分は、.STLファイル(一般的なCADファイル形式)をインポートしており、全体的なパフォーマンスが制限されています。

.STLファイル形式が要約されているhere- 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 

はしかし、私は厳格なフォーマット要件がないことに気付きました。また、インポート関数は最小限のエラーチェックを行う必要があります。

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(); 
     } 
    } 
: - - 1.177568秒

ループを解析ループの解析3.894250秒

stl_importを():私は、43,000行ファイルを提供します(クロノを使用して)いくつかのパフォーマンスの測定を行ってきました

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ファイルのための最高の解析戦略が何であるかの問い合わせのですか?

+0

最も適切な方法は、間違いなく適切なライブラリを見つけることです。優れた解析ルーチンは、ファイルデータへの読み取りアクセスを高速化しようとするよりも良い結果をもたらすでしょう。 –

+0

私はこれらの編集を行ったが、パフォーマンスには影響しません。 – Chris

+0

ファイルを解析する前にファイル全体をインポートするのはなぜですか?あなたはたくさんの記憶を無駄にしているでしょうし、おそらくそれを行うことによっても少し時間がかかります。 –

答えて

2

時間が費やされた場所を測定するために使用できるデータがないと、実際に性能を向上させるものを特定することは困難です。既に仕事をしているまともな図書館が最も簡単なアプローチかもしれません。しかし、現在のコードでは、パフォーマンスを向上させるための簡単な方法がいくつかあります。私が見つけたものがあります:

  1. ストリームライブラリは先行する空白をスキップするのにはかなり良いです。空白を最初に読み込んだ後にトリミングしないで、std::getline(infile >> std::ws, line)を使用することができます。std::wsマニピュレータは空白の先頭をスキップします。
  2. 文字列リテラルでstarts_with()を使用する代わりに、各行を「コマンド」と行の末尾に読み込み、コマンドをstd::string constオブジェクトと比較します。文字比較の代わりに、サイズを比較するだけで十分でしょう。

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

  3. 代わりのsplit()私はむしろ、適切なストリーム(カスタムメモリストリームおそらくコピーを防止するためにおそらくstd::istringstream)をリセットし、それから直接読んだ空白にstd::vector<std::string>std::stringをINGのこのアプローチには、フォーマットチェックを可能にするという利点があります。信頼できるソースからのものであっても、受け取った入力は常に不信です。

  4. 文字シーケンスの調整やサブシーケンスへの分割を主張する場合は、std::string_viewを使用することを強くお勧めします(または、このC++ 17クラスには同じクラスがない場合は移動を避けることをお勧めします)。周囲の文字。
  5. ファイルがかなりのサイズであると仮定して、ファイルを読み取ってstd::vector<std::string>に読み込んでから解析することをお勧めします。代わりに、私はその場でファイルを解析します。この方法では、ホットメモリは、後の後処理のためにキャッシュから移動するのではなく、すぐに再利用されます。補助ストリーム(上記のポイント3を参照)を扱うこの方法は、回避することができます。あまりにも複雑な読み取りループを防ぐために、ネストされたセクションを適切な関数に分割し、終了タグでそれらを戻します。さらに、私はpointのような構造体の入力関数を定義してストリームから読み込むだけです。
  6. あなたが作業しているシステムによっては、ファイルを読む前にstd::ios_base::sync_with_stdio(false)に電話するとよいでしょう。この呼び出しの恩恵を受けるストリームの実装がよく使われていました。
関連する問題