Autodesk Community Tips- ADNオープン
Autodesk Community Tipsではちょっとしたコツ、やり方、ショートカット、アドバイスやヒントを共有しています。

AutoCAD .NET API:複数図面に対する連続処理の高速化

Issue

AutoCAD .NET API でフォルダ内の DWG ファイルを順に開いて処理していますが、サイズの大きい図面があると相対的に処理時間が長くなってしまいます。高速化するアイデアはありますか?

 

Solution

 

AutoCAD 上に図面を開いて表示する際、描画に多く時間がかかってしまいます。

もし、ユーザインターフェース上に図面を表示する必要がないのであれば、Database.ReadDwgFile メソッドを使って、メモリ上に図面を展開する方法を採用することで、描画にかかかる時間を省いて処理全体を高速化させることが出来ます。

 

次のコードは、フォルダを指定後にフォルダ内の .dwg ファイルを順に Database.ReadDwgFile メソッドでメモリ展開し、モデル空間のオブジェクト タイプを表示するものです。

  [CommandMethod("MyCommand", CommandFlags.Modal)]
  public void MyCommand()
  {
      Document doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument;
      Editor ed = doc.Editor;

      using (FolderBrowserDialog fd = new FolderBrowserDialog())
      {
          if (fd.ShowDialog() == DialogResult.OK)
          {
              string folder = fd.SelectedPath;
              System.IO.DirectoryInfo di = new System.IO.DirectoryInfo(folder);
              IEnumerable<System.IO.FileInfo> files =
    di.EnumerateFiles("*.dwg", System.IO.SearchOption.AllDirectories);
              if (files == null)
                  return;

              ed.WriteMessage("\n\t{0}", folder);
              foreach (System.IO.FileInfo f in files)
              {
                  string file = f.FullName;
                  ed.WriteMessage("\n - {0}", file);

                  try
                  {
                      using (Database db = new Database(false, true))
                      {
                        db.ReadDwgFile(file, FileOpenMode.OpenForReadAndAllShare, false, null);
                        using (Transaction tr = db.TransactionManager.StartTransaction())
                        {
                            BlockTableRecord btr = (BlockTableRecord)tr.GetObject(SymbolUtilityServices.GetBlockModelSpaceId(db), OpenMode.ForRead);
                            foreach (ObjectId id in btr)
                            {
                                Entity ent = (Entity)tr.GetObject(id, OpenMode.ForRead);
                                ed.WriteMessage("\n   - {0}", ent.GetType().ToString());
                            }
                            tr.Commit();
                        }
                    }
                }
                catch (System.Exception ex)
                {
                    ed.WriteMessage(ex.ToString());
                }
            }
        }
    }
}

 

2025-04-04_12-48-16.jpg

なお、Database.ReadDwgFile メソッドの使用時には、次の点に注意が必要です。

 

  • Database.ReadDwgFile メソッドで読み込む Database インスタンスを new ステートメントで用意する必要があります。この際、最低限必要なシンボルテーブルとオーナーシップを持つ Database 構造は、読み込む DWG ファイルに定義されているため、コンストラクタには Database.Database([MarshalAs(UnmanagedType.U1)] bool, [MarshalAs(UnmanagedType.U1)] bool)  オーバーロードを使用して、第1パラメーターの値を false にして、読み込む DWG ファイルの Database 構造との競合を抑止する必要があります。
  • AutoCAD のユーザインターフェースに表示された Database インスタンスは、同図面を表示している MDI 子ウィンドウを閉じると、AutoCAD が Database 領域をメモリから削除します。ただし、Database.ReadDwgFile メソッドでメモリ上に展開した Database インスタンスの領域は、展開したアドイン アプリがメモリーから削除しなければなりません。削除には上、記コードのように using ステートメントを利用してスコープ内の処理後に削除させるか、using ステートメントでスコープ指定せずに Dispose メソッドを明示的に呼び出すことも出来ます。
  • Database.ReadDwgFile メソッドで読み込んだ Database インスタンス内の DBText オブジェクトや AttributeReference オブジェクトの位置合わせを変更する場合、Database インスタンスを HostApplicationServices.WorkingDatabase プロパティで設定していないと予期しないズレが発生する場合があります。これは、DBText クラス実装が、位置合わせ時に現在の図面データベース(Database)を参照している関係で発生してしまう現象です。Database インスタンスを HostApplicationServices.WorkingDatabase プロパティで設定して処理した場合、処理後にオリジナル(ユーザーインターフェースに開いている図面の Database インスタンスを HostApplicationServices.WorkingDatabase プロパティで再設定する必要があります。