2010年4月30日金曜日

.NET の勉強 「AutoCAD コマンド ラインへのアクセス」(AutoCAD 2011)

金曜日なので、.NET の勉強をしました。


AutoLISP では、(command "._LINE" "0,0" "100,100" "") みたいに、COMMAND 関数を使って、コマンド ラインに入力するのと同じ手順を書くことによってコマンドを実行することができますが、同じようなことを .NET でできないか調べてみました。


すると、サンプルにこんなのがありました。

Imports Autodesk.AutoCAD.ApplicationServices
Imports Autodesk.AutoCAD.Runtime

<CommandMethod("SendACommandToAutoCAD")> _

Public Sub SendACommandToAutoCAD()
  Dim acDoc As Document = Application.DocumentManager.MdiActiveDocument
  '' Draws a circle and zooms to the extents or
  '' limits of the drawing
  acDoc.SendStringToExecute("._circle 2,2,0 4 ", True, False, False)
  acDoc.SendStringToExecute("._zoom _all ", True, False, False)
End Sub



さっそくこれをカット&ペーストして確認してみたところ、CRCLE コマンドと ZOOM コマンドが無事実行されました。


SendStringToExecute ってやつで実行するんですね。


試しに、

acDoc.SendStringToExecute("._line 0,0 100,100  ", True, False, False)

を追記してみたら、問題なく線分を作成することができました。

2010年4月23日金曜日

.NET の勉強 「arxmgd.chm を見ながらオブジェクトの作成」(AutoCAD 2011)

金曜日なので、.NET の勉強です。


先週は、「今後も、どんどん進んでいこうと思います。」 と言っていましたが、ちょっとヘルプの見方とか少しですが分かってきたような気がするので、もう一度復習でオブジェクトの作図についてやってみようと思います。


C:\ObjectARX 2011\docs フォルダにある arxmgd.chm を見ながら、オブジェクトを描くプログラムを作成したいと思います。


まず最初に、こんなコードを書いてみます。

Imports Autodesk.AutoCAD.ApplicationServices
Imports Autodesk.AutoCAD.EditorInput
Imports Autodesk.AutoCAD.Runtime
Imports Autodesk.AutoCAD.DatabaseServices

Public Class Class1
     <CommandMethod("DrawObjects")> _
    Public Sub DrawObjects()

        '' Get the current document and database
        Dim acDoc As Document = Application.DocumentManager.MdiActiveDocument
        Dim acCurDb As Database = acDoc.Database

        '' Start a transaction
        Using acTrans As Transaction = acCurDb.TransactionManager.StartTransaction()

            '' Open the Block table for read
            Dim acBlkTbl As BlockTable
            acBlkTbl = acTrans.GetObject(acCurDb.BlockTableId, OpenMode.ForRead)

            '' Open the Block table record Model space for write
            Dim acBlkTblRec As BlockTableRecord
            acBlkTblRec = acTrans.GetObject(acBlkTbl(BlockTableRecord.ModelSpace), _
                                                  OpenMode.ForWrite)

            ''線分を作成
            Dim acLine As New Line()

            acBlkTblRec.AppendEntity(acLine)
            acTrans.AddNewlyCreatedDBObject(acLine, True)

            '' Save the new object to the database
            acTrans.Commit()
        End Using
    End Sub
End Class


ここで、線分を作成しているのは、Dim acLine As New Line() になります。
arxmgd.chm の
Autodesk.AutoCAD.DatabaseServices Namespace > Line Class > Line Constructor
にある Line.Line() について以下の記述があります。
Default constructor. Initializes the normal vector to (0,0,1), the start and end points to (0,0,0), and the thickness to 0.0. All coordinates are WCS.
ということで、これを実行すると、始点も終点も 0,0 の線分が作成されます。


また、arxmgd.chm の
Autodesk.AutoCAD.DatabaseServices Namespace > Line Class > Line Properties
を見ると、以下のプロパティがあります。
Angle、Delta、EndPoint、Length、Normal、StartPoint、Thickness
でも、Angle、Delta、Length の Conditions は Read-only と書かれているので、線分を作成するときに EndPoint、Normal、StartPoint、Thickness のプロパティを使えるんだと思います。


そこで、以下のように 4 つのプロパティを指定するよう追記してみました。

Dim acLine As Line = NEW Line()
acLine.StartPoint = New Point3d(50, 50, 0)
acLine.EndPoint = New Point3d(100, 100, 0)
acLine.Normal = New Vector3d(1, 0, 0)
acLine.Thickness = 2


