Author Topic: Copying the ScaleFactor to an AttributeReference  (Read 8156 times)

0 Members and 1 Guest are viewing this topic.

smcclure

  • Guest
Copying the ScaleFactor to an AttributeReference
« 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

Glenn R

  • Guest
Re: Copying the ScaleFactor to an AttributeReference
« Reply #1 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.

Nathan Taylor

  • Guest
Re: Copying the ScaleFactor to an AttributeReference
« Reply #2 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

smcclure

  • Guest
Re: Copying the ScaleFactor to an AttributeReference
« Reply #3 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

Maybe you could help explain how this function is supposed to work.

smcclure

  • Guest
Re: Copying the ScaleFactor to an AttributeReference
« Reply #4 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

mohnston

  • Bull Frog
  • Posts: 305
  • CAD Programmer
Re: Copying the ScaleFactor to an AttributeReference
« Reply #5 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.
It's amazing what you can do when you don't know what you can't do.
CAD Programming Solutions

Nathan Taylor

  • Guest
Re: Copying the ScaleFactor to an AttributeReference
« Reply #6 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
« Last Edit: August 15, 2006, 07:00:27 PM by Nathan Taylor »

Nathan Taylor

  • Guest
Re: Copying the ScaleFactor to an AttributeReference
« Reply #7 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

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

smcclure

  • Guest
Re: Copying the ScaleFactor to an AttributeReference
« Reply #8 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

Glenn R

  • Guest
Re: Copying the ScaleFactor to an AttributeReference
« Reply #9 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.

Nathan Taylor

  • Guest
Re: Copying the ScaleFactor to an AttributeReference
« Reply #10 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

smcclure

  • Guest
Re: Copying the ScaleFactor to an AttributeReference
« Reply #11 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

Maverick®

  • Seagull
  • Posts: 14778
Re: Copying the ScaleFactor to an AttributeReference
« Reply #12 on: August 18, 2006, 09:54:48 AM »
*Swoop in*

  Awesome first posts Nathan Taylor!!  Wow

  Welcome to da Swamp!

 *Kick out*

smcclure

  • Guest
Re: Copying the ScaleFactor to an AttributeReference
« Reply #13 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

Nathan Taylor

  • Guest
Re: Copying the ScaleFactor to an AttributeReference
« Reply #14 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