Author Topic: ** SOLVED ** - Alignment Parameter in Jig  (Read 222 times)

0 Members and 1 Guest are viewing this topic.

cmwade77

  • Swamp Rat
  • Posts: 1443
** SOLVED ** - Alignment Parameter in Jig
« on: February 21, 2024, 08:03:30 PM »
I am trying to create a jig that simulates the alignment parameter, which I found the code below at: https://spiderinnet1.typepad.com/blog/2012/11/autocad-net-jig-dynamic-block-with-alignment-parameter-using-entityjig.html

The problem is that it will align to non-nested entities, but not to any entities nested in a block or xRef, I have tried many different variations to fix this, but nothin has worked so far, can you please help me?

ETA: Solution in 3rd Post

Code - C#: [Select]
  1. public class DynamicBlockAlignmentJig : EntityJig
  2. {
  3.     #region Fields
  4.  
  5.     private int mCurJigFactorNumber = 1;
  6.  
  7.     private bool mIsDynamicAlignment = false;
  8.     private double mAlignmentAngle = 0.0;
  9.     private ObjectId mObjectIdToAlignWith = ObjectId.Null;
  10.  
  11.     private double mAngleOffset = 0.0;
  12.     private Point3d mPosition = new Point3d(0, 0, 0); // Factor #1
  13.     private double mRotation = 0.0;                 // Factor #2
  14.     private double mScaleFactor = 1.0;              // Factor #3
  15.  
  16.     #endregion
  17.  
  18.     #region Constructors
  19.  
  20.     public DynamicBlockAlignmentJig(BlockReference ent)
  21.         : base(ent)
  22.     {
  23.         mAngleOffset = ent.Rotation;
  24.  
  25.         if (ent.IsDynamicBlock)
  26.             mIsDynamicAlignment = true;
  27.     }
  28.  
  29.     #endregion
  30.  
  31.     #region Properties
  32.  
  33.     protected static Editor CurEditor
  34.     {
  35.         get
  36.         {
  37.             return Autodesk.AutoCAD.ApplicationServices.Core.Application.DocumentManager.MdiActiveDocument.Editor;
  38.         }
  39.     }
  40.  
  41.     protected static Matrix3d UCS
  42.     {
  43.         get
  44.         {
  45.             return CurEditor.CurrentUserCoordinateSystem;
  46.         }
  47.     }
  48.  
  49.     protected new BlockReference Entity
  50.     {
  51.         get
  52.         {
  53.             return (BlockReference)base.Entity;
  54.         }
  55.     }
  56.  
  57.     #endregion
  58.  
  59.     #region Overrides
  60.  
  61.     protected override bool Update()
  62.     {
  63.         switch (mCurJigFactorNumber)
  64.         {
  65.             case 1:
  66.                 Entity.Position = mPosition.TransformBy(UCS);
  67.                 if (mIsDynamicAlignment && !mObjectIdToAlignWith.IsNull)
  68.                 {
  69.                     if (mObjectIdToAlignWith.ObjectClass.IsDerivedFrom(RXClass.GetClass(typeof(Curve))))
  70.                     {
  71.                         Curve curve = (Curve)Entity.Database.TransactionManager.TopTransaction.GetObject(mObjectIdToAlignWith, OpenMode.ForRead);
  72.                         Vector3d dir = curve.GetFirstDerivative(curve.GetClosestPointTo(Entity.Position, false)).TransformBy(UCS.Inverse());
  73.                         mAlignmentAngle = Vector3d.XAxis.GetAngleTo(dir, Vector3d.ZAxis);
  74.                         Entity.Rotation = mAlignmentAngle + mAngleOffset;
  75.                     }
  76.                     else
  77.                         mObjectIdToAlignWith = ObjectId.Null;
  78.                 }
  79.                 break;
  80.             case 2:
  81.                 Entity.Rotation = mRotation + mAngleOffset;
  82.                 ;
  83.                 break;
  84.             case 3:
  85.                 Entity.ScaleFactors = new Scale3d(mScaleFactor);
  86.                 break;
  87.             default:
  88.                 break;
  89.         }
  90.  
  91.         return true;
  92.     }
  93.  
  94.     protected override SamplerStatus Sampler(JigPrompts prompts)
  95.     {
  96.         switch (mCurJigFactorNumber)
  97.         {
  98.             case 1:
  99.                 JigPromptPointOptions prOptions1 = new JigPromptPointOptions("\nBlock insertion point:");
  100.                 PromptPointResult prResult1 = prompts.AcquirePoint(prOptions1);
  101.                 if (prResult1.Status == PromptStatus.Cancel)
  102.                     return SamplerStatus.Cancel;
  103.  
  104.                 Point3d tempPt = prResult1.Value.TransformBy(UCS.Inverse());
  105.                 if (tempPt.IsEqualTo(mPosition))
  106.                 {
  107.                     return SamplerStatus.NoChange;
  108.                 }
  109.                 else
  110.                 {
  111.                     mPosition = tempPt;
  112.                     mObjectIdToAlignWith = pickObjId;
  113.                     return SamplerStatus.OK;
  114.                 }
  115.             case 2:
  116.                 JigPromptAngleOptions prOptions2 = new JigPromptAngleOptions("\nBlock rotation angle:");
  117.                 prOptions2.BasePoint = mPosition.TransformBy(UCS);
  118.                 prOptions2.UseBasePoint = true;
  119.                 PromptDoubleResult prResult2 = prompts.AcquireAngle(prOptions2);
  120.                 if (prResult2.Status == PromptStatus.Cancel)
  121.                     return SamplerStatus.Cancel;
  122.  
  123.                 if (prResult2.Value.Equals(mRotation))
  124.                 {
  125.                     return SamplerStatus.NoChange;
  126.                 }
  127.                 else
  128.                 {
  129.                     mRotation = prResult2.Value;
  130.                     return SamplerStatus.OK;
  131.                 }
  132.             case 3:
  133.                 JigPromptDistanceOptions prOptions3 = new JigPromptDistanceOptions("\nBlock scale factor:");
  134.                 prOptions3.BasePoint = mPosition.TransformBy(UCS);
  135.                 prOptions3.UseBasePoint = true;
  136.                 PromptDoubleResult prResult3 = prompts.AcquireDistance(prOptions3);
  137.                 if (prResult3.Status == PromptStatus.Cancel)
  138.                     return SamplerStatus.Cancel;
  139.  
  140.                 if (prResult3.Value.Equals(mScaleFactor))
  141.                 {
  142.                     return SamplerStatus.NoChange;
  143.                 }
  144.                 else
  145.                 {
  146.                     mScaleFactor = prResult3.Value;
  147.                     return SamplerStatus.OK;
  148.                 }
  149.             default:
  150.                 break;
  151.         }
  152.  
  153.         return SamplerStatus.OK;
  154.     }
  155.  
  156.     #endregion
  157.  
  158.     #region Point Monitor
  159.  
  160.     private static ObjectId pickObjId = ObjectId.Null;
  161.     private static void Editor_PointMonitor(object sender, PointMonitorEventArgs e)
  162.     {
  163.         Point3d computedPt = e.Context.ComputedPoint;
  164.         FullSubentityPath[] pickedEnts = e.Context.GetPickedEntities();
  165.  
  166.         if (pickedEnts != null && pickedEnts.Length > 0)
  167.         {
  168.             pickObjId = pickedEnts[0].GetObjectIds()[0];
  169.         }
  170.         else
  171.             pickObjId = ObjectId.Null;
  172.     }
  173.  
  174.     #endregion
  175.  
  176.     #region Method to Call
  177.  
  178.     public static bool Jig(BlockReference ent)
  179.     {
  180.         try
  181.         {
  182.             DynamicBlockAlignmentJig jigger = new DynamicBlockAlignmentJig(ent);
  183.             PromptResult pr;
  184.             do
  185.             {
  186.                 pr = CurEditor.Drag(jigger);
  187.                 if (jigger.mCurJigFactorNumber == 1 && jigger.mIsDynamicAlignment && !jigger.mObjectIdToAlignWith.IsNull)
  188.                     jigger.mCurJigFactorNumber++;
  189.             } while (pr.Status != PromptStatus.Cancel && pr.Status != PromptStatus.Error && jigger.mCurJigFactorNumber++ <= 3);
  190.  
  191.             return pr.Status == PromptStatus.OK;
  192.         }
  193.         catch
  194.         {
  195.             return false;
  196.         }
  197.     }
  198.  
  199.     #endregion
  200.  
  201.     #region Test Command
  202.  
  203.     [CommandMethod("DynamicBlockAlignmentJig")]
  204.     public static void BlockAttributeJig_Method()
  205.     {
  206.         Database db = HostApplicationServices.WorkingDatabase;
  207.         try
  208.         {
  209.             PromptResult pr = CurEditor.GetString("\nName of the block to jig:");
  210.             if (pr.Status == PromptStatus.OK)
  211.             {
  212.                 using (Transaction tr = db.TransactionManager.StartTransaction())
  213.                 {
  214.                     BlockTable bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead);
  215.                     if (!bt.Has(pr.StringResult))
  216.                     {
  217.                         CurEditor.WriteMessage("\nThe block <{0}> does not exist.", pr.StringResult);
  218.                         return;
  219.                     }
  220.  
  221.                     BlockTableRecord btr = tr.GetObject(bt[pr.StringResult], OpenMode.ForRead) as BlockTableRecord;
  222.                     using (BlockReference ent = new BlockReference(new Point3d(0, 0, 0), btr.ObjectId))
  223.                     {
  224.                         ent.TransformBy(UCS);
  225.                         BlockTableRecord modelspace = (BlockTableRecord)tr.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForWrite);
  226.                         modelspace.AppendEntity(ent);
  227.                         tr.AddNewlyCreatedDBObject(ent, true);
  228.  
  229.                         CurEditor.TurnForcedPickOn();
  230.                         CurEditor.PointMonitor += Editor_PointMonitor;
  231.  
  232.                         if (DynamicBlockAlignmentJig.Jig(ent))
  233.                             tr.Commit();
  234.  
  235.                         CurEditor.PointMonitor -= Editor_PointMonitor;
  236.                         CurEditor.TurnForcedPickOff();
  237.                     }
  238.                 }
  239.             }
  240.         }
  241.         catch (Autodesk.AutoCAD.Runtime.Exception ex)
  242.         {
  243.             CurEditor.WriteMessage(ex.Message);
  244.         }
  245.     }
  246.  
  247.     #endregion
