Author Topic: BlockTesting2011  (Read 35192 times)

0 Members and 1 Guest are viewing this topic.

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
BlockTesting2011
« on: March 30, 2011, 09:26:38 PM »
This will be an ongoing thread with functions added as I get a chance.
Refer to the attached Zip for the full solution.
The routines are noted for functionality.

There are some gotcha's and traps in these incomplete samples.
The intent was to proceed step by step to explore the concepts involved.
//---------------------------------------------------------------
Jeff H has volunteered to convert these Methods to VB.net
Thanks Jeff.

gile has volunteered to convert these Methods to F#
Thanks gile.
//---------------------------------------------------------------

NOTE Solutions updated
//------------------------------- Sample Blocks
3DBlock.dwg  - block with no attibutes is attached to this first post :
 
3DBlock_A.dwg - block with one attibute is attached to this first post :

3DBlock_4A.dwg - block with 4 attibutes is attached to this post :
http://www.theswamp.org/index.php?topic=37686.msg427676#msg427676

 //------------------------------- C# Solutions
BlockTesting2011 _20110331.1115.zip is attached to this first post :

BlockTesting2011 _20110401.0936.zip is attached to this post :
http://www.theswamp.org/index.php?topic=37686.msg427348#msg427348

BlockTesting2011 _ 20110405.1206.zip  is attached to this post :
http://www.theswamp.org/index.php?topic=37686.msg427833#msg427833

//------------------------------- VB Solutions
BlockTesting2011VB_04012011.zip is attached to this post :
http://www.theswamp.org/index.php?topic=37686.msg427562#msg427562

BlockTesting2011VB_04042011.zip is attached to this post :
http://www.theswamp.org/index.php?topic=37686.msg427562#msg427562

//------------------------------- F# Solutions
BlockTesting2011FS_20110403.zip is attached to this post :
http://www.theswamp.org/index.php?topic=37686.msg427619#msg427619

BlockTesting2011FS_20110405.zip   is attached to this post :
http://www.theswamp.org/index.php?topic=37686.msg427843#msg427843
//---------------------------------------------------------------

Container :
Code - C#: [Select]
  1. // CodeHimBelonga kdub@theSwamp 20110331
  2. //
  3. using System;
  4. using System.IO;
  5.  
  6. using Autodesk.AutoCAD.Runtime;
  7. using Autodesk.AutoCAD.ApplicationServices;
  8. using Autodesk.AutoCAD.DatabaseServices;
  9. using Autodesk.AutoCAD.Geometry;
  10. using Autodesk.AutoCAD.EditorInput;
  11. //
  12. using AcadApp = Autodesk.AutoCAD.ApplicationServices.Application;
  13. using AcUtils = Autodesk.AutoCAD.Internal.Utils;
  14.  
  15. [assembly: CommandClass(typeof(KdubTesting.BlockTesting2011))]
  16.  
  17. namespace KdubTesting
  18. {
  19.     public class BlockTesting2011
  20.     {
  21.         Document doc;
  22.         Database db;
  23.         Editor ed;
  24.  
  25.         public BlockTesting2011()
  26.         {
  27.             ActiveDoc = AcadApp.DocumentManager.MdiActiveDocument;
  28.         }
  29.  
  30.         Document ActiveDoc
  31.         {
  32.             get { return doc; }
  33.             set
  34.             {
  35.                 doc = value;
  36.                 if( doc == null ) {
  37.                     db = null;
  38.                     ed = null;
  39.                 } else {
  40.                     db = doc.Database;
  41.                     ed = doc.Editor;
  42.                 }
  43.             }
  44.         }
  45.         //=======================================================================
  46.  
  47.         // Methods go here < snip>
  48.         //=======================================================================
  49.     }
  50. }
  51.  
  52.  

Code - C#: [Select]
  1.         //=======================================================================
  2.         // add the block to the ActiveDrawing blockTable
  3.  
  4.         [CommandMethod("BI_1")]
  5.         public void BlockInsert_1()
  6.         {
  7.             string blockQualifiedFileName = "K:\\ToTest\\3Dblock_A.dwg";
  8.             string blockName = "3Dblock_A";
  9.             Database tmpDb = new Database(false, true);
  10.             tmpDb.ReadDwgFile(blockQualifiedFileName, System.IO.FileShare.Read, true, "");
  11.  
  12.             // add the block to the ActiveDrawing blockTable
  13.             db.Insert(blockName, tmpDb, true);
  14.  
  15.             // add the block to the ActiveDrawing blockTable with a Temporary Name
  16.             db.Insert("TmpTest", tmpDb, true);
  17.         }
  18.         //=======================================================================
  19.  

Code - C#: [Select]
  1.        //=======================================================================
  2.         // add the block to the current space (Model or Paper).
  3.         // block is exploded IE: copy of original
  4.         // Insert will be at World 0,0,0 and transformed for Scale
  5.  
  6.         [CommandMethod("BI_2")]
  7.         public void BlockInsert_2()
  8.         {
  9.             string blockQualifiedFileName = "K:\\ToTest\\3Dblock_A.dwg";
  10.             double scale = 5.0;
  11.  
  12.             Database tmpDb = new Database(false, true);
  13.             tmpDb.ReadDwgFile(blockQualifiedFileName, System.IO.FileShare.Read, true, "");
  14.  
  15.             Matrix3d Transform = Matrix3d.Identity;
  16.             Transform = Transform *
  17.                 Matrix3d.Scaling(scale, Point3d.Origin);
  18.  
  19.             db.Insert(Transform, tmpDb, true);
  20.         }
  21.         //=======================================================================
  22.  

Code - C#: [Select]
  1.        //=======================================================================
  2.         // add the block to the current space (Model or Paper).
  3.         // block is exploded IE: copy of original
  4.         // Insert will be at UCS 0,0,0 honouring current X, Y, Z Axis.
  5.         // and transformed for Scale
  6.  
  7.         [CommandMethod("BI_3")]
  8.         public void BlockInsert_3()
  9.         {
  10.             string blockQualifiedFileName = "K:\\ToTest\\3Dblock.dwg";
  11.             double scale = 2.5;
  12.  
  13.             Database tmpDb = new Database(false, true);
  14.             tmpDb.ReadDwgFile(blockQualifiedFileName, System.IO.FileShare.Read, true, "");
  15.  
  16.             Matrix3d Transform = ed.CurrentUserCoordinateSystem;
  17.             Transform = Transform *
  18.                 Matrix3d.Scaling(scale, Point3d.Origin);
  19.  
  20.             db.Insert(Transform, tmpDb, true);
  21.         }
  22.         //=======================================================================
  23.  

Code - C#: [Select]
  1.        //=======================================================================
  2.         // add the block to the current space (Model or Paper).
  3.         // block is exploded IE: copy of original
  4.         // Insert will be at UCS 0,0,0 honouring current X, Y, Z Axis.
  5.         // and transformed for Scale
  6.         // and transformed for Displacement
  7.         // note that the nominated displacement will be scaled !!
  8.  
  9.         [CommandMethod("BI_4")]
  10.         public void BlockInsert_4()
  11.         {
  12.             string blockQualifiedFileName = "K:\\ToTest\\3Dblock.dwg";
  13.             double scale = 3.0;
  14.             Vector3d DispacementVector = new Vector3d(20, 50, 0);
  15.             //
  16.             Database tmpDb = new Database(false, true);
  17.             tmpDb.ReadDwgFile(blockQualifiedFileName, System.IO.FileShare.Read, true, "");
  18.  
  19.             Matrix3d Transform = ed.CurrentUserCoordinateSystem;
  20.  
  21.             Transform = Transform *
  22.                 Matrix3d.Scaling(scale, Point3d.Origin) *
  23.                 Matrix3d.Displacement(DispacementVector);
  24.  
  25.             db.Insert(Transform, tmpDb, true);
  26.         }
  27.         //=======================================================================
  28.  

Code - C#: [Select]
  1.  
  2.        //=======================================================================
  3.         // add the block to the current space (Model or Paper).
  4.         // block is exploded IE: copy of original
  5.         // Insert will be at UCS 0,0,0 honouring current X, Y, Z Axis.
  6.         // and transformed for Scale
  7.         // and transformed for Displacement
  8.         // note that the nominated displacement will be honoured
  9.  
  10.         [CommandMethod("BI_5")]
  11.         public void BlockInsert_5()
  12.         {
  13.             string blockQualifiedFileName = "K:\\ToTest\\3Dblock_a.dwg";
  14.             double scale = 3.0;
  15.             Vector3d DispacementVector = new Vector3d(20, 50, 0);
  16.             //
  17.             Database tmpDb = new Database(false, true);
  18.             tmpDb.ReadDwgFile(blockQualifiedFileName, System.IO.FileShare.Read, true, "");
  19.  
  20.             Matrix3d Transform = ed.CurrentUserCoordinateSystem;
  21.  
  22.             Transform = Transform *
  23.                 Matrix3d.Scaling(scale, Point3d.Origin) *
  24.                 Matrix3d.Displacement(DispacementVector / scale);
  25.  
  26.             db.Insert(Transform, tmpDb, true);
  27.         }
  28.         //=======================================================================
  29.  
  30.  
