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 を使おうかと思います。

4 件のコメント:

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

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

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

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

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

    返信削除