DeepClone Dynamic BlockTableRecord

DeepClone Dynamic BlockTableRecord

Anonymous
Not applicable
1,043 Views
4 Replies
Message 1 of 5

DeepClone Dynamic BlockTableRecord

Anonymous
Not applicable
Public Overridable Function InsertBlockRef(ByVal dblInsert As Point3d, ByVal btrSpace As BlockTableRecord, ByVal strSourceBlockName As String, ByVal strSourceBlockPath As String, Optional ByVal strBlockNewName As String = "") As BlockReference
Dim dlock As DocumentLock = Nothing
Dim bt As BlockTable
Dim btr As BlockTableRecord = Nothing
Dim br As BlockReference = Nothing
'Dim id As ObjectId
Dim db As Autodesk.AutoCAD.DatabaseServices.Database = HostApplicationServices.WorkingDatabase
Using trans As Transaction = db.TransactionManager.StartTransaction
Dim ed As Autodesk.AutoCAD.EditorInput.Editor = Application.DocumentManager.MdiActiveDocument.Editor
'insert block and rename it
Try
Try
dlock = ThisDrawing.LockDocument
Catch ex As Exception
Dim aex As New System.Exception("Error locking document for InsertBlock: " & strSourceBlockName & ": ", ex)
Throw aex
End Try
bt = trans.GetObject(db.BlockTableId, OpenMode.ForWrite)
Dim btrSource As BlockTableRecord = GetBlock(strSourceBlockName, strSourceBlockPath, strBlockNewName)
'if getblock returns nothing then the rest of this code is worthless, skip it and dispose the transaction
If btrSource IsNot Nothing Then
btr = trans.GetObject(btrSource.ObjectId, OpenMode.ForRead)
btrSpace = trans.GetObject(btrSpace.ObjectId, OpenMode.ForWrite)
'Get the Attributes
Dim attColl As AttributeCollection
Dim ent As Entity
Dim btrenum As BlockTableRecordEnumerator
br = New BlockReference(dblInsert, btr.ObjectId)
btrSpace.AppendEntity(br)
trans.AddNewlyCreatedDBObject(br, True)
attColl = br.AttributeCollection
btrenum = btr.GetEnumerator
While btrenum.MoveNext
ent = btrenum.Current.GetObject(OpenMode.ForWrite)
If TypeOf ent Is AttributeDefinition Then
Dim attdef As AttributeDefinition = ent
Dim attref As New AttributeReference
attref.SetAttributeFromBlock(attdef, br.BlockTransform)
attref.TextString = attdef.TextString
attColl.AppendAttribute(attref)
trans.AddNewlyCreatedDBObject(attref, True)
End If
End While
trans.Commit()
End If
Catch ex As System.Exception
Dim aex2 As New System.Exception("Error in inserting new block: " & strSourceBlockName & ": ", ex)
Throw aex2
Finally
If Not trans Is Nothing Then trans.Dispose()
If Not dlock Is Nothing Then dlock.Dispose()
End Try
End Using
Return br
End Function

Public Function GetBlock(ByVal strsourceblockname As String, ByVal strsourceblockpath As String, Optional ByVal strblocknewname As String = "") As BlockTableRecord
Dim dlock As DocumentLock = Nothing
Dim bt As BlockTable
Dim btr As BlockTableRecord = Nothing
Dim id As ObjectId
Dim db As Autodesk.AutoCAD.DatabaseServices.Database = HostApplicationServices.WorkingDatabase
Using trans As Transaction = db.TransactionManager.StartTransaction
Dim ed As Autodesk.AutoCAD.EditorInput.Editor = Application.DocumentManager.MdiActiveDocument.Editor
'insert block and rename it
Try
Try
dlock = ThisDrawing.LockDocument
Catch ex As Exception
Dim aex As New System.Exception("Error locking document for InsertBlock: " & strsourceblockname & ": ", ex)
Throw aex
End Try
bt = trans.GetObject(db.BlockTableId, OpenMode.ForWrite)
If bt.Has(strsourceblockname) Then
'block found, get instance for copying
If strblocknewname <> "" Then
'renaming source block, so create a new definition
Dim idMap As New IdMapping
Dim btrS As BlockTableRecord = trans.GetObject(bt.Item(strsourceblockname), OpenMode.ForWrite)
btr = btrS.DeepClone(bt, idMap, True)
btr.Name = strblocknewname
bt.Add(btr)
trans.AddNewlyCreatedDBObject(btr, True)
Else
btr = trans.GetObject(bt.Item(strsourceblockname), OpenMode.ForRead)
End If
Else
'block not found, insert into drawing
Using sourcedb As Database = New Database(False, False)
Try
sourcedb.ReadDwgFile(strsourceblockpath, IO.FileShare.Read, True, "")
id = db.Insert(strsourceblockpath, sourcedb, True)
btr = trans.GetObject(id, OpenMode.ForWrite)
If strblocknewname <> "" Then
btr.Name = strblocknewname
Else
btr.Name = strsourceblockname
End If
Catch ex As System.Exception
Dim aex As New System.Exception("Block file not found " & strsourceblockpath & ": ", ex)
Throw aex
Exit Function
End Try
sourcedb.Dispose()
End Using
End If
trans.Commit()
Catch ex As System.Exception
Dim aex2 As New System.Exception("Error in inserting new block: " & strsourceblockname & ": ", ex)
Throw aex2
Finally
If Not trans Is Nothing Then trans.Dispose()
If Not dlock Is Nothing Then dlock.Dispose()
End Try
End Using
Return btr
End Function
0 Likes
1,044 Views
4 Replies
Replies (4)
Message 2 of 5