すると、始点が 50,50、終点が 100,100、UCS に依存する押し出し方向が 1,0,0、厚さが 2 の線分が作成されました。

※ Point3d や Vector3d は、Autodesk.AutoCAD.Geometry 名前空間になるので、「Imports Autodesk.AutoCAD.Geometry」 という記述も追加しました。


プロパティには、線分以外のオブジェクトに共通のものがありますよね。例えば、色とか線種とか。
それは、きっと
Autodesk.AutoCAD.DatabaseServices Namespace > Entity Class > Entity Properties
にある内容になるんだと思います。


そこで、以下も追加してみました。

acLine.ColorIndex = 1
acLine.Linetype = "continuous"
acLine.LineWeight = &HD3


すると、赤色で、線種が continuous で、線の太さが 2.11 mm になりました。


では、今度は楕円にチャレンジです。
(Autodesk.AutoCAD.DatabaseServices Namespace > Ellipse Class を見ながらやりました。)


線分と同じような感じで、以下のようにやってみましたが、エラーとなって描けませんでした。

Dim acEllipse As Ellipse = New Ellipse()
acEllipse.StartParam = 0
acEllipse.EndParam = 1
acEllipse.Center = New Point3d(10, 10, 0)
acEllipse.RadiusRatio = 0.5
acEllipse.StartAngle = 0
acEllipse.EndAngle = PI

acBlkTblRec.AppendEntity(acEllipse)
acTrans.AddNewlyCreatedDBObject(acEllipse, True)


何ででしょうね?いろいろ試してみましたが、管理人には何故かわかりませんでした。


そこで、以下のように記述を変えて実行したところ、楕円も作成できました。

Dim acEllipse As Ellipse = New Ellipse(New Point3d(10, 10, 0), Vector3d.ZAxis, New Vector3d(1, 0, 0), 0.5, 0, PI)
acEllipse.StartParam = 0
acEllipse.EndParam = 1
acEllipse.Center = New Point3d(10, 10, 0)
acEllipse.RadiusRatio = 0.5
acEllipse.StartAngle = 0
acEllipse.EndAngle = PI

acBlkTblRec.AppendEntity(acEllipse)
acTrans.AddNewlyCreatedDBObject(acEllipse, True)


※ PI を認識するために、「Imports System.Math」 も追記しました。


以前よりも理解しながらオブジェクトを作れたような気がします。
次回は、今度こそ、先に進んで新しいことにチャレンジしたいと思います。

2010年4月16日金曜日

.NET の勉強 「オブジェクトの削除、コピー、移動」(AutoCAD 2011)

先週から、金曜日は .NET の勉強をしようかということにしたので、今日はその続きです。

前回は、オブジェクトを作成するプログラムの勉強をしたので、今回は、オブジェクトの削除やコピーや移動などを行うサンプルを探してみました。


そこで、こんなサンプルを見つけて、とりあえず実行してみました。

Imports Autodesk.AutoCAD.Runtime
Imports Autodesk.AutoCAD.ApplicationServices
Imports Autodesk.AutoCAD.DatabaseServices
Imports Autodesk.AutoCAD.Geometry

<CommandMethod("EraseObject")> _
Public Sub EraseObject()

    '' Get the current document and database
    Dim acDoc As Document = Application.DocumentManager.MdiActiveDocument
    Dim acCurDb As Database = acDoc.Database

    '' Start a transaction
    Using acTrans As Transaction = acCurDb.TransactionManager.StartTransaction()

        '' Open the Block table for read
        Dim acBlkTbl As BlockTable
        acBlkTbl = acTrans.GetObject(acCurDb.BlockTableId, OpenMode.ForRead)

        '' Open the Block table record Model space for write
        Dim acBlkTblRec As BlockTableRecord
        acBlkTblRec = acTrans.GetObject(acBlkTbl(BlockTableRecord.ModelSpace), _
                                                            OpenMode.ForWrite)

        '' Create a lightweight polyline
        Dim acPoly As Polyline = New Polyline()
        acPoly.SetDatabaseDefaults()
        acPoly.AddVertexAt(0, New Point2d(2, 4), 0, 0, 0)
        acPoly.AddVertexAt(1, New Point2d(4, 2), 0, 0, 0)
        acPoly.AddVertexAt(2, New Point2d(6, 4), 0, 0, 0)

        '' Add the new object to the block table record and the transaction
        acBlkTblRec.AppendEntity(acPoly)
        acTrans.AddNewlyCreatedDBObject(acPoly, True)

        '' Update the display and display an alert message
        acDoc.Editor.Regen()
        Application.ShowAlertDialog("Erase the newly added polyline.")

        '' Erase the polyline from the drawing
        acPoly.Erase(True)

        '' Save the new object to the database
        acTrans.Commit()

    End Using