« Last Edit: December 18, 2011, 12:36:00 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 #1 on: March 31, 2011, 01:45:12 AM »
Hi Kerry,

In the last code (honoured displacement), you can replace:

Code - C#: [Select]
  1. Transform = Transform *
  2.                 Matrix3d.Scaling(scale, Point3d.Origin) *
  3.                 Matrix3d.Displacement(DispacementVector / scale);

with:

Code - C#: [Select]
  1. Transform = Transform *
  2.                 Matrix3d.Displacement(DispacementVector) *
  3.                 Matrix3d.Scaling(scale, Point3d.Origin);

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.

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

Code - C#: [Select]
  1. Transform = Matrix3d
  2.     .Scaling(scale, Point3d.Origin)
  3.     .PreMultiplyBy(Matrix3d.Displacement(DispacementVector))
  4.     .PreMultiplyBy(Transform);
« Last Edit: December 18, 2011, 12:36:55 AM by Kerry »
Speaking English as a French Frog

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: BlockTesting2011
« Reply #2 on: March 31, 2011, 03:09:48 AM »
Thanks gile, that's a better option ... and valuable information.
I had planned on doing some more investigation on the Transform but ran out of time :)

I'll update the Solution next time I post it.

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

I think the PreMultiplyBy method will be better also
« Last Edit: March 31, 2011, 03:14:16 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.

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: BlockTesting2011
« Reply #3 on: March 31, 2011, 03:31:16 AM »
Thinking about it, this may be better ... but a little more difficult to debug ( if ever necessary) :)

Code - C#: [Select]
  1.  
  2.  
  3.             // **remove** Matrix3d Transform = ed.CurrentUserCoordinateSystem;
  4.  
  5.             Matrix3d Transform = Matrix3d
  6.                 .Scaling(scale, Point3d.Origin)
  7.                 .PreMultiplyBy( Matrix3d.Displacement(DispacementVector))
  8.                 .PreMultiplyBy(ed.CurrentUserCoordinateSystem);
  9.  
  10.             db.Insert(Transform, tmpDb, true);
  11.  
  12.  
« Last Edit: December 18, 2011, 12:37:27 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.

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: BlockTesting2011
« Reply #4 on: March 31, 2011, 04:58:29 AM »
Next series :
Refer notations.

Transforms use PreMultiplyBy method as suggested by gile :)


Code - C#: [Select]
  1.        //=======================================================================
  2.         // add the block to the ActiveDrawing CurrentSpace
  3.         // Expects to find the Block in the BlockTable
  4.         // does not handle Attributes
  5.  
  6.         [CommandMethod("BI_10")]
  7.         public void BlockInsert_10()
  8.         {
  9.             string blockName = "3Dblock";
  10.  
  11.             using( Transaction tr = db.TransactionManager.StartTransaction() ) {
  12.                 BlockTable bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead);
  13.                 if( !bt.Has(blockName) ) {
  14.                     ed.WriteMessage("\nBlock '{0}' is not available in the current drawing.", blockName);
  15.                     return;
  16.                 }
  17.                 PromptPointResult ppr = ed.GetPoint("\nSpecify insertion point: ");
  18.                 if( ppr.Status != PromptStatus.OK )
  19.                     return;
  20.  
  21.                 BlockTableRecord btr = (BlockTableRecord)tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite);
  22.                 BlockReference br = new BlockReference(Point3d.Origin, bt[ blockName ]);
  23.  
  24.                 br.TransformBy(Matrix3d
  25.                     .Displacement(ppr.Value - Point3d.Origin)
  26.                     .PreMultiplyBy(ed.CurrentUserCoordinateSystem));
  27.  
  28.                 btr.AppendEntity(br);
  29.                 tr.AddNewlyCreatedDBObject(br, true);
  30.                 tr.Commit();
  31.             }
  32.         }
  33.         //=======================================================================
  34.  

Code - C#: [Select]
  1.        //=======================================================================
  2.         // add the block to the ActiveDrawing CurrentSpace
  3.         // Imports the Block if not found in the BlockTable
  4.         // does not handle Attributes
  5.  
  6.         [CommandMethod("BI_11")]
  7.         public void BlockInsert_11()
  8.         {
  9.             string blockQualifiedFileName = "K:\\ToTest\\3Dblock.dwg";
  10.             string blockName = "3Dblock";
  11.  
  12.             using( Transaction tr = db.TransactionManager.StartTransaction() ) {
  13.                 BlockTable bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead);
  14.                 if( !bt.Has(blockName) ) {
  15.                     Database tmpDb = new Database(false, true);
  16.                     tmpDb.ReadDwgFile(blockQualifiedFileName, System.IO.FileShare.Read, true, "");
  17.                     // add the block to the ActiveDrawing blockTable
  18.                     db.Insert(blockName, tmpDb, true);
  19.                 }
  20.  
  21.                 PromptPointResult ppr = ed.GetPoint("\nSpecify insertion point: ");
  22.                 if( ppr.Status != PromptStatus.OK )
  23.                     return;
  24.  
  25.                 BlockTableRecord btr = (BlockTableRecord)tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite);
  26.                 BlockReference br = new BlockReference(Point3d.Origin, bt[ blockName ]);
  27.  
  28.                 br.TransformBy(Matrix3d
  29.                     .Displacement(ppr.Value - Point3d.Origin)
  30.                     .PreMultiplyBy(ed.CurrentUserCoordinateSystem));
  31.  
  32.                 btr.AppendEntity(br);
  33.                 tr.AddNewlyCreatedDBObject(br, true);
  34.                 tr.Commit();
  35.             }
  36.         }
  37.         //=======================================================================
  38.  
« Last Edit: December 18, 2011, 12:44: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.

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: BlockTesting2011
« Reply #5 on: March 31, 2011, 05:19:18 AM »
Next; Rotations with Displacement and Scale
.
Be carefull with the sequence for the PreMultiplyBy method
We usually do not want the  Displacement rotated.

If you DO want the displacement rotated swap the sequence of the Rotation and Displacement
Like this
Code - C#: [Select]
  1.  
  2.             Matrix3d Transform = Matrix3d
  3.                 .Scaling(scale, Point3d.Origin)                
  4.                 .PreMultiplyBy(Matrix3d.Displacement(DispacementVector))
  5.                 .PreMultiplyBy(Matrix3d.Rotation(rotation, zAxis, Point3d.Origin))              
  6.                 .PreMultiplyBy(ed.CurrentUserCoordinateSystem);
  7.  
  8.  

Code - C#: [Select]
  1.  
  2.         //=======================================================================
  3.         public const double kPi = 3.14159265358979323846;
  4.         //=======================================================================
  5.         public static double RadiansToDegrees(double radians)
  6.         {
  7.             return (radians * (kPi / 180.0));
  8.         }
  9.         //=======================================================================
  10.  

Code - C#: [Select]
  1.        //=======================================================================
  2.         // add the block to the current space (Model or Paper).
  3.         // block is exploded IE: copy of original
  4.         // Insert will be at UCS 0,0,0 honouring current X, Y, Z Axis.
  5.         // and transformed for Scale
  6.         // and transformed for Rotation
  7.         // and transformed for Displacement
  8.         // does not handle Attributes
  9.  
  10.         [CommandMethod("BI_6")]
  11.         public void BlockInsert_6()
  12.         {
  13.             string blockQualifiedFileName = "K:\\ToTest\\3Dblock.dwg";
  14.             double scale = 3.0;
  15.             Vector3d DispacementVector = new Vector3d(-20, -50, 0);
  16.             Vector3d zAxis = ed.CurrentUserCoordinateSystem.CoordinateSystem3d.Zaxis;
  17.             double rotation = RadiansToDegrees(15.0);
  18.             //
  19.             Database tmpDb = new Database(false, true);
  20.             tmpDb.ReadDwgFile(blockQualifiedFileName, System.IO.FileShare.Read, true, "");
  21.  
  22.             Matrix3d Transform = Matrix3d
  23.                 .Scaling(scale, Point3d.Origin)
  24.                 .PreMultiplyBy(Matrix3d.Rotation(rotation, zAxis, Point3d.Origin))
  25.                 .PreMultiplyBy(Matrix3d.Displacement(DispacementVector))                
  26.                 .PreMultiplyBy(ed.CurrentUserCoordinateSystem);
  27.  
  28.             db.Insert(Transform, tmpDb, true);
  29.         }
  30.         //=======================================================================
  31.  
