Author Topic: BlockTesting2011  (Read 34980 times)

0 Members and 1 Guest are viewing this topic.

gile

  • Gator
  • Posts: 2507
  • Marseille, France
Re: BlockTesting2011
« Reply #15 on: April 02, 2011, 06:30:02 PM »
Next Stage :
Inserting Attributes.

Library stuff
Two different named functions have to be defined because F# do not allow function overloading

The first one is written in an 'imperative' style (closer to C# or VB), the second one is writen in a more 'functional' style (using F# specific features)
Code - F#: [Select]
  1. //=======================================================================
  2. // Insert ALL AttributeReferences from BlockTableRecord into BlockReference
  3. let insertDefaultAttibuteInBlockRef (blkRef:BlockReference) (tr:Transaction) =
  4.     for attId in tr.GetObject(blkRef.BlockTableRecord, OpenMode.ForRead) :?> BlockTableRecord do
  5.         let dbObj= tr.GetObject(attId, OpenMode.ForRead)
  6.         if dbObj:? AttributeDefinition then
  7.             let attDef = dbObj:?> AttributeDefinition
  8.             let attRef = new AttributeReference()
  9.             attRef.SetAttributeFromBlock(attDef, blkRef.BlockTransform)
  10.             blkRef.AttributeCollection.AppendAttribute(attRef) |> ignore
  11.             tr.AddNewlyCreatedDBObject(attRef, true)
  12. //=======================================================================
  13. // Insert ALL AttributeReferences from BlockTableRecord into BlockReference      
  14. let insertAttibuteInBlockRef (blkRef:BlockReference) attributeTag attributeText (tr:Transaction) =
  15.     tr.GetObject(blkRef.BlockTableRecord, OpenMode.ForRead) :?> BlockTableRecord
  16.     |> Seq.cast<_>
  17.     |> Seq.map (fun id -> tr.GetObject(id, OpenMode.ForRead))
  18.     |> Seq.choose (function :? AttributeDefinition as att -> Some att | _ -> None)
  19.     |> Seq.iter (fun attDef ->
  20.         let attRef = new AttributeReference()
  21.         attRef.SetAttributeFromBlock(attDef, blkRef.BlockTransform) |> ignore
  22.         if attRef.Tag = attributeTag then
  23.             attRef.TextString <- attributeText
  24.             blkRef.AttributeCollection.AppendAttribute(attRef) |> ignore
  25.             tr.AddNewlyCreatedDBObject(attRef, true))
  26. //=======================================================================

Test routines
Code - F#: [Select]
  1. //=======================================================================
  2. // add the block to the ActiveDrawing CurrentSpace
  3. // Imports the Block if not found in the BlockTable
  4. // Adds ALL AttributeReference to the BlockReference
  5. [<CommandMethod("BI_15")>]
  6. let blockInsert_15 () =
  7.     let blockQualifiedFileName = "K:\\ToTest\\3Dblock_A.dwg"
  8.     let blockName = "3Dblock_A"
  9.    
  10.     use tr = db.TransactionManager.StartTransaction()
  11.     let bt = tr.GetObject(db.BlockTableId, OpenMode.ForRead) :?> BlockTable
  12.     if not (bt.Has(blockName)) then
  13.         use tmpDb = new Database()
  14.         tmpDb.ReadDwgFile(blockQualifiedFileName, System.IO.FileShare.Read, true, "")
  15.         // add the block to the ActiveDrawing blockTable
  16.         db.Insert(blockName, tmpDb, true) |> ignore
  17.        
  18.     let ppr = ed.GetPoint("\nSpecify insertion point: ")
  19.     if ppr.Status = PromptStatus.OK then
  20.         let btr = tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite) :?> BlockTableRecord
  21.         use br = new BlockReference(Point3d.Origin, bt.[blockName])
  22.         br.TransformBy(Matrix3d.Displacement(ppr.Value.GetAsVector())
  23.                        |> (*) ed.CurrentUserCoordinateSystem)
  24.         btr.AppendEntity(br) |> ignore
  25.         tr.AddNewlyCreatedDBObject(br, true)
  26.         insertDefaultAttibuteInBlockRef br tr
  27.         tr.Commit()
  28. //=======================================================================

Code - F#: [Select]
  1. //=======================================================================
  2. // add the block to the ActiveDrawing CurrentSpace
  3. // Imports the Block if not found in the BlockTable
  4. // Adds ALL AttributeReference to the BlockReference
  5. // Set the attributeText in a nominated
  6. [<CommandMethod("BI_16")>]
  7. let blockInsert_16 () =
  8.     let blockQualifiedFileName = "K:\\ToTest\\3Dblock_A.dwg"
  9.     let blockName = "3Dblock_A"
  10.     let attTag = "ATTRIBUTETAG"
  11.     let attText = "Yes, we have no bananas"
  12.    
  13.     use tr = db.TransactionManager.StartTransaction()
  14.     let bt = tr.GetObject(db.BlockTableId, OpenMode.ForRead) :?> BlockTable
  15.     if not (bt.Has(blockName)) then
  16.         use tmpDb = new Database()
  17.         tmpDb.ReadDwgFile(blockQualifiedFileName, System.IO.FileShare.Read, true, "")
  18.         // add the block to the ActiveDrawing blockTable
  19.         db.Insert(blockName, tmpDb, true) |> ignore
  20.        
  21.     let ppr = ed.GetPoint("\nSpecify insertion point: ")
  22.     if ppr.Status = PromptStatus.OK then
  23.         let btr = tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite) :?> BlockTableRecord
  24.         use br = new BlockReference(Point3d.Origin, bt.[blockName])
  25.         br.TransformBy(Matrix3d.Displacement(ppr.Value.GetAsVector())
  26.                        |> (*) ed.CurrentUserCoordinateSystem)
  27.         btr.AppendEntity(br) |> ignore
  28.         tr.AddNewlyCreatedDBObject(br, true)
  29.         insertAttibuteInBlockRef br attTag attText tr
  30.         tr.Commit()
  31. //=======================================================================
« Last Edit: January 25, 2012, 07:17:22 AM by Kerry »
Speaking English as a French Frog

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: BlockTesting2011
« Reply #16 on: April 02, 2011, 09:37:20 PM »
Next for C# :

Set ScaleFactor, Rotation as BlockReference Properties rather than by Transform
Set Layer as BlockReference Properties
Test for Layer assertion.

