TheSwamp

Code Red => .NET => Topic started by: smcclure on August 14, 2006, 11:28:35 AM

Title: Copying the ScaleFactor to an AttributeReference
Post by: smcclure on August 14, 2006, 11:28:35 AM
I am changing the ScaleFactor member of a BlockReference upon creating the block, although I found that (logically) the scale does not get applied to all AttributeReferences. I figured I would also apply the scale to each attribute while I was creating them. This proved to be difficult, though, since there is no ScaleFactor member for an AttributeReference. I started to try to apply the scale myself, but my attempts are failing.

My question is how should I apply the ScaleFactor from the block to the AttributeReference?

Currently, I use something like this (it doesnt work....)
attref.Position.ScaleBy(scale,new Point3d(0,0,0))
attref.Height *= scale
attref.WidthFactor *= scale

P.S. I also posted this in the AC Discussion Groups... the thread can be found at http://discussion.autodesk.com/thread.jspa?threadID=490763 (http://discussion.autodesk.com/thread.jspa?threadID=490763)
Title: Re: Copying the ScaleFactor to an AttributeReference
Post by: Glenn R on August 14, 2006, 06:20:59 PM
Off the top of my head, I believe you would get the block transform and then apply that using transform to the attribute references...at least that's what I would try first.
Title: Re: Copying the ScaleFactor to an AttributeReference
Post by: Nathan Taylor on August 14, 2006, 07:15:47 PM
Off the top of my head, I believe you would get the block transform and then apply that using transform to the attribute references...at least that's what I would try first.

Something like
Code: [Select]
objAttRef = New AttributeReference
objAttRef.SetAttributeFromBlock(objAttDef, objBlockRef.BlockTransform)

Regards - Nathan
Title: Re: Copying the ScaleFactor to an AttributeReference
Post by: smcclure on August 15, 2006, 09:34:29 AM
Code: [Select]
objAttRef.SetAttributeFromBlock(objAttDef, objBlockRef.BlockTransform)

I have tried this in the past and I am still very unclear about it's function. I thought it would copy over the height, rotation, text width, etc. from the attdef to the attref and apply the block transform from the bref. It doesnt do any of this, though... The function seems to do absolutely nothing.

I started a thread about it in the AD forums where I was told this was the expected functionality (which still makes no sense)... The thread can be found at http://discussion.autodesk.com/thread.jspa?messageID=5205969 (http://discussion.autodesk.com/thread.jspa?messageID=5205969)

Maybe you could help explain how this function is supposed to work.
Title: Re: Copying the ScaleFactor to an AttributeReference
Post by: smcclure on August 15, 2006, 09:37:46 AM
Off the top of my head, I believe you would get the block transform and then apply that using transform to the attribute references...at least that's what I would try first.

