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

Working With Nested Blocks

48 REPLIES 48
Reply
Message 1 of 49
HEnnulat
2575 Views, 48 Replies

Working With Nested Blocks

I'm trying to insert a block that contains other blocks and then change the values of the attributes of the nested block. This seems like a whole new problem then doing the same thing with just one base level block. Could someone offer any guidance on this?
48 REPLIES 48
Message 41 of 49
HEnnulat
in reply to: HEnnulat

I remember seeing this now. However it didn't come to mind as I didn't know what this is at the time. I'm still in the fuzzy stage actually....
Message 42 of 49
jerrywinters
in reply to: HEnnulat

Doooh!

Yes. That is an old snippet from an old book written by an old man. For everyone's benefit, here is the new code from the new book written by a new and improved (at least I'm trying to improve) man.

I have supplied three SetAttributes Procedures. First, the ArrayList, ArrayList one (from the old book written by the old man). Second, using the HashTable, and Third, the Dictionary(Of String, String). The benefit of using the HashTable and Dictionary Classes is that they support the use of a Key by which we can get the Attribute Values instead of two separate ArrayLists. They are using Strings as their 'values' in these examples. Other Types can be used as well.

Thanks.

Jerry



{code}
_
Public Sub InsertBlocks()
Dim myBlkRefID As ObjectId = InsertBlock(New Point3d(0, 3, 0), "BlockA", 1, 1, 1)
Dim tagArray As New ArrayList
Dim valArray As New ArrayList
tagArray.Add("TAGA") : valArray.Add("not")
tagArray.Add("TAGB") : valArray.Add("the")
tagArray.Add("TAGC") : valArray.Add("best")
tagArray.Add("TAGD") : valArray.Add("way")
SetAttributes(myBlkRefID, tagArray, valArray)

myBlkRefID = InsertBlock(New Point3d(2, 3, 0), "BlockA", 1, 1, 1)
Dim myAttHash As New Hashtable
myAttHash.Add("TAGA", "A")
myAttHash.Add("TAGB", "B")
myAttHash.Add("TAGC", "C")
myAttHash.Add("TAGD", "D")
SetAttributes(myBlkRefID, myAttHash)

myBlkRefID = InsertBlock(New Point3d(4, 3, 0), "BlockA", 1, 1, 1)
Dim myAttDictionary As New Dictionary(Of String, String)
myAttDictionary.Add("TAGA", "1")
myAttDictionary.Add("TAGB", "2")
myAttDictionary.Add("TAGC", "3")
myAttDictionary.Add("TAGD", "4")
SetAttributes(myBlkRefID, myAttDictionary)
End Sub

Public Function InsertBlock(ByVal InsPt As Geometry.Point3d, _
ByVal BlockName As String, ByVal XScale As Double, _
ByVal YScale As Double, ByVal ZScale As Double) As DatabaseServices.ObjectId

Dim retObjectID As ObjectId = ObjectId.Null
Dim myDB As Database = HostApplicationServices.WorkingDatabase
Using myTrans As Transaction = myDB.TransactionManager.StartTransaction
'Open the database for Write
Dim myBT As BlockTable = myDB.BlockTableId.GetObject(OpenMode.ForRead)
Dim myBTR As BlockTableRecord = myBT(BlockTableRecord.ModelSpace).GetObject(OpenMode.ForWrite)
'Check to see if the Block exists
If Not myBT.Has(BlockName) Then Return retObjectID
'Insert the Block
Dim myBlockDef As BlockTableRecord = myBT(BlockName).GetObject(OpenMode.ForRead)
Dim myBlockRef As New DatabaseServices.BlockReference(InsPt, myBT(BlockName))
myBlockRef.ScaleFactors = New Geometry.Scale3d(XScale, YScale, ZScale)

myBTR.AppendEntity(myBlockRef)
myTrans.AddNewlyCreatedDBObject(myBlockRef, True)

'Set the Attribute Value
Dim myAttColl As DatabaseServices.AttributeCollection
Dim myEnt As DatabaseServices.Entity
myAttColl = myBlockRef.AttributeCollection
For Each myOID As ObjectId In myBlockDef
myEnt = myOID.GetObject(OpenMode.ForWrite)
If TypeOf myEnt Is DatabaseServices.AttributeDefinition Then
Dim myAttDef As DatabaseServices.AttributeDefinition = myEnt
Dim myAttRef As New DatabaseServices.AttributeReference
myAttRef.SetAttributeFromBlock(myAttDef, myBlockRef.BlockTransform)
myAttColl.AppendAttribute(myAttRef)
myTrans.AddNewlyCreatedDBObject(myAttRef, True)
End If
Next
retObjectID = myBlockRef.ObjectId
'Commit the Transaction
myTrans.Commit()
End Using
Return retObjectID
End Function

Public Sub SetAttributes(ByVal BlockID As DatabaseServices.ObjectId, _
ByVal TagList As ArrayList, ByVal StringList As ArrayList)

Using myTrans As DatabaseServices.Transaction = BlockID.Database.TransactionManager.StartTransaction
Dim myBlkRef As DatabaseServices.BlockReference
Dim myAttColl As DatabaseServices.AttributeCollection
myBlkRef = BlockID.GetObject(OpenMode.ForWrite)
myAttColl = myBlkRef.AttributeCollection
Dim myAttID As DatabaseServices.ObjectId
Dim myAttRef As DatabaseServices.AttributeReference
For Each myAttID In myAttColl
myAttRef = myAttID.GetObject(OpenMode.ForWrite)
Dim X As Integer = TagList.IndexOf(myAttRef.Tag)
If X >= 0 Then
myAttRef.TextString = StringList(X)
End If
Next
myTrans.Commit()
End Using
End Sub

