AutoCAD エンティティを図面上に表示するには、インスタンスを生成してモデルスペースに登録する方法が一般的です。しかしポリラインは他のエンティティと比べると少し癖がありますので、混乱される方もおられるようです。そこで本稿では、ポリラインの生成方法に焦点を当ててみたいと思います。

なおサンプルコードは VisualStudio2005 の C# で作成し、 AutoCAD2007 / 2008 / 2009 で動作確認を行いました。

ポリラインのサンプル

ポリラインも他のエンティティと同じく new キーワードを使ってインスタンスを生成します。次に生成したポリラインインスタンスに対して頂点を登録しますが、この登録方法に癖がありますので注意してください。

サンプルコード

[CommandMethod( "CREATE_PLINE" )]
public void CreatePolyline()
{
    Transaction trans = null;
    try
    {
        Document active_doc = Application.DocumentManager.MdiActiveDocument;
        Database active_db = active_doc.Database;

        trans = active_db.TransactionManager.StartTransaction();

        // 1.ポリラインのインスタンスを生成する
        Polyline pline = new Polyline( 4 );

        // 2.ポリラインの頂点を登録する
        pline.AddVertexAt( 0, new Point2d( 0, 0 ), 0, 0, 0 );
        pline.AddVertexAt( 1, new Point2d( 100, 0 ), 0, 0, 0 );
        pline.AddVertexAt( 2, new Point2d( 100, 100 ), 0, 0, 0 );
        pline.AddVertexAt( 3, new Point2d( 200, 100 ), 0, 0, 0 );

        ObjectId blk_tbl_id = active_db.BlockTableId;
        BlockTable blk_tbl = (BlockTable)trans.GetObject( blk_tbl_id, OpenMode.ForRead );

        // 3.モデルスペースに登録する
        ObjectId model_space_id = blk_tbl[ BlockTableRecord.ModelSpace ];
        BlockTableRecord model_space =
            (BlockTableRecord)trans.GetObject( model_space_id, OpenMode.ForWrite );

        model_space.AppendEntity( pline );
        trans.AddNewlyCreatedDBObject( pline, true );

        trans.Commit();
    }
    catch( System.Exception ex )
    {
        Editor edit = Application.DocumentManager.MdiActiveDocument.Editor;
        edit.WriteMessage( "\n{0}", ex.Message );
    }
    finally
    {
        if( trans != null )
        {
            trans.Dispose();
        }
    }
}

サンプルプロジェクト (5 KB)

環境によっては、コンパイル時に "この参照を解決できませんでした" という警告が出ます。この場合 "acdbmgd.dll" と "acmgd.dll" を削除し、 AutoCAD のインストールディレクトリから参照しなおしてください。

出力結果

出力結果(3セグメントのポリライン)

上記出力結果のうち、コマンド実行時に出力されるのは白のポリラインのみです。グレーの寸法線はコマンド実行後に別途描画しました。

サンプルコード解説

ポリラインのインスタンスを生成する

他のエンティティと同じく、Polyline クラスインスタンスを new で生成します。このクラスのコンストラクタには int 型の引数を要求するものがありますが、ここには生成するポリラインの頂点の数を指定します。

この引数は必ずしも指定する必要はありません。Polylin クラスの内部では頂点は動的配列で管理されていますので、この引数を指定しなかったり、あるいはこの引数を超えて頂点を登録しても問題なく動作します。しかしこのコンストラクタ引数を指定した方が高速に動作する(*1)ため、頂点数があらかじめわかっている場合は指定することをおすすめします。

ポリラインの頂点を登録する

ポリラインインスタンスに AddVertexAt() を使って頂点を登録します。第一引数は登録する頂点のインデックス、第二引数は頂点の座標を二次元で指定します。直線状のセグメントだけでポリラインを作成する場合、第三引数以降にはすべて 0 を指定します。

第一引数には、0 から NumberOfVertices の範囲で指定してください。ここで指定した値が、ポリラインの頂点配列中でのインデックスになります。たとえばすべて NumberOfVertices を指定すると、頂点をポリラインの始点側から順に登録したことになります。また逆に 0 を指定するとポリラインの終点側から頂点配列が生成されます。
頂点インデックスに上記の範囲外の値を指定すると、eInvalidIndex エラーが発生します。

関数仕様

Polyline.AddVertexAt メソッド

ポリラインに頂点を追加する。

public void AddVertexAt(
    int index,
    Point2d pt,
    double bulge,
    double startWidth,
    double endWidth
);
引数 概要
int index 頂点インデックス(0ベース)
Point2d pt 頂点座標(二次元)
double bulge ふくらみの値
double startWidth この頂点を始点とするセグメントの開始幅
double endWidth この頂点を始点とするセグメントの終了幅

この関数はポリラインに頂点を追加する。index の値が 0 の場合、この頂点はポリラインの最初の頂点として登録される。NumberOfVertices の場合はポリラインの最後の頂点である。その他の場合、現在そのインデックスにある頂点の直前に挿入される。

pt はオブジェクト座標系(OCS)で指定する。ワールド座標系(WCS)ではない。

bulge はこの頂点と次の頂点との間の円弧の中心角の 1/4 の正接(*2)である。この値が負の場合、この頂点からみて時計回りの方向に次の頂点があることを示す。この値が0の場合は直線セグメント、1は半円を表す(*3)

(MINERVA 深津貴成)
  1. ^ どれだけ高速に動作するかは頂点数によって異なりますが、トランザクションやモデルスペースへの登録を考慮しても平均で 50% 程度は高速化するようです。しかし最悪のケースでは頂点数を指定してもしなくてもほぼ同じになります。サンプルプロジェクトにベンチマークプログラムも入れておきましたので、ご自身の環境で試してみてください。
  2. ^ 要するに tan(θ/4) です。この値は三角関数ですので直線的な比例関係になりません。たとえば四半円(中心角 90°)を描画する場合は 0.5 ではなく、 0.414213562373095 を指定します。
  3. ^ この定義は ObjectARX Documentation の AddVertexAt() の項には書かれていません。GetBulgeAt() か ObjectARX の AcDbPolyline::getBulgeAt()、あるいは VBA リファレンスの SetBulge メソッドをご覧ください。