« Last Edit: December 18, 2011, 12:45:34 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.

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: BlockTesting2011
« Reply #6 on: March 31, 2011, 07:34:23 PM »
Next Stage :
Inserting Attributes.

Updated Solution Zip added:

Library stuff:
Code - C#: [Select]
  1.         //=======================================================================
  2.         /// <summary>
  3.         /// Insert ALL AttributeReferences from BlockTableRecord into BlockReference
  4.         /// </summary>
  5.         /// <param name="blkRef"></param>
  6.         /// <param name="tr"></param>
  7.         public static void InsertAttibuteInBlockRef(
  8.             BlockReference blkRef,
  9.             Transaction tr)
  10.         {
  11.             BlockTableRecord btr = (BlockTableRecord)tr.GetObject(blkRef.BlockTableRecord, OpenMode.ForRead);
  12.             foreach( ObjectId attId in btr ) {
  13.                 Entity ent = (Entity)tr.GetObject(attId, OpenMode.ForRead);
  14.                 if( ent is AttributeDefinition ) {
  15.                     AttributeDefinition attDef = (AttributeDefinition)ent;
  16.                     AttributeReference attRef = new AttributeReference();
  17.                     attRef.SetAttributeFromBlock(attDef, blkRef.BlockTransform);
  18.                     ObjectId id = blkRef.AttributeCollection.AppendAttribute(attRef);
  19.                     tr.AddNewlyCreatedDBObject(attRef, true);
  20.                 }
  21.             }
  22.         }
  23.         //=======================================================================
  24.         /// <summary>
  25.         ///  Insert ALL AttributeReferences from BlockTableRecord into BlockReference
  26.         ///  Set the value of Attribute 'attributeTag' to 'attributeText'
  27.         /// </summary>
  28.         /// <param name="blkRef"></param>
  29.         /// <param name="attributeTag"></param>
  30.         /// <param name="attributeText"></param>
  31.         /// <param name="tr"></param>
  32.         public static void InsertAttibuteInBlockRef(
  33.             BlockReference blkRef,
  34.             string attributeTag,
  35.             string attributeText,
  36.             Transaction tr)
  37.         {
  38.             BlockTableRecord btr = (BlockTableRecord)tr.GetObject(blkRef.BlockTableRecord, OpenMode.ForRead);
  39.             foreach( ObjectId attId in btr ) {
  40.                 Entity ent = (Entity)tr.GetObject(attId, OpenMode.ForRead);
  41.                 if( ent is AttributeDefinition ) {
  42.                     AttributeDefinition attDef = (AttributeDefinition)ent;
  43.                     AttributeReference attRef = new AttributeReference();
  44.                     attRef.SetAttributeFromBlock(attDef, blkRef.BlockTransform);
  45.                     if( attRef.Tag == attributeTag )
  46.                         attRef.TextString = attributeText;
  47.                     ObjectId id = blkRef.AttributeCollection.AppendAttribute(attRef);
  48.                     tr.AddNewlyCreatedDBObject(attRef, true);
  49.                 }
  50.             }
  51.         }
  52.         //=======================================================================
  53.  


Test Routines:
Code - C#: [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.  
  6.         [CommandMethod("BI_15")]
  7.         public void BlockInsert_15()
  8.         {
  9.             string blockQualifiedFileName = "K:\\ToTest\\3Dblock_A.dwg";
  10.             string blockName = "3Dblock_A";
  11.  
  12.             using( Transaction tr = db.TransactionManager.StartTransaction() ) {
  13.                 BlockTable bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead);
  14.                 if( !bt.Has(blockName) ) {
  15.                     Database tmpDb = new Database(false, true);
  16.                     tmpDb.ReadDwgFile(blockQualifiedFileName, System.IO.FileShare.Read, true, "");
  17.                     // add the block to the ActiveDrawing blockTable
  18.                     db.Insert(blockName, tmpDb, true);
  19.                 }
  20.  
  21.                 PromptPointResult ppr = ed.GetPoint("\nSpecify insertion point: ");
  22.                 if( ppr.Status != PromptStatus.OK )
  23.                     return;
  24.  
  25.                 BlockTableRecord btr = (BlockTableRecord)tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite);
  26.  
  27.                 using( BlockReference br = new BlockReference(Point3d.Origin, bt[ blockName ]) ) {
  28.                     br.TransformBy(Matrix3d
  29.                         .Displacement(ppr.Value - Point3d.Origin)
  30.                         .PreMultiplyBy(ed.CurrentUserCoordinateSystem));
  31.  
  32.                     btr.AppendEntity(br);
  33.                     tr.AddNewlyCreatedDBObject(br, true);
  34.                     //                    
  35.                     InsertAttibuteInBlockRef(br, tr);
  36.                 }
  37.                 tr.Commit();
  38.             }
  39.         }
  40.         //=======================================================================
  41.  

Code - C#: [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.  
  7.         [CommandMethod("BI_16")]
  8.         public void BlockInsert_16()
  9.         {
  10.             string blockQualifiedFileName = "K:\\ToTest\\3Dblock_A.dwg";
  11.             string blockName = "3Dblock_A";
  12.             string attTag = "ATTRIBUTETAG";
  13.             string attText = "Yes, we have no bananas";
  14.  
  15.             using( Transaction tr = db.TransactionManager.StartTransaction() ) {
  16.                 BlockTable bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead);
  17.                 if( !bt.Has(blockName) ) {
  18.                     Database tmpDb = new Database(false, true);
  19.                     tmpDb.ReadDwgFile(blockQualifiedFileName, System.IO.FileShare.Read, true, "");
  20.                     // add the block to the ActiveDrawing blockTable
  21.                     db.Insert(blockName, tmpDb, true);
  22.                 }
  23.  
  24.                 PromptPointResult ppr = ed.GetPoint("\nSpecify insertion point: ");
  25.                 if( ppr.Status != PromptStatus.OK )
  26.                     return;
  27.  
  28.                 BlockTableRecord btr = (BlockTableRecord)tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite);
  29.  
  30.                 using( BlockReference br = new BlockReference(Point3d.Origin, bt[ blockName ]) ) {
  31.                     br.TransformBy(Matrix3d
  32.                         .Displacement(ppr.Value - Point3d.Origin)
  33.                         .PreMultiplyBy(ed.CurrentUserCoordinateSystem));
  34.  
  35.                     btr.AppendEntity(br);
  36.                     tr.AddNewlyCreatedDBObject(br, true);
  37.                     //                    
  38.                     InsertAttibuteInBlockRef(br, attTag, attText, tr);
  39.                 }
  40.                 tr.Commit();
  41.             }
  42.         }
  43.         //=======================================================================
  44.  
« Last Edit: December 18, 2011, 12:46:16 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: 6150
Re: BlockTesting2011
« Reply #7 on: April 01, 2011, 07:47:27 PM »
Laying it out the same as Kerry.
You will notice the extra calls to DirectCast because
Option strict is on.

I used http://www.developerfusion.com/tools/convert/csharp-to-vb/ to check and did good job only messed up a couple of things.

I will attach zip in last post and update along with kerry.

Container:
Code - vb.net: [Select]
  1. 'Option strict and explicit are turned on
  2. 'Code converted from C#
  3. 'Original C# code located  @ http://www.theswamp.org/index.php?topic=37686.0
  4. 'Check link in above line as code is posted for learning resource and likely to be updated.
  5. 'Please thank Kerry at above link
  6. 'If something is wrong it is probably error converting from C#
  7.  
  8. 'CodeHimBelonga kdub@theSwamp 20110331
  9.  
  10.  
  11. Imports Autodesk.AutoCAD.Runtime
  12. Imports Autodesk.AutoCAD.ApplicationServices
  13. Imports Autodesk.AutoCAD.DatabaseServices
  14. Imports Autodesk.AutoCAD.Geometry
  15. Imports Autodesk.AutoCAD.EditorInput
  16. Imports Autodesk.AutoCAD.ApplicationServices.Application
  17. Imports AcUtils = Autodesk.AutoCAD.Internal.Utils
  18.  
  19. <Assembly: CommandClass(GetType(KdubTesting.BlockTesting2011))>
  20.  
  21.     Namespace KdubTesting
  22.         Public Class BlockTesting2011
  23.             Private doc As Document
  24.             Private db As Database
  25.             Private ed As Editor
  26.  
  27.             Public Sub New()
  28.                 ActiveDoc = AcadApp.DocumentManager.MdiActiveDocument
  29.             End Sub
  30.  
  31.             Private Property ActiveDoc() As Document
  32.                 Get
  33.                     Return doc
  34.                 End Get
  35.  
  36.                 Set(ByVal value As Document)
  37.                     doc = value
  38.  
  39.                     If doc = Nothing Then
  40.                         db = Nothing
  41.                         ed = Nothing
  42.                     Else
  43.                         db = doc.Database
  44.                         ed = doc.Editor
  45.                     End If
  46.                 End Set
  47.  
  48.             End Property
  49.             '=======================================================================
  50.  
  51.             ' Methods go here < snip>
  52.             '=======================================================================
  53.         End Class
  54.  
  55.     End Namespace
  56.  

