.NET APIを使用してAutoCAD用のプラグインを作成する(パート5-ブロックの紹介)

AutoCADのプラグインの開発に特化したシリーズの第5部では、単純なブロックを作成して図面に配置する方法について説明します。



public static string disclaimer = "          AutoCAD.   –      ."
      
      







はじめに



図面で作業するときに同じタイプのオブジェクトを作成する必要が生じた場合、単一のオブジェクトとして動作するオブジェクトの名前付きグループというブロックメカニズムを使用してこれを行うのが最善です。 ブロックに関する一般的な情報は、 ここで取得できます



ブロック定義とブロック発生 という 2つの概念を明確に区別できることが重要です。 違いの詳細な説明は、 ここ (英語)とここ (rus)にあります。 本質を簡単に説明します。新しいブロックを作成すると、AutoCADはその説明を特別なブロックテーブルに配置します。 この記述はブロック定義と呼ばれます 。 ブロック定義はブロックテーブルにのみ存在し、図面には表示されません。 AutoCADは、 ブロック参照を図面フィールドに直接配置します-ブロック定義へのリンク。 ブロックの定義を変更すると、ブロックのすべての出現がこれらの変更を繰り返します。 記事の後半では、最初の単語(「定義」または「エントリ」)を省略して、単に「ブロック」と書くことがあります。



注意:
私は個人的に、「ブロックエントリ」よりも「ブロックインスタンス」という翻訳が好きだと言わなければなりません。 しかし、それはドキュメントに書かれているので...

彼らが言うように、あなたの父親を敬い、あなたの母親を敬い、取扱説明書を読んでください。



Autocadと通信する過程で、 regulardynamicの 2種類のブロックに出会いました。 後者の主な機能は、要素に特定の「カスタマイズ可能な」パラメータ(たとえば、ブロック内の線の長さやその傾斜角)を設定できることです。 動的ブロックの主な欠点は、.NET APIを使用して作成できないことです。



ダイナミックブロックについては、もう1度説明します。 それまでの間、従来のブロックをどのように使用できるかを見てみましょう。



AutoCADを使用してブロックを手動で作成する



まず、AutoCADで直接ブロックを作成しましょう。 ここではプログラミングは行われませんが、プラグインの結果を少なくともおよそ評価できるようにするために、手動でブロックを作成する機能が役立ちます。 プロセスの詳細-ネタバレの下。



読者が既にAutoCADでブロックを編集することに慣れている場合、このセクションから新しいことを学ぶことはありません。
したがって、まず、ブロックに結合する要素を図面に追加する必要があります。 まず、ブロックに単純な円を追加します。



AutoCADコマンドラインでCIRCLEコマンドを実行し、中心と半径を指定します。 図面に円が表示されます。







円を選択して、 BLOCKコマンドを実行します。 画面にブロック作成メニューが表示されます。 「ブロック」パネルの「作成」ボタンを押すと、同様の結果が得られます。







ブロックに名前を付け、ユニットを「Unitless」に設定し、「Block Editorで開く」ボックスをオフにして、「OK」をクリックします。







注意:
測定単位を選択すると、単位のサイズを指定できます。このサイズは、さまざまな測定システム(ヨーロッパではメートルとミリメートル、アメリカではフィートとインチ)に自動的に変換されます。 値を「単位なし」に設定すると、単位は図面にインストールされている測定単位を使用します。 値は常に「Unitless」に設定します。 良いか悪いかはわかりません。



その後、AutoCADは、基本単位となる図面上のポイントを指定するように求めます。 通常、ブロックの中心またはその左下隅がこの点として指定されます。 円の中心を基点として示します。



ブロックの作成が完了しました。 ブロックの最初の出現は自動的に図面に追加され、このブロックが作成された要素を置き換えます。 作成したブロックの複数のオカレンスを図面に追加するには、[ブロック]パネルでINSERTコマンドまたは同じ名前のボタンを使用できます。







コマンドを実行するかボタンを押すと、ブロックを挿入するためのウィンドウが画面に表示されます。







リストで目的のブロックを選択し、[OK]をクリックして、挿入ポイントを指定します-ブロックが図面に表示されます。 オブジェクトを選択し、プロパティウィンドウを見ると、これがブロックであることを確認できます。







ブロックを編集するには、 BEDITコマンドまたは「ブロック」パネルの対応するボタンによって呼び出されるエディターを使用します。







コマンドを実行するか、前述のボタンをクリックすると、ブロック定義を選択するためのウィンドウが画面に表示されます。







このウィンドウで、編集する定義を選択し、「OK」をクリックする必要があります。 その後、AutoCADはブロックエディターを開きます。 私の意見では、エディターパネルの最も重要なボタンについて見ていきましょう。







  • ブロックの保存 -すべての変更を保存します。 ブロックエディタを閉じた後、図面にあるすべてのブロックオカレンスは、ブロック定義の変更に従って更新されます。
  • オーサリングパレット -属性ウィンドウを表示または非表示にします。 このウィンドウは、動的ブロックを操作するときに役立ちます。
  • ポイント -このドロップダウンサブメニューの項目は「ベースポイント」で、これを使用してブロックに新しいベースポイントを設定できます。
  • ブロックエディターを閉じる - ブロックエディターを閉じます 。 保存されていない変更はすべて失われます。