Code - C#: [Select]
  1.         //=======================================================================
  2.         // add the block to the ActiveDrawing CurrentSpace
  3.         // Imports the Block if not found in the BlockTable
  4.         //
  5.         // Set ScaleFactor, Rotation and Layer as BlockReference Properties
  6.         //
  7.         //   Add ALL AttributeReference to the BlockReference
  8.         //   and Set the attributeText in a nominated  Attribute  
  9.         //
  10.         // Includes a test for Layer assertion.
  11.  
  12.         [CommandMethod("BI_17")]
  13.         public void BlockInsert_17()
  14.         {
  15.             string blockQualifiedFileName = "K:\\ToTest\\3Dblock_A.dwg";
  16.             string blockName = "3Dblock_A";
  17.             string attTag = "ATTRIBUTETAG";
  18.             string attText = "Sample BI_17";
  19.             //
  20.             double scale = 2.3;
  21.             double rotation = RadiansToDegrees(20.0);
  22.             string layerName = "Test BI_17";
  23.  
  24.             // Assert the layer exists
  25.             CreateLayer(db, layerName, 8);
  26.  
  27.             using( Transaction tr = db.TransactionManager.StartTransaction() ) {
  28.                 try {
  29.                     BlockTable bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead);
  30.                     if( !bt.Has(blockName) ) {
  31.                         Database tmpDb = new Database(false, true);
  32.                         tmpDb.ReadDwgFile(blockQualifiedFileName, System.IO.FileShare.Read, true, "");
  33.                         // add the block to the ActiveDrawing blockTable
  34.                         db.Insert(blockName, tmpDb, true);
  35.                     }
  36.  
  37.                     PromptPointResult ppr = ed.GetPoint("\nSpecify insertion point: ");
  38.                     if( ppr.Status != PromptStatus.OK )
  39.                         return;
  40.  
  41.                     BlockTableRecord btr = (BlockTableRecord)tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite);
  42.  
  43.                     using( BlockReference br = new BlockReference(Point3d.Origin, bt[ blockName ]) ) {
  44.                         br.ScaleFactors = new Scale3d(scale);
  45.                         br.Rotation = rotation;
  46.                         br.Layer = layerName;
  47.  
  48.                         br.TransformBy(Matrix3d
  49.                             .Displacement(ppr.Value - Point3d.Origin)
  50.                             .PreMultiplyBy(ed.CurrentUserCoordinateSystem));
  51.  
  52.                         btr.AppendEntity(br);
  53.                         tr.AddNewlyCreatedDBObject(br, true);
  54.                         //
  55.                         InsertAttibuteInBlockRef(br, attTag, attText, tr);
  56.                     }
  57.                     tr.Commit();
  58.  
  59.                 } catch( Autodesk.AutoCAD.Runtime.Exception exx ) {
  60.                     ed.WriteMessage("\n" + exx.ToString());
  61.                 }
  62.             }
  63.         }
  64.         //=======================================================================
  65.  

Code - C#: [Select]
  1.         //=======================================================================
  2.         /// <summary>
  3.         ///  CreateLayer layer if not existing
  4.         /// </summary>
  5.         /// <param name="db"></param>
  6.         /// <param name="layerName"></param>
  7.         /// <param name="color"></param>
  8.         /// <returns> ObjectId of existing or new layer </returns>
  9.         public static ObjectId CreateLayer(Database db, string layerName, short color)
  10.         {
  11.             ObjectId layerId = ObjectId.Null;
  12.             using( Transaction tr = db.TransactionManager.StartTransaction() ) {
  13.                 LayerTable lt = (LayerTable)tr.GetObject(db.LayerTableId, OpenMode.ForWrite);
  14.                 //Check if EmployeeLayer exists...
  15.                 if( lt.Has(layerName) ) {
  16.                     layerId = lt[ layerName ];
  17.                 } else {
  18.                     //if not, create the layer here.
  19.                     LayerTableRecord ltr = new LayerTableRecord();
  20.                     ltr.Name = layerName;
  21.                     ltr.Color = Autodesk.AutoCAD.Colors.Color.FromColorIndex(
  22.                         Autodesk.AutoCAD.Colors.ColorMethod.ByAci, color);
  23.                     layerId = lt.Add(ltr);
  24.                     tr.AddNewlyCreatedDBObject(ltr, true);
  25.                 }
  26.                 tr.Commit();
  27.             }
  28.             return layerId;
  29.         }
  30.         //=======================================================================
  31.  
« Last Edit: December 18, 2011, 12:48:42 AM by Kerry »
kdub, kdub_nz in other timelines.
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

gile

  • Gator
  • Posts: 2507
  • Marseille, France
Re: BlockTesting2011
« Reply #17 on: April 03, 2011, 04:05:47 AM »
Next for F# :

Set ScaleFactor, Rotation as BlockReference Properties rather than by Transform
Set Layer as BlockReference Properties
Test for Layer assertion.

I put the  sub function first because with F# a function have to be defined in the code prior to be called (as local LISP sub routines)
Code - F#: [Select]
  1. //=======================================================================
  2. /// <summary>
  3. ///  CreateLayer layer if not existing
  4. /// </summary>
  5. /// <param name="db"></param>
  6. /// <param name="layerName"></param>
  7. /// <param name="color"></param>
  8. /// <returns> ObjectId of existing or new layer </returns>
  9. open Autodesk.AutoCAD.Colors
  10. let createLayer (db:Database) (layerName:string) color =
  11.     use tr = db.TransactionManager.StartTransaction()
  12.     let lt = tr.GetObject(db.LayerTableId, OpenMode.ForRead) :?> LayerTable
  13.     if lt.Has(layerName) then
  14.         lt.[layerName]
  15.     else
  16.         let ltr = new LayerTableRecord()
  17.         ltr.Name <- layerName
  18.         ltr.Color <- Color.FromColorIndex(ColorMethod.ByAci, color)
  19.         lt.UpgradeOpen()
  20.         let layerId = lt.Add(ltr)
  21.         tr.AddNewlyCreatedDBObject(ltr, true)
  22.         tr.Commit()
  23.         layerId
  24. //=======================================================================

Code - F#: [Select]
  1. //=======================================================================
  2. // add the block to the ActiveDrawing CurrentSpace
  3. // Imports the Block if not found in the BlockTable
  4. //
  5. // Set ScaleFactor, Rotation and Layer as BlockReference Properties
  6. //
  7. //   Add ALL AttributeReference to the BlockReference
  8. //   and Set the attributeText in a nominated  Attribute  
  9. //
  10. // Includes a test for Layer assertion
  11. [<CommandMethod("BI_17")>]
  12. let blockInsert_17 () =
  13.     let blockQualifiedFileName = "K:\\ToTest\\3Dblock_A.dwg"
  14.     let blockName = "3Dblock_A"
  15.     let attTag = "ATTRIBUTETAG"
  16.     let attText = "Sample BI_17"
  17.    
  18.     let scale = 2.3
  19.     let rotation = degreesToRadians 20.0
  20.     let layerName = "Test BI_17"
  21.    
  22.     createLayer db layerName 8s |> ignore
  23.    
  24.     use tr = db.TransactionManager.StartTransaction()
  25.     try
  26.         let bt = tr.GetObject(db.BlockTableId, OpenMode.ForRead) :?> BlockTable
  27.         if not (bt.Has(blockName)) then
  28.             use tmpDb = new Database()
  29.             tmpDb.ReadDwgFile(blockQualifiedFileName, System.IO.FileShare.Read, true, "")
  30.             db.Insert(blockName, tmpDb, true) |> ignore
  31.            
  32.         let ppr = ed.GetPoint("\nSpecify insertion point: ")
  33.         if ppr.Status = PromptStatus.OK then
  34.             let btr = tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite) :?> BlockTableRecord
  35.             use br = new BlockReference(Point3d.Origin, bt.[blockName])
  36.             br.ScaleFactors <- new Scale3d(scale)
  37.             br.Rotation <- rotation
  38.             br.Layer <- layerName
  39.            
  40.             br.TransformBy(Matrix3d.Displacement(ppr.Value.GetAsVector())
  41.                            |> (*) ed.CurrentUserCoordinateSystem)
  42.             btr.AppendEntity(br) |> ignore
  43.             tr.AddNewlyCreatedDBObject(br, true)
  44.            
  45.             insertAttibuteInBlockRef br attTag attText tr
  46.             tr.Commit()
  47.     with
  48.         | :? Autodesk.AutoCAD.Runtime.Exception as ex -> ed.WriteMessage("\n" + ex.Message)
  49. //=======================================================================