Code - vb.net: [Select]
  1.  
  2.         <CommandMethod("BI_1")> _
  3.         Public Sub BlockInsert_1()
  4.             Dim blockQualifiedFileName As String = "K:\ToTest\3Dblock_A.dwg"
  5.             Dim blockName As String = "3Dblock_A"
  6.             Dim tmpDb As New Database(False, True)
  7.             tmpDb.ReadDwgFile(blockQualifiedFileName, System.IO.FileShare.Read, True, "")
  8.  
  9.             ' add the block to the ActiveDrawing blockTable
  10.             db.Insert(blockName, tmpDb, True)
  11.  
  12.             ' add the block to the ActiveDrawing blockTable with a Temporary Name
  13.             db.Insert("TmpTest", tmpDb, True)
  14.         End Sub
  15.  
Code - vb.net: [Select]
  1.  '=======================================================================
  2.         ' add the block to the current space (Model or Paper).
  3.         ' block is exploded IE: copy of original
  4.         ' Insert will be at World 0,0,0 and transformed for Scale
  5.  
  6.         <CommandMethod("BI_2")> _
  7.         Public Sub BlockInsert_2()
  8.             Dim blockQualifiedFileName As String = "K:\ToTest\3Dblock_A.dwg"
  9.             Dim scale As Double = 5.0
  10.  
  11.             Dim tmpDb As New Database(False, True)
  12.             tmpDb.ReadDwgFile(blockQualifiedFileName, System.IO.FileShare.Read, True, "")
  13.  
  14.             Dim Transform As Matrix3d = Matrix3d.Scaling(scale, Point3d.Origin).PreMultiplyBy(Matrix3d.Identity)
  15.  
  16.             db.Insert(Transform, tmpDb, True)
  17.         End Sub
  18.  

Code - vb.net: [Select]
  1. '=======================================================================
  2.         ' add the block to the current space (Model or Paper).
  3.         ' block is exploded IE: copy of original
  4.         ' Insert will be at UCS 0,0,0 honouring current X, Y, Z Axis.
  5.         ' and transformed for Scale
  6.  
  7.         <CommandMethod("BI_3")> _
  8.         Public Sub BlockInsert_3()
  9.             Dim blockQualifiedFileName As String = "K:\ToTest\3Dblock.dwg"
  10.             Dim scale As Double = 2.5
  11.  
  12.             Dim tmpDb As New Database(False, True)
  13.             tmpDb.ReadDwgFile(blockQualifiedFileName, System.IO.FileShare.Read, True, "")
  14.  
  15.             Dim Transform As Matrix3d = Matrix3d _
  16.                 .Scaling(scale, Point3d.Origin) _
  17.                 .PreMultiplyBy(ed.CurrentUserCoordinateSystem)
  18.  
  19.             db.Insert(Transform, tmpDb, True)
  20.         End Sub
  21.  
Code - vb.net: [Select]
  1.   '=======================================================================
  2.         ' add the block to the current space (Model or Paper).
  3.         ' block is exploded IE: copy of original
  4.         ' Insert will be at UCS 0,0,0 honouring current X, Y, Z Axis.
  5.         ' and transformed for Scale
  6.         ' and transformed for Displacement
  7.  
  8.         <CommandMethod("BI_4")> _
  9.         Public Sub BlockInsert_4()
  10.             Dim blockQualifiedFileName As String = "K:\ToTest\3Dblock.dwg"
  11.             Dim scale As Double = 3.0
  12.             Dim DispacementVector As New Vector3d(20, 50, 0)
  13.             '
  14.             Dim tmpDb As New Database(False, True)
  15.             tmpDb.ReadDwgFile(blockQualifiedFileName, System.IO.FileShare.Read, True, "")
  16.  
  17.             Dim Transform As Matrix3d = Matrix3d _
  18.                                         .Scaling(scale, Point3d.Origin) _
  19.                                         .PreMultiplyBy(Matrix3d.Displacement(DispacementVector)) _
  20.                                         .PreMultiplyBy(ed.CurrentUserCoordinateSystem)
  21.  
  22.             db.Insert(Transform, tmpDb, True)
  23.         End Sub
  24.  
Code - vb.net: [Select]
  1.  
  2.         '=======================================================================
  3.         ' add the block to the current space (Model or Paper).
  4.         ' block is exploded IE: copy of original
  5.         ' Insert will be at UCS 0,0,0 honouring current X, Y, Z Axis.
  6.         ' and transformed for Scale
  7.         ' and transformed for Displacement
  8.  
  9.         <CommandMethod("BI_5")> _
  10.         Public Sub BlockInsert_5()
  11.             Dim blockQualifiedFileName As String = "K:\ToTest\3Dblock_a.dwg"
  12.             Dim scale As Double = 3.0
  13.             Dim DispacementVector As New Vector3d(20, 50, 0)
  14.             '
  15.             Dim tmpDb As New Database(False, True)
  16.             tmpDb.ReadDwgFile(blockQualifiedFileName, System.IO.FileShare.Read, True, "")
  17.  
  18.             Dim Transform As Matrix3d = Matrix3d _
  19.                                         .Scaling(scale, Point3d.Origin) _
  20.                                         .PreMultiplyBy(Matrix3d.Displacement(DispacementVector)) _
  21.                                         .PreMultiplyBy(ed.CurrentUserCoordinateSystem)
  22.  
  23.             db.Insert(Transform, tmpDb, True)
  24.         End Sub
  25.  
« Last Edit: January 25, 2012, 07:01:31 AM by Kerry »

Jeff H

  • Needs a day job
  • Posts: 6150
Re: BlockTesting2011
« Reply #8 on: April 01, 2011, 07:55:19 PM »
Next series :
Refer notations.

Transforms use PreMultiplyBy method as suggested by gile  :-)


Code - vb.net: [Select]
  1.   '=======================================================================
  2.  
  3.         '=======================================================================
  4.         ' add the block to the ActiveDrawing CurrentSpace
  5.         ' Expects to find the Block in the BlockTable
  6.         ' does not handle Attributes
  7.  
  8.         <CommandMethod("BI_10")> _
  9.         Public Sub BlockInsert_10()
  10.             Dim blockName As String = "3Dblock"
  11.  
  12.             Using tr As Transaction = db.TransactionManager.StartTransaction()
  13.                 Dim bt As BlockTable = DirectCast(tr.GetObject(db.BlockTableId, OpenMode.ForRead), BlockTable)
  14.  
  15.                 If Not bt.Has(blockName) Then
  16.                     ed.WriteMessage(vbLf & "Block '{0}' is not available in the current drawing.", blockName)
  17.                     Return
  18.                 End If
  19.  
  20.                 Dim ppr As PromptPointResult = ed.GetPoint(vbLf & "Specify insertion point: ")
  21.  
  22.                 If ppr.Status <> PromptStatus.OK Then
  23.                     Return
  24.                 End If
  25.  
  26.                 Dim btr As BlockTableRecord = DirectCast(tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite), BlockTableRecord)
  27.                 Dim br As New BlockReference(Point3d.Origin, bt(blockName))
  28.  
  29.                 br.TransformBy(Matrix3d.Displacement(ppr.Value - Point3d.Origin) _
  30.                                .PreMultiplyBy(ed.CurrentUserCoordinateSystem))
  31.  
  32.                 btr.AppendEntity(br)
  33.                 tr.AddNewlyCreatedDBObject(br, True)
  34.                 tr.Commit()
  35.  
  36.             End Using
  37.         End Sub
  38.  