エディター内で、ブロック定義に新しいオブジェクトを追加し、不要なオブジェクトを削除できます。 ブロックの編集は、通常の図面の編集に似ています。



これで、AutoCADでのブロックの作成に関する短い説明は終わりです。 コードにアクセスできます。 :-)





AutoCAD .NET APIを使用してブロックを作成する





単純なブロックを作成する例



このセクションは、対応するKean Walmsleyのブログ投稿に基づいています(元のソースと比較した例の方がはるかに簡単です)。 ポリライン、円、テキストのブロックで構成される単純なブロックを作成します。



ソーセージスクラップについて少し
ところで、ソーセージのスクラップについて話し始めてから......

過去数年にわたって(神、時間の経過!)多くの良いことが起こりました。 特に、 世界ベストアンドグレイテストカンパニーは、無料のプロフェッショナルバージョンのVisual Studioをリリースしています。

はい、Visual Studio Community EditionはExpressよりも多くのスペースを必要とし、そのインターフェイスはもう少し複雑です-しかし、遅かれ早かれ開発者は通常IDEアドオンで作業する必要があり、Expressバージョンではサポートされません。 そのようなこと。

実例:これらの行の作成者はVS Expressでプラグインを元気に書きましたが、問題は何も移植しませんでした...インストーラー(Wixテクノロジーを使用して作成されたmsiファイル)を追加するまで。 その結果、すべてのインストーラーコードをメモ帳++で記述し、ドキュメントを毎分チェックし、手動でコンパイルする必要がありました。



また、Visual Studio Professionalでは、プラグインをプラグインするだけでWixを操作し、IDEですべてを実行できます。ヒント、コード補完、およびプロジェクトでのコンパイルが可能です。 できます。 それは...



一般的に、PCが250台以下で年間収入が1,000,000ドル未満の会社で働いている場合、余計な意味のない数時間の生活がある場合は、この製品をインストールしてから作業することを強くお勧めします。

人生に意味のない時間がなければ、すべてが腐りやすく、人生は痛みであり、インストールされたVisual Studio Community Editionなしであなたの存在を引き出すことは、この世界のエントロピーを増やすことを意味します。



ブロックを作成し、そのオカレンスを図面に配置するには、次を実行する必要があります。

  1. ブロックテーブルに新しいレコードを作成します(ブロック定義)。
  2. 必要な幾何学的オブジェクトをブロック定義に追加します。
  3. 図面にブロックエントリを追加します。


それでは始めましょう。



外部リンクの接続、 CopyLocal



禁止、.NETバージョンの指定など、プラグイン作成のマイナーな機能についてはCopyLocal



これは、シリーズの以前の投稿で繰り返し議論されています。 この例では、 AcMgdおよびAcDBMgdライブラリへの参照が必要です。 コードはほとんどありません。 一度にすべて持ってきて、詳細を分析します。