End Sub



このプログラムは、ポリラインをひとつ作成して、それを削除するようです。


ポリラインの作成に関しては、前回の線分、円、MTEXT の作成と同じように、オブジェクトを宣言したあと、それぞれのプロパティを指定しているようです。(「'' Create a lightweight polyline」 以下の 5 行 および 「'' Add the new object to the block table record and the transaction」 以下の 2 行。)


で、削除しているのは、acPoly.Erase(True) ですね。
意外と簡単ですね。


他のコピーを行うサンプルを見てみたところ、Clone っていうのでコピーするみたいです。
なので、acPoly.Erase(True) の代わりに以下を記述したところ、無事コピーされました。

Dim acPolyClone As Polyline = acPoly.Clone()

acBlkTblRec.AppendEntity(acPolyClone)
acTrans.AddNewlyCreatedDBObject(acPolyClone, True)



ただし、まったく同じ場所にコピーされるので、もとのポリラインと重なっています。
他の場所にコピーしたいときは、どうするんだろう???移動と組み合わせるのかな???


そこで、移動を行うサンプルを見てみたところ、移動する場所を示すマトリックスを作ってから移動するようです。
そこで、以下のように記述を変更して実行してみたところ、無事に コピー+移動 を行うことができました。(基点が 0,0 で、目的点が 2,0)

Dim acPolyClone As Polyline = acPoly.Clone()

Dim acPt3d As Point3d = New Point3d(0, 0, 0)
Dim acVec3d As Vector3d = acPt3d.GetVectorTo(New Point3d(2, 0, 0))
acPolyClone.TransformBy(Matrix3d.Displacement(acVec3d))

acBlkTblRec.AppendEntity(acPolyClone)
acTrans.AddNewlyCreatedDBObject(acPolyClone, True)



ここで、ちょっと疑問に思ったのが、この例ではプログラムで作成したオブジェクトを移動しましたが、元からあるオブジェクトを選択して、移動したいときはどうなるんでしょう???
AutoLISP だと、entsel とか使うやつです。


サンプルを探してみたところ、きっと GetSelection ってやつですね。
そこで、前述の代わりに、以下を記述してみたところ、オブジェクトの選択を求められて、それを移動することができました。

※ このとき、「Imports Autodesk.AutoCAD.EditorInput」 も追加しました。


'' Request for objects to be selected in the drawing area
Dim acSSPrompt As PromptSelectionResult = acDoc.Editor.GetSelection()

'' If the prompt status is OK, objects were selected
If acSSPrompt.Status = PromptStatus.OK Then
    Dim acSSet As SelectionSet = acSSPrompt.Value

    '' Step through the objects in the selection set        
    For Each acSSObj As SelectedObject In acSSet

        '' Check to make sure a valid SelectedObject object was returned            
        If Not IsDBNull(acSSObj) Then
            '' Open the selected object for write                
            Dim acEnt As Entity = acTrans.GetObject(acSSObj.ObjectId, OpenMode.ForWrite)
            If Not IsDBNull(acEnt) Then
                Dim acClone As Entity = acEnt.Clone()
                Dim acPt3d As Point3d = New Point3d(0, 0, 0)
                Dim acVec3d As Vector3d = acPt3d.GetVectorTo(New Point3d(2, 0, 0))

                acClone.TransformBy(Matrix3d.Displacement(acVec3d))
                acBlkTblRec.AppendEntity(acClone)
                acTrans.AddNewlyCreatedDBObject(acClone, True)
            End If
        End If
    Next
End If



まだちゃんと理解できたわけではありませんが、とりあえず、オブジェクトの作成、削除、コピー、移動を実行するプログラムは作れるようになりました。


今後も、どんどん進んでいこうと思います。
きっとそのうち、自然と理解できるるようになるだろうと期待してます。

2010年4月9日金曜日

.NET の勉強 「線分、円、MTEXT の作成」(AutoCAD 2011)

今日は、ながーらくサボっていた .NET の勉強を、やっと再開したので、そこのとについてです。


