Hi,
I'm facing some strange behavior.
In my Project I build a static Block by inserting dynamic blocks from a template dwg and then explode them.
Actually I create a new DataBase, insert the blocks from my template, set the according Dynamic Properties, Explode the Block in the temp DB and then wblockclone the resulting Objects in my destination BlockTableRecord.
This works fine, but:
in my source dyn. block there is an associative surface defined by a Polyline(Rectangle) , attached a stretch action to change the size. I can set the Width parameter, after the Explode the polyline itself is updated, but the planar surface is not... so if I explode this block I get a well stretched Polyline and the "base" surface.
Manipulating the dynamic Block works fine... If I have stretched 3D-Meshes, they are ok as well.
It seem's to be something with the planar surface object.
Dim objs As New DBObjectCollection idsToImport.Clear() If Helpers.Registry.GetValueFromRegistry("ExplodeSubs").ToString = "1" Then ' debug switch bref.Explode(objs) 'the dyn BlockRef in the external (temp) Database bref.Erase(True) For Each obj As DBObject In objs Dim ent As Entity = TryCast(obj, Entity) If Not ent.Visible Then 'for visible states obj.Dispose() Continue For End If ems.AppendEntity(ent) ' ems: external Modelspace etr.AddNewlyCreatedDBObject(ent, True) idsToImport.Add(ent.ObjectId) ent.Dispose() obj.Dispose() Next bref.Dispose() Else idsToImport.Add(bref.ObjectId) End If Dim map As New IdMapping edb.WblockCloneObjects(idsToImport, btr.ObjectId, map, DuplicateRecordCloning.Ignore, False)
Any hints are appreciated!
thanks in advance,
Daniel
Hello Jeff,
thanks for the quick answer. I wasn't aware of this Method.
Unfortunatelly this didn't help, it produced the same behavior.
I will run further tests on certain Blocks.
I tried to generate my surface by a loft between 2 lines. Same result: lines do move, surface is not refreshed.
Somehow I have the feeling, it's related to the fact, that the db is not loaded in the editor and the Surface needed to Update on Screen...
On the other side, meshes do refresh... They are 3D, can this matter...?
Thanks again!
Best regards,
Daniel
Hi all,
I would like to discuss what is happening here. Actually I've got the same issue - dynamic block in model space and try to explode this block reference. Until I strech this dynamic block I can see it in BlockTable. But after I use strech functionality of this block It seems that it's not a part of block table anymore.
Do you know how to add id there to be able to use .explode on that block reference?
Many thanks,
Peter
Public Sub selectDynamicBlockReferences() Dim doc As Document = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument Dim db As Database = doc.Database Dim ed As Editor = doc.Editor Using trx As Transaction = db.TransactionManager.StartTransaction() Dim bt As BlockTable = TryCast(db.BlockTableId.GetObject(OpenMode.ForRead), BlockTable) For Each objId As ObjectId In bt Dim btr As BlockTableRecord = DirectCast(objId.GetObject(OpenMode.ForRead), BlockTableRecord) If btr.IsDynamicBlock Then Dim brefObjidColl As ObjectIdCollection = btr.GetBlockReferenceIds(True, True) Dim anonObjIdsColl As ObjectIdCollection = btr.GetAnonymousBlockIds() For Each anonObjId As ObjectId In anonObjIdsColl Dim btrAnon As BlockTableRecord = DirectCast(anonObjId.GetObject(OpenMode.ForRead), BlockTableRecord) Dim ObjidColl As ObjectIdCollection = btrAnon.GetBlockReferenceIds(True, True) For Each Id As ObjectId In ObjidColl brefObjidColl.Add(Id) Next Next For Each brefObjId As ObjectId In brefObjidColl Dim bref As Autodesk.AutoCAD.DatabaseServices.BlockReference = TryCast(brefObjId.GetObject(OpenMode.ForWrite), Autodesk.AutoCAD.DatabaseServices.BlockReference) ' Do something here with the blocks ''' Next End If Next End Using End Sub
What about the code above (not created by me - credit to others)
Hi,
in my case, the BR-method "ExplodeToOwnerSpace" did the trick, not sure anymore, who pointed me to this. Unfortunatelly, this method does not produce a Return value, so you have to collect the objectids of the objects in the BTR Modelspace before and after the method was called, and the difference gives you the new ones... If I recall correctly, the origin BR must be erased afterwards.
BR,
Daniel
Hi Daniel
I'm trying to explode the dynamic blocks and get some readonly information from the entites inside by exploding too. I haven't got my code to work yet (see below). Would you be able to post some of your code as it seems you have this working? (or maybe someone could explain why mine isn't working?). Thanks
<CommandMethod("DTest2")> _ Public Sub DynamicBlockValuesofVisibleEntites() Dim doc As Document = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument Dim db As Database = doc.Database Dim ed As Editor = doc.Editor Dim tm As DBTransactionManager = db.TransactionManager Dim i As Integer = 0 Using trx As Transaction = db.TransactionManager.StartTransaction() Try Dim bt As BlockTable = DirectCast(trx.GetObject(db.BlockTableId, OpenMode.ForRead), BlockTable) Dim btr As BlockTableRecord = tm.GetObject(bt(BlockTableRecord.ModelSpace), OpenMode.ForWrite, False) Dim Ids As ObjectIdCollection = GetDynamicBlocksObjectIds() ' Gets a list of objectIDs that are the Dynamic Blocks of Modelspace For Each id As ObjectId In Ids If id.IsErased Then Continue For ' We know from GetDynamicBlocksObjectIds that the ObjectId is a BlockReference (All DynamicBlocks are BlockReferences) Dim bref As Autodesk.AutoCAD.DatabaseServices.BlockReference = CType(trx.GetObject(id, Autodesk.AutoCAD.DatabaseServices.OpenMode.ForRead, False), Autodesk.AutoCAD.DatabaseServices.BlockReference) ' i += 1 Dim objs As New DBObjectCollection bref.UpgradeOpen() bref.ConvertToStaticBlock() ' Converts block reference to a static anonymous block to get the Visible Entities as a static block bref.Explode(objs) bref.Erase(True) Dim strDesc As String = "" ' For Each entity As Autodesk.AutoCAD.DatabaseServices.Entity In entities For Each obj As Autodesk.AutoCAD.DatabaseServices.DBObject In objs ' I TRY TO DO SOMETHING HERE BUT FOR SOME REASON MY CODE ISN'T WORKING??? obj.Dispose() Next obj bref.Dispose() Next id ' ed.WriteMessage("There are " & i & " entities in the dynamic blocks") Catch ex As System.Exception MsgBox("Error in Dtest2 routine: " + ex.Message) Finally trx.Commit() trx.Dispose() End Try End Using End Sub ' Currently not working - awaiting forum response Public Shared Function GetDynamicBlocksObjectIds() As ObjectIdCollection Dim res As New ObjectIdCollection() Dim db As Database = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument.Database Using trans As Transaction = db.TransactionManager.StartTransaction() 'get the blockTable and iterate through all block Defs Dim bt As BlockTable = DirectCast(trans.GetObject(db.BlockTableId, OpenMode.ForRead), BlockTable) For Each btrId As ObjectId In bt 'get the block Def and see if it is anonymous Dim btr As BlockTableRecord = DirectCast(trans.GetObject(btrId, OpenMode.ForRead), BlockTableRecord) If btr.IsDynamicBlock Then ' AndAlso btr.Name.Equals(BlkName) Then 'get all anonymous blocks from this dynamic block Dim anonymousIds As ObjectIdCollection = btr.GetAnonymousBlockIds() Dim dynBlockRefs As New ObjectIdCollection() For Each anonymousBtrId As ObjectId In anonymousIds 'get the anonymous block Dim anonymousBtr As BlockTableRecord = DirectCast(trans.GetObject(anonymousBtrId, OpenMode.ForRead), BlockTableRecord) 'and all references to this block Dim blockRefIds As ObjectIdCollection = anonymousBtr.GetBlockReferenceIds(True, True) For Each id As ObjectId In blockRefIds dynBlockRefs.Add(id) Next Next res = dynBlockRefs Exit For End If Next trans.Commit() trans.Dispose() End Using Return res End Function
later on.... tm.getobject???? you can't get an object by the transactionmanager! transaction can do such a thing 🙂
Hello Hugh,
I'm not sure what you try to achieve, but this code should work (acad 2012). Maybe it leads you to the right direction.
Paste this into your command-class!
BR,
daniel
Dim ids_diff As New ObjectIdCollection <CommandMethod("DBINFO", CommandFlags.Modal)> _ Public Sub MyCommand() Dim doc As Document = Application.DocumentManager.MdiActiveDocument Dim db As Database = doc.Database Dim ed As Editor = doc.Editor Using tr As Transaction = db.TransactionManager.StartTransaction Dim ms As BlockTableRecord = tr.GetObject(SymbolUtilityServices.GetBlockModelSpaceId(db), OpenMode.ForWrite) For Each id As ObjectId In ms Dim br As BlockReference = TryCast(tr.GetObject(id, OpenMode.ForWrite), BlockReference) If br Is Nothing Then Continue For If Not br.IsDynamicBlock Then Continue For ids_diff.Clear() AddHandler db.ObjectAppended, AddressOf db_ObjectAppended br.ExplodeToOwnerSpace() RemoveHandler db.ObjectAppended, AddressOf db_ObjectAppended For Each id2 As ObjectId In ids_diff ed.WriteMessage(vbNewLine & "Object Exploded to Modelspace: " & id2.ObjectClass.Name) Next Next tr.Commit() End Using End Sub Public Sub db_ObjectAppended(s As Object, e As ObjectEventArgs) ids_diff.Add(e.DBObject.ObjectId) End Sub
Hi Daniel
Your code works great and I am able to do what I want with the entities that were part of the Dynamic block.
Thank you very much. I had given up on using Dynamic Blocks but this has inspired me to push on. I expect lots of people will find it useful.
P.S. I use the Transaction Manager to get hold of Property Sets - these are for AutoCAD ACA. I use this method since the ACA example code does too.
Hello Hugh,
glad I could help. I wasn't aware, you are programming against ACA, therefore the misunderstanding to the transaction-thing. So I guess, the ACA (AEC?) Namespace has the DBTransactionmanager class, which seems to differ from the autodesk.autocad.databaseservices.database.transactionmanager class. 🙂
However, dynblocks are pure Acad objects so you need to manipulate them via the db-transaction of the autocad-ns.
In case you weren't working with this class yet: never, I repeat never forget to close the transaction by using tr.commit (or tr.abort if you don't want to save changes)!!!! :-))))
BR,
Daniel