Code Red > .NET
** SOLVED ** - Alignment Parameter in Jig
(1/1)
cmwade77:
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#: ---public class DynamicBlockAlignmentJig : EntityJig{ #region Fields private int mCurJigFactorNumber = 1; private bool mIsDynamicAlignment = false; private double mAlignmentAngle = 0.0; private ObjectId mObjectIdToAlignWith = ObjectId.Null; private double mAngleOffset = 0.0; private Point3d mPosition = new Point3d(0, 0, 0); // Factor #1 private double mRotation = 0.0; // Factor #2 private double mScaleFactor = 1.0; // Factor #3 #endregion #region Constructors public DynamicBlockAlignmentJig(BlockReference ent) : base(ent) { mAngleOffset = ent.Rotation; if (ent.IsDynamicBlock) mIsDynamicAlignment = true; } #endregion #region Properties protected static Editor CurEditor { get { return Autodesk.AutoCAD.ApplicationServices.Core.Application.DocumentManager.MdiActiveDocument.Editor; } } protected static Matrix3d UCS { get { return CurEditor.CurrentUserCoordinateSystem; } } protected new BlockReference Entity { get { return (BlockReference)base.Entity; } } #endregion #region Overrides protected override bool Update() { switch (mCurJigFactorNumber) { case 1: Entity.Position = mPosition.TransformBy(UCS); if (mIsDynamicAlignment && !mObjectIdToAlignWith.IsNull) { if (mObjectIdToAlignWith.ObjectClass.IsDerivedFrom(RXClass.GetClass(typeof(Curve)))) { Curve curve = (Curve)Entity.Database.TransactionManager.TopTransaction.GetObject(mObjectIdToAlignWith, OpenMode.ForRead); Vector3d dir = curve.GetFirstDerivative(curve.GetClosestPointTo(Entity.Position, false)).TransformBy(UCS.Inverse()); mAlignmentAngle = Vector3d.XAxis.GetAngleTo(dir, Vector3d.ZAxis); Entity.Rotation = mAlignmentAngle + mAngleOffset; } else mObjectIdToAlignWith = ObjectId.Null; } break; case 2: Entity.Rotation = mRotation + mAngleOffset; ; break; case 3: Entity.ScaleFactors = new Scale3d(mScaleFactor); break; default: break; } return true; } protected override SamplerStatus Sampler(JigPrompts prompts) { switch (mCurJigFactorNumber) { case 1: JigPromptPointOptions prOptions1 = new JigPromptPointOptions("\nBlock insertion point:"); PromptPointResult prResult1 = prompts.AcquirePoint(prOptions1); if (prResult1.Status == PromptStatus.Cancel) return SamplerStatus.Cancel; Point3d tempPt = prResult1.Value.TransformBy(UCS.Inverse()); if (tempPt.IsEqualTo(mPosition)) { return SamplerStatus.NoChange; } else { mPosition = tempPt; mObjectIdToAlignWith = pickObjId; return SamplerStatus.OK; } case 2: JigPromptAngleOptions prOptions2 = new JigPromptAngleOptions("\nBlock rotation angle:"); prOptions2.BasePoint = mPosition.TransformBy(UCS); prOptions2.UseBasePoint = true; PromptDoubleResult prResult2 = prompts.AcquireAngle(prOptions2); if (prResult2.Status == PromptStatus.Cancel) return SamplerStatus.Cancel; if (prResult2.Value.Equals(mRotation)) { return SamplerStatus.NoChange; } else { mRotation = prResult2.Value; return SamplerStatus.OK; } case 3: JigPromptDistanceOptions prOptions3 = new JigPromptDistanceOptions("\nBlock scale factor:"); prOptions3.BasePoint = mPosition.TransformBy(UCS); prOptions3.UseBasePoint = true; PromptDoubleResult prResult3 = prompts.AcquireDistance(prOptions3); if (prResult3.Status == PromptStatus.Cancel) return SamplerStatus.Cancel; if (prResult3.Value.Equals(mScaleFactor)) { return SamplerStatus.NoChange; } else { mScaleFactor = prResult3.Value; return SamplerStatus.OK; } default: break; } return SamplerStatus.OK; } #endregion #region Point Monitor private static ObjectId pickObjId = ObjectId.Null; private static void Editor_PointMonitor(object sender, PointMonitorEventArgs e) { Point3d computedPt = e.Context.ComputedPoint; FullSubentityPath[] pickedEnts = e.Context.GetPickedEntities(); if (pickedEnts != null && pickedEnts.Length > 0) { pickObjId = pickedEnts[0].GetObjectIds()[0]; } else pickObjId = ObjectId.Null; } #endregion #region Method to Call public static bool Jig(BlockReference ent) { try { DynamicBlockAlignmentJig jigger = new DynamicBlockAlignmentJig(ent); PromptResult pr; do { pr = CurEditor.Drag(jigger); if (jigger.mCurJigFactorNumber == 1 && jigger.mIsDynamicAlignment && !jigger.mObjectIdToAlignWith.IsNull) jigger.mCurJigFactorNumber++; } while (pr.Status != PromptStatus.Cancel && pr.Status != PromptStatus.Error && jigger.mCurJigFactorNumber++ <= 3); return pr.Status == PromptStatus.OK; } catch { return false; } } #endregion #region Test Command [CommandMethod("DynamicBlockAlignmentJig")] public static void BlockAttributeJig_Method() { Database db = HostApplicationServices.WorkingDatabase; try { PromptResult pr = CurEditor.GetString("\nName of the block to jig:"); if (pr.Status == PromptStatus.OK) { using (Transaction tr = db.TransactionManager.StartTransaction()) { BlockTable bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead); if (!bt.Has(pr.StringResult)) { CurEditor.WriteMessage("\nThe block <{0}> does not exist.", pr.StringResult); return; } BlockTableRecord btr = tr.GetObject(bt[pr.StringResult], OpenMode.ForRead) as BlockTableRecord; using (BlockReference ent = new BlockReference(new Point3d(0, 0, 0), btr.ObjectId)) { ent.TransformBy(UCS); BlockTableRecord modelspace = (BlockTableRecord)tr.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForWrite); modelspace.AppendEntity(ent); tr.AddNewlyCreatedDBObject(ent, true); CurEditor.TurnForcedPickOn(); CurEditor.PointMonitor += Editor_PointMonitor; if (DynamicBlockAlignmentJig.Jig(ent)) tr.Commit(); CurEditor.PointMonitor -= Editor_PointMonitor; CurEditor.TurnForcedPickOff(); } } } } catch (Autodesk.AutoCAD.Runtime.Exception ex) { CurEditor.WriteMessage(ex.Message); } } #endregion
cmwade77:
I also attempted a bit different approach, as follows:
--- Code - C#: --- public class BlockInsertJig : EntityJig { private Point3d position; private Matrix3d alignmentTransform; private BlockReference blockRef; private Point3d? point1; private Point3d? point2; public BlockInsertJig(BlockReference blockReference) : base(blockReference) { blockRef = blockReference; position = blockReference.Position; alignmentTransform = Matrix3d.Identity; } protected override SamplerStatus Sampler(JigPrompts prompts) { JigPromptPointOptions options = new JigPromptPointOptions("\nInsertion point: "); options.UserInputControls = (UserInputControls.Accept3dCoordinates | UserInputControls.NoNegativeResponseAccepted); PromptPointResult result = prompts.AcquirePoint(options); if (result.Status == PromptStatus.OK && result.Value != position) { position = result.Value; return SamplerStatus.OK; } return SamplerStatus.NoChange; } protected override bool Update() { if (point1.HasValue && point2.HasValue) { Vector3d direction = point2.Value - point1.Value; double angle = Vector3d.XAxis.GetAngleTo(direction, Vector3d.ZAxis); alignmentTransform = Matrix3d.Rotation(angle, Vector3d.ZAxis, blockRef.Position); } else { alignmentTransform = Matrix3d.Identity; } blockRef.Position = position; blockRef.TransformBy(alignmentTransform); return true; } public void SetAlignmentPoints(Point3d p1, Point3d p2) { point1 = p1; point2 = p2; } public void ClearAlignmentPoints() { point1 = null; point2 = null; } } public class Commands2 { private static BlockInsertJig jig; [CommandMethod("InsertAlignedBlock")] public void InsertAlignedBlock() { Document doc = Application.DocumentManager.MdiActiveDocument; Database db = doc.Database; Editor ed = doc.Editor; // Load or define the block to be inserted ObjectId blockId = ObjectId.Null; // Assuming the block is already defined in the drawing using (Transaction tr = db.TransactionManager.StartTransaction()) { BlockTable bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead); BlockTableRecord btr = (BlockTableRecord)tr.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForWrite); BlockReference blockRef = new BlockReference(Point3d.Origin, bt["ROUND_TAKEOFF_SIDE"]); btr.AppendEntity(blockRef); tr.AddNewlyCreatedDBObject(blockRef, true); jig = new BlockInsertJig(blockRef); ed.PointMonitor += OnPointMonitor; PromptResult res = ed.Drag(jig); ed.PointMonitor -= OnPointMonitor; if (res.Status == PromptStatus.OK) { tr.Commit(); } else { tr.Abort(); } } } private static void OnPointMonitor(object sender, PointMonitorEventArgs e) { Document doc = Application.DocumentManager.MdiActiveDocument; Editor ed = doc.Editor; FullSubentityPath[] paths = e.Context.GetPickedEntities(); if (paths.Length > 0) { using (Transaction tr = doc.TransactionManager.StartTransaction()) { Entity entity = tr.GetObject(paths[0].GetObjectIds()[0], OpenMode.ForRead) as Entity; if (entity != null && entity is Curve curve) { ed.WriteMessage("\nWorks"); Point3d closestPoint = curve.GetClosestPointTo(e.Context.RawPoint, false); Vector3d direction = curve.GetFirstDerivative(closestPoint); Point3d secondPoint = closestPoint + direction; jig.SetAlignmentPoints(closestPoint, secondPoint); } else { jig.ClearAlignmentPoints(); } tr.Commit(); } } else { jig.ClearAlignmentPoints(); } } }
In this one I tried using alignment points instead.
cmwade77:
I finally got it, it may not be the most elegant solution, but it does get the job done:
--- Code - C#: ---public class DynamicBlockAlignmentJig : EntityJig{ #region Fields private int mCurJigFactorNumber = 1; private bool mIsDynamicAlignment = false; private double mAlignmentAngle = 0.0; private ObjectId mObjectIdToAlignWith = ObjectId.Null; private double mAngleOffset = 0.0; private Point3d mPosition = new Point3d(0, 0, 0); // Factor #1 private double mRotation = 0.0; // Factor #2 private double mScaleFactor = 1.0; // Factor #3 private static ObjectId pickBlockRefId = ObjectId.Null; #endregion #region Constructors public DynamicBlockAlignmentJig(BlockReference ent) : base(ent) { mAngleOffset = ent.Rotation; if (ent.IsDynamicBlock) mIsDynamicAlignment = true; } #endregion #region Properties protected static Editor CurEditor { get { return Autodesk.AutoCAD.ApplicationServices.Core.Application.DocumentManager.MdiActiveDocument.Editor; } } protected static Matrix3d UCS { get { return CurEditor.CurrentUserCoordinateSystem; } } protected new BlockReference Entity { get { return (BlockReference)base.Entity; } } #endregion #region Overrides protected override bool Update() { switch (mCurJigFactorNumber) { case 1: Entity.Position = mPosition.TransformBy(UCS); if (mIsDynamicAlignment && !mObjectIdToAlignWith.IsNull) { using (Transaction tr = Entity.Database.TransactionManager.StartTransaction()) { DBObject obj = tr.GetObject(mObjectIdToAlignWith, OpenMode.ForRead); if (obj is Curve curve) { Matrix3d transform = Matrix3d.Identity; if (!pickBlockRefId.IsNull) // Check if the subentity is part of a block { BlockReference blockRef = tr.GetObject(pickBlockRefId, OpenMode.ForRead) as BlockReference; if (blockRef != null) { transform = blockRef.BlockTransform; } } curve = (Curve)curve.GetTransformedCopy(transform); Point3d closestPoint = curve.GetClosestPointTo(Entity.Position, false); Vector3d dir = curve.GetFirstDerivative(closestPoint).TransformBy(UCS.Inverse()); mAlignmentAngle = Vector3d.XAxis.GetAngleTo(dir, Vector3d.ZAxis); Entity.Rotation = mAlignmentAngle + mAngleOffset; } else { mObjectIdToAlignWith = ObjectId.Null; } tr.Commit(); } } break; // Other cases remain unchanged } return true; } protected override SamplerStatus Sampler(JigPrompts prompts) { switch (mCurJigFactorNumber) { case 1: JigPromptPointOptions prOptions1 = new JigPromptPointOptions("\nBlock insertion point:"); PromptPointResult prResult1 = prompts.AcquirePoint(prOptions1); if (prResult1.Status == PromptStatus.Cancel) return SamplerStatus.Cancel; Point3d tempPt = prResult1.Value.TransformBy(UCS.Inverse()); if (tempPt.IsEqualTo(mPosition)) { return SamplerStatus.NoChange; } else { mPosition = tempPt; mObjectIdToAlignWith = pickObjId; return SamplerStatus.OK; } case 2: JigPromptAngleOptions prOptions2 = new JigPromptAngleOptions("\nBlock rotation angle:"); prOptions2.BasePoint = mPosition.TransformBy(UCS); prOptions2.UseBasePoint = true; PromptDoubleResult prResult2 = prompts.AcquireAngle(prOptions2); if (prResult2.Status == PromptStatus.Cancel) return SamplerStatus.Cancel; if (prResult2.Value.Equals(mRotation)) { return SamplerStatus.NoChange; } else { mRotation = prResult2.Value; return SamplerStatus.OK; } case 3: JigPromptDistanceOptions prOptions3 = new JigPromptDistanceOptions("\nBlock scale factor:"); prOptions3.BasePoint = mPosition.TransformBy(UCS); prOptions3.UseBasePoint = true; PromptDoubleResult prResult3 = prompts.AcquireDistance(prOptions3); if (prResult3.Status == PromptStatus.Cancel) return SamplerStatus.Cancel; if (prResult3.Value.Equals(mScaleFactor)) { return SamplerStatus.NoChange; } else { mScaleFactor = prResult3.Value; return SamplerStatus.OK; } default: break; } return SamplerStatus.OK; } #endregion #region Point Monitor private static ObjectId pickObjId = ObjectId.Null; private static void Editor_PointMonitor(object sender, PointMonitorEventArgs e) { Document doc = Application.DocumentManager.MdiActiveDocument; Database db = doc.Database; Editor ed = doc.Editor; if (e.Context == null) { return; } FullSubentityPath[] fullEntPath = e.Context.GetPickedEntities(); if (fullEntPath.Length > 0) { try { using (Transaction tr = db.TransactionManager.StartTransaction()) { Entity topLevelEntity = tr.GetObject(fullEntPath.First().GetObjectIds().First(), OpenMode.ForRead) as Entity; Point3d cursorPosition = e.Context.ComputedPoint; if (topLevelEntity is BlockReference blockRef) { BlockTableRecord blockDef = tr.GetObject(blockRef.BlockTableRecord, OpenMode.ForRead) as BlockTableRecord; foreach (ObjectId entId in blockDef) { Entity subEntity = tr.GetObject(entId, OpenMode.ForRead) as Entity; if (IsCursorOnEntity(subEntity, cursorPosition, blockRef, tr)) { pickObjId = subEntity.ObjectId; pickBlockRefId = blockRef.ObjectId; // Store the block reference ObjectId break; } } } else { pickObjId = topLevelEntity.ObjectId; pickBlockRefId = ObjectId.Null; // Reset the block reference ObjectId } tr.Commit(); } } catch (System.Exception ex) { pickObjId = ObjectId.Null; pickBlockRefId = ObjectId.Null; } } else { pickObjId = ObjectId.Null; pickBlockRefId = ObjectId.Null; } } #endregion // Helper method to check if the cursor is on the entity within a block reference private static bool IsCursorOnEntity(Entity entity, Point3d cursorPosition, BlockReference blockRef, Transaction tr) { // Adjust tolerance as needed double tolerance = 0.01; // Transform the cursor position from WCS to the block reference's ECS Matrix3d transform = blockRef.BlockTransform.Inverse(); Point3d transformedCursorPosition = cursorPosition.TransformBy(transform); if (entity is Curve curve) { // Get the closest point on the curve to the transformed cursor position Point3d closestPoint = curve.GetClosestPointTo(transformedCursorPosition, false); // Check if the distance between the closest point and the transformed cursor position is within the tolerance return transformedCursorPosition.DistanceTo(closestPoint) <= tolerance; } else { // For non-curve entities, check if the transformed cursor position is within the entity's geometric extents Extents3d extents = entity.GeometricExtents; return transformedCursorPosition.X >= extents.MinPoint.X - tolerance && transformedCursorPosition.X <= extents.MaxPoint.X + tolerance && transformedCursorPosition.Y >= extents.MinPoint.Y - tolerance && transformedCursorPosition.Y <= extents.MaxPoint.Y + tolerance && transformedCursorPosition.Z >= extents.MinPoint.Z - tolerance && transformedCursorPosition.Z <= extents.MaxPoint.Z + tolerance; } } #region Method to Call public static bool Jig(BlockReference ent) { try { DynamicBlockAlignmentJig jigger = new DynamicBlockAlignmentJig(ent); PromptResult pr; do { pr = CurEditor.Drag(jigger); if (jigger.mCurJigFactorNumber == 1 && jigger.mIsDynamicAlignment && !jigger.mObjectIdToAlignWith.IsNull) jigger.mCurJigFactorNumber++; } while (pr.Status != PromptStatus.Cancel && pr.Status != PromptStatus.Error && jigger.mCurJigFactorNumber++ <= 3); return pr.Status == PromptStatus.OK; } catch { return false; } } #endregion #region Test Command [CommandMethod("DynamicBlockAlignmentJig")] public static void BlockAttributeJig_Method() { Database db = HostApplicationServices.WorkingDatabase; try { string pr = "ROUND_TAKEOFF_SIDE"; using (Transaction tr = db.TransactionManager.StartTransaction()) { BlockTable bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead); if (!bt.Has(pr)) { CurEditor.WriteMessage("\nThe block <{0}> does not exist.", pr); return; } BlockTableRecord btr = tr.GetObject(bt[pr], OpenMode.ForRead) as BlockTableRecord; using (BlockReference ent = new BlockReference(new Point3d(0, 0, 0), btr.ObjectId)) { ent.TransformBy(UCS); BlockTableRecord modelspace = (BlockTableRecord)tr.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForWrite); modelspace.AppendEntity(ent); tr.AddNewlyCreatedDBObject(ent, true); CurEditor.TurnForcedPickOn(); CurEditor.PointMonitor += Editor_PointMonitor; if (DynamicBlockAlignmentJig.Jig(ent)) tr.Commit(); CurEditor.PointMonitor -= Editor_PointMonitor; CurEditor.TurnForcedPickOff(); } } } catch (Autodesk.AutoCAD.Runtime.Exception ex) { CurEditor.WriteMessage(ex.Message); } #endregion }}
Navigation
[0] Message Index
Go to full version