« Last Edit: February 22, 2024, 05:48:24 PM by cmwade77 »

cmwade77

  • Swamp Rat
  • Posts: 1443
Re: Alignment Parameter in Jig
« Reply #1 on: February 21, 2024, 08:04:39 PM »
I also attempted a bit different approach, as follows:

Code - C#: [Select]
  1.  public class BlockInsertJig : EntityJig
  2.  {
  3.      private Point3d position;
  4.      private Matrix3d alignmentTransform;
  5.      private BlockReference blockRef;
  6.      private Point3d? point1;
  7.      private Point3d? point2;
  8.  
  9.      public BlockInsertJig(BlockReference blockReference) : base(blockReference)
  10.      {
  11.          blockRef = blockReference;
  12.          position = blockReference.Position;
  13.          alignmentTransform = Matrix3d.Identity;
  14.      }
  15.  
  16.      protected override SamplerStatus Sampler(JigPrompts prompts)
  17.      {
  18.          JigPromptPointOptions options = new JigPromptPointOptions("\nInsertion point: ");
  19.          options.UserInputControls = (UserInputControls.Accept3dCoordinates | UserInputControls.NoNegativeResponseAccepted);
  20.          PromptPointResult result = prompts.AcquirePoint(options);
  21.  
  22.          if (result.Status == PromptStatus.OK && result.Value != position)
  23.          {
  24.              position = result.Value;
  25.              return SamplerStatus.OK;
  26.          }
  27.  
  28.          return SamplerStatus.NoChange;
  29.      }
  30.  
  31.      protected override bool Update()
  32.      {
  33.          if (point1.HasValue && point2.HasValue)
  34.          {
  35.              Vector3d direction = point2.Value - point1.Value;
  36.              double angle = Vector3d.XAxis.GetAngleTo(direction, Vector3d.ZAxis);
  37.              alignmentTransform = Matrix3d.Rotation(angle, Vector3d.ZAxis, blockRef.Position);
  38.          }
  39.          else
  40.          {
  41.              alignmentTransform = Matrix3d.Identity;
  42.          }
  43.  
  44.          blockRef.Position = position;
  45.          blockRef.TransformBy(alignmentTransform);
  46.  
  47.          return true;
  48.      }
  49.  
  50.      public void SetAlignmentPoints(Point3d p1, Point3d p2)
  51.      {
  52.          point1 = p1;
  53.          point2 = p2;
  54.      }
  55.  
  56.      public void ClearAlignmentPoints()
  57.      {
  58.          point1 = null;
  59.          point2 = null;
  60.      }
  61.  }
  62.  
  63.  
  64.  
  65.  
  66.  public class Commands2
  67.  {
  68.      private static BlockInsertJig jig;
  69.      [CommandMethod("InsertAlignedBlock")]
  70.  
  71.      public void InsertAlignedBlock()
  72.      {
  73.          Document doc = Application.DocumentManager.MdiActiveDocument;
  74.          Database db = doc.Database;
  75.          Editor ed = doc.Editor;
  76.  
  77.          // Load or define the block to be inserted
  78.          ObjectId blockId = ObjectId.Null;
  79.          // Assuming the block is already defined in the drawing
  80.  
  81.          using (Transaction tr = db.TransactionManager.StartTransaction())
  82.          {
  83.              BlockTable bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead);
  84.              BlockTableRecord btr = (BlockTableRecord)tr.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForWrite);
  85.  
  86.              BlockReference blockRef = new BlockReference(Point3d.Origin, bt["ROUND_TAKEOFF_SIDE"]);
  87.              btr.AppendEntity(blockRef);
  88.              tr.AddNewlyCreatedDBObject(blockRef, true);
  89.  
  90.              jig = new BlockInsertJig(blockRef);
  91.  
  92.              ed.PointMonitor += OnPointMonitor;
  93.  
  94.              PromptResult res = ed.Drag(jig);
  95.  
  96.              ed.PointMonitor -= OnPointMonitor;
  97.  
  98.              if (res.Status == PromptStatus.OK)
  99.              {
  100.                  tr.Commit();
  101.              }
  102.              else
  103.              {
  104.                  tr.Abort();
  105.              }
  106.          }
  107.      }
  108.  
  109.      private static void OnPointMonitor(object sender, PointMonitorEventArgs e)
  110.      {
  111.          Document doc = Application.DocumentManager.MdiActiveDocument;
  112.          Editor ed = doc.Editor;
  113.          FullSubentityPath[] paths = e.Context.GetPickedEntities();
  114.          if (paths.Length > 0)
  115.          {
  116.              using (Transaction tr = doc.TransactionManager.StartTransaction())
  117.              {
  118.                  Entity entity = tr.GetObject(paths[0].GetObjectIds()[0], OpenMode.ForRead) as Entity;
  119.  
  120.                  if (entity != null && entity is Curve curve)
  121.                  {
  122.                      ed.WriteMessage("\nWorks");
  123.                      Point3d closestPoint = curve.GetClosestPointTo(e.Context.RawPoint, false);
  124.                      Vector3d direction = curve.GetFirstDerivative(closestPoint);
  125.                      Point3d secondPoint = closestPoint + direction;
  126.  
  127.                      jig.SetAlignmentPoints(closestPoint, secondPoint);
  128.                  }
  129.                  else
  130.                  {
  131.                      jig.ClearAlignmentPoints();
  132.                  }
  133.  
  134.                  tr.Commit();
  135.              }
  136.          }
  137.          else
  138.          {
  139.              jig.ClearAlignmentPoints();
  140.          }
  141.      }
  142.  
  143.  }