Public Sub SetAttributes(ByVal BlockID As DatabaseServices.ObjectId, _
ByVal AttValues As Hashtable)

Using myTrans As DatabaseServices.Transaction = BlockID.Database.TransactionManager.StartTransaction
Dim myBlkRef As DatabaseServices.BlockReference
Dim myAttColl As DatabaseServices.AttributeCollection
myBlkRef = BlockID.GetObject(OpenMode.ForWrite)
myAttColl = myBlkRef.AttributeCollection
Dim myAttID As DatabaseServices.ObjectId
Dim myAttRef As DatabaseServices.AttributeReference
For Each myAttID In myAttColl
myAttRef = myAttID.GetObject(OpenMode.ForWrite)
If AttValues.ContainsKey(myAttRef.Tag) Then
myAttRef.TextString = AttValues(myAttRef.Tag)
End If
Next
myTrans.Commit()
End Using
End Sub

Public Sub SetAttributes(ByVal BlockID As DatabaseServices.ObjectId, _
ByVal AttValues As Dictionary(Of String, String))

Using myTrans As DatabaseServices.Transaction = BlockID.Database.TransactionManager.StartTransaction
Dim myBlkRef As DatabaseServices.BlockReference
Dim myAttColl As DatabaseServices.AttributeCollection
myBlkRef = BlockID.GetObject(OpenMode.ForWrite)
myAttColl = myBlkRef.AttributeCollection
Dim myAttID As DatabaseServices.ObjectId
Dim myAttRef As DatabaseServices.AttributeReference
For Each myAttID In myAttColl
myAttRef = myAttID.GetObject(OpenMode.ForWrite)
If AttValues.ContainsKey(myAttRef.Tag) Then
myAttRef.TextString = AttValues(myAttRef.Tag)
End If
Next
myTrans.Commit()
End Using
End Sub
{code}
Message 43 of 49
patrick1256
in reply to: HEnnulat

Why are you exploding to do what you are doing? Would not a recursive approach be much better suited without exploding?

Patrick Johnson
http:\\www.cadenhancement.com
Message 44 of 49
HEnnulat
in reply to: HEnnulat

Pat, The reason is found in my post dated Posted: Nov 12, 2009 4:55 PM. Long thread I know, so easy to miss... read the 2 paragraphs starting with "My purpose...."
Message 45 of 49
HEnnulat
in reply to: HEnnulat

It looks like the Dictionary class is a HashTable as the Dictinary is implemented as a HashTable.
Why would you use one over the other? It wasn't obvious by looking up the help.
Message 46 of 49
HEnnulat
in reply to: HEnnulat

Jerry, thanks for working this out. It does seem a little more elegant and saves a few lines of code, but comparing all three (3) approaches they all look quite similiar. Not sure it saves any time. Still its nice to have options and learn the finer points. The help for HashTablles and Dictionary classes has a lot of warnings about failures that can occur..... makes me wonder if there is anything we need to worry about.... I'm thinking these warnings refer to changing keys however which we are not doing.
Message 47 of 49
jerrywinters
in reply to: HEnnulat

The HashTable allows us to add Objects with a String Key. The Objects added can be of any Type. So, we could have Strings, Integers, Lines, BlockReferences all in the same HashTable.

The Dictionary(of . . .) allows us to specify the type of Key we are going to use as well as the type of Object that is going to be placed in the Dictionary.

{code}

Dim myAttDictionary As New Dictionary(Of String, String)
myAttDictionary.Add("TAGA", "1")
myAttDictionary.Add("TAGB", "2")
myAttDictionary.Add("TAGC", "3")
myAttDictionary.Add("TAGD", "4")
myAttDictionary.Add("TAGE", New Point3d(0, 0, 0))
{code}

If you attempt to use this code, you will find that Visual Studio does Type checking and will tell you a Point3d can not be converted into a String. So, the Dictionary provides Type Checking which may be preferable.

As mentioned above, we can use Keys other than Strings with the Dictionary. An example of this would be if we wanted to use a numeric value as the key.

{code}
Dim myAttDictionary2 As New Dictionary(Of Integer, String)
myAttDictionary2.Add(1, "01")
myAttDictionary2.Add(2, "02")
myAttDictionary2.Add(3, "03")
myAttDictionary2.Add(4, "04")
{code}

Jerry
Message 48 of 49
Anonymous
in reply to: HEnnulat

{quote}
The HashTable allows us to add Objects with a String Key
{quote}

HashTable allows the use of any type for both the key and the value, which
is why it is much slower than the Dictionary.

--
http://www.caddzone.com

AcadXTabs: MDI Document Tabs for AutoCAD
Supporting AutoCAD 2000 through 2010

http://www.acadxtabs.com

Email: string.Format("{0}@{1}.com", "tonyt", "caddzone");
Message 49 of 49
Anonymous
in reply to: HEnnulat

Dictionary(Of Key,Value) is a generic type.

You can find lots of background information on generic types in .NET, and
why they have advantages over non-generic equivalents by searching the net.

--
http://www.caddzone.com

AcadXTabs: MDI Document Tabs for AutoCAD
Supporting AutoCAD 2000 through 2010

http://www.acadxtabs.com

Email: string.Format("{0}@{1}.com", "tonyt", "caddzone");

wrote in message news:6292789@discussion.autodesk.com...
It looks like the Dictionary class is a HashTable as the Dictinary is
implemented as a HashTable.
Why would you use one over the other? It wasn't obvious by looking up the
help.

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