I've previously only programmed in vlisp and I'm making my transition to .net C#, so a lot of this is new to me. I'm trying to make a basic dimension command which will be similar to the out of the box commands "dimlinear" and "dimaligned."
In vlisp i can just do a (command "dimlinear" pause pause pause) and do entlast to modify the dimension afterwards, in .net I don't have this ability anymore.
So i have two questions, first one is simple, then the second one is more complex.
Here's the code I have so far for my first question. (I used an example from online with a jig and modified from there):
using Autodesk.AutoCAD.ApplicationServices; using Autodesk.AutoCAD.DatabaseServices; using Autodesk.AutoCAD.Runtime; using Autodesk.AutoCAD.EditorInput; using Autodesk.AutoCAD.Geometry; using Autodesk.AutoCAD.Windows; using MgdAcApplication = Autodesk.AutoCAD.ApplicationServices.Application; using MgdAcDocument = Autodesk.AutoCAD.ApplicationServices.Document; using AcWindowsNS = Autodesk.AutoCAD.Windows; [assembly: CommandClass(typeof(Test.MyCommand))] namespace Test { public class MyCommand { [CommandMethod("TestRotJigger")] public static void TestRotJigger() { Editor ed = MgdAcApplication.DocumentManager.MdiActiveDocument.Editor; if (RotDimJigger.Jig()) { ed.WriteMessage("\nA rotated dimension has been successfully jigged and added to the database.\n"); } else { ed.WriteMessage("\nIt failed to jig and add a rotated dimension to the database.\n"); } } public class RotDimJigger : EntityJig { #region Fields public Point3d mLinePoint = new Point3d(); // Factor #1 #endregion #region Constructors public RotDimJigger(RotatedDimension ent) : base(ent) { } #endregion #region Overrides protected override bool Update() { (Entity as RotatedDimension).DimLinePoint = mLinePoint; return true; } protected override SamplerStatus Sampler(JigPrompts prompts) { JigPromptPointOptions prOptions1 = new JigPromptPointOptions("\nDimension line point:"); prOptions1.UserInputControls = UserInputControls.Accept3dCoordinates | UserInputControls.AnyBlankTerminatesInput | UserInputControls.GovernedByUCSDetect | UserInputControls.UseBasePointElevation | UserInputControls.InitialBlankTerminatesInput | UserInputControls.NullResponseAccepted | UserInputControls.GovernedByOrthoMode; PromptPointResult prResult1 = prompts.AcquirePoint(prOptions1); if (prResult1.Status == PromptStatus.Cancel) return SamplerStatus.Cancel; if (prResult1.Value.Equals(mLinePoint)) { return SamplerStatus.NoChange; } else { mLinePoint = prResult1.Value; return SamplerStatus.OK; } } #endregion #region Method to Call public static bool Jig() { try { Editor ed = MgdAcApplication.DocumentManager.MdiActiveDocument.Editor; Database db = HostApplicationServices.WorkingDatabase; Point3dCollection colPts = new Point3dCollection(); PromptPointOptions ppo = new PromptPointOptions(""); // Prompt for the first point PromptPointResult ppr = ed.GetPoint("\nSpecify first point of the dimension"); if (ppr.Status != PromptStatus.OK) return false; colPts.Add(ppr.Value); // Prompt for the second point ppo.Message = "\nSpecify second point of the dimension: "; ppo.UseBasePoint = true; ppo.BasePoint = colPts[0]; ppr = ed.GetPoint(ppo); if (ppr.Status != PromptStatus.OK) return false; colPts.Add(ppr.Value); // Create entity of rotated dimension RotatedDimension ent = new RotatedDimension(0,colPts[0],colPts[1],colPts[0],"<>",db.Dimstyle); RotatedDimension rotDim = new RotatedDimension(); rotDim.DimLinePoint // Create jigger ent.TransformBy(MgdAcApplication.DocumentManager.MdiActiveDocument.Editor.CurrentUserCoordinateSystem); RotDimJigger jigger = new RotDimJigger(ent); PromptResult pr = ed.Drag(jigger); if (pr.Status == PromptStatus.OK) { 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); btr.AppendEntity(jigger.Entity); tr.AddNewlyCreatedDBObject(jigger.Entity, true); tr.Commit(); } } else { ent.Dispose(); return false; } return true; } catch { return false; } } #endregion } } }
Solved! Go to Solution.
Solved by _gile. Go to Solution.
Solved by _gile. Go to Solution.
Just to share, I figured out the solution to my first question. I doubt it's the most efficient way of doing it, but it's the only way i figured out how to make it work.
using Autodesk.AutoCAD.ApplicationServices; using Autodesk.AutoCAD.DatabaseServices; using Autodesk.AutoCAD.Runtime; using Autodesk.AutoCAD.EditorInput; using Autodesk.AutoCAD.Geometry; using Autodesk.AutoCAD.Windows; using System; using System.Diagnostics; using MgdAcApplication = Autodesk.AutoCAD.ApplicationServices.Application; using MgdAcDocument = Autodesk.AutoCAD.ApplicationServices.Document; using AcWindowsNS = Autodesk.AutoCAD.Windows; [assembly: CommandClass(typeof(Extrusion_Design.RotatedDim))] namespace Extrusion_Design { public class RotatedDim { [CommandMethod("TestRotJigger")] public static void TestRotJigger() { Editor ed = MgdAcApplication.DocumentManager.MdiActiveDocument.Editor; if (RotDimJigger.Jig()) { ed.WriteMessage("\nA rotated dimension has been successfully jigged and added to the database.\n"); } else { ed.WriteMessage("\nIt failed to jig and add a rotated dimension to the database.\n"); } } public class RotDimJigger : EntityJig { #region Fields public Point3d mLinePoint = new Point3d(); // Factor #1 public Point3d mMid; // Value assigned during Constructors public double mRound = (90 * Math.PI) / 180; // get radian version of 90° used for rounding #endregion #region Constructors public RotDimJigger(RotatedDimension ent) : base(ent) { // get mid point for reference Point3d start = ent.XLine1Point, end = ent.XLine2Point; LineSegment3d mLine = new LineSegment3d(start, end); mMid = mLine.MidPoint; } #endregion #region Overrides protected override bool Update() { //Matrix3d ucsmtx = mEd.CurrentUserCoordinateSystem; //CoordinateSystem3d ucs = ucsmtx.CoordinateSystem3d; //Plane ucsplane = new Plane(ucs.Origin, ucs.Xaxis, ucs.Yaxis); Plane ucsplane = new Plane(Point3d.Origin, Vector3d.XAxis, Vector3d.YAxis); Vector3d Vec = mLinePoint - mMid; double Rad = Vec.AngleOnPlane(ucsplane); double Ang = (Rad * 180) / Math.PI; double rndAng = Math.Round(Ang / 90) * 90; Rad = (rndAng * Math.PI) / 180; Debug.WriteLine("mVec = " + Vec + " mAng = " + Ang + " mLinePoint = " + mLinePoint); (Entity as RotatedDimension).DimLinePoint = mLinePoint; // (Entity as RotatedDimension).Rotation = Ang - mRound; (Entity as RotatedDimension).Rotation = Rad - mRound; return true; } protected override SamplerStatus Sampler(JigPrompts prompts) { JigPromptPointOptions prOptions1 = new JigPromptPointOptions("\nDimension line point:"); prOptions1.UserInputControls = UserInputControls.Accept3dCoordinates | UserInputControls.AnyBlankTerminatesInput | UserInputControls.GovernedByUCSDetect | UserInputControls.UseBasePointElevation | UserInputControls.InitialBlankTerminatesInput | UserInputControls.NullResponseAccepted; PromptPointResult prResult1 = prompts.AcquirePoint(prOptions1); if (prResult1.Status == PromptStatus.Cancel) return SamplerStatus.Cancel; if (prResult1.Value.DistanceTo(mLinePoint) < Tolerance.Global.EqualPoint) { return SamplerStatus.NoChange; } else { mLinePoint = prResult1.Value; return SamplerStatus.OK; } } #endregion #region Method to Call public static bool Jig() { try { Editor ed = MgdAcApplication.DocumentManager.MdiActiveDocument.Editor; Database db = HostApplicationServices.WorkingDatabase; Point3dCollection colPts = new Point3dCollection(); PromptPointOptions ppo = new PromptPointOptions(""); // Prompt for the first point PromptPointResult ppr = ed.GetPoint("\nSpecify first point of the dimension"); if (ppr.Status != PromptStatus.OK) return false; colPts.Add(ppr.Value); // Prompt for the second point ppo.Message = "\nSpecify second point of the dimension: "; ppo.UseBasePoint = true; ppo.BasePoint = colPts[0]; ppr = ed.GetPoint(ppo); if (ppr.Status != PromptStatus.OK) return false; colPts.Add(ppr.Value); // Create entity of rotated dimension RotatedDimension ent = new RotatedDimension(); // 0,colPts[0],colPts[1],colPts[0],"<>",db.Dimstyle ent.Rotation = 0; // Note this is in radians ent.XLine1Point = colPts[0]; ent.XLine2Point = colPts[1]; ent.DimLinePoint = colPts[1]; ent.DimensionStyle = db.DimStyleTableId; ent.Annotative = AnnotativeStates.True; // Create jigger ent.TransformBy(MgdAcApplication.DocumentManager.MdiActiveDocument.Editor.CurrentUserCoordinateSystem); RotDimJigger jigger = new RotDimJigger(ent); PromptResult pr = ed.Drag(jigger); if (pr.Status == PromptStatus.OK) { 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); btr.AppendEntity(jigger.Entity); tr.AddNewlyCreatedDBObject(jigger.Entity, true); tr.Commit(); } } else { ent.Dispose(); return false; } return true; } catch { return false; } } #endregion } } }
Okay, just tested this some more and it only works if the user is on the world ucs, if the user changes his UCS to something else it doesn't produce the desired effect. Back to the drawing board...
James.Pascual a écrit :
I've previously only programmed in vlisp and I'm making my transition to .net C#, so a lot of this is new to me. I'm trying to make a basic dimension command which will be similar to the out of the box commands "dimlinear" and "dimaligned."
In vlisp i can just do a (command "dimlinear" pause pause pause) and do entlast to modify the dimension afterwards, in .net I don't have this ability anymore.
It can also be done with .NET:
[CommandMethod("DIMLIN")] public async void DimLinearCmd() { var doc = Application.DocumentManager.MdiActiveDocument; var db = doc.Database; var ed = doc.Editor; await ed.CommandAsync("_dimlinear", Editor.PauseToken, Editor.PauseToken, Editor.PauseToken); var lastEntId = Autodesk.AutoCAD.Internal.Utils.EntLast(); if (lastEntId.ObjectClass != RXObject.GetClass(typeof(RotatedDimension))) return; using (var tr = db.TransactionManager.StartTransaction()) { var dim = (RotatedDimension)tr.GetObject(lastEntId, OpenMode.ForWrite); dim.ColorIndex = 30; tr.Commit(); } }
But it looks like you've got a good understanding of some .NET features, keep on learning this way.
Thanks Gilles! That code looks a hell of a lot simpler than what I have, it's good to know what options I have. I thought if I wanted to pushing commands to AutoCAD, I have to use COMS Interop and the command only runs after the .net assembly is finished. So this "await" and "async" is a good tip, so thanks.
I couldn't get your code to work until I realized I was missing the "async" when declaring the function.
About dealing with ucs and rotated dimension jig, maybe you can get some inspiration from this:
[CommandMethod("DIMJIG")] public void RotatedDimJigCmd() { var doc = Application.DocumentManager.MdiActiveDocument; var db = doc.Database; var ed = doc.Editor; var ptOpts = new PromptPointOptions("\nSpecify first extension line origin: "); var ptRes = ed.GetPoint(ptOpts); if (ptRes.Status != PromptStatus.OK) return; var pt1 = ptRes.Value; ptOpts.Message = "\nSpecify second extension line origin: "; ptOpts.BasePoint = pt1; ptOpts.UseBasePoint = true; ptRes = ed.GetPoint(ptOpts); if (ptRes.Status != PromptStatus.OK) return; var pt2 = ptRes.Value; using (var tr = db.TransactionManager.StartTransaction()) using(var dim = new RotatedDimension()) { dim.XLine1Point = pt1; dim.XLine2Point = pt2; dim.DimLinePoint = pt1; dim.TransformBy(ed.CurrentUserCoordinateSystem); dim.HorizontalRotation = Math.PI * 2.0 - dim.Rotation; var ucs = ed.CurrentUserCoordinateSystem.Inverse(); var jig = new RotatedDimJig(dim, pt1.X, pt2.X, ucs); var result = ed.Drag(jig); if(result.Status == PromptStatus.OK) { var space = (BlockTableRecord)tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite); space.AppendEntity(dim); tr.AddNewlyCreatedDBObject(dim, true); } tr.Commit(); } } class RotatedDimJig : EntityJig { RotatedDimension dim; Matrix3d ucs; Point3d dragPt; double minX, maxX, rotation; public RotatedDimJig(RotatedDimension dim, double x1, double x2, Matrix3d ucs) : base(dim) { this.dim = dim; rotation = dim.Rotation; minX = Math.Min(x1, x2); maxX = Math.Max(x1, x2); this.ucs = ucs; } protected override SamplerStatus Sampler(JigPrompts prompts) { var opts = new JigPromptPointOptions("\nSpecify dimension line location: "); opts.UserInputControls = UserInputControls.Accept3dCoordinates; var result = prompts.AcquirePoint(opts); if (result.Value.IsEqualTo(dragPt)) return SamplerStatus.NoChange; dragPt = result.Value; return SamplerStatus.OK; } protected override bool Update() { double x = dragPt.TransformBy(ucs).X; if (maxX < x || x < minX) dim.Rotation = rotation + Math.PI * 0.5; else dim.Rotation = rotation; dim.DimLinePoint = dragPt; return true; } }
While testing your code the dimension stays ortho in only 1 axis, but I do see how it will work of the user UCS. Like you said, I will use this to learn how that's done. Thanks for more inspiration code to pick apart, since I do want to learn how to do this without relying on pushing commandline commands to AutoCAD.
Hi,
It was late here when I posted the upper snippet.
I'm not sure to understand what you mean with "the dimension stays ortho in only 1axis" but from the some tests I did the lower code seems to work as the native command.
Anyway, the main things to remember when playing with jigs and UCS are:
Here, to manage RotatedDimension.Rotation we have to compare UCS coordinates within the Jig class which requires some point transformations.
[CommandMethod("DIMJIG")] public void RotatedDimJigCmd() { var doc = Application.DocumentManager.MdiActiveDocument; var db = doc.Database; var ed = doc.Editor; var ptOpts = new PromptPointOptions("\nSpecify first extension line origin: "); var ptRes = ed.GetPoint(ptOpts); if (ptRes.Status != PromptStatus.OK) return; var pt1 = ptRes.Value; // UCS coordinates ptOpts.Message = "\nSpecify second extension line origin: "; ptOpts.BasePoint = pt1; ptOpts.UseBasePoint = true; ptRes = ed.GetPoint(ptOpts); if (ptRes.Status != PromptStatus.OK) return; var pt2 = ptRes.Value; // UCS coordinates // tranformation matrix from UCS to WCS var ucs2wcs = ed.CurrentUserCoordinateSystem; using (var tr = db.TransactionManager.StartTransaction()) using (var dim = new RotatedDimension()) { dim.XLine1Point = pt1; // UCS coordinates dim.XLine2Point = pt2; // UCS coordinates dim.DimLinePoint = pt1; // UCS coordinates dim.TransformBy(ucs2wcs); // transformation from UCS to WCS dim.HorizontalRotation = Math.PI * 2.0 - dim.Rotation; var jig = new RotatedDimJig(dim, pt1, pt2, ucs2wcs); var result = ed.Drag(jig); if (result.Status == PromptStatus.OK) { var space = (BlockTableRecord)tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite); space.AppendEntity(dim); tr.AddNewlyCreatedDBObject(dim, true); } tr.Commit(); } } class RotatedDimJig : EntityJig { RotatedDimension dim; Matrix3d wcs2ucs; Point3d dragPt; double minX, maxX, minY, maxY, rotation; public RotatedDimJig(RotatedDimension dim, Point3d pt1, Point3d pt2, Matrix3d ucs2wcs) : base(dim) { this.dim = dim; rotation = dim.Rotation; minX = Math.Min(pt1.X, pt2.X); // UCS coordinates maxX = Math.Max(pt1.X, pt2.X); // UCS coordinates minY = Math.Min(pt1.Y, pt2.Y); // UCS coordinates maxY = Math.Max(pt1.Y, pt2.Y); // UCS coordinates wcs2ucs = ucs2wcs.Inverse(); // transformation matrix from WCS to UCS } protected override SamplerStatus Sampler(JigPrompts prompts) { var opts = new JigPromptPointOptions("\nSpecify dimension line location: "); opts.UserInputControls = UserInputControls.Accept3dCoordinates; var result = prompts.AcquirePoint(opts); // WCS coordinates if (result.Value.IsEqualTo(dragPt)) return SamplerStatus.NoChange; dragPt = result.Value; // WCS coordinates return SamplerStatus.OK; } protected override bool Update() { Point3d pt = dragPt.TransformBy(wcs2ucs); // ucs coordinates double x = pt.X, // UCS coordinate y = pt.Y; // UCS coordinate // UCS coordinates comparison if (dim.Rotation == rotation) { if ((minY < y && y < maxY) && (x < minX || maxX < x)) dim.Rotation += Math.PI * 0.5; } else { if ((minX < x && x < maxX) && (y < minY || maxY < y)) dim.Rotation -= Math.PI * 0.5; } dim.DimLinePoint = dragPt; // WCS coordinates return true; } }
Can't find what you're looking for? Ask the community or share your knowledge.