« Last Edit: January 25, 2012, 07:11:24 AM by Kerry »
Speaking English as a French Frog

kaefer

  • Guest
Re: BlockTesting2011
« Reply #18 on: April 03, 2011, 11:19:37 AM »
The Matrix3d multiplication operator (*) is equivalent to PostMultiplyBy that means transformations occur in reverse order : Scaling, then Displacement, then UCS rotation(s) and origin displacement.

Hi gile,

sorry for coming late to the party. Order of evaluation isn't quite what is at play here, think associativity.

Quote
Maybe it's more 'readable' to use the PreMultiplyBy method to write the transformations the same order they occur:

Code: [Select]
Transform = Matrix3d
    .Scaling(scale, Point3d.Origin)
    .PreMultiplyBy(Matrix3d.Displacement(DispacementVector))
    .PreMultiplyBy(Transform);

You have already addressed the method chaining with pipelining, eg.

Quote
Code: [Select]
let transform = Matrix3d.Scaling(scale, Point3d.Origin)
                        |> (*) (Matrix3d.Rotation(rotation, zAxis, Point3d.Origin))
                        |> (*) (Matrix3d.Displacement(dispacementVector))
                        |> (*) ed.CurrentUserCoordinateSystem

There's another functional fix for the natural order of these transforms: treat them as sequence and flip the order of the overloaded operators arguments (i.e. of PostMultiplyBy). Use this to reduce the seq<Matrix3d>, or better yet, fold it with its identity, to get a meaningful value even if the input sequence is empty.

Code: [Select]
        let flip f x y = f y x
        let fold xs = Seq.fold (flip (*)) Matrix3d.Identity xs

        let transform =
            fold[
                Matrix3d.Scaling(scale, Point3d.Origin)   
                Matrix3d.Rotation(rotation, zAxis, Point3d.Origin)
                Matrix3d.Displacement dispacementVector
                ed.CurrentUserCoordinateSystem   
            ]

gile

  • Gator
  • Posts: 2507
  • Marseille, France
Re: BlockTesting2011
« Reply #19 on: April 03, 2011, 12:52:34 PM »
Nice trick,Thorsten, as usual.
Speaking English as a French Frog

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: BlockTesting2011
« Reply #20 on: April 03, 2011, 06:17:33 PM »
Intermission : before we move on to handling multiple attributes.

I'd like opinions ( or reasoned arguments)
   
The method InsertAttibuteInBlockRef() only needs to be called if the BlockReference has attributes.
   
In InsertAttibuteInBlockRef_Original()I think I have too much casting occuring.
   ie
    Iterating the BlockTableRecord
    casting each Object to an Entity using a direct cast
    then testing if that Entity is an AttributeDefinition
    If that test is true
       direct-casting the Entity to an AttributeDefinition.
       Proceed to define the AttributeReference
   
 InsertAttibuteInBlockRef_Option
A better alternative may be to combine the cast using the 'as' keyword and forgo all direct casts.
If the conversion is not possible, 'as' returns null, which can be tested   
  ie
  Iterating the BlockTableRecord
  casting each Object to an AttributeDefinition using 'as'
  test if the AttributeDefinition is NOT null (compatible reference types)
  if NOT null,    Proceed to define the AttributeReference.
 
Code - C#: [Select]
  1.   public static void InsertAttibuteInBlockRef_Original(
  2.       BlockReference blkRef,
  3.       string attributeTag,
  4.       string attributeText,
  5.       Transaction tr)
  6.   {
  7.       BlockTableRecord btr = (BlockTableRecord)tr.GetObject(blkRef.BlockTableRecord, OpenMode.ForRead);
  8.       foreach( ObjectId id in btr ) {
  9.           Entity ent = (Entity)tr.GetObject(id, OpenMode.ForRead);
  10.           if( ent is AttributeDefinition ) {
  11.               AttributeDefinition attDef = (AttributeDefinition)ent;
  12.               AttributeReference attRef = new AttributeReference();
  13.               attRef.SetAttributeFromBlock(attDef, blkRef.BlockTransform);
  14.               if( attRef.Tag == attributeTag )
  15.                   attRef.TextString = attributeText;
  16.               blkRef.AttributeCollection.AppendAttribute(attRef);
  17.               tr.AddNewlyCreatedDBObject(attRef, true);
  18.           }
  19.       }
  20.   }  
  21.  

Code - C#: [Select]
  1.  
  2.   public static void InsertAttibuteInBlockRef_Option(
  3.       BlockReference blkRef,
  4.       string attributeTag,
  5.       string attributeText,
  6.       Transaction tr)
  7.   {
  8.       BlockTableRecord btr = (BlockTableRecord)tr.GetObject(blkRef.BlockTableRecord, OpenMode.ForRead);
  9.       foreach( ObjectId id in btr ) {
  10.           AttributeDefinition aDef = tr.GetObject(id, OpenMode.ForRead) as AttributeDefinition;
  11.           if( aDef != null ) {
  12.               AttributeReference aRef = new AttributeReference();
  13.               aRef.SetAttributeFromBlock(aDef, blkRef.BlockTransform);
  14.               if( aRef.Tag == attributeTag )
  15.                   aRef.TextString = attributeText;
  16.               blkRef.AttributeCollection.AppendAttribute(aRef);
  17.               tr.AddNewlyCreatedDBObject(aRef, true);
  18.           }
  19.       }
  20.   }  


Comments appreciated.   
« Last Edit: December 18, 2011, 12:53:41 AM by Kerry »
kdub, kdub_nz in other timelines.
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

Jeff H

  • Needs a day job
  • Posts: 6144
Re: BlockTesting2011
« Reply #21 on: April 03, 2011, 07:04:02 PM »
How about checking a property of the ObjectID and then if it matches criteria, then use the transaction to open the object and cast it.

MSDN or VS help says about 'as'
Quote
It is equivalent to the following expression except that expression is evaluated only one time

expression is type ? (type)expression : (type)null

Does not go into any real depth or exactly has it is implemented, but using that description I would think it has to open each object then check the type.

ObjectId.ObjectClass Property
Quote from:  Description
Accesses the RXClass of the object that is associated with the object id, thus guaranteeing that the result can be safely de-referenced and correctly compared against any class derived from DBObject. This is done because the entire purpose of this property is to streamline code being written; having to always compare the result against NULL would partially defeat the purpose of the function.
Quote from:  Notes
Use this property to obtain the associated object class without having to open and close the object itself.
If the object has not been read in from disk, the disk image will be scanned, but the object will remain on disk after the usage.