Anonymous
Not applicable
Hello everybody,

Sorry to let off as I can solve all my own problems, but I can't...

I attempted to speed up my program by creating a system that did not insert the block from file everytime, rather to insert a master block, and clone that one as I needed to. This worked great for the blocks that all have the same definition block table record, but when I wanted to copy the block table record into a new block I get in trouble.

In this mess are 2 functions I created that are supposed to be my one shoe fits all for inserting a block/block reference. My problem is when I insert a dynamic block, I get the Multiply owned object error upon save; where my source dynamic block, and the cloned dynamic block both have the same entities inside them (by handle). 'Audit' only makes things worse, by putting new handles on all the entities in the source block in addition to the original entities (now I have a block table ref with 2 times the number of entities as the source dwg file.)

Can anybody point out the error in my code / logic path please...

Thank you,

jvj
0 Likes
Message 3 of 5

Anonymous
Not applicable
Maybe this helps.
[code]
public static void TransformClonedSelectionSet(SelectionSet ss, Matrix3d
transMatrix)
{

if (ss.Count == 0)

return;

Database targetDatabase = ss[0].ObjectId.Database;

using (Transaction trans =
targetDatabase.TransactionManager.StartTransaction())

{

ObjectIdCollection entityCollection = new
ObjectIdCollection(ss.GetObjectIds());

IdMapping idMap = new IdMapping();

targetDatabase.DeepCloneObjects(entityCollection,
targetDatabase.CurrentSpaceId, idMap, false);

foreach (IdPair pair in idMap)

{

Entity clonedEntity = trans.GetObject(pair.Value, OpenMode.ForRead) as
Entity;

if (clonedEntity != null)

{

Type et = clonedEntity.GetType();

if (typeof(SequenceEnd) != et && typeof(AttributeReference) != et)

{

clonedEntity.UpgradeOpen();

clonedEntity.TransformBy(transMatrix);

clonedEntity.DowngradeOpen();

}

}

}

trans.Commit();

}

}

[/code]

schrieb im Newsbeitrag
news:5973147@discussion.autodesk.com...
Hello everybody,

Sorry to let off as I can solve all my own problems, but I can't...

I attempted to speed up my program by creating a system that did not insert
the block from file everytime, rather to insert a master block, and clone
that one as I needed to. This worked great for the blocks that all have the
same definition block table record, but when I wanted to copy the block
table record into a new block I get in trouble.

In this mess are 2 functions I created that are supposed to be my one shoe
fits all for inserting a block/block reference. My problem is when I insert
a dynamic block, I get the Multiply owned object error upon save; where my
source dynamic block, and the cloned dynamic block both have the same
entities inside them (by handle). 'Audit' only makes things worse, by
putting new handles on all the entities in the source block in addition to
the original entities (now I have a block table ref with 2 times the number
of entities as the source dwg file.)

Can anybody point out the error in my code / logic path please...

Thank you,

jvj
0 Likes
Message 4 of 5

Anonymous
Not applicable
Thankyou for your reply Roland,

So what your saying is that I need to use the database.deepcloneobjects instead of the entity.deepclone in order to get the results i'm after?

Then you are applying some sort of optional transformation (move, rotate) at the end on all entities that are not SequenceEnd and AttributeReferences.

This is for copying block references, or block definitions? Because I want to copy dynamic block definitions and rename them as well.

Thanks,

jvj
0 Likes
Message 5 of 5

Anonymous
Not applicable
I can copy dynamic block references with it and get all the dynamic
properties.
schrieb im Newsbeitrag
news:5981579@discussion.autodesk.com...
Thankyou for your reply Roland,

So what your saying is that I need to use the database.deepcloneobjects
instead of the entity.deepclone in order to get the results i'm after?

Then you are applying some sort of optional transformation (move, rotate) at
the end on all entities that are not SequenceEnd and AttributeReferences.

This is for copying block references, or block definitions? Because I want
to copy dynamic block definitions and rename them as well.

Thanks,

jvj
0 Likes