.NET
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Explode dynamic block with stretch Action

12 REPLIES 12
Reply
Message 1 of 13
dba78
1531 Views, 12 Replies

Explode dynamic block with stretch Action

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

 

12 REPLIES 12
Message 2 of 13
jeff
in reply to: dba78

Have tried using BlockReference.ConvertToStaticBlock()?

 

Converts the dynamic block instance to a legacy (non-dynamic) anonymous block.

 

You can also find your answers @ TheSwamp
Message 3 of 13
dba78
in reply to: jeff

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

Message 4 of 13
xpeter88
in reply to: dba78

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

Message 5 of 13
Hugh_Compton
in reply to: dba78

    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)

Message 6 of 13

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

Message 7 of 13
daniel.balogh
in reply to: xpeter88

As you edit a dynamic Block by its Properties, acad creates a so called "Anonymous Block Definition" related to the original Blockdef. Orig Blockdef holds original geometry and settings, anonymous blockdef holds the altered geometry. This new Blockdef is called something like "*U123", so if you browse Modelspace by Blockname, you wont find it anymore.
HTH.
BR,
Daniel
Message 8 of 13
Hugh_Compton
in reply to: dba78

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

 

Message 9 of 13

Hello Hugh,
as a quick feedback, you define a variable "tm as DBTransactionmanager=...". I'n not sure, what acad you are programming in, but there is no type defined in acad 2012/2013 named "DBTransactionmanager".....
I'm not checked the rest, but this wont work for sure... wonder how you could compile this anyway, VS wouldn't let me....
Okay, testing your code now to see what else could be wrong.
BR,
D
Message 10 of 13

later on.... tm.getobject???? you can't get an object by the transactionmanager! transaction can do such a thing 🙂

Message 11 of 13

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

 

Message 12 of 13

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. 

Message 13 of 13

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

 

Can't find what you're looking for? Ask the community or share your knowledge.

Post to forums  

Autodesk DevCon in Munich May 28-29th


Autodesk Design & Make Report

”Boost