コード:
 using System; using System.IO; using Autodesk.AutoCAD.Runtime; using Autodesk.AutoCAD.DatabaseServices; using Autodesk.AutoCAD.Geometry; using Autodesk.AutoCAD.ApplicationServices; using Autodesk.AutoCAD.EditorInput; using acad = Autodesk.AutoCAD.ApplicationServices.Application; namespace HabrPlug_SimpleBlock { public class ClassMyAutoCADDLL_SimpleBlock { public class Commands : IExtensionApplication { //        AutoCAD  "HabrCommand" [CommandMethod("HabrCommand")] public void HabrCommand() { //        Document doc = Application.DocumentManager.MdiActiveDocument; Database db = doc.Database; //   "Editor"         AutoCAD Editor ed = doc.Editor; //    const string blockName = "pvtBlock"; //   Transaction tr = db.TransactionManager.StartTransaction(); using (tr) { //*** //  1 -       //*** //      BlockTable bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForWrite); //  ,         //   -         if (bt.Has(blockName)) { ed.WriteMessage("\nA block with the name \"" + blockName + "\" already exists."); return; } //    ,    BlockTableRecord btr = new BlockTableRecord(); btr.Name = blockName; //          , //  ID    (   ) ObjectId btrId = bt.Add(btr); tr.AddNewlyCreatedDBObject(btr, true); //*** //  2 -        //*** //   Polyline poly = new Polyline(); poly.SetDatabaseDefaults(); poly.AddVertexAt(0, new Point2d(-50, -125), 0, 0, 0); poly.AddVertexAt(1, new Point2d(-50, 105), 0, 0, 0); poly.AddVertexAt(2, new Point2d(-20, 125), 0, 0, 0); poly.AddVertexAt(3, new Point2d(20, 125), 0, 0, 0); poly.AddVertexAt(4, new Point2d(50, 105), 0, 0, 0); poly.AddVertexAt(5, new Point2d(50, -125), 0, 0, 0); poly.AddVertexAt(6, new Point2d(-50, -125), 0, 0, 0); //         btr.AppendEntity(poly); tr.AddNewlyCreatedDBObject(poly, true); //   Circle cir = new Circle(); cir.SetDatabaseDefaults(); cir.Center = new Point3d(0, 90, 0); cir.Radius = 15; //         btr.AppendEntity(cir); tr.AddNewlyCreatedDBObject(cir, true); //   DBText text = new DBText(); text.Position = new Point3d(-25, -95, 0); text.Height = 35; text.TextString = "BC"; //         btr.AppendEntity(text); tr.AddNewlyCreatedDBObject(text, true); //*** //  3 -       //*** //      BlockTableRecord ms = (BlockTableRecord)tr.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForWrite); //    ,    ID   BlockReference br = new BlockReference(Point3d.Origin, btrId); //           ms.AppendEntity(br); tr.AddNewlyCreatedDBObject(br, true); //   tr.Commit(); } } //  Initialize()  Terminate() ,    IExtensionApplication public void Initialize() { } public void Terminate() { } } } }
      
      





プラグインをロードしてHabrCommandコマンドを実行すると、次の図が表示されます。






それでは、コードで何が起こるかを理解しましょう。



最初に、準備操作を実行します。ドキュメント、そのデータベース、およびEditor



プロパティへのリンクを取得し、新しいブロックの名前を設定して、トランザクションを開始します。 おそらくEditor



プロパティを除き、これには新しいものはありません。



Editor



クラスの詳細な情報を即座に見つけることができませんでした。 知識のある人がこのクラスとそのメソッドの正しい説明(または、少なくともObjectARXリファレンスのどこにあるのか)へのリンクを促してくれたら嬉しいです。 この例では、 Editor



クラスは、同じ名前のブロックがデータベースに既に存在するというメッセージを表示するためにのみ使用されます。 AutoCADでは、このメッセージは次のようになります。







トランザクション内では、このサブセクションの冒頭で概説したアルゴリズムに従います。



最初のステップでは、ブロックテーブルに新しいレコードを作成します。

  1. ブロックテーブルを開きます(変更を加えるため、書き込みアクセスを要求します)。
  2. テーブルにその名前のブロックが存在するかどうかを確認します(ブロックテーブルに既に存在する名前のブロックを作成しようとすると、 eDuplicateRecordName



    例外が発生しますが、これは絶対に必要ありません)。
  3. 新しいブロック定義を作成します。
  4. 作成されたブロック定義に名前を設定します。
  5. 作成したブロック定義をブロックテーブルとトランザクションに追加します。


2番目のステップでは、作成されたレコードに必要な幾何プリミティブを追加します。 ポリライン、円、テキストの3つがあります。



ポリラインと円を図面に追加する方法については、前の記事で説明しました。 テキストでは、すべてが同じように起こります。 通常、グラフィックオブジェクトをブロックに追加するには、3つの手順を実行します。

  1. 必要なオブジェクトが作成されます。
  2. このオブジェクトのプロパティが設定されます。
  3. 作成されたオブジェクトは、ブロック定義とトランザクションに追加されます。


これは、ポリラインと円の両方、およびテキストに適用されます。 コードのどの部分がどのアイテムに責任があるのか​​は明らかです。 図面へのテキストの追加について詳しくは、 こちら (英語)とこちら (rus)をご覧ください



3番目のステップでは、作成したブロックのオカレンスを図面に追加します。 ここでの手順は次のとおりです。

  1. モデル空間は記録用に開かれています。
  2. 新しいブロックエントリが作成されます。
  3. 作成されたブロックエントリがモデル空間とトランザクションに追加されます。


新しいブロックエントリを作成するときに使用されるBlockReference



クラスのコンストラクターについて詳しく説明します。 このコンストラクターは、ブロック配置ポイント(ブロックのベースエントリポイントがこのポイントと結合される)とブロック定義IDの2つのパラメーターを取ります。 つまり、AutoCADに表示するブロックと場所を指示する必要があります。 この例では、ブロックの原点( Point3d.Origin



)がブロック配置ポイントとして示されており、この定義を作成する最初のステップでブロック定義IDを保存しました。



ドキュメントブロックテーブルに既にあるブロックを使用する



前の例でHabrCommandコマンドを実行してから、表示されたブロックを図面から削除してHabrCommandコマンドを再度実行すると、「pvtBlockという名前のブロックが既に存在します」というメッセージが表示され、図面には何も表示されません。 以前に作成したブロック定義を使用するにObjectID



この定義のObjectID



を知る必要がObjectID



ます。 この場合、コードは次のように書き換えることができます。



チームコード:
 [CommandMethod("HabrCommand")] public void HabrCommand() { //        Document doc = Application.DocumentManager.MdiActiveDocument; Database db = doc.Database; //   "Editor"         AutoCAD Editor ed = doc.Editor; //    const string blockName = "pvtBlock"; //   Transaction tr = db.TransactionManager.StartTransaction(); using (tr) { //*** //  1 -       (  ID ) //*** //      BlockTable bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead); // ,         //   -   ID ObjectId btrId; if (bt.Has(blockName)) { btrId = bt[blockName]; } else { //      bt.UpgradeOpen(); //    ,    BlockTableRecord btr = new BlockTableRecord(); btr.Name = blockName; //       ,   ID btrId = bt.Add(btr); //       tr.AddNewlyCreatedDBObject(btr, true); //*** //  2 -        //*** //   Polyline poly = new Polyline(); poly.SetDatabaseDefaults(); poly.AddVertexAt(0, new Point2d(-50, -125), 0, 0, 0); poly.AddVertexAt(1, new Point2d(-50, 105), 0, 0, 0); poly.AddVertexAt(2, new Point2d(-20, 125), 0, 0, 0); poly.AddVertexAt(3, new Point2d(20, 125), 0, 0, 0); poly.AddVertexAt(4, new Point2d(50, 105), 0, 0, 0); poly.AddVertexAt(5, new Point2d(50, -125), 0, 0, 0); poly.AddVertexAt(6, new Point2d(-50, -125), 0, 0, 0); //         btr.AppendEntity(poly); tr.AddNewlyCreatedDBObject(poly, true); //   Circle cir = new Circle(); cir.SetDatabaseDefaults(); cir.Center = new Point3d(0, 90, 0); cir.Radius = 15; //         btr.AppendEntity(cir); tr.AddNewlyCreatedDBObject(cir, true); //   DBText text = new DBText(); text.Position = new Point3d(-33, -95, 0); text.Height = 35; text.TextString = "BC"; //         btr.AppendEntity(text); tr.AddNewlyCreatedDBObject(text, true); } //*** //  3 -       //*** //      BlockTableRecord ms = (BlockTableRecord)tr.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForWrite); //    ,    ID   BlockReference br = new BlockReference(Point3d.Origin, btrId); //          ms.AppendEntity(br); tr.AddNewlyCreatedDBObject(br, true); //   tr.Commit(); } }
      
      





ここでHabrCommandコマンドを実行し、表示されているブロックを削除してHabrCommandコマンドを再実行すると、ブロックのエントリが図面に再表示されます。 この場合、新しいブロック定義は作成されません-プラグインはすでにブロックテーブルにあるレコードを取得します。



この例では、変更のためにUpgradeOpen()



メソッドを使用しUpgradeOpen()



。これは、例やドキュメントに頻繁に登場します。 仕組みを見てみましょう。



最初の例で、書き込み用にブロックのテーブルをすぐに開いた場合( OpenMode.ForWrite



)、読み取り専用にブロックのテーブルを開きます( OpenMode.ForRead



)。 これでテーブルを表示し、名前のブロックが含まれているかどうかを確認できます。 そのようなブロックが見つかった場合、そのObjectID



を読み取ることができますが、この場合も読み取り専用アクセスのみが可能です。 私たちの名前のブロックがテーブルにない場合、それを追加する必要があり、そのためには書き込みアクセスが必要になります。 このアクセスを取得するには、 UpgradeOpen()



メソッドを使用します。このメソッドを呼び出した後、 OpenMode.ForWrite



アクセスOpenMode.ForWrite



開いたようにブロックテーブルを操作できOpenMode.ForWrite







注意:
UpgradeOpen()



を使用することをおUpgradeOpen()



ます。 少なくともキーン・ウォルムズリーはまさにそれをします。 しかし、 UpgradeOpen()



を使用する人に与えられる人生の宝と祝福に関する詳細なデータはありません。 私自身は、このデザインを仕事に使用せず、これについてあまり悲しみを感じませんでした。 誰かがUpgradeOpen()



使用に関して自分の立場を示すことがUpgradeOpen()



ば-コメントまたはPMでそれを見てうれしいです。


ブロック挿入位置の変更



図面内のブロックが表示される場所では、次の2つのことに依存して事前に予測することは不可能です。



この例では、基点はブロックの中心にあります。



写真:






ブロック定義を作成するときに、基点を明示的に指定したことはありません。このような場合、AutoCADは基点を原点と見なします。 この例では、座標の中心と一致するように、フィギュアの「中心」が特別に選択されています。



ブロックエディター(これを行う方法、投稿の最初のセクションで説明しました)または.NET APIを使用して、ブロックのベース定義ポイントを手動で変更できます。後者の場合、この目的のためにOrigin



クラスプロパティが使用されBlockTableRecord



ます。例として、ブロック定義の基点を左下隅に移動してみましょう。これを行うには、ブロックの名前を指定した後、プロパティを設定しますOrigin





 //    btr.Name = blockName; //    btr.Origin = new Point3d(-50, -125, 0);
      
      





-50と-125の数値は、それぞれX軸とY軸に沿ったブロックの最小座標です(ブロックの外側の境界を形成するポリラインの左下の頂点には、このような座標があります)。



結果:




ブロックが移動しました。


次に、ブロックの挿入ポイントを扱います。ブロックが出現するたびに設定され、ブロックを挿入した後、その基点がどこにあるかを示します。このプロパティは、クラスコンストラクターで設定されます。BlockReference



たとえば、次のようになります。

 BlockReference br = new BlockReference(new Point3d(150, 150, 0), btrId);
      
      





基点と挿入点を同時に変更すると、次の図が表示されます。




.


Position



クラスのプロパティを使用してブロック挿入ポイントを変更することもできますBlockReference





 BlockReference br = new BlockReference(Point3d.Origin, btrId); br.Position = new Point3d(150, 150, 0);
      
      





効果は、クラスコンストラクターでポイントを直接設定する場合と同じBlockReference



です。



ブロック内でブロックを使用する



ここではブロックが大好きなので、ブロックをいくつか追加して、描画を単純化しながら描画を単純化しましょう。



ヨダウ!






ブロックをブロック定義に追加することは難しくありません。主な機能は、ブロックにジオメトリプリミティブを追加するのではなく、補助ブロックのオカレンスを追加する場合、この補助ブロックの定義がドキュメントブロックのテーブルにあることを確認する必要があることです。



チームコード:
 [CommandMethod("HabrCommand")] public void HabrCommand() { //        Document doc = Application.DocumentManager.MdiActiveDocument; Database db = doc.Database; //   "Editor"         AutoCAD Editor ed = doc.Editor; //    const string blockName = "ltBlock"; //    const string auxBlockName = "starBlock"; //   Transaction tr = db.TransactionManager.StartTransaction(); using (tr) { //      BlockTable bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForWrite); //*** //  0 -         (  ID ) //*** // ,         //   -   ID ObjectId btrIdAux; if (bt.Has(auxBlockName)) { btrIdAux = bt[auxBlockName]; } else { //    ,    BlockTableRecord btr = new BlockTableRecord(); btr.Name = auxBlockName; //       ,   ID btrIdAux = bt.Add(btr); //       tr.AddNewlyCreatedDBObject(btr, true); //   Polyline poly = new Polyline(); poly.SetDatabaseDefaults(); poly.AddVertexAt(0, new Point2d(0, -6), 0, 0, 0); poly.AddVertexAt(1, new Point2d(-9, -12), 0, 0, 0); poly.AddVertexAt(2, new Point2d(-7, -2), 0, 0, 0); poly.AddVertexAt(3, new Point2d(-14, 6), 0, 0, 0); poly.AddVertexAt(4, new Point2d(-5, 6), 0, 0, 0); poly.AddVertexAt(5, new Point2d(0, 15), 0, 0, 0); poly.AddVertexAt(6, new Point2d(5, 6), 0, 0, 0); poly.AddVertexAt(7, new Point2d(14, 6), 0, 0, 0); poly.AddVertexAt(8, new Point2d(7, -2), 0, 0, 0); poly.AddVertexAt(9, new Point2d(9, -12), 0, 0, 0); poly.AddVertexAt(10, new Point2d(0, -6), 0, 0, 0); //         btr.AppendEntity(poly); tr.AddNewlyCreatedDBObject(poly, true); } //*** //     (  ID  ) //*** //*** //  1 -       (  ID ) //*** // ,         //   -   ID ObjectId btrId; if (bt.Has(blockName)) { btrId = bt[blockName]; } else { //    ,    BlockTableRecord btr = new BlockTableRecord(); btr.Name = blockName; //       ,   ID btrId = bt.Add(btr); //       tr.AddNewlyCreatedDBObject(btr, true); //*** //  2 -        //*** //   Polyline polyExt = new Polyline(); polyExt.SetDatabaseDefaults(); polyExt.AddVertexAt(0, new Point2d(-50, -125), 0, 0, 0); polyExt.AddVertexAt(1, new Point2d(-50, 105), 0, 0, 0); polyExt.AddVertexAt(2, new Point2d(-20, 125), 0, 0, 0); polyExt.AddVertexAt(3, new Point2d(20, 125), 0, 0, 0); polyExt.AddVertexAt(4, new Point2d(50, 105), 0, 0, 0); polyExt.AddVertexAt(5, new Point2d(50, -125), 0, 0, 0); polyExt.AddVertexAt(6, new Point2d(-50, -125), 0, 0, 0); //         btr.AppendEntity(polyExt); tr.AddNewlyCreatedDBObject(polyExt, true); //     Polyline polyIn = new Polyline(); polyIn.SetDatabaseDefaults(); polyIn.AddVertexAt(0, new Point2d(-5, -125), 0, 0, 0); polyIn.AddVertexAt(1, new Point2d(-5, 125), 0, 0, 0); polyIn.AddVertexAt(2, new Point2d(5, 125), 0, 0, 0); polyIn.AddVertexAt(3, new Point2d(5, -125), 0, 0, 0); //          btr.AppendEntity(polyIn); tr.AddNewlyCreatedDBObject(polyIn, true); //   Circle cir = new Circle(); cir.SetDatabaseDefaults(); cir.Center = new Point3d(0, 90, 0); cir.Radius = 15; //         btr.AppendEntity(cir); tr.AddNewlyCreatedDBObject(cir, true); //         BlockReference starLeft = new BlockReference(new Point3d(-27, -75, 0), btrIdAux); btr.AppendEntity(starLeft); tr.AddNewlyCreatedDBObject(starLeft, true); BlockReference starRight = new BlockReference(new Point3d(27, -75, 0), btrIdAux); btr.AppendEntity(starRight); tr.AddNewlyCreatedDBObject(starRight, true); } //*** //  3 -       //*** //      BlockTableRecord ms = (BlockTableRecord)tr.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForWrite); //    ,    ID   BlockReference br = new BlockReference(new Point3d(150, 150, 0), btrId); //          ms.AppendEntity(br); tr.AddNewlyCreatedDBObject(br, true); //   tr.Commit(); } }
      
      





結果:






ここで、概して、コメントすることは何もありません。補助ブロックの定義をブロックテーブルに追加してから、補助ブロックのエントリを作成し、挿入ポイントの座標を設定します。



簡単な独立した演習として、読者はブロック要素をペイントし、注文番号1500に従ってサイズと位置を指定してください。



サンプル:








ブロックを使用する理由



主に2つの理由があります... 2番目から始めましょう。



第二の理由



図面に同じタイプのオブジェクトが多数含まれている場合、ブロックを使用すると、図面ファイルのサイズが大幅に削減されます。次のコードはこれを感じるのに役立ちます。



プラグインコード:
 using System; using System.IO; using Autodesk.AutoCAD.Runtime; using Autodesk.AutoCAD.DatabaseServices; using Autodesk.AutoCAD.Geometry; using Autodesk.AutoCAD.ApplicationServices; using Autodesk.AutoCAD.EditorInput; using acad = Autodesk.AutoCAD.ApplicationServices.Application; namespace HabrPlug_SimpleBlock { public class ClassMyAutoCADDLL_SimpleBlock { public class Commands : IExtensionApplication { // ,         public void drawFigure(double x, double y) { //        Document doc = Application.DocumentManager.MdiActiveDocument; Database db = doc.Database; //   Transaction tr = db.TransactionManager.StartTransaction(); using (tr) { //      BlockTable bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForWrite); //      BlockTableRecord ms = (BlockTableRecord)tr.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForWrite); //   Polyline polyExt = new Polyline(); polyExt.SetDatabaseDefaults(); polyExt.AddVertexAt(0, new Point2d(x - 50, y - 125), 0, 0, 0); polyExt.AddVertexAt(1, new Point2d(x - 50, y + 105), 0, 0, 0); polyExt.AddVertexAt(2, new Point2d(x - 20, y + 125), 0, 0, 0); polyExt.AddVertexAt(3, new Point2d(x + 20, y + 125), 0, 0, 0); polyExt.AddVertexAt(4, new Point2d(x + 50, y + 105), 0, 0, 0); polyExt.AddVertexAt(5, new Point2d(x + 50, y - 125), 0, 0, 0); polyExt.AddVertexAt(6, new Point2d(x - 50, y - 125), 0, 0, 0); //         ms.AppendEntity(polyExt); tr.AddNewlyCreatedDBObject(polyExt, true); //    Polyline polyIn = new Polyline(); polyIn.SetDatabaseDefaults(); polyIn.AddVertexAt(0, new Point2d(x - 5, y - 125), 0, 0, 0); polyIn.AddVertexAt(1, new Point2d(x - 5, y + 125), 0, 0, 0); polyIn.AddVertexAt(2, new Point2d(x + 5, y + 125), 0, 0, 0); polyIn.AddVertexAt(3, new Point2d(x + 5, y - 125), 0, 0, 0); //          ms.AppendEntity(polyIn); tr.AddNewlyCreatedDBObject(polyIn, true); //   Circle cir = new Circle(); cir.SetDatabaseDefaults(); cir.Center = new Point3d(x, y + 90, 0); cir.Radius = 15; //         ms.AppendEntity(cir); tr.AddNewlyCreatedDBObject(cir, true); //  ,         Polyline starLeft= new Polyline(); starLeft.SetDatabaseDefaults(); starLeft.AddVertexAt(0, new Point2d(x - 27, y - 75 - 6), 0, 0, 0); starLeft.AddVertexAt(1, new Point2d(x - 27 - 9, y - 75 - 12), 0, 0, 0); starLeft.AddVertexAt(2, new Point2d(x - 27 - 7, y - 75 - 2), 0, 0, 0); starLeft.AddVertexAt(3, new Point2d(x - 27 - 14, y - 75 + 6), 0, 0, 0); starLeft.AddVertexAt(4, new Point2d(x - 27 - 5, y - 75 + 6), 0, 0, 0); starLeft.AddVertexAt(5, new Point2d(x - 27, y - 75 + 15), 0, 0, 0); starLeft.AddVertexAt(6, new Point2d(x - 27 + 5, y - 75 + 6), 0, 0, 0); starLeft.AddVertexAt(7, new Point2d(x - 27 + 14, y - 75 + 6), 0, 0, 0); starLeft.AddVertexAt(8, new Point2d(x - 27 + 7, y - 75 - 2), 0, 0, 0); starLeft.AddVertexAt(9, new Point2d(x - 27 + 9, y - 75 - 12), 0, 0, 0); starLeft.AddVertexAt(10, new Point2d(x - 27, y - 75 - 6), 0, 0, 0); ms.AppendEntity(starLeft); tr.AddNewlyCreatedDBObject(starLeft, true); Polyline starRight = new Polyline(); starRight.SetDatabaseDefaults(); starRight.AddVertexAt(0, new Point2d(x + 27, y - 75 - 6), 0, 0, 0); starRight.AddVertexAt(1, new Point2d(x + 27 - 9, y - 75 - 12), 0, 0, 0); starRight.AddVertexAt(2, new Point2d(x + 27 - 7, y - 75 - 2), 0, 0, 0); starRight.AddVertexAt(3, new Point2d(x + 27 - 14, y - 75 + 6), 0, 0, 0); starRight.AddVertexAt(4, new Point2d(x + 27 - 5, y - 75 + 6), 0, 0, 0); starRight.AddVertexAt(5, new Point2d(x + 27, y - 75 + 15), 0, 0, 0); starRight.AddVertexAt(6, new Point2d(x + 27 + 5, y - 75 + 6), 0, 0, 0); starRight.AddVertexAt(7, new Point2d(x + 27 + 14, y - 75 + 6), 0, 0, 0); starRight.AddVertexAt(8, new Point2d(x + 27 + 7, y - 75 - 2), 0, 0, 0); starRight.AddVertexAt(9, new Point2d(x + 27 + 9, y - 75 - 12), 0, 0, 0); starRight.AddVertexAt(10, new Point2d(x + 27, y - 75 - 6), 0, 0, 0); ms.AppendEntity(starRight); tr.AddNewlyCreatedDBObject(starRight, true); //   tr.Commit(); } } // ,       public void drawBlock(double x, double y) { //        Document doc = Application.DocumentManager.MdiActiveDocument; Database db = doc.Database; //   "Editor"         AutoCAD Editor ed = doc.Editor; //    const string blockName = "ltBlock"; const string auxBlockName = "starBlock"; //   Transaction tr = db.TransactionManager.StartTransaction(); using (tr) { //      BlockTable bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForWrite); //*** //  0 -         (  ID ) //*** ObjectId btrIdAux; if (bt.Has(auxBlockName)) { btrIdAux = bt[auxBlockName]; } else { //    ,    BlockTableRecord btr = new BlockTableRecord(); btr.Name = auxBlockName; //       ,   ID btrIdAux = bt.Add(btr); //       tr.AddNewlyCreatedDBObject(btr, true); //   Polyline poly = new Polyline(); poly.SetDatabaseDefaults(); poly.AddVertexAt(0, new Point2d(0, -6), 0, 0, 0); poly.AddVertexAt(1, new Point2d(-9, -12), 0, 0, 0); poly.AddVertexAt(2, new Point2d(-7, -2), 0, 0, 0); poly.AddVertexAt(3, new Point2d(-14, 6), 0, 0, 0); poly.AddVertexAt(4, new Point2d(-5, 6), 0, 0, 0); poly.AddVertexAt(5, new Point2d(0, 15), 0, 0, 0); poly.AddVertexAt(6, new Point2d(5, 6), 0, 0, 0); poly.AddVertexAt(7, new Point2d(14, 6), 0, 0, 0); poly.AddVertexAt(8, new Point2d(7, -2), 0, 0, 0); poly.AddVertexAt(9, new Point2d(9, -12), 0, 0, 0); poly.AddVertexAt(10, new Point2d(0, -6), 0, 0, 0); //         btr.AppendEntity(poly); tr.AddNewlyCreatedDBObject(poly, true); } //*** //  1 -       (  ID ) //*** // ,         //   -   ID ObjectId btrId; if (bt.Has(blockName)) { btrId = bt[blockName]; } else { //    ,    BlockTableRecord btr = new BlockTableRecord(); btr.Name = blockName; //       ,   ID btrId = bt.Add(btr); //       tr.AddNewlyCreatedDBObject(btr, true); //*** //  2 -        //*** //   Polyline polyExt = new Polyline(); polyExt.SetDatabaseDefaults(); polyExt.AddVertexAt(0, new Point2d(-50, -125), 0, 0, 0); polyExt.AddVertexAt(1, new Point2d(-50, 105), 0, 0, 0); polyExt.AddVertexAt(2, new Point2d(-20, 125), 0, 0, 0); polyExt.AddVertexAt(3, new Point2d(20, 125), 0, 0, 0); polyExt.AddVertexAt(4, new Point2d(50, 105), 0, 0, 0); polyExt.AddVertexAt(5, new Point2d(50, -125), 0, 0, 0); polyExt.AddVertexAt(6, new Point2d(-50, -125), 0, 0, 0); //         btr.AppendEntity(polyExt); tr.AddNewlyCreatedDBObject(polyExt, true); //    Polyline polyIn = new Polyline(); polyIn.SetDatabaseDefaults(); polyIn.AddVertexAt(0, new Point2d(-5, -125), 0, 0, 0); polyIn.AddVertexAt(1, new Point2d(-5, 125), 0, 0, 0); polyIn.AddVertexAt(2, new Point2d(5, 125), 0, 0, 0); polyIn.AddVertexAt(3, new Point2d(5, -125), 0, 0, 0); //          btr.AppendEntity(polyIn); tr.AddNewlyCreatedDBObject(polyIn, true); //   Circle cir = new Circle(); cir.SetDatabaseDefaults(); cir.Center = new Point3d(0, 90, 0); cir.Radius = 15; //         btr.AppendEntity(cir); tr.AddNewlyCreatedDBObject(cir, true); //   BlockReference starLeft = new BlockReference(new Point3d(-27, -75, 0), btrIdAux); btr.AppendEntity(starLeft); tr.AddNewlyCreatedDBObject(starLeft, true); BlockReference starRight = new BlockReference(new Point3d(27, -75, 0), btrIdAux); btr.AppendEntity(starRight); tr.AddNewlyCreatedDBObject(starRight, true); } //*** //  3 -       //*** //      BlockTableRecord ms = (BlockTableRecord)tr.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForWrite); //    ,    ID   BlockReference br = new BlockReference(new Point3d(x, y, 0), btrId); //          ms.AppendEntity(br); tr.AddNewlyCreatedDBObject(br, true); //   tr.Commit(); } } //        AutoCAD  "HabrCommand_DrawFigures" [CommandMethod("HabrCommand_DrawFigures")] public void HabrCommand_DrawFigures() { for (int x = 0; x < 100; x++) { for (int y = 0; y < 100; y++) { drawFigure(125 * x, 300 * y); } } } //        AutoCAD  "HabrCommand_DrawBlocks" [CommandMethod("HabrCommand_DrawBlocks")] public void HabrCommand_DrawBlocks() { for (int x = 0; x < 100; x++) { for (int y = 0; y < 100; y++) { drawBlock(125 * x, 300 * y); } } } //  Initialize()  Terminate() ,    IExtensionApplication public void Initialize() { } public void Terminate() { } } } }
      
      





コードは非常に簡単です。2つの手順があります- drawFigure(double x, double y)



drawBlock(double x, double y)



最初のブロックは、指定されたポイントにブロックを正確に繰り返す一連の図形を描画し、2番目のブロックは指定されたポイントにブロックのオカレンスを作成します。HabrCommand_DrawFiguresHabrCommand_DrawBlocksの



2つのコマンドが続きます1つ目は図面に10,000セットの図形を描画し、2つ目はブロックの10,000回の出現を描画します。



作業結果
:







:







:







:







:







AutoCADを実行し、最初のコマンドを実行して、図面を保存します。次に、AutoCADを閉じて、2番目のコマンドに対して同じ手順を繰り返します。その結果、2つのdwgファイルを取得します。サイズを比較します。



終わりは少し予測可能です:
:







:







第一の理由



図面ファイルのサイズをわずかに大きくすることは良くありませんが、それほど怖くはありません。ロシアは大きく、誰もが十分なスペースがあります。ただし、問題があり、より深刻です。



前述の注文番号1500で、ショルダーストラップのボタンの位置を厳密に規制する追加が行われ、すべてのショルダーストラップの現在の位置からわずかに高い位置を移動する必要があると想像してください



ブロックを使用した場合、タスクは数行のコードで解決されます。ブロックの定義を開き、そこで円を見つけ、その中心を目的のポイントに移動するだけです。ブロックのすべての出現は同じ定義を参照するため、コマンドの実行後、それらはすべて自動的に更新されます。



チームコード:
 [CommandMethod("HabrCommand_MoveButton")] public void HabrCommand_MoveButton() { //        Document doc = Application.DocumentManager.MdiActiveDocument; Database db = doc.Database; //   "Editor"         AutoCAD Editor ed = doc.Editor; //    const string blockName = "ltBlock"; //   Transaction tr = db.TransactionManager.StartTransaction(); using (tr) { //      BlockTable bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForWrite); // ,         //   -       if (!bt.Has(blockName)) { ed.WriteMessage("Block not found!"); return; } else { //      BlockTableRecord btr = tr.GetObject(bt[blockName], OpenMode.ForWrite) as BlockTableRecord; //    ID     foreach (ObjectId id in btr) { //   ID   ,     DBObject obj = tr.GetObject(id, OpenMode.ForRead); //    -  (Circle),           if (obj.GetType() == typeof(Circle)) { obj.UpgradeOpen(); (obj as Circle).Center = new Point3d(0, 100, 0); } } //   tr.Commit(); } }
      
      





注意:
, . ; . (.) (.) . , , , . , , .



細部:AutoCADはブロックのすべての出現を実際に更新しますが、これを確認するには、REGENコマンドを実行する必要があります







結果:
:







:







もちろん、このような操作は、ブロックの出現ではなく幾何学的図形の場合に実行できますが、図面全体を操作し、円の中心の座標を1回ではなく1万回変更する必要があります。テストは行いませんでしたが、この手順はブロック定義を編集するよりも少し時間がかかると思います。



一方、各コインには表と裏があり、ブロックを使用するとその制限が課せられます。



たとえば、11行目と42列目にある中eの肩章をキャプテンの肩章に置き換える必要がある場合、通常の方法でブロックを使用すると、これを行うことができません。



あなたは船長のために新しいブロックを作成するか、星を手動で仕上げるか、いくつかの追加の倒錯に頼らなければなりません。



注意:
NBpaeHu — , . , .



簡単な結論(まあ、それなし):ブロックを使用すると、労力と時間を大幅に節約できますが、必要に応じて合理的に使用する必要があります。



これは終わると思います。次回は、図面内のオブジェクトの検索と編集について説明します。いつものように、私はコメントやPMでフィードバック、コメント、提案を喜んでいます。



ご清聴ありがとうございました!



All Articles