今回は、何か図形を描いてみたいと思って、サンプル ファイルを探してみました。
まずは、基本からなので、線分を作成する以下のサンプル見つけて、それをやってみました。
(プロジェクトの作成は、以前書いた手順で行いました。)
Imports Autodesk.AutoCAD.Runtime
Imports Autodesk.AutoCAD.ApplicationServices
Imports Autodesk.AutoCAD.DatabaseServices
Imports Autodesk.AutoCAD.Geometry

<CommandMethod("AddLine")> _
Public Sub AddLine()

    '' Get the current document and database
    Dim acDoc As Document = Application.DocumentManager.MdiActiveDocument
    Dim acCurDb As Database = acDoc.Database

    '' Start a transaction
    Using acTrans As Transaction = acCurDb.TransactionManager.StartTransaction()

        '' Open the Block table for read
        Dim acBlkTbl As BlockTable
        acBlkTbl = acTrans.GetObject(acCurDb.BlockTableId, OpenMode.ForRead)

        '' Open the Block table record Model space for write
        Dim acBlkTblRec As BlockTableRecord
        acBlkTblRec = acTrans.GetObject(acBlkTbl(BlockTableRecord.ModelSpace), _
                                              OpenMode.ForWrite)

        '' Create a line that starts at 5,5 and ends at 12,3
        Dim acLine As Line = New Line(New Point3d(5, 5, 0), _
                                            New Point3d(12, 3, 0))
        acLine.SetDatabaseDefaults()

        '' Add the new object to the block table record and the transaction
        acBlkTblRec.AppendEntity(acLine)
        acTrans.AddNewlyCreatedDBObject(acLine, True)

        '' Save the new object to the database
        acTrans.Commit()
    End Using
End Sub
線分1本描くのにいろいろやらなきゃいけないんですね。
確かに 5,5 から 12,3 の線分が描けましたが、何やってるんでしょう???
管理人には難しすぎて、ほとんど理解不能です。。。


オンライン ヘルプに、こんな絵が載ってました。
サンプルでは、Document、Database、Block table、Block table record の順番に開いているのは、この絵の順番なんだろうか???きっとそうだ。そう思おう。


ということで、あんまり難しいことを理解しようとすると、何も前に進まないので、「'' Create a line that starts at 5,5 and ends at 12,3」のところの作図部分だけをいろいろいじってみることにしました。


どういじったかというと、試しに、もうひとつの線分と 円と MTEXT を描くために、こんな内容を追加してみました。
Dim L1 As Line = New Line()
L1.SetDatabaseDefaults()
L1.StartPoint = New Point3d(0, 0, 0)
L1.EndPoint = New Point3d(100, 100, 0)

acBlkTblRec.AppendEntity(L1)
acTrans.AddNewlyCreatedDBObject(L1, True)


Dim c1 As Circle = New Circle()
c1.SetDatabaseDefaults()
c1.Center = New Point3d(50, 50, 0)
c1.Radius = 20
c1.ColorIndex = 1
c1.Normal = Vector3d.ZAxis

acBlkTblRec.AppendEntity(c1)
acTrans.AddNewlyCreatedDBObject(c1, True)


Dim mt1 As MText = New MText()
mt1.SetDatabaseDefaults()
mt1.Location = New Point3d(50, 50, 0)
mt1.Width = 100.0
mt1.TextHeight = 10.0
mt1.Contents = "てすとです。"

acBlkTblRec.AppendEntity(mt1)
acTrans.AddNewlyCreatedDBObject(mt1, True)
これで、実行してみたところ、無事 線分、円、MTEXT を作成することができました。


各オブジェクトを宣言したあと、それぞれのプロパティを指定してあげれば、オブジェクトを作成できるようです。

  • 線分の場合は、L1 を宣言して、L1 の始点、終点 を指定しました。
  • 円の場合は、c1 を宣言して、c1 の中心点、半径、色、法線方向 を指定しました。
  • MTEXT の場合は、mt1 を宣言して、文字の位置、幅、文字高さ、文字 を指定しました。


なんとなく、コツがつかめたような感じがします。他のオブジェクトもこんな感じで描けると思います。
意味が分からないところがありますが、とりあえず図形は描けるようになりました。


まだ勉強を始めたばかりなので、分からないところばかりにこだわらずに、これからもどんどん次に進んでいこうかと思います。

※ これから、毎週金曜日は .NET の日にしようかなぁー、、、と思ってたりします。