お知らせ

--------------------------------------------------

プログラム作成/コンサルティングの申し込みはこちら

--------------------------------------------------

2010年10月21日木曜日

.NET - ダイナミック ブロックをコピーする(AutoCAD 2011)

先日アンケートをいただいて、その中にダイナミック ブロックのコピーがうまくいかないという質問をいただきました。

ということで、dblk.dwg という図面を作って試してみました。

dblk.dwg には、上から
        test という名前のダイナミック ブロック
        test2 という名前のダイナミック ブロック
        円
がありますが、clone メソッドでコピーしてみると、下の2つは問題ないのですが、test に関しては、ブロック名が test ではなくて *U4 になってしまいました。

きっとダイナミック ブロックはコピーしなきゃいけない情報が他のオブジェクトよりもあるのでしょう。

そこで、いろいろググッてみました。
なかなかそれらしいのが見つからなかったのですが DeepCloneObjects っていうのでできそうってことをやっと見つけました。

何度か諦めようかと思ったのですが、やっぱりあると信じて辛抱強く探すことが大事だなと再認識です。

ということで、以下のような感じでやってみたら test という名前のダイナミック ブロックもブロック名が変わることなくコピーできました。

'---------------------------------------------------------
Dim doc As Document = Application.DocumentManager.MdiActiveDocument
Dim db As Database = doc.Database
Dim ed As Editor = doc.Editor

Using trans As Transaction = db.TransactionManager.StartTransaction
    Try
        Dim selEntID As ObjectId = Application.DocumentManager.MdiActiveDocument.Editor.GetEntity("オブジェクトを選択").ObjectId
        Dim objIds As ObjectIdCollection = New ObjectIdCollection()
        objIds.Add(selEntID)
        Dim idMap As IdMapping = New IdMapping
        db.DeepCloneObjects(objIds, db.CurrentSpaceId, idMap, False)
        For Each idP As IdPair In idMap
            Dim cpObj As DBObject = trans.GetObject(idP.Value, OpenMode.ForWrite)
            If TypeOf cpObj Is Entity Then
                Dim cpEnt As Entity = cpObj
                cpEnt.ColorIndex = 1

                Dim pt1 As Point3d = New Point3d(0, 0, 0)
                Dim vec1 As Vector3d = pt1.GetVectorTo(New Point3d(110, 0, 0))
                cpEnt.TransformBy(Matrix3d.Displacement(vec1))
            End If
        Next

        trans.Commit()

    Catch ex As Autodesk.AutoCAD.Runtime.Exception
        Application.ShowAlertDialog(ex.Message)

    End Try
End Using
'---------------------------------------------------------


それと、全然別件なのですが、このときたまたま CurrentSpaceId っていうのがあることに気が付きました。
今まで管理人は、現在モデル空間にるかペーパー空間にいるかの判断を以下のように CVPORT を見てやっていました。

'---------------------------------------------------------

If Application.GetSystemVariable("CVPORT") = 1 Then
    btRec = trans.GetObject(bt(BlockTableRecord.PaperSpace), OpenMode.ForWrite)
Else
    btRec = trans.GetObject(bt(BlockTableRecord.ModelSpace), OpenMode.ForWrite)
End If

'---------------------------------------------------------

でも、以下のように CurrentSpaceId を使った方が良さそうですね。

'---------------------------------------------------------

Dim cSpace As BlockTableRecord = trans.GetObject(db.CurrentSpaceId, OpenMode.ForRead)
If cSpace.Name = "*Model_Space" Then
    btRec = trans.GetObject(bt(BlockTableRecord.ModelSpace), OpenMode.ForWrite)
Else
    btRec = trans.GetObject(bt(BlockTableRecord.PaperSpace), OpenMode.ForWrite)
End If

'---------------------------------------------------------

ということで、これからは CurrentSpaceId を使おうかと思います。

8 件のコメント:

  1. 質問させて頂いた者です。すばらしいです。ありがとうございます。私もあちこちググってDeepCloneあたりまでは行ったのですが、引数が意味不明でお手上げでした。
    これから自分のマクロに組み込んでみます。

    返信削除
  2. そうなんですよね、DeepClone でもできそうな感じなんですが、私もよく分かりませんでした。

    また何かあればお尋ねくださいね。

    返信削除
  3. CurrentSpaceId
    わー、すごい。これこれ!!
    ありがとうございます。
    もぐもぐ、食べちゃったです。

    返信削除
  4. おー、喜んでもらえてよかったです。
    管理人も偶然見つけられて嬉しかったです。

    返信削除
  5. 初めまして、ダイナミックブロックがコピーできなくて困っていました。是非、使わせていただきたいです
    私は、AutoCAD2009なのですが どこへコピーすれば良いのかを教えていただけないでしょうか
    ど素人の質問で申し訳ございません
    宜しく、お願い致します。

    返信削除
  6. こんにちは。
    私は AutoCAD 2009 で .NET のプログラムを作ったことがないんですよ。
    でも、きっと AutoCAD 2011 と同じだと思います。

    上のコードは、コマンドを実行するためのメソッドの中にコピーすれば OK です。

    具体的には、私は AVDO_CPDBLK というコマンドを作ったので、以下の場所にコピーです。

    _
    Public Sub AVDO_CPDBLK()
    '
    End Sub

    これって確認したかった答になってます?
    もし、違ったら言ってくださいね。

    返信削除
  7. おはようございます
    早々に、ありがとうございます
    御手数をお掛けいたしまして申し訳ございません
    操作する以外に全くPCのことは分かりません
    例えば C:\***\***\***といった感じで
    コピーする場所を教えてください
    それから、コピーするだけではなく何か指示を与える
    書き込みも必要なのでしょうか?
    分からなさ過ぎて申し訳ございません
    どうぞ、よろしくお願い致します

    返信削除
  8. おはようございます。

    この内容は、プログラムでダイナミック ブロックをコピーするコマンドを作るときの方法です。
    そのため、プログラムを作れる人でないと、どこかにコピーして使えるっていうものではないです。

    ダイナミック ブロックをコピーするのであれば、他の図形と同じように、プログラムを作らなくても[複写(COPY)]コマンドでコピーでるはずなんですが…

    [複写(COPY)]コマンドでコピーしようとすると、どうなっちゃうんでしょうか?

    返信削除