In this one I tried using alignment points instead.

cmwade77

  • Swamp Rat
  • Posts: 1443
** SOLVED ** - Re: Alignment Parameter in Jig
« Reply #2 on: February 22, 2024, 05:47:43 PM »
I finally got it, it may not be the most elegant solution, but it does get the job done:
Code - C#: [Select]
  1. public class DynamicBlockAlignmentJig : EntityJig
  2. {
  3.     #region Fields
  4.  
  5.     private int mCurJigFactorNumber = 1;
  6.  
  7.     private bool mIsDynamicAlignment = false;
  8.     private double mAlignmentAngle = 0.0;
  9.     private ObjectId mObjectIdToAlignWith = ObjectId.Null;
  10.  
  11.     private double mAngleOffset = 0.0;
  12.     private Point3d mPosition = new Point3d(0, 0, 0); // Factor #1
  13.     private double mRotation = 0.0;                 // Factor #2
  14.     private double mScaleFactor = 1.0;              // Factor #3
  15.     private static ObjectId pickBlockRefId = ObjectId.Null;
  16.  
  17.     #endregion
  18.  
  19.     #region Constructors
  20.  
  21.     public DynamicBlockAlignmentJig(BlockReference ent)
  22.         : base(ent)
  23.     {
  24.         mAngleOffset = ent.Rotation;
  25.  
  26.         if (ent.IsDynamicBlock)
  27.             mIsDynamicAlignment = true;
  28.     }
  29.  
  30.     #endregion
  31.  
  32.     #region Properties
  33.  
  34.     protected static Editor CurEditor
  35.     {
  36.         get
  37.         {
  38.             return Autodesk.AutoCAD.ApplicationServices.Core.Application.DocumentManager.MdiActiveDocument.Editor;
  39.         }
  40.     }
  41.  
  42.     protected static Matrix3d UCS
  43.     {
  44.         get
  45.         {
  46.             return CurEditor.CurrentUserCoordinateSystem;
  47.         }
  48.     }
  49.  
  50.     protected new BlockReference Entity
  51.     {
  52.         get
  53.         {
  54.             return (BlockReference)base.Entity;
  55.         }
  56.     }
  57.  
  58.     #endregion
  59.  
  60.     #region Overrides
  61.  
  62.     protected override bool Update()
  63.     {
  64.         switch (mCurJigFactorNumber)
  65.         {
  66.             case 1:
  67.                 Entity.Position = mPosition.TransformBy(UCS);
  68.                 if (mIsDynamicAlignment && !mObjectIdToAlignWith.IsNull)
  69.                 {
  70.                     using (Transaction tr = Entity.Database.TransactionManager.StartTransaction())
  71.                     {
  72.                         DBObject obj = tr.GetObject(mObjectIdToAlignWith, OpenMode.ForRead);
  73.                         if (obj is Curve curve)
  74.                         {
  75.                             Matrix3d transform = Matrix3d.Identity;
  76.                             if (!pickBlockRefId.IsNull) // Check if the subentity is part of a block
  77.                             {
  78.                                 BlockReference blockRef = tr.GetObject(pickBlockRefId, OpenMode.ForRead) as BlockReference;
  79.                                 if (blockRef != null)
  80.                                 {
  81.                                     transform = blockRef.BlockTransform;
  82.                                 }
  83.                             }
  84.  
  85.                             curve = (Curve)curve.GetTransformedCopy(transform);
  86.                             Point3d closestPoint = curve.GetClosestPointTo(Entity.Position, false);
  87.                             Vector3d dir = curve.GetFirstDerivative(closestPoint).TransformBy(UCS.Inverse());
  88.                             mAlignmentAngle = Vector3d.XAxis.GetAngleTo(dir, Vector3d.ZAxis);
  89.                             Entity.Rotation = mAlignmentAngle + mAngleOffset;
  90.                         }
  91.                         else
  92.                         {
  93.                             mObjectIdToAlignWith = ObjectId.Null;
  94.                         }
  95.  
  96.                         tr.Commit();
  97.                     }
  98.                 }
  99.                 break;
  100.                 // Other cases remain unchanged
  101.         }
  102.  
  103.         return true;
  104.     }
  105.  
  106.  
  107.     protected override SamplerStatus Sampler(JigPrompts prompts)
  108.     {
  109.         switch (mCurJigFactorNumber)
  110.         {
  111.             case 1:
  112.                 JigPromptPointOptions prOptions1 = new JigPromptPointOptions("\nBlock insertion point:");
  113.                 PromptPointResult prResult1 = prompts.AcquirePoint(prOptions1);
  114.                 if (prResult1.Status == PromptStatus.Cancel)
  115.                     return SamplerStatus.Cancel;
  116.  
  117.                 Point3d tempPt = prResult1.Value.TransformBy(UCS.Inverse());
  118.                 if (tempPt.IsEqualTo(mPosition))
  119.                 {
  120.                     return SamplerStatus.NoChange;
  121.                 }
  122.                 else
  123.                 {
  124.                     mPosition = tempPt;
  125.                     mObjectIdToAlignWith = pickObjId;
  126.                     return SamplerStatus.OK;
  127.                 }
  128.             case 2:
  129.                 JigPromptAngleOptions prOptions2 = new JigPromptAngleOptions("\nBlock rotation angle:");
  130.                 prOptions2.BasePoint = mPosition.TransformBy(UCS);
  131.                 prOptions2.UseBasePoint = true;
  132.                 PromptDoubleResult prResult2 = prompts.AcquireAngle(prOptions2);
  133.                 if (prResult2.Status == PromptStatus.Cancel)
  134.                     return SamplerStatus.Cancel;
  135.  
  136.                 if (prResult2.Value.Equals(mRotation))
  137.                 {
  138.                     return SamplerStatus.NoChange;
  139.                 }
  140.                 else
  141.                 {
  142.                     mRotation = prResult2.Value;
  143.                     return SamplerStatus.OK;
  144.                 }
  145.             case 3:
  146.                 JigPromptDistanceOptions prOptions3 = new JigPromptDistanceOptions("\nBlock scale factor:");
  147.                 prOptions3.BasePoint = mPosition.TransformBy(UCS);
  148.                 prOptions3.UseBasePoint = true;
  149.                 PromptDoubleResult prResult3 = prompts.AcquireDistance(prOptions3);
  150.                 if (prResult3.Status == PromptStatus.Cancel)
  151.                     return SamplerStatus.Cancel;
  152.  
  153.                 if (prResult3.Value.Equals(mScaleFactor))
  154.                 {
  155.                     return SamplerStatus.NoChange;
  156.                 }
  157.                 else
  158.                 {
  159.                     mScaleFactor = prResult3.Value;
  160.                     return SamplerStatus.OK;
  161.                 }
  162.             default:
  163.                 break;
  164.         }
  165.  
  166.         return SamplerStatus.OK;
  167.     }
  168.  
  169.     #endregion
  170.  
  171.     #region Point Monitor
  172.  
  173.     private static ObjectId pickObjId = ObjectId.Null;
  174.  
  175.     private static void Editor_PointMonitor(object sender, PointMonitorEventArgs e)
  176.     {
  177.         Document doc = Application.DocumentManager.MdiActiveDocument;
  178.         Database db = doc.Database;
  179.         Editor ed = doc.Editor;
  180.  
  181.         if (e.Context == null)
  182.         {
  183.             return;
  184.         }
  185.  
  186.         FullSubentityPath[] fullEntPath = e.Context.GetPickedEntities();
  187.  
  188.         if (fullEntPath.Length > 0)
  189.         {
  190.             try
  191.             {
  192.                 using (Transaction tr = db.TransactionManager.StartTransaction())
  193.                 {
  194.                     Entity topLevelEntity = tr.GetObject(fullEntPath.First().GetObjectIds().First(), OpenMode.ForRead) as Entity;
  195.                     Point3d cursorPosition = e.Context.ComputedPoint;
  196.  
  197.                     if (topLevelEntity is BlockReference blockRef)
  198.                     {
  199.                         BlockTableRecord blockDef = tr.GetObject(blockRef.BlockTableRecord, OpenMode.ForRead) as BlockTableRecord;
  200.  
  201.                         foreach (ObjectId entId in blockDef)
  202.                         {
  203.                             Entity subEntity = tr.GetObject(entId, OpenMode.ForRead) as Entity;
  204.                             if (IsCursorOnEntity(subEntity, cursorPosition, blockRef, tr))
  205.                             {
  206.                                 pickObjId = subEntity.ObjectId;
  207.                                 pickBlockRefId = blockRef.ObjectId; // Store the block reference ObjectId
  208.                                 break;
  209.                             }
  210.                         }
  211.                     }
  212.                     else
  213.                     {
  214.                         pickObjId = topLevelEntity.ObjectId;
  215.                         pickBlockRefId = ObjectId.Null; // Reset the block reference ObjectId
  216.                     }
  217.  
  218.                     tr.Commit();
  219.                 }
  220.             }
  221.             catch (System.Exception ex)
  222.             {
  223.                 pickObjId = ObjectId.Null;
  224.                 pickBlockRefId = ObjectId.Null;
  225.             }
  226.         }
  227.         else
  228.         {
  229.             pickObjId = ObjectId.Null;
  230.             pickBlockRefId = ObjectId.Null;
  231.         }
  232.     }
  233.  
  234.  
  235.     #endregion
  236.  
  237.  
  238.     // Helper method to check if the cursor is on the entity within a block reference
  239.     private static bool IsCursorOnEntity(Entity entity, Point3d cursorPosition, BlockReference blockRef, Transaction tr)
  240.     {
  241.         // Adjust tolerance as needed
  242.         double tolerance = 0.01;
  243.  
  244.         // Transform the cursor position from WCS to the block reference's ECS
  245.         Matrix3d transform = blockRef.BlockTransform.Inverse();
  246.         Point3d transformedCursorPosition = cursorPosition.TransformBy(transform);
  247.  
  248.         if (entity is Curve curve)
  249.         {
  250.             // Get the closest point on the curve to the transformed cursor position
  251.             Point3d closestPoint = curve.GetClosestPointTo(transformedCursorPosition, false);
  252.             // Check if the distance between the closest point and the transformed cursor position is within the tolerance
  253.             return transformedCursorPosition.DistanceTo(closestPoint) <= tolerance;
  254.         }
  255.         else
  256.         {
  257.             // For non-curve entities, check if the transformed cursor position is within the entity's geometric extents
  258.             Extents3d extents = entity.GeometricExtents;
  259.             return transformedCursorPosition.X >= extents.MinPoint.X - tolerance &&
  260.                    transformedCursorPosition.X <= extents.MaxPoint.X + tolerance &&
  261.                    transformedCursorPosition.Y >= extents.MinPoint.Y - tolerance &&
  262.                    transformedCursorPosition.Y <= extents.MaxPoint.Y + tolerance &&
  263.                    transformedCursorPosition.Z >= extents.MinPoint.Z - tolerance &&
  264.                    transformedCursorPosition.Z <= extents.MaxPoint.Z + tolerance;
  265.         }
  266.     }
  267.  
  268.  
  269.  
  270.  
  271.  
  272.  
  273.     #region Method to Call
  274.  
  275.     public static bool Jig(BlockReference ent)
  276.     {
  277.         try
  278.         {
  279.             DynamicBlockAlignmentJig jigger = new DynamicBlockAlignmentJig(ent);
  280.             PromptResult pr;
  281.             do
  282.             {
  283.                 pr = CurEditor.Drag(jigger);
  284.                 if (jigger.mCurJigFactorNumber == 1 && jigger.mIsDynamicAlignment && !jigger.mObjectIdToAlignWith.IsNull)
  285.                     jigger.mCurJigFactorNumber++;
  286.             } while (pr.Status != PromptStatus.Cancel && pr.Status != PromptStatus.Error && jigger.mCurJigFactorNumber++ <= 3);
  287.  
  288.             return pr.Status == PromptStatus.OK;
  289.         }
  290.         catch
  291.         {
  292.             return false;
  293.         }
  294.     }
  295.  
  296.     #endregion
  297.  
  298.     #region Test Command
  299.  
  300.     [CommandMethod("DynamicBlockAlignmentJig")]
  301.     public static void BlockAttributeJig_Method()
  302.     {
  303.         Database db = HostApplicationServices.WorkingDatabase;
  304.         try
  305.         {
  306.             string pr = "ROUND_TAKEOFF_SIDE";
  307.  
  308.             using (Transaction tr = db.TransactionManager.StartTransaction())
  309.             {
  310.                 BlockTable bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead);
  311.                 if (!bt.Has(pr))
  312.                 {
  313.                     CurEditor.WriteMessage("\nThe block <{0}> does not exist.", pr);
  314.                     return;
  315.                 }
  316.  
  317.                 BlockTableRecord btr = tr.GetObject(bt[pr], OpenMode.ForRead) as BlockTableRecord;
  318.                 using (BlockReference ent = new BlockReference(new Point3d(0, 0, 0), btr.ObjectId))
  319.                 {
  320.                     ent.TransformBy(UCS);
  321.                     BlockTableRecord modelspace = (BlockTableRecord)tr.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForWrite);
  322.                     modelspace.AppendEntity(ent);
  323.                     tr.AddNewlyCreatedDBObject(ent, true);
  324.  
  325.                     CurEditor.TurnForcedPickOn();
  326.                     CurEditor.PointMonitor += Editor_PointMonitor;
  327.  
  328.                     if (DynamicBlockAlignmentJig.Jig(ent))
  329.                         tr.Commit();
  330.  
  331.                     CurEditor.PointMonitor -= Editor_PointMonitor;
  332.                     CurEditor.TurnForcedPickOff();
  333.                 }
  334.             }
  335.  
  336.         }
  337.         catch (Autodesk.AutoCAD.Runtime.Exception ex)
  338.         {
  339.             CurEditor.WriteMessage(ex.Message);
  340.         }
  341.  
  342.         #endregion
  343.  
  344.  
  345.  
  346.  
  347.     }
  348. }