Code - vb.net: [Select]
  1.  '=======================================================================
  2.         ' add the block to the ActiveDrawing CurrentSpace
  3.         ' Imports the Block if not found in the BlockTable
  4.         ' does not handle Attributes
  5.  
  6.         <CommandMethod("BI_11")> _
  7.         Public Sub BlockInsert_11()
  8.  
  9.             Dim blockQualifiedFileName As String = "K:\ToTest\3Dblock.dwg"
  10.             Dim blockName As String = "3Dblock"
  11.  
  12.             Using tr As Transaction = db.TransactionManager.StartTransaction()
  13.                 Dim bt As BlockTable = DirectCast(tr.GetObject(db.BlockTableId, OpenMode.ForRead), BlockTable)
  14.  
  15.                 If Not bt.Has(blockName) Then
  16.                     Dim tmpDb As New Database(False, True)
  17.                     tmpDb.ReadDwgFile(blockQualifiedFileName, System.IO.FileShare.Read, True, "")
  18.                     ' add the block to the ActiveDrawing blockTable
  19.                     db.Insert(blockName, tmpDb, True)
  20.                 End If
  21.  
  22.                 Dim ppr As PromptPointResult = ed.GetPoint(vbLf & "Specify insertion point: ")
  23.  
  24.                 If ppr.Status <> PromptStatus.OK Then
  25.                     Return
  26.                 End If
  27.  
  28.                 Dim btr As BlockTableRecord = DirectCast(tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite), BlockTableRecord)
  29.                 Dim br As New BlockReference(Point3d.Origin, bt(blockName))
  30.  
  31.                 br.TransformBy(Matrix3d.Displacement(ppr.Value - Point3d.Origin) _
  32.                                .PreMultiplyBy(ed.CurrentUserCoordinateSystem))
  33.  
  34.                 btr.AppendEntity(br)
  35.                 tr.AddNewlyCreatedDBObject(br, True)
  36.                 tr.Commit()
  37.  
  38.             End Using
  39.         End Sub
  40.  



Rotations with Displacement and Scale
.
Be carefull with the sequence for the PreMultiplyBy method
We usually do not want the  Displacement rotated.

If you DO want the displacement rotated swap the sequence of the Rotation and Displacement
Like this
Code - vb.net: [Select]
  1.             Dim Transform As Matrix3d = Matrix3d _
  2.                                      .Scaling(scale, Point3d.Origin) _
  3.                                      .PreMultiplyBy(Matrix3d.Displacement(DispacementVector)) _
  4.                                      .PreMultiplyBy(Matrix3d.Rotation(rotation, zAxis, Point3d.Origin)) _
  5.                                      .PreMultiplyBy(ed.CurrentUserCoordinateSystem)
  6.  
  7.             db.Insert(Transform, tmpDb, True)
  8.  

Code - vb.net: [Select]
  1.         '=======================================================================
  2.         Public Const kPi As Double = 3.1415926535897931
  3.         '=======================================================================
  4.         Public Shared Function RadiansToDegrees(ByVal radians As Double) As Double
  5.             Return radians * (kPi / 180.0)
  6.         End Function
  7.  

Code - vb.net: [Select]
  1.  
  2.         '=======================================================================
  3.         '=======================================================================
  4.         ' add the block to the current space (Model or Paper).
  5.         ' block is exploded IE: copy of original
  6.         ' Insert will be at UCS 0,0,0 honouring current X, Y, Z Axis.
  7.         ' and transformed for Scale
  8.         ' and transformed for Rotation
  9.         ' and transformed for Displacement
  10.         ' does not handle Attributes
  11.  
  12.         <CommandMethod("BI_6")> _
  13.         Public Sub BlockInsert_6()
  14.             Dim blockQualifiedFileName As String = "K:\ToTest\3Dblock.dwg"
  15.             Dim scale As Double = 3.0
  16.             Dim DispacementVector As New Vector3d(-20, -50, 0)
  17.             Dim zAxis As Vector3d = ed.CurrentUserCoordinateSystem.CoordinateSystem3d.Zaxis
  18.             Dim rotation As Double = RadiansToDegrees(15.0)
  19.             '
  20.             Dim tmpDb As New Database(False, True)
  21.             tmpDb.ReadDwgFile(blockQualifiedFileName, System.IO.FileShare.Read, True, "")
  22.  
  23.             Dim Transform As Matrix3d = Matrix3d _
  24.                                         .Scaling(scale, Point3d.Origin) _
  25.                                         .PreMultiplyBy(Matrix3d.Rotation(rotation, zAxis, Point3d.Origin)) _
  26.                                         .PreMultiplyBy(Matrix3d.Displacement(DispacementVector)) _
  27.                                         .PreMultiplyBy(ed.CurrentUserCoordinateSystem)
  28.  
  29.         End Sub
  30.  
« Last Edit: January 25, 2012, 07:00:51 AM by Kerry »

Jeff H

  • Needs a day job
  • Posts: 6150
Re: BlockTesting2011
« Reply #9 on: April 01, 2011, 08:03:59 PM »
********************Edit***************
Solution Updated 4/4/2011
********************End Edit***************
Next Stage :
Inserting Attributes.