So to keep from opening each object and trying to cast it maybe something like this?

Code - C#: [Select]
  1. public static void InsertAttibuteInBlockRef_OptionA(
  2.               BlockReference blkRef,
  3.               string attributeTag,
  4.               string attributeText,
  5.               Transaction tr)
  6.         {
  7.             BlockTableRecord btr = (BlockTableRecord)tr.GetObject(blkRef.BlockTableRecord, OpenMode.ForRead);
  8.             foreach (ObjectId id in btr)
  9.             {
  10.  
  11.                 if (id.ObjectClass.Name == "AcDbAttributeDefinition")
  12.                 {
  13.                     AttributeDefinition aDef = (AttributeDefinition)tr.GetObject(id, OpenMode.ForRead);  
  14.                     AttributeReference aRef = new AttributeReference();
  15.                     aRef.SetAttributeFromBlock(aDef, blkRef.BlockTransform);
  16.                     if (aRef.Tag == attributeTag)
  17.                         aRef.TextString = attributeText;
  18.                     blkRef.AttributeCollection.AppendAttribute(aRef);
  19.                     tr.AddNewlyCreatedDBObject(aRef, true);
  20.                 }
  21.             }
  22.         }
  23.  
  24.  
« Last Edit: December 18, 2011, 12:57:00 AM by Kerry »

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: BlockTesting2011
« Reply #22 on: April 03, 2011, 07:28:19 PM »

That should work very nicely Jeff.


again, proof of 'use it or lose it" :D
http://www.theswamp.org/index.php?topic=31351.msg369348#msg369348
kdub, kdub_nz in other timelines.
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: BlockTesting2011
« Reply #23 on: April 03, 2011, 10:40:36 PM »
Next  deals with :

non-unifirm scaling
using the  PromptKeywordOptions
attribute Rotation.

Attached is a new block '3DBLOCK_4A' which has 4 attributes with differing justification.
This block will be used in this example and for the following multi attribute update examples.

This example is a little long for a sample but most of the concepts used should be familiar to the reader by now.

The Solution will be updated after the next example.

Code - C#: [Select]
  1.  
  2.        //=======================================================================
  3.         // add the block to the ActiveDrawing CurrentSpace
  4.         // Imports the Block if not found in the BlockTable
  5.         //
  6.         // Set ScaleFactor, Rotation and Layer as BlockReference Properties
  7.         // The scale can be non-uniform (demonstrated)
  8.         //
  9.         //   Add ALL AttributeReference to the BlockReference
  10.         //   and Set the attributeText in a nominated  Attribute  
  11.         //
  12.         // Includes a test for Layer assertion.
  13.         //
  14.         // Rotate the nominated Attribute Tag to either UCS, WCS, or Aligned with block insert
  15.  
  16.         [CommandMethod("BI_18")]
  17.         public void BlockInsert_18()
  18.         {
  19.             string blockQualifiedFileName = "K:\\ToTest\\3Dblock_4A.dwg";
  20.             string blockName = "3DBLOCK_4A";
  21.             string attTag = "ATTRIBUTETAG_MC";
  22.             string attText = "BI_18";
  23.             //
  24.             double scale = 2.5;
  25.             double rotation = RadiansToDegrees(-25.0);
  26.             double tagRotationAngle = 0.0;
  27.             string layerName = "Test BI_18";
  28.  
  29.             // Assert the layer exists
  30.             CreateLayer(db, layerName, 8);
  31.  
  32.             using( Transaction tr = db.TransactionManager.StartTransaction() ) {
  33.                 try {
  34.                     BlockTable bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead);
  35.                     if( !bt.Has(blockName) ) {
  36.                         Database tmpDb = new Database(false, true);
  37.                         tmpDb.ReadDwgFile(blockQualifiedFileName, System.IO.FileShare.Read, true, "");
  38.                         // add the block to the ActiveDrawing blockTable
  39.                         db.Insert(blockName, tmpDb, true);
  40.                     }
  41.  
  42.                     PromptPointResult ppr = ed.GetPoint("\nSpecify insertion point: ");
  43.                     if( ppr.Status != PromptStatus.OK )
  44.                         return;
  45.  
  46.                     PromptKeywordOptions pkOpt = new PromptKeywordOptions("\nRotate Attribute to :");
  47.                     pkOpt.Keywords.Add("UCS");
  48.                     pkOpt.Keywords.Add("WCS");
  49.                     pkOpt.Keywords.Add("Aligned");
  50.                     PromptResult prRes = ed.GetKeywords(pkOpt);
  51.                     if( prRes.Status != PromptStatus.OK )
  52.                         return;
  53.  
  54.                     BlockTableRecord btr = (BlockTableRecord)tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite);
  55.  
  56.                     using( BlockReference br = new BlockReference(Point3d.Origin, bt[ blockName ]) ) {
  57.                         br.ScaleFactors = new Scale3d(scale, scale, 1.0);
  58.                         br.Rotation = rotation;
  59.                         br.Layer = layerName;
  60.  
  61.                         br.TransformBy(Matrix3d
  62.                             .Displacement(ppr.Value - Point3d.Origin)
  63.                             .PreMultiplyBy(ed.CurrentUserCoordinateSystem));
  64.  
  65.                         btr.AppendEntity(br);
  66.                         tr.AddNewlyCreatedDBObject(br, true);
  67.                         //  
  68.                         InsertAttibuteInBlockRef(br, attTag, attText, tr);
  69.  
  70.                         switch( prRes.StringResult ) {
  71.                             case "WCS":
  72.                                 tagRotationAngle = 0.0;
  73.                                 break;
  74.                             case "UCS":
  75.                                 tagRotationAngle = br.Rotation - rotation;
  76.                                 break;
  77.                             case "Aligned":
  78.                                 tagRotationAngle = br.Rotation;
  79.                                 break;
  80.                         }
  81.  
  82.                         foreach( ObjectId idAttColl in br.AttributeCollection ) {
  83.                             AttributeReference ar = tr.GetObject(idAttColl, OpenMode.ForWrite) as AttributeReference;
  84.                             if( ar != null ) {
  85.                                 if( ar.Tag.ToUpper() == attTag ) {
  86.                                     ar.Rotation = tagRotationAngle;
  87.                                 }
  88.                             }
  89.                         }
  90.                     }
  91.                     tr.Commit();
  92.  
  93.                 } catch( Autodesk.AutoCAD.Runtime.Exception exx ) {
  94.                     ed.WriteMessage("\n" + exx.ToString());
  95.                 }
  96.             }
  97.         }
  98.         //=======================================================================
  99.  

« Last Edit: December 18, 2011, 12:51:51 AM by Kerry »
kdub, kdub_nz in other timelines.
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

gile

  • Gator
  • Posts: 2507
  • Marseille, France
Re: BlockTesting2011
« Reply #24 on: April 04, 2011, 03:33:32 AM »
Hi,