This is basically what Tony suggested on the AD forums. I use the code below to copy my attribute information. The code in the comments worked, but did not apply the scale. The lines with the "NEW" comments were just added to incorporate your suggestion (and Tony's) and it doesnt work...

Any suggestions?

Code: [Select]
    Public Shared Sub CopyAttribute(ByRef def As AttributeDefinition, ByRef ref As AttributeReference, ByRef bref As BlockReference)
        With ref
            .HorizontalMode = def.HorizontalMode
            .VerticalMode = def.VerticalMode
            If def.VerticalMode <> TextVerticalMode.TextBase Or def.HorizontalMode <> TextHorizontalMode.TextLeft Then
                '.AlignmentPoint = New Point3d(def.AlignmentPoint.X + bref.Position.X, _
                '                              def.AlignmentPoint.Y + bref.Position.Y, _
                '                              def.AlignmentPoint.Z + bref.Position.Z)
                .AlignmentPoint = def.AlignmentPoint 'NEW
            End If
            .WidthFactor = def.WidthFactor
            .FieldLength = def.FieldLength
            .Height = def.Height
            .Rotation = def.Rotation
            .TextStyle = def.TextStyle
            .Position = def.Position 'NEW
            '.Position = New Point3d(def.Position.X + bref.Position.X, _
            '                        def.Position.Y + bref.Position.Y, _
            '                        def.Position.Z + bref.Position.Z)
            .TransformBy(bref.BlockTransform) 'NEW
            .Tag = def.Tag
            .Layer = def.Layer
            .Color = def.Color
            .Linetype = def.Linetype
            .TextString = def.TextString
        End With
    End Sub
Title: Re: Copying the ScaleFactor to an AttributeReference
Post by: mohnston on August 15, 2006, 02:55:18 PM
I am changing the ScaleFactor member of a BlockReference upon creating the block, although I found that (logically) the scale does not get applied to all AttributeReferences. I figured I would also apply the scale to each attribute while I was creating them. This proved to be difficult, though, since there is no ScaleFactor member for an AttributeReference. I started to try to apply the scale myself, but my attempts are failing.

My question is how should I apply the ScaleFactor from the block to the AttributeReference?

Are you saying that you are creating attribute definitions and setting their scale but the attribute references do not display at the scale set for their definitions? You can't create AttributeReferences. You can get them (GetAttributes method) but they can only be created when a block with definitions is inserted.

As far as I know the only thing you can change about an attribute reference is the value.
The attribute definition is a different story.
Title: Re: Copying the ScaleFactor to an AttributeReference
Post by: Nathan Taylor on August 15, 2006, 06:58:51 PM
Are you saying that you are creating attribute definitions and setting their scale but the attribute references do not display at the scale set for their definitions? You can't create AttributeReferences. You can get them (GetAttributes method) but they can only be created when a block with definitions is inserted.

As far as I know the only thing you can change about an attribute reference is the value.
The attribute definition is a different story.
With the .NET API when you insert a block it does not include the attribute references you have to add them yourself.

Regards - Nathan
Title: Re: Copying the ScaleFactor to an AttributeReference
Post by: Nathan Taylor on August 15, 2006, 07:06:39 PM
Code: [Select]
objAttRef.SetAttributeFromBlock(objAttDef, objBlockRef.BlockTransform)

I have tried this in the past and I am still very unclear about it's function. I thought it would copy over the height, rotation, text width, etc. from the attdef to the attref and apply the block transform from the bref. It doesnt do any of this, though... The function seems to do absolutely nothing.

I started a thread about it in the AD forums where I was told this was the expected functionality (which still makes no sense)... The thread can be found at http://discussion.autodesk.com/thread.jspa?messageID=5205969 (http://discussion.autodesk.com/thread.jspa?messageID=5205969)

Maybe you could help explain how this function is supposed to work.
Please include the code where you are appending the attributeref to the blockref and adding the blockref to the database.

Regards - Nathan
Title: Re: Copying the ScaleFactor to an AttributeReference
Post by: smcclure on August 16, 2006, 08:33:19 AM
This is the code that calls the CopyAttribute function.

Thanks!
 - Scott

Code: [Select]
    Public Shared Sub InsertSymbolFromFile(ByVal doc As Document, ByVal dwgPath As String, ByVal insertPoint As Point3d, Optional ByRef attribValues As System.Collections.Specialized.StringDictionary = Nothing, Optional ByVal prompt As Boolean = False)
        If Not System.IO.File.Exists(dwgPath) Then Throw New System.IO.FileNotFoundException("Could not find symbol file file to insert.", dwgPath)
        If doc Is Nothing Then Throw New ArgumentNullException("The document cannot be null.", "doc")

        Using t As Transaction = doc.TransactionManager.StartTransaction(), db As Database = New Database(False, False)
            'read drawing
            db.ReadDwgFile(dwgPath, System.IO.FileShare.Read, True, Nothing)

            'insert it as a new block
            Dim idBTR As ObjectId = doc.Database.Insert("Watermark", db, True)

            Using bt As BlockTable = CType(t.GetObject(doc.Database.BlockTableId, OpenMode.ForRead), BlockTable), _
                  modelSpace As BlockTableRecord = CType(t.GetObject(bt(BlockTableRecord.ModelSpace), OpenMode.ForWrite), BlockTableRecord), _
                  bref As BlockReference = New BlockReference(insertPoint, idBTR)

                Dim tbScale As Double = TitleblockScale()
                bref.ScaleFactors = New Scale3d(tbScale, tbScale, tbScale)

                'Add the blockreference...
                modelSpace.AppendEntity(bref)
                doc.TransactionManager.AddNewlyCreatedDBObject(bref, True)

                'Add the attributereferences...
                Using btAttRec As BlockTableRecord = CType(t.GetObject(bref.BlockTableRecord, OpenMode.ForRead), BlockTableRecord)
                    For Each idEnt As ObjectId In btAttRec
                        Dim ent As Entity = CType(t.GetObject(idEnt, OpenMode.ForRead), Entity)
                        If TypeOf (ent) Is AttributeDefinition Then
                            Dim attDef As AttributeDefinition = CType(ent, AttributeDefinition)
                            Dim attRef As AttributeReference = New AttributeReference()

                            CopyAttribute(attDef, attRef, bref)

                            If attribValues IsNot Nothing AndAlso attribValues.ContainsKey(attDef.Tag) Then
                                attRef.TextString = attribValues(attDef.Tag)
                            ElseIf prompt Then
                                Dim value As String = InputBox(attDef.Prompt, "Set Attribute Value", "")
                                If attribValues IsNot Nothing Then attribValues.Add(attDef.Tag, value)
                                attRef.TextString = value
                            End If

                            bref.AppendAttribute(attRef)
                            doc.TransactionManager.AddNewlyCreatedDBObject(attRef, True)
                        End If
                    Next
                End Using

            End Using
            t.Commit()
        End Using
    End Sub
Title: Re: Copying the ScaleFactor to an AttributeReference
Post by: Glenn R on August 16, 2006, 07:15:48 PM
This is how I've done it in the past - note the calls to SetPRopertiesFrom and SetAttributeFromBlock:

Code: [Select]
// Open the newly created block definition for reading...
BlockTableRecord detailBtr = (BlockTableRecord)myT.GetObject(detailMarkBlockId, OpenMode.ForRead);
foreach (ObjectId btrId in detailBtr) {
Entity ent = (Entity)myT.GetObject(btrId, OpenMode.ForRead);
AttributeDefinition attDef = ent as AttributeDefinition;
if (attDef == null)
continue;

AttributeReference pAttRef = new AttributeReference();
pAttRef.SetPropertiesFrom(attDef);

pAttRef.SetAttributeFromBlock(attDef, newDetailBlkRef.BlockTransform);

if (attDef.Tag == "DRAWINGNUMBER")
pAttRef.TextString = dlg.DrawingNumber;
else if (attDef.Tag == "DETAILNUMBER")
pAttRef.TextString = dlg.DetailNumber;

newDetailBlkRef.AttributeCollection.AppendAttribute(pAttRef);
myT.AddNewlyCreatedDBObject(pAttRef, true);

}

Cheers,
Glenn.
Title: Re: Copying the ScaleFactor to an AttributeReference
Post by: Nathan Taylor on August 16, 2006, 07:27:47 PM
This is the code that calls the CopyAttribute function.

Thanks!
 - Scott

Code: [Select]
    Public Shared Sub InsertSymbolFromFile(ByVal doc As Document, ByVal dwgPath As String, ByVal insertPoint As Point3d, Optional ByRef attribValues As System.Collections.Specialized.StringDictionary = Nothing, Optional ByVal prompt As Boolean = False)
        If Not System.IO.File.Exists(dwgPath) Then Throw New System.IO.FileNotFoundException("Could not find symbol file file to insert.", dwgPath)
        If doc Is Nothing Then Throw New ArgumentNullException("The document cannot be null.", "doc")

        Using t As Transaction = doc.TransactionManager.StartTransaction(), db As Database = New Database(False, False)
            'read drawing
            db.ReadDwgFile(dwgPath, System.IO.FileShare.Read, True, Nothing)

            'insert it as a new block
            Dim idBTR As ObjectId = doc.Database.Insert("Watermark", db, True)

            Using bt As BlockTable = CType(t.GetObject(doc.Database.BlockTableId, OpenMode.ForRead), BlockTable), _
                  modelSpace As BlockTableRecord = CType(t.GetObject(bt(BlockTableRecord.ModelSpace), OpenMode.ForWrite), BlockTableRecord), _
                  bref As BlockReference = New BlockReference(insertPoint, idBTR)

                Dim tbScale As Double = TitleblockScale()
                bref.ScaleFactors = New Scale3d(tbScale, tbScale, tbScale)

                'Add the blockreference...
                modelSpace.AppendEntity(bref)
                doc.TransactionManager.AddNewlyCreatedDBObject(bref, True)

                'Add the attributereferences...
                Using btAttRec As BlockTableRecord = CType(t.GetObject(bref.BlockTableRecord, OpenMode.ForRead), BlockTableRecord)
                    For Each idEnt As ObjectId In btAttRec
                        Dim ent As Entity = CType(t.GetObject(idEnt, OpenMode.ForRead), Entity)
                        If TypeOf (ent) Is AttributeDefinition Then
                            Dim attDef As AttributeDefinition = CType(ent, AttributeDefinition)
                            Dim attRef As AttributeReference = New AttributeReference()

                            CopyAttribute(attDef, attRef, bref)

                            If attribValues IsNot Nothing AndAlso attribValues.ContainsKey(attDef.Tag) Then
                                attRef.TextString = attribValues(attDef.Tag)
                            ElseIf prompt Then
                                Dim value As String = InputBox(attDef.Prompt, "Set Attribute Value", "")
                                If attribValues IsNot Nothing Then attribValues.Add(attDef.Tag, value)
                                attRef.TextString = value
                            End If

                            bref.AppendAttribute(attRef)
                            doc.TransactionManager.AddNewlyCreatedDBObject(attRef, True)
                        End If
                    Next
                End Using

            End Using
            t.Commit()
        End Using
    End Sub
I'm not sure if this is your problem but I would change the following lines to use the transaction you have created. Note though that I am a novice with the .NET API so what you have done may be fine.

Code: [Select]
doc.TransactionManager.AddNewlyCreatedDBObject(bref, True)TO
Code: [Select]
t.AddNewlyCreatedDBObject(bref, True)
Code: [Select]
doc.TransactionManager.AddNewlyCreatedDBObject(attRef, True)TO
Code: [Select]
t.AddNewlyCreatedDBObject(attRef, True)
Regards - Nathan
Title: Re: Copying the ScaleFactor to an AttributeReference
Post by: smcclure on August 18, 2006, 09:44:49 AM
Code: [Select]
doc.TransactionManager.AddNewlyCreatedDBObject(bref, True)TO
Code: [Select]
t.AddNewlyCreatedDBObject(bref, True)
Code: [Select]
doc.TransactionManager.AddNewlyCreatedDBObject(attRef, True)TO
Code: [Select]
t.AddNewlyCreatedDBObject(attRef, True)

I am using AC2005, and the AddNewlyCreatedDBObject doesnt exist under the Transaction object until 2006 or beyond.

 - Scott
Title: Re: Copying the ScaleFactor to an AttributeReference
Post by: Maverick® on August 18, 2006, 09:54:48 AM
*Swoop in*

  Awesome first posts Nathan Taylor!!  Wow

  Welcome to da Swamp!

 *Kick out*
Title: Re: Copying the ScaleFactor to an AttributeReference
Post by: smcclure on August 18, 2006, 10:12:01 AM
Code: [Select]
AttributeReference pAttRef = new AttributeReference();
pAttRef.SetPropertiesFrom(attDef);
pAttRef.SetAttributeFromBlock(attDef, newDetailBlkRef.BlockTransform);

I gave the lines above a try (unfortunately I wasnt able to use the whole sample because I am using 2005) and it didn't work. I wonder if it is an issue with 2005? Has anyone had any success getting this to work for 2005?

This is the first time I have ever seen a call to SetPropertiesFrom and it makes complete sense. As usual, though, Autodesk's documentation on both functions is almost non-existent.

Any other methods? At this point, I would like to just figure out a way to manually apply the scale at minimum since I have been copying everything manually already anyways... If anyone knows how to get this (the two-line solution) to work, though, that would be best.

Thanks for your help everyone!
 - Scott
Title: Re: Copying the ScaleFactor to an AttributeReference
Post by: Nathan Taylor on August 20, 2006, 07:41:11 PM
*Swoop in*

  Awesome first posts Nathan Taylor!!  Wow

  Welcome to da Swamp!

 *Kick out*

Thanks. This seems to be the best resource for AutoCAD .NET API. Hopefully I will learn a lot here.

Regards - Nathan