Solution Zip added for everything posted:
Library stuff:
Code - vb.net: [Select]
  1.         '=======================================================================
  2.         '=======================================================================
  3.         ''' <summary>
  4.         ''' Insert ALL AttributeReferences from BlockTableRecord into BlockReference
  5.         ''' </summary>
  6.         ''' <param name="blkRef"></param>
  7.         ''' <param name="tr"></param>
  8.         Public Shared Sub InsertAttibuteInBlockRef(blkRef As BlockReference, tr As Transaction)
  9.             Dim btr As BlockTableRecord = DirectCast(tr.GetObject(blkRef.BlockTableRecord, OpenMode.ForRead), BlockTableRecord)
  10.  
  11.             For Each attId As ObjectId In btr
  12.                 Dim ent As Entity = DirectCast(tr.GetObject(attId, OpenMode.ForRead), Entity)
  13.  
  14.                 If TypeOf ent Is AttributeDefinition Then
  15.  
  16.                     Dim attDef As AttributeDefinition = DirectCast(ent, AttributeDefinition)
  17.                     Dim attRef As New AttributeReference()
  18.  
  19.                     attRef.SetAttributeFromBlock(attDef, blkRef.BlockTransform)
  20.  
  21.                     Dim id As ObjectId = blkRef.AttributeCollection.AppendAttribute(attRef)
  22.                     tr.AddNewlyCreatedDBObject(attRef, True)
  23.  
  24.                 End If
  25.  
  26.             Next
  27.  
  28.         End Sub
  29.  
  30.         '=======================================================================
  31.         ''' <summary>
  32.         '''  Insert ALL AttributeReferences from BlockTableRecord into BlockReference
  33.         '''  Set the value of Attribute 'attributeTag' to 'attributeText'
  34.         ''' </summary>
  35.         ''' <param name="blkRef"></param>
  36.         ''' <param name="attributeTag"></param>
  37.         ''' <param name="attributeText"></param>
  38.         ''' <param name="tr"></param>
  39.         Public Shared Sub InsertAttibuteInBlockRef(blkRef As BlockReference, attributeTag As String, attributeText As String, tr As Transaction)
  40.  
  41.             Dim btr As BlockTableRecord = DirectCast(tr.GetObject(blkRef.BlockTableRecord, OpenMode.ForRead), BlockTableRecord)
  42.  
  43.             For Each attId As ObjectId In btr
  44.                 Dim ent As Entity = DirectCast(tr.GetObject(attId, OpenMode.ForRead), Entity)
  45.  
  46.                 If TypeOf ent Is AttributeDefinition Then
  47.  
  48.                     Dim attDef As AttributeDefinition = DirectCast(ent, AttributeDefinition)
  49.                     Dim attRef As New AttributeReference()
  50.                     attRef.SetAttributeFromBlock(attDef, blkRef.BlockTransform)
  51.  
  52.                     If attRef.Tag = attributeTag Then
  53.                         attRef.TextString = attributeText
  54.                     End If
  55.  
  56.                     Dim id As ObjectId = blkRef.AttributeCollection.AppendAttribute(attRef)
  57.                     tr.AddNewlyCreatedDBObject(attRef, True)
  58.  
  59.                 End If
  60.  
  61.             Next
  62.  
  63.         End Sub
  64.  


Test Routines:
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.         ' Adds ALL AttributeReference to the BlockReference
  6.  
  7.         <CommandMethod("BI_15")> _
  8.         Public Sub BlockInsert_15()
  9.  
  10.             Dim blockQualifiedFileName As String = "K:\ToTest\3Dblock_A.dwg"
  11.             Dim blockName As String = "3Dblock_A"
  12.  
  13.             Using tr As Transaction = db.TransactionManager.StartTransaction()
  14.  
  15.                 Dim bt As BlockTable = DirectCast(tr.GetObject(db.BlockTableId, OpenMode.ForRead), BlockTable)
  16.  
  17.                 If Not bt.Has(blockName) Then
  18.                     Dim tmpDb As New Database(False, True)
  19.                     tmpDb.ReadDwgFile(blockQualifiedFileName, System.IO.FileShare.Read, True, "")
  20.                     ' add the block to the ActiveDrawing blockTable
  21.                     db.Insert(blockName, tmpDb, True)
  22.                 End If
  23.  
  24.                 Dim ppr As PromptPointResult = ed.GetPoint(vbLf & "Specify insertion point: ")
  25.  
  26.                 If ppr.Status <> PromptStatus.OK Then
  27.                     Return
  28.                 End If
  29.  
  30.                 Dim btr As BlockTableRecord = DirectCast(tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite), BlockTableRecord)
  31.  
  32.                 Using br As New BlockReference(Point3d.Origin, bt(blockName))
  33.                     br.TransformBy(Matrix3d.Displacement(ppr.Value - Point3d.Origin).PreMultiplyBy(ed.CurrentUserCoordinateSystem))
  34.  
  35.                     btr.AppendEntity(br)
  36.                     tr.AddNewlyCreatedDBObject(br, True)
  37.                     '                    
  38.                     InsertAttibuteInBlockRef(br, tr)
  39.                 End Using
  40.  
  41.                 tr.Commit()
  42.             End Using
  43.         End Sub
  44.  

Code - vb.net: [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.  
  7.         <CommandMethod("BI_16")> _
  8.         Public Sub BlockInsert_16()
  9.  
  10.             Dim blockQualifiedFileName As String = "K:\ToTest\3Dblock_A.dwg"
  11.             Dim blockName As String = "3Dblock_A"
  12.             Dim attTag As String = "ATTRIBUTETAG"
  13.             Dim attText As String = "Yes, we have no bananas"
  14.  
  15.             Using tr As Transaction = db.TransactionManager.StartTransaction()
  16.  
  17.                 Dim bt As BlockTable = DirectCast(tr.GetObject(db.BlockTableId, OpenMode.ForRead), BlockTable)
  18.  
  19.                 If Not bt.Has(blockName) Then
  20.                     Dim tmpDb As New Database(False, True)
  21.                     tmpDb.ReadDwgFile(blockQualifiedFileName, System.IO.FileShare.Read, True, "")
  22.                     ' add the block to the ActiveDrawing blockTable
  23.                     db.Insert(blockName, tmpDb, True)
  24.                 End If
  25.  
  26.                 Dim ppr As PromptPointResult = ed.GetPoint(vbLf & "Specify insertion point: ")
  27.  
  28.                 If ppr.Status <> PromptStatus.OK Then
  29.                     Return
  30.                 End If
  31.  
  32.                 Dim btr As BlockTableRecord = DirectCast(tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite), BlockTableRecord)
  33.  
  34.                 Using br As New BlockReference(Point3d.Origin, bt(blockName))
  35.                     br.TransformBy(Matrix3d.Displacement(ppr.Value - Point3d.Origin).PreMultiplyBy(ed.CurrentUserCoordinateSystem))
  36.  
  37.                     btr.AppendEntity(br)
  38.                     tr.AddNewlyCreatedDBObject(br, True)
  39.                     '                    
  40.                     InsertAttibuteInBlockRef(br, attTag, attText, tr)
  41.                 End Using
  42.  
  43.                 tr.Commit()
  44.             End Using
  45.  
  46.         End Sub
  47.  
« Last Edit: January 25, 2012, 07:08:56 AM by Kerry »

gile

  • Gator
  • Posts: 2507
  • Marseille, France
Re: BlockTesting2011
« Reply #10 on: April 02, 2011, 12:34:22 PM »
Should I try a F# translation ?
Speaking English as a French Frog

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: BlockTesting2011
« Reply #11 on: April 02, 2011, 05:22:34 PM »

Sure gile.
I'm trying to concentrate on concepts not language so any 'language' questions that arise  can be split off this topic.

Regards,
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 #12 on: April 02, 2011, 06:09:59 PM »
So, here's a F# translation of  the C# code from the 'BlockTesting2011 _20110331.1115' source.
Maybe it's not 'very good' F# coding (I'm newby) but every command seems to work as expected (and it was a fine exercice).

If you don't use VS 2010 pro,
- to run the dll, you have to install the F# runtime.
- to play with F#, you can add F# to Visual Studio 2008 (Standard edition or greater) or use a free Visual Studio Shell (2008 or 2010) see here.

I'll post the code the same way as Kerry and Jeff H to make easier comparisons, just adding some 'off code' comments for F# main differences from C# or VB.

Container
No need to contain all functions in a class
Code - F#: [Select]
  1. // Code translated from C#
  2. // Original C# code located  @ http://www.theswamp.org/index.php?topic=37686.0
  3. // Check link in above line as code is posted for learning resource and likely to be updated.
  4. // Please thank Kerry at above link
  5.  
  6. module KdubTesting.BlockTesting2011
  7.  
  8. open System
  9. open System.IO
  10. open Autodesk.AutoCAD.ApplicationServices
  11. open Autodesk.AutoCAD.DatabaseServices
  12. open Autodesk.AutoCAD.EditorInput
  13. open Autodesk.AutoCAD.Geometry
  14. open Autodesk.AutoCAD.Runtime
  15.  
  16. type AcAp = Autodesk.AutoCAD.ApplicationServices.Application
  17. type AcUt = Autodesk.AutoCAD.Internal.Utils
  18.  
  19. let doc = AcAp.DocumentManager.MdiActiveDocument
  20. let db = doc.Database
  21. let ed = doc.Editor
  22.  
  23. // Functions go here
  24. //=======================================================================

Code - F#: [Select]
  1. //=======================================================================
  2. // add the block to the ActiveDrawing blockTable
  3. [<CommandMethod("BI_1")>]
  4. let blockInsert_1 () =
  5.     let blockQualifiedFileName = "K:\\ToTest\\3Dblock_A.dwg"
  6.     let blockName = "3DBlock_a"
  7.    
  8.     use tmpDb = new Database()
  9.     tmpDb.ReadDwgFile(blockQualifiedFileName, System.IO.FileShare.Read, true, "")
  10.    
  11.     // add the block to the ActiveDrawing blockTable
  12.     db.Insert(blockName, tmpDb, true) |> ignore
  13.    
  14.     // add the block to the ActiveDrawing blockTable with a Temporary Name
  15.     db.Insert("TmpTest", tmpDb, true) |> ignore
  16. //=======================================================================

Code - F#: [Select]
  1. //=======================================================================
  2. // add the block to the current space (Model or Paper).
  3. // block is exploded IE: copy of original
  4. // Insert will be at World 0,0,0 and transformed for Scale
  5. [<CommandMethod("BI_2")>]
  6. let blockInsert_2 () =
  7.     let blockQualifiedFileName = "K:\\ToTest\\3Dblock_A.dwg"
  8.     let scale = 5.0
  9.    
  10.     use tmpDb = new Database()
  11.     tmpDb.ReadDwgFile(blockQualifiedFileName, System.IO.FileShare.Read, true, "")
  12.     let transform = Matrix3d.Scaling(scale, Point3d.Origin)
  13.     db.Insert(transform, tmpDb, true)
  14. //=======================================================================

The matrix multiplication uses 'pipe-lining' operator which looks like the PreMultiplyBy method
Code - F#: [Select]
  1. //=======================================================================
  2. // add the block to the current space (Model or Paper).
  3. // block is exploded IE: copy of original
  4. // Insert will be at UCS 0,0,0 honouring current X, Y, Z Axis.
  5. // and transformed for Scale
  6. [<CommandMethod("BI_3")>]
  7. let blockInsert_3 () =
  8.     let blockQualifiedFileName = "K:\\ToTest\\3Dblock.dwg"
  9.     let scale = 2.5
  10.    
  11.     use tmpDb = new Database()
  12.     tmpDb.ReadDwgFile(blockQualifiedFileName, System.IO.FileShare.Read, true, "")
  13.     let transform = Matrix3d.Scaling(scale, Point3d.Origin)
  14.                     |> (*) ed.CurrentUserCoordinateSystem
  15.     db.Insert(transform, tmpDb, true)
  16. //=======================================================================

Code - F#: [Select]
  1. //=======================================================================
  2. // add the block to the current space (Model or Paper).
  3. // block is exploded IE: copy of original
  4. // Insert will be at UCS 0,0,0 honouring current X, Y, Z Axis.
  5. // and transformed for Scale
  6. // and transformed for Displacement
  7. [<CommandMethod("BI_4")>]
  8. let blockInsert_4 () =
  9.     let blockQualifiedFileName = "K:\\ToTest\\3Dblock.dwg"
  10.     let scale = 3.0
  11.     let dispacementVector = new Vector3d(20.0, 50.0, 0.0)
  12.    
  13.     use tmpDb = new Database()
  14.     tmpDb.ReadDwgFile(blockQualifiedFileName, System.IO.FileShare.Read, true, "")
  15.     let transform = Matrix3d.Scaling(scale, Point3d.Origin)
  16.                     |> (*) (Matrix3d.Displacement(dispacementVector))
  17.                     |> (*) ed.CurrentUserCoordinateSystem
  18.     db.Insert(transform, tmpDb, true)
  19. //=======================================================================

« Last Edit: January 25, 2012, 07:12:18 AM by Kerry »
Speaking English as a French Frog

gile

  • Gator
  • Posts: 2507
  • Marseille, France
Re: BlockTesting2011
« Reply #13 on: April 02, 2011, 06:15:51 PM »
Next; Rotations with Displacement and Scale

renamed RadiansToDegrees into degreesToRadians which seems more correct
Code - F#: [Select]
  1. //=======================================================================
  2. let kPi = 3.14159265358979323846
  3. //=======================================================================
  4. let degreesToRadians degrees =
  5.     degrees * (kPi / 180.0)
  6. //=======================================================================

Code - F#: [Select]
  1. //=======================================================================
  2. // add the block to the current space (Model or Paper).
  3. // block is exploded IE: copy of original
  4. // Insert will be at UCS 0,0,0 honouring current X, Y, Z Axis.
  5. // and transformed for Scale
  6. // and transformed for Rotation
  7. // and transformed for Displacement
  8. // does not handle Attributes
  9. [<CommandMethod("BI_6")>]
  10. let blockInsert_6 () =
  11.     let blockQualifiedFileName = "K:\\ToTest\\3Dblock.dwg"
  12.     let scale = 3.0
  13.     let dispacementVector = new Vector3d(-20.0, -50.0, 0.0)
  14.     let zAxis = ed.CurrentUserCoordinateSystem.CoordinateSystem3d.Zaxis
  15.     let rotation = degreesToRadians 15.0
  16.    
  17.     use tmpDb = new Database()
  18.     tmpDb.ReadDwgFile(blockQualifiedFileName, System.IO.FileShare.Read, true, "")
  19.     let transform = Matrix3d.Scaling(scale, Point3d.Origin)
  20.                     |> (*) (Matrix3d.Rotation(rotation, zAxis, Point3d.Origin))
  21.                     |> (*) (Matrix3d.Displacement(dispacementVector))
  22.                     |> (*) ed.CurrentUserCoordinateSystem
  23.     db.Insert(transform, tmpDb, true)
  24. //=======================================================================
« Last Edit: January 25, 2012, 07:14:25 AM by Kerry »
Speaking English as a French Frog

gile

  • Gator
  • Posts: 2507
  • Marseille, France
Re: BlockTesting2011
« Reply #14 on: April 02, 2011, 06:18:21 PM »
Next series

Looking in the BlockTable

Code - F#: [Select]
  1. //=======================================================================
  2. // add the block to the ActiveDrawing CurrentSpace
  3. // Expects to find the Block in the BlockTable
  4. // does not handle Attributes
  5. [<CommandMethod("BI_10")>]
  6. let blockInsert_10 () =
  7.     let blockName = "3Dblock"
  8.    
  9.     use tr = db.TransactionManager.StartTransaction()
  10.     let bt = tr.GetObject(db.BlockTableId, OpenMode.ForRead) :?> BlockTable
  11.     if bt.Has(blockName) then
  12.         let ppr = ed.GetPoint("\nSpecify insertion point: ")
  13.         if ppr.Status = PromptStatus.OK then
  14.             let btr = tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite) :?> BlockTableRecord
  15.             let br = new BlockReference(Point3d.Origin, bt.[blockName])
  16.             br.TransformBy(Matrix3d.Displacement(ppr.Value.GetAsVector())
  17.                            |> (*) ed.CurrentUserCoordinateSystem)
  18.             btr.AppendEntity(br) |> ignore
  19.             tr.AddNewlyCreatedDBObject(br, true)
  20.             tr.Commit()
  21.     else
  22.         ed.WriteMessage("\nBlock '{0}' is not available in the current drawing.", blockName)
  23. //=======================================================================

Code - F#: [Select]
  1. //=======================================================================
  2. // add the block to the ActiveDrawing CurrentSpace
  3. // Imports the Block if not found in the BlockTable
  4. // does not handle Attributes
  5. [<CommandMethod("BI_11")>]
  6. let blockInsert_11 () =
  7.     let blockQualifiedFileName = "K:\\ToTest\\3Dblock.dwg"
  8.     let blockName = "3Dblock"
  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.         let 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.         tr.Commit()
  27. //=======================================================================
« Last Edit: January 25, 2012, 07:18:28 AM by Kerry »
Speaking English as a French Frog

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: 6150
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: 6150
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

kaefer

  • Guest
Re: BlockTesting2011
« Reply #30 on: April 05, 2011, 09:43:36 PM »
F# translation

Multi-Attribute Block Insert

A couple of observations with this F# version, which I expect to concern the other languages too:

1. FindFile throws Autodesk.AutoCAD.Runtime.Exception: eFilerError if the block isn't found. May be intentional.

2. Multiline attributes do not get transformed.

I suggest something like this:
Code: [Select]
                let ar = new AttributeReference()
                ar.SetAttributeFromBlock(ad, br.BlockTransform)
                if ar.IsMTextAttribute then
                    ar.UpdateMTextAttribute()
                    ar.TransformBy br.BlockTransform

3. The InsertBlockReference method would benefit greatly from named and optional parameters. All of them - except the block name - have sensible defaults. Alas, to do this in C# seems to require 4.0.

A possible signature for F# might be thus:
Code: [Select]
type Document with
  member
    InsertBlockReference : blockName:string *
                           ?insertPoint:Autodesk.AutoCAD.Geometry.Point3d *
                           ?scale:Autodesk.AutoCAD.Geometry.Scale3d *
                           ?angle:float * ?layer:string *
                           ?attValues:seq<string * string> *
                           ?annotationScaleNames:seq<string> *
                           ?ownerId:Autodesk.AutoCAD.DatabaseServices.ObjectId ->
                             Autodesk.AutoCAD.DatabaseServices.ObjectId option

Note: Optional parameters are only permitted on type members, that's why there's now an extension method. The complete example is attached.

Other areas of unauthorized tampering with your collective wisdom include dumping the map/hashtable, replaced by a read-only dictionary internally, and provision of a sequence of annotation scales and of an owner BTR Id as additional parameters,

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: BlockTesting2011
« Reply #31 on: April 05, 2011, 11:59:35 PM »

kaefer,
Thanks for the comments, I'm pleased someone is playing with these.
As I stated at the outset these samples are not complete and have subtle issues. The idea was to start with basic concepts and build up from there.
I had expected a few more comments.


Quote
1. FindFile throws Autodesk.AutoCAD.Runtime.Exception: eFilerError if the block isn't found. May be intentional.
Yes it does. And yes, it was ignored intentionally ... untill 'someone' discovered the exception.
The idea was to see the error and find a resolution.

Quote
2. Multiline attributes do not get transformed
Yes.
And Dynamic blocks need addressing explicitly.
And Mirrors,
And Attribute modification to pre-inserted blocks.
And a few other things :)

Quote
3. < .. >  optional parameters. < .. > Alas, to do this in C# seems to require 4.0.
Yes, optional parameters are version and language specific. Most people trying these in c# will not be using .NET 4.0.
I didn't want to branch into language distinctions with this series.

Quote
Other areas of unauthorized tampering with your collective wisdom include dumping the map/hashtable, replaced by a read-only dictionary internally, and provision of a sequence of annotation scales and of an owner BTR Id as additional parameters

Doing this requres a structural change to the samples.
I had intended providing a Dictionary sample using the current structure.
My thought was to also use the HashTable and/or Dictionary for extracting attributes.

Thanks again kaefer.

Regards,
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 #32 on: April 06, 2011, 03:14:57 AM »
About the FindFile exception, I'd suggest to use a new library method/function.

C#
Code - C#: [Select]
  1.        //=======================================================================
  2.         /// <summary>
  3.         ///  GetBlock: search for the block table record ObjectId in the block table or the search pathes
  4.         /// </summary>
  5.         /// <param name="bName"></param>
  6.         /// <param name="db"></param>
  7.         /// <returns>ObjectId of BlockTableRecord (or ObjectId.Null) </returns>
  8.         public ObjectId GetBlock(string bName, Database db)
  9.         {
  10.             ObjectId result;
  11.             using (Transaction tr = db.TransactionManager.StartTransaction())
  12.             {
  13.                 BlockTable bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead);
  14.                 if (bt.Has(bName))
  15.                     result = bt[bName];
  16.                 else
  17.                 {
  18.                     try
  19.                     {
  20.                         string path = HostApplicationServices.Current.FindFile(bName + ".dwg", db, FindFileHint.Default);
  21.                         using (Database tmpDb = new Database())
  22.                         {
  23.                             tmpDb.ReadDwgFile(path, System.IO.FileShare.Read, true, "");
  24.                             result = db.Insert(bName, tmpDb, true);
  25.                         }
  26.                     }
  27.                     catch
  28.                     {
  29.                         result = ObjectId.Null;
  30.                     }
  31.                 }
  32.                 tr.Commit();
  33.             }
  34.             return result;
  35.         }
  36.         //=======================================================================

F#
Code - F#: [Select]
  1.  //=======================================================================
  2. /// <summary>
  3. ///  getBlock: search for the block table record ObjectId in the block table or the search pathes
  4. /// </summary>
  5. /// <param name="bName"></param>
  6. /// <param name="db"></param>
  7. /// <returns>ObjectId of BlockTableRecord (or ObjectId.Null) </returns>
  8. let getBlock (bName:string) (db:Database) =
  9.     use tr = db.TransactionManager.StartTransaction()
  10.     let bt = tr.openForRead(db.BlockTableId) :?> BlockTable
  11.     if bt.Has(bName) then bt.[bName]
  12.     else
  13.         try
  14.             let path = HostApplicationServices.Current.FindFile(bName + ".dwg", db, FindFileHint.Default)
  15.             use tmpDb = new Database()
  16.             tmpDb.ReadDwgFile(path, System.IO.FileShare.Read, true, "")
  17.             let id = db.Insert(bName, tmpDb, true)
  18.             tr.Commit()
  19.             id
  20.         with
  21.             |_ -> ObjectId.Null
  22. //=======================================================================
« Last Edit: January 25, 2012, 07:04:56 AM by Kerry »
Speaking English as a French Frog

dan.glassman

  • Guest
Re: BlockTesting2011
« Reply #33 on: April 08, 2011, 01:35:45 AM »
I'll bite -- sorry I've been silent.

Annotative police, plus one change with comment [and for comment] below. 

Planned contributions, unless somebody beats me to it [preferably Autodesk, in some cases -- though I hope I'm not that slow]:

BlockReference annotative portion when time allows -- intending current scale only.  IEnumerable<ObjectContext> per kaefer...meh -- that's up to the user's ANNOAUTOSCALE, in my opinion; don't see a reason to include it in a lib, but may not be seeing past the end of my nose.

Attributes maybe shouldn't be an IDictionary<string, string> in the "use this collective goodness" version, since AutoCAD allows duplicate tags.  Unless there's a corresponding "we refuse to accept your block until you fix your duplicate tags" warning/exception.

IsMTextAttribute/IsDefaultAlignment issues.

DrawOrderTable preservation issues.

Sync Attribute properties to destination drawing TextStyle properties. 

Code - C#: [Select]
  1. try
  2. {
  3.     string path = HostApplicationServices.Current.FindFile(bName + ".dwg", db, FindFileHint.Default);
  4.     bool isAnno = False;
  5.     using (Database tmpDb = new Database())
  6.     {
  7.       tmpDb.ReadDwgFile(path, System.IO.FileShare.Read, true, "");
  8.       isAnno = tmpDb.AnnotativeDwg;
  9.       result = db.Insert(bName, tmpDb, [color=red]false[/color]);  // tmpDb is immediately disposed because of using -- no need to preserve it
  10.     }
  11.  
  12.     if (isAnno)
  13.     {
  14.       BlockTableRecord btr = (BlockTableRecord)(tr.Open(result, OpenMode.ForWrite));
  15.       btr.Annotative = AnnotativeStates.True;
  16.     }
  17. }
  18. catch
  19. {
  20.     result = ObjectId.Null;
  21. }
  22.  
  23.  
« Last Edit: December 18, 2011, 12:50:29 AM by Kerry »

Jeff H

  • Needs a day job
  • Posts: 6150
Re: BlockTesting2011
« Reply #34 on: April 08, 2011, 09:06:23 PM »
Just a couple of things noticed real quick for InsertBlockReference function.

Do you think 'br' or when the new block reference is created that it should be in a using block in case of an error?
The transaction will know nothing about it and will not dispose of it until 'tr.AddNewlyCreatedDBObject(br, true)' is reached.
Same for 'aRef' AttributeReference

Would it save enough time(That probably will never be noticeable) not using bt[blockName] twice by not searching the BlockTable a second time use btr.ObjectID

Changes in red

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

« Last Edit: October 23, 2023, 04:08:47 PM by kdub_nz »

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: BlockTesting2011
« Reply #35 on: April 09, 2011, 01:15:45 AM »

Quote
Do you think 'br' or when the new block reference is created that it should be in a using block in case of an error?

Yes, probably Jeff.

I had done that with the some of the other samples ... missed it for this one.
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: 6150
Re: BlockTesting2011
« Reply #36 on: April 13, 2011, 04:09:27 AM »
Just wanted to add I really like the way you intialize your Document, Database,  & Editor------clever idea


I messed around to see when the destructor was called if for some reason someone needed to keep up with open documents you have run a command in, but the destructor was not consistent when called.

No big deal was mainly wondering if it was disposed when a document was closed but I am defintely going to borrow that little setup if it is okay with you and of course will note who I stole it from.

Glenn R

  • Guest
Re: BlockTesting2011
« Reply #37 on: April 13, 2011, 05:32:02 AM »
Well, seeing as Kerry has been quite clever and only used public non-static methods for his command definitions, the class is spun up once and once only for each document the command is called in.

This is the opposite to how a public static command method definition, which is only spun up once per-session.

Not too shabby Kerry, not too shabby at all.

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: BlockTesting2011
« Reply #38 on: April 13, 2011, 05:51:21 AM »

< .. >
I am defintely going to borrow that little setup if it is okay with you and of course will note who I stole it from.


You're welcome to perloin the procedure Jeff. don't be fussed about the attribution though cause I stole the idea several years ago and have since lost the reference. :-)

< .. >

Not too shabby Kerry, not too shabby at all.

Thanks Glenn .. I'm pretty satisfied with it.

I'm trying to find the time to finish the rest of the samples I had planned.

Be well guys.
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.

kaefer

  • Guest
Re: BlockTesting2011
« Reply #39 on: April 13, 2011, 08:33:15 AM »
Well, seeing as Kerry has been quite clever and only used public non-static methods for his command definitions, the class is spun up once and once only for each document the command is called in.

Question: What does Kerry's technique buy that can't be bought by standard assignment inside each command? That is, except cutting those assignments themselves?

Not to appear a spoil-sport, I appreciate this feature nonetheless, see F# example below. But IMHO instance member commands display their full power if there's per-document data to store, which doesn't (yet) seem to be the case here. Besides, what about the failure mode, when doc is null: Under which circumstances can that possibly happen?

Code: [Select]
// Class with implicit constructor, let bindings, do bindings and members must
// appear in the order indicated
type ActiveDocumentTest() =
    // 1. Let bindings in implicit constructor
    let (doc, db, ed) =
        match AcadApp.DocumentManager.MdiActiveDocument with
        | null -> failwith "No Active Document"  // Can't happen?
        | doc -> doc, doc.Database, doc.Editor
   
    // 2. Do bindings in implicit constructor
    do  ed.WriteMessage("\nDocument {0} initialized. ", doc.Name)
   
    // 3. Member definitions
    [<CommandMethod "ActiveDocumentTestCmd">]
    member __.ActiveDocumentTestCmd() =
        ed.WriteMessage("\nCommand in document {0} executed. ", doc.Name)

Glenn R

  • Guest
Re: BlockTesting2011
« Reply #40 on: April 13, 2011, 10:15:35 AM »
Question: What does Kerry's technique buy that can't be bought by standard assignment inside each command? That is, except cutting those assignments themselves?

Nothing, but he's using the class constructor in a different way to what most use. I do use constructors and their chaining quite a bit, I just never thought of doing it for acad command methods. In most instances, like others, I omit the constructor when defining an acad command as it's normally not necessary and the compiler synthesized one is adequate.

What language is that you posted kaefer - French?  :evil:

gile

  • Gator
  • Posts: 2507
  • Marseille, France
Re: BlockTesting2011
« Reply #41 on: April 13, 2011, 10:57:55 AM »
What language is that you posted kaefer - French?  :evil:

No, it's not French (French is much more verbose), but the Frenchy I am understands it a bit and likes it more and more. :wink:

One more time, many thanks to all, I learn every day new things here (both Programming languages and English).
Speaking English as a French Frog

LE3

  • Guest
Re: BlockTesting2011
« Reply #42 on: April 13, 2011, 11:13:25 AM »
Quote
The idea was to start with basic concepts and build up from there.

Great stuff Kerry - thank you for sharing! - and of course the same goes to the ones doing the porting/translations. nice.