Just one thing about casting issues.
If we avoid using using the 'ObjectId.ObjectClass' route so that this sample can be used with AutoCAD version prior to 2009, I think the 'as' statement is the right way for C# (maybe fo VB too (with TryCast ?)).
But I can't find a F# equivalent for it (maybe there's none). I use the ':?' operator which is closed to 'is' C# keyword and I think this way can be used avoiding the cast from DBObject (returned by GetObject) to Entity:
Code - F#: [Select]
  1. DBObject dbo = tr.GetObject(id, OpenMode.ForRead);
  2. if (dbo is AttributeDefinition) { ... }

Anyway, here's a F# translation of the upper example.
Dealing with attribute rotation

Note: as F# default uses immutable values bound to symbols (using 'let'), 'variable' features need to explicitly use the 'mutable' keyword or use 'reference cells' with the 'ref' operator. This second way needs to be used in the following code with 'tagRotationAngle' because the lambda expression using the 'tagRotationAngle' value generates a closure.
Code - F#: [Select]
  1. //=======================================================================
  2. // add the block to the ActiveDrawing CurrentSpace
  3. // Imports the Block if not found in the BlockTable
  4. //
  5. // Set ScaleFactor, Rotation and Layer as BlockReference Properties
  6. // The scale can be non-uniform (demonstrated)
  7. //
  8. //   Add ALL AttributeReference to the BlockReference
  9. //   and Set the attributeText in a nominated  Attribute  
  10. //
  11. // Includes a test for Layer assertion.
  12. //
  13. // Rotate the nominated Attribute Tag to either UCS, WCS, or Aligned with block insert
  14. [<CommandMethod("BI_18")>]
  15. let blockInsert_18 () =
  16.     let blockQualifiedFileName = "K:\\ToTest\\3Dblock_4A.dwg"
  17.     let blockName = "3Dblock_4A"
  18.     let attTag = "ATTRIBUTETAG_MC"
  19.     let attText = "BI_18"
  20.    
  21.     let scale = 2.5
  22.     let rotation = degreesToRadians -25.0
  23.     let tagRotationAngle = ref 0.0
  24.     let layerName = "Test BI_18"
  25.    
  26.     createLayer db layerName 8s |> ignore
  27.    
  28.     use tr = db.TransactionManager.StartTransaction()
  29.     try
  30.         let bt = tr.GetObject(db.BlockTableId, OpenMode.ForRead) :?> BlockTable
  31.         if not (bt.Has(blockName)) then
  32.             use tmpDb = new Database()
  33.             tmpDb.ReadDwgFile(blockQualifiedFileName, System.IO.FileShare.Read, true, "")
  34.             db.Insert(blockName, tmpDb, true) |> ignore
  35.            
  36.         let ppr = ed.GetPoint("\nSpecify insertion point: ")
  37.         if ppr.Status = PromptStatus.OK then
  38.             let pkOpt = new PromptKeywordOptions("\nRotate Attribute to :")
  39.             pkOpt.Keywords.Add("UCS");
  40.             pkOpt.Keywords.Add("WCS");
  41.             pkOpt.Keywords.Add("Aligned");
  42.             let prRes = ed.GetKeywords(pkOpt)
  43.             if prRes.Status = PromptStatus.OK then
  44.                 let btr = tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite) :?> BlockTableRecord
  45.                 use br = new BlockReference(Point3d.Origin, bt.[blockName])
  46.                 br.ScaleFactors <- new Scale3d(scale)
  47.                 br.Rotation <- rotation
  48.                 br.Layer <- layerName
  49.                
  50.                 br.TransformBy(Matrix3d.Displacement(ppr.Value.GetAsVector())
  51.                                |> (*) ed.CurrentUserCoordinateSystem)
  52.                 btr.AppendEntity(br) |> ignore
  53.                 tr.AddNewlyCreatedDBObject(br, true)
  54.                
  55.                 insertAttibuteInBlockRef br attTag attText tr
  56.                
  57.                 match prRes.StringResult with
  58.                 | "WCS" -> tagRotationAngle := 0.0
  59.                 | "UCS" -> tagRotationAngle := br.Rotation - rotation
  60.                 | "Aligned" -> tagRotationAngle := br.Rotation
  61.                 | _ -> ()
  62.                
  63.                 br.AttributeCollection
  64.                 |> Seq.cast<_>
  65.                 |> Seq.map (fun id -> tr.GetObject(id, OpenMode.ForWrite))
  66.                 |> Seq.choose (function :? AttributeReference as ar -> Some ar | _ -> None)
  67.                 |> Seq.iter (fun ar -> ar.Rotation <- !tagRotationAngle)      
  68.                 tr.Commit()
  69.     with
  70.         | :? Autodesk.AutoCAD.Runtime.Exception as ex -> ed.WriteMessage("\n" + ex.Message)
  71. //=======================================================================

EDIT:
For those who prefer an 'imperative style' , just replace these lines (note that as there's no more closure, a 'mutable' variable can be used instead of a 'reference cell'):
Code: [Select]
let tagRotationAngle = ref 0.0and
Code - F#: [Select]
  1.                 match prRes.StringResult with
  2.                 < ... >    
  3.                 tr.Commit()

with
Code - F#: [Select]
  1. let mutable tagRotationAngle = 0.0
and
Code - F#: [Select]
  1.                 match prRes.StringResult with
  2.                 | "WCS" -> tagRotationAngle <- 0.0
  3.                 | "UCS" -> tagRotationAngle <- br.Rotation - rotation
  4.                 | "Aligned" -> tagRotationAngle <- br.Rotation
  5.                 | _ -> ()
  6.                
  7.                 for id in br.AttributeCollection do
  8.                     let dbObj = tr.GetObject(id, OpenMode.ForWrite)
  9.                     if dbObj :? AttributeReference then
  10.                         let ar = dbObj :?> AttributeReference
  11.                         if ar.Tag.ToUpper() = attTag then
  12.                             ar.Rotation <- tagRotationAngle
  13.                 tr.Commit()
« Last Edit: January 25, 2012, 07:16:11 AM by Kerry »
Speaking English as a French Frog

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: BlockTesting2011
« Reply #25 on: April 04, 2011, 03:43:02 AM »
Hi,

Just one thing about casting issues.
If we avoid using using the 'ObjectId.ObjectClass' route so that this sample can be used with AutoCAD version prior to 2009, I think the 'as' statement is the right way for C# (maybe fo VB too (with TryCast ?)).
< .. >

I had chosen the option indicated in InsertAttibuteInBlockRef_Option()   .. ( which is the 'as' statement combined with a null test.)
The next Solution (to be posted) will have code reflecting that choice.

Thanks gile, the F# samples are getting easier to read for me :)
Regards


//
Does anyone have any problems following the samples ??

« Last Edit: April 04, 2011, 03:46:25 AM by Kerry »
kdub, kdub_nz in other timelines.
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

Jeff H

  • Needs a day job
  • Posts: 6144
Re: BlockTesting2011
« Reply #26 on: April 04, 2011, 04:18:38 AM »
Next for VB :

Set ScaleFactor, Rotation as BlockReference Properties rather than by Transform
Set Layer as BlockReference Properties
Test for Layer assertion.

Code - vb.net: [Select]
  1. '=======================================================================
  2.         '=======================================================================
  3.         ' add the block to the ActiveDrawing CurrentSpace
  4.         ' Imports the Block if not found in the BlockTable
  5.         '
  6.         ' Set ScaleFactor, Rotation and Layer as BlockReference Properties
  7.         '
  8.         '   Add ALL AttributeReference to the BlockReference
  9.         '   and Set the attributeText in a nominated  Attribute  
  10.         '
  11.         ' Includes a test for Layer assertion.
  12.  
  13.         <CommandMethod("BI_17")> _
  14.         Public Sub BlockInsert_17()
  15.             Dim blockQualifiedFileName As String = "K:\ToTest\3Dblock_A.dwg"
  16.             Dim blockName As String = "3Dblock_A"
  17.             Dim attTag As String = "ATTRIBUTETAG"
  18.             Dim attText As String = "Sample BI_17"
  19.             '
  20.             Dim scale As Double = 2.3
  21.             Dim rotation As Double = RadiansToDegrees(20.0)
  22.             Dim layerName As String = "Test BI_17"
  23.  
  24.             ' Assert the layer exists
  25.             CreateLayer(db, layerName, 8)
  26.  
  27.             Using tr As Transaction = db.TransactionManager.StartTransaction()
  28.                 Try
  29.                     Dim bt As BlockTable = DirectCast(tr.GetObject(db.BlockTableId, OpenMode.ForRead), BlockTable)
  30.                     If Not bt.Has(blockName) Then
  31.                         Dim tmpDb As New Database(False, True)
  32.                         tmpDb.ReadDwgFile(blockQualifiedFileName, System.IO.FileShare.Read, True, "")
  33.                         ' add the block to the ActiveDrawing blockTable
  34.                         db.Insert(blockName, tmpDb, True)
  35.                     End If
  36.  
  37.                     Dim ppr As PromptPointResult = ed.GetPoint(vbLf & "Specify insertion point: ")
  38.                     If ppr.Status <> PromptStatus.OK Then
  39.                         Return
  40.                     End If
  41.  
  42.                     Dim btr As BlockTableRecord = DirectCast(tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite), BlockTableRecord)
  43.  
  44.                     Using br As New BlockReference(Point3d.Origin, bt(blockName))
  45.                         br.ScaleFactors = New Scale3d(scale)
  46.                         br.Rotation = rotation
  47.                         br.Layer = layerName
  48.  
  49.                         br.TransformBy(Matrix3d.Displacement(ppr.Value - Point3d.Origin).PreMultiplyBy(ed.CurrentUserCoordinateSystem))
  50.  
  51.                         btr.AppendEntity(br)
  52.                         tr.AddNewlyCreatedDBObject(br, True)
  53.                         '
  54.                         InsertAttibuteInBlockRef(br, attTag, attText, tr)
  55.                     End Using
  56.  
  57.                     tr.Commit()
  58.                 Catch exx As Autodesk.AutoCAD.Runtime.Exception
  59.                     ed.WriteMessage(vbLf & exx.ToString())
  60.                 End Try
  61.             End Using
  62.         End Sub
  63.  
Code - vb.net: [Select]
  1.         '=======================================================================
  2.         '=======================================================================
  3.         ''' <summary>
  4.         '''  CreateLayer layer if not existing
  5.         ''' </summary>
  6.         ''' <param name="db"></param>
  7.         ''' <param name="layerName"></param>
  8.         ''' <param name="color"></param>
  9.         ''' <returns> ObjectId of existing or new layer </returns>
  10.         Public Shared Function CreateLayer(db As Database, layerName As String, color As Short) As ObjectId
  11.             Dim layerId As ObjectId = ObjectId.Null
  12.             Using tr As Transaction = db.TransactionManager.StartTransaction()
  13.                 Dim lt As LayerTable = DirectCast(tr.GetObject(db.LayerTableId, OpenMode.ForWrite), LayerTable)
  14.                 'Check if EmployeeLayer exists...
  15.                 If lt.Has(layerName) Then
  16.                     layerId = lt(layerName)
  17.                 Else
  18.                     'if not, create the layer here.
  19.                     Dim ltr As New LayerTableRecord()
  20.                     ltr.Name = layerName
  21.                     ltr.Color = Autodesk.AutoCAD.Colors.Color.FromColorIndex(Autodesk.AutoCAD.Colors.ColorMethod.ByAci, color)
  22.                     layerId = lt.Add(ltr)
  23.                     tr.AddNewlyCreatedDBObject(ltr, True)
  24.                 End If
  25.                 tr.Commit()
  26.             End Using
  27.             Return layerId
  28.         End Function
  29.  

Next  deals with :

non-unifirm scaling
using the  PromptKeywordOptions
attribute Rotation.

Code - vb.net: [Select]
  1.         '=======================================================================
  2.         '=======================================================================
  3.         ' add the block to the ActiveDrawing CurrentSpace
  4.         ' Imports the Block if not found in the BlockTable
  5.         '
  6.         ' Set ScaleFactor, Rotation and Layer as BlockReference Properties
  7.         ' The scale can be non-uniform (demonstrated)
  8.         '
  9.         '   Add ALL AttributeReference to the BlockReference
  10.         '   and Set the attributeText in a nominated  Attribute  
  11.         '
  12.         ' Includes a test for Layer assertion.
  13.         '
  14.         ' Rotate the nominated Attribute Tag to either UCS, WCS, or Aligned with block insert
  15.  
  16.         <CommandMethod("BI_18")> _
  17.         Public Sub BlockInsert_18()
  18.             Dim blockQualifiedFileName As String = "K:\ToTest\3Dblock_4A.dwg"
  19.             Dim blockName As String = "3DBLOCK_4A"
  20.             Dim attTag As String = "ATTRIBUTETAG_MC"
  21.             Dim attText As String = "BI_18"
  22.             '
  23.             Dim scale As Double = 2.5
  24.             Dim rotation As Double = RadiansToDegrees(-25.0)
  25.             Dim tagRotationAngle As Double = 0.0
  26.             Dim layerName As String = "Test BI_18"
  27.  
  28.             ' Assert the layer exists
  29.             CreateLayer(db, layerName, 8)
  30.  
  31.             Using tr As Transaction = db.TransactionManager.StartTransaction()
  32.                 Try
  33.                     Dim bt As BlockTable = DirectCast(tr.GetObject(db.BlockTableId, OpenMode.ForRead), BlockTable)
  34.  
  35.                     If Not bt.Has(blockName) Then
  36.                         Dim tmpDb As New Database(False, True)
  37.                         tmpDb.ReadDwgFile(blockQualifiedFileName, System.IO.FileShare.Read, True, "")
  38.                         ' add the block to the ActiveDrawing blockTable
  39.                         db.Insert(blockName, tmpDb, True)
  40.                     End If
  41.  
  42.                     Dim ppr As PromptPointResult = ed.GetPoint(vbLf & "Specify insertion point: ")
  43.  
  44.                     If ppr.Status <> PromptStatus.OK Then
  45.                         Return
  46.                     End If
  47.  
  48.                     Dim pkOpt As New PromptKeywordOptions(vbLf & "Rotate Attribute to :")
  49.                     pkOpt.Keywords.Add("UCS")
  50.                     pkOpt.Keywords.Add("WCS")
  51.                     pkOpt.Keywords.Add("Aligned")
  52.  
  53.                     Dim prRes As PromptResult = ed.GetKeywords(pkOpt)
  54.  
  55.                     If prRes.Status <> PromptStatus.OK Then
  56.                         Return
  57.                     End If
  58.  
  59.                     Dim btr As BlockTableRecord = DirectCast(tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite), BlockTableRecord)
  60.  
  61.                     Using br As New BlockReference(Point3d.Origin, bt(blockName))
  62.                         br.ScaleFactors = New Scale3d(scale, scale, 1.0)
  63.                         br.Rotation = rotation
  64.                         br.Layer = layerName
  65.  
  66.                         br.TransformBy(Matrix3d.Displacement(ppr.Value - Point3d.Origin).PreMultiplyBy(ed.CurrentUserCoordinateSystem))
  67.  
  68.                         btr.AppendEntity(br)
  69.                         tr.AddNewlyCreatedDBObject(br, True)
  70.                         '  
  71.                         InsertAttibuteInBlockRef(br, attTag, attText, tr)
  72.  
  73.                         Select Case prRes.StringResult
  74.                             Case "WCS"
  75.                                 tagRotationAngle = 0.0
  76.                             Case "UCS"
  77.                                 tagRotationAngle = br.Rotation - rotation
  78.                             Case "Aligned"
  79.                                 tagRotationAngle = br.Rotation
  80.  
  81.                         End Select
  82.  
  83.                         For Each idAttColl As ObjectId In br.AttributeCollection
  84.  
  85.                             Dim ar As AttributeReference = TryCast(tr.GetObject(idAttColl, OpenMode.ForWrite), AttributeReference)
  86.  
  87.                             If ar IsNot Nothing Then
  88.                                 If ar.Tag.ToUpper() = attTag Then
  89.                                     ar.Rotation = tagRotationAngle
  90.                                 End If
  91.                             End If
  92.  
  93.                         Next
  94.  
  95.                     End Using
  96.  
  97.                     tr.Commit()
  98.  
  99.                 Catch exx As Autodesk.AutoCAD.Runtime.Exception
  100.                     ed.WriteMessage(vbLf & exx.ToString())
  101.                 End Try
  102.  
  103.             End Using
  104.  
  105.  
  106.         End Sub
  107.         '=======================================================================
  108.  


Post with 3DBLOCK_4A block
« Last Edit: January 25, 2012, 07:03:27 AM by Kerry »

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: BlockTesting2011
« Reply #27 on: April 04, 2011, 09:45:44 PM »

Next will be the Multi Attribute example.
First, a Piccy.
kdub, kdub_nz in other timelines.
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: BlockTesting2011
« Reply #28 on: April 04, 2011, 10:09:35 PM »
Multi-Attribute Block Insert

First the helper Method ;

Code - C#: [Select]
  1.  
  2.        //=======================================================================
  3.         /// <summary>
  4.         ///  InsertBlockReference
  5.         /// </summary>
  6.         /// <param name="db"></param>
  7.         /// <param name="blockName"></param>
  8.         /// <param name="insertPoint"> In Current UCS</param>
  9.         /// <param name="scale"> </param>
  10.         /// <param name="angle"> </param>
  11.         /// <param name="layer"> </param>
  12.         /// <param name="attValues"></param>
  13.         /// <returns>ObjectId of BlockReference </returns>
  14.         public ObjectId InsertBlockReference(
  15.             Database db,
  16.             string blockName,
  17.             Point3d insertPoint,
  18.             Scale3d scale,
  19.             double angle,
  20.             string layer,
  21.             System.Collections.Hashtable attValues)
  22.         {
  23.             using( Transaction tr = db.TransactionManager.StartTransaction() ) {
  24.                 BlockTable bt = tr.GetObject(db.BlockTableId, OpenMode.ForRead) as BlockTable;
  25.                 if( !bt.Has(blockName) ) {
  26.                     string blockPath = HostApplicationServices.Current.FindFile(blockName + ".dwg", db, FindFileHint.Default);
  27.                     if( string.IsNullOrEmpty(blockPath) ) {
  28.                         return ObjectId.Null;
  29.                     }
  30.                     bt.UpgradeOpen();
  31.                     using( Database tmpDb = new Database(false, true) ) {
  32.                         tmpDb.ReadDwgFile(blockPath, FileShare.Read, true, null);
  33.                         db.Insert(blockName, tmpDb, true);
  34.                     }
  35.                 }
  36.                 BlockTableRecord btr = tr.GetObject(bt[ blockName ], OpenMode.ForRead) as BlockTableRecord;
  37.                 BlockReference br = new BlockReference(insertPoint, bt[ blockName ]) {
  38.                     ScaleFactors = scale,
  39.                     Rotation = angle,
  40.                     Layer = layer
  41.                 };
  42.                 br.TransformBy(ed.CurrentUserCoordinateSystem);
  43.  
  44.                 br.RecordGraphicsModified(true);
  45.                 if( btr.Annotative == AnnotativeStates.True ) {
  46.                     ObjectContextCollection contextCollection = db.ObjectContextManager.GetContextCollection("ACDB_ANNOTATIONSCALES");
  47.                     Autodesk.AutoCAD.Internal.ObjectContexts.AddContext(br, contextCollection.GetContext("1:1"));
  48.                 }
  49.                 (tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite) as BlockTableRecord).AppendEntity(br);
  50.                 foreach( ObjectId id in btr ) {
  51.                     AttributeDefinition aDef = tr.GetObject(id, OpenMode.ForRead) as AttributeDefinition;
  52.                     if( aDef != null ) {
  53.                         AttributeReference aRef = new AttributeReference();
  54.                         aRef.SetAttributeFromBlock(aDef, br.BlockTransform);
  55.                         aRef.Position = aDef.Position + br.Position.GetAsVector();
  56.                         if( attValues.ContainsKey(aDef.Tag.ToUpper()) ) {
  57.                             aRef.TextString = attValues[ aDef.Tag.ToUpper() ].ToString();
  58.                         }
  59.                         br.AttributeCollection.AppendAttribute(aRef);
  60.                         tr.AddNewlyCreatedDBObject(aRef, true);
  61.                     }
  62.                 }
  63.                 tr.AddNewlyCreatedDBObject(br, true);
  64.                 tr.Commit();
  65.                 return br.ObjectId;
  66.             }
  67.         }
  68.         //=======================================================================
  69.  

Then a test function ;
Code - C#: [Select]
  1.  
  2.         //=======================================================================
  3.         // A generic sample to test the  InsertBlockReference() Method.
  4.         // Attempt to FindFile the block dwg if it is not in the ActiveDocument
  5.         // ... so the dwg must be on the file search path
  6.         //
  7.         // Uses a HashTable to pass the  tag:Value associations to the method.
  8.         // Test for Layer.
  9.         //
  10.         // The InsertPoint is expressed in the current UCS.
  11.         //
  12.  
  13.         [CommandMethod("BI_20")]
  14.         public void BlockInsert_20()
  15.         {
  16.             string blockName = "3DBLOCK_4A";
  17.             double scale = 2.5;
  18.             double rotation = RadiansToDegrees(0.0);
  19.  
  20.             string layerName = "Test BI_20";
  21.             // Assert the layer exists
  22.             CreateLayer(db, layerName, 8);
  23.  
  24.             System.Collections.Hashtable ht = new System.Collections.Hashtable();
  25.             ht.Add("ATTRIBUTETAG_MC", "BI_20");
  26.             ht.Add("ATTRIBUTETAG_MR", "9 O'Clock");
  27.             ht.Add("ATTRIBUTETAG_BL", "3 O'Clock");
  28.             ht.Add("ATTRIBUTETAG_TC", "6 O'Clock");
  29.  
  30.             PromptPointResult ppr = ed.GetPoint("\nSpecify insertion point: ");
  31.             if( ppr.Status != PromptStatus.OK )
  32.                 return;
  33.  
  34.             ObjectId blockRefID = InsertBlockReference(
  35.                                     db,
  36.                                     blockName,
  37.                                     ppr.Value,   // point in current UCS
  38.                                     new Scale3d(scale, scale, 1),
  39.                                     rotation,
  40.                                     layerName,
  41.                                     ht
  42.             );
  43.         }
  44.         //=======================================================================
  45.  

The complete solution is Attached
The .DLL file is included if anyone wants to test the Functions without compiling the source.
« Last Edit: December 18, 2011, 12:54:55 AM by Kerry »
kdub, kdub_nz in other timelines.
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

gile

  • Gator
  • Posts: 2507
  • Marseille, France
Re: BlockTesting2011
« Reply #29 on: April 05, 2011, 04:24:40 AM »
F# translation

Multi-Attribute Block Insert

First the helper Method ;

Code - F#: [Select]
  1. //=======================================================================
  2. /// <summary>
  3. ///  InsertBlockReference
  4. /// </summary>
  5. /// <param name="db"></param>
  6. /// <param name="blockName"></param>
  7. /// <param name="insertPoint"> In Current UCS</param>
  8. /// <param name="scale"> </param>
  9. /// <param name="angle"> </param>
  10. /// <param name="layer"> </param>
  11. /// <param name="attValues"></param>
  12. /// <returns>ObjectId of BlockReference </returns>
  13. let insertBlockReference (dBase:Database) blockName insertPoint scale angle layer attValues =
  14.     use tr = dBase.TransactionManager.StartTransaction()
  15.     let bt = tr.GetObject(dBase.BlockTableId, OpenMode.ForRead) :?> BlockTable
  16.     let btrId =
  17.         if bt.Has(blockName:string) then bt.[blockName]
  18.         else
  19.             let path = HostApplicationServices.Current.FindFile(blockName + ".dwg", dBase, FindFileHint.Default)
  20.             if String.IsNullOrEmpty(path) then ObjectId.Null
  21.             else
  22.                 use tmpDb = new Database()
  23.                 tmpDb.ReadDwgFile(path, System.IO.FileShare.Read, true, "")
  24.                 dBase.Insert(blockName, tmpDb, true)
  25.     if btrId = ObjectId.Null then ObjectId.Null
  26.     else
  27.         let btr = tr.GetObject(btrId, OpenMode.ForRead) :?> BlockTableRecord
  28.         let br = new BlockReference(insertPoint, bt.[blockName])
  29.         br.ScaleFactors <- scale
  30.         br.Rotation <- angle
  31.         br.Layer <- layer
  32.         br.TransformBy(ed.CurrentUserCoordinateSystem)
  33.         br.RecordGraphicsModified(true)
  34.         if btr.Annotative = AnnotativeStates.True then
  35.             let contextCollection = dBase.ObjectContextManager.GetContextCollection("ACDB_ANNOTATIONSCALES")
  36.             Autodesk.AutoCAD.Internal.ObjectContexts.AddContext(br, contextCollection.GetContext("1:1"))
  37.         (tr.GetObject(dBase.CurrentSpaceId, OpenMode.ForWrite) :?> BlockTableRecord).AppendEntity(br) |> ignore
  38.        
  39.         btr |> Seq.cast<_>
  40.             |> Seq.choose (fun id ->
  41.                 let dbObj = tr.GetObject(id, OpenMode.ForRead)
  42.                 match dbObj with :? AttributeDefinition as aDef -> Some aDef | _ -> None)
  43.             |> Seq.iter (fun aDef ->
  44.                 let aRef = new AttributeReference()
  45.                 aRef.SetAttributeFromBlock(aDef, br.BlockTransform);
  46.                 aRef.Position <- aDef.Position + br.Position.GetAsVector()
  47.                 if Map.containsKey (aDef.Tag.ToUpper()) attValues then
  48.                     aRef.TextString <- attValues.[aDef.Tag.ToUpper()]
  49.                 br.AttributeCollection.AppendAttribute(aRef) |> ignore
  50.                 tr.AddNewlyCreatedDBObject(aRef, true))
  51.  
  52.         tr.AddNewlyCreatedDBObject(br, true)
  53.         tr.Commit()
  54.         br.ObjectId
  55. //=======================================================================

Then a test function ;

Code - F#: [Select]
  1. //=======================================================================
  2. // A generic sample to test the  InsertBlockReference() Method.
  3. // Attempt to FindFile the block dwg if it is not in the ActiveDocument
  4. // ... so the dwg must be on the file search path
  5. //
  6. // Uses a HashTable to pass the  tag:Value associations to the method.
  7. // Test for Layer.
  8. //
  9. // The InsertPoint is expressed in the current UCS.
  10. [<CommandMethod("BI_20")>]
  11. let blockInsert_20() =
  12.     let blockName = "3DBLOCK_4A";
  13.     let scale = 2.5;
  14.     let rotation = degreesToRadians(0.0);
  15.  
  16.     let layerName = "Test BI_20";
  17.     // Assert the layer exists
  18.     createLayer db layerName 8s |> ignore
  19.    
  20.     let ht = Map<string,string>[
  21.                 ("ATTRIBUTETAG_MC", "BI_20");
  22.                 ("ATTRIBUTETAG_MR", "9 O'Clock");
  23.                 ("ATTRIBUTETAG_BL", "3 O'Clock");
  24.                 ("ATTRIBUTETAG_TC", "6 O'Clock")]
  25.    
  26.     let ppr = ed.GetPoint("\nSpecify insertion point: ")
  27.     if ppr.Status = PromptStatus.OK then
  28.         insertBlockReference db blockName ppr.Value (new Scale3d(scale, scale, 1.0)) rotation layerName ht |> ignore

The complete solution is Attached
The .DLL file is included (BlockTesting2011\bin\Debug) if anyone wants to test the Functions without compiling the source.
If F# isn't already installed on the computer (via VS2010 or F# CTP), you have to install F# Runtime
« Last Edit: January 25, 2012, 07:06:33 AM by Kerry »
Speaking English as a French Frog