.NET
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

How does AutoCAD's new DIM command work?

8 REPLIES 8
SOLVED
Reply
Message 1 of 9
James.Pascual
1264 Views, 8 Replies

How does AutoCAD's new DIM command work?

 

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.

 

  1. While creating a RotatedDimension all the examples in the AutoCAD SDK and online forums just hard type in the angle for ".rotation" property.  How do I get the user to input the ".rotation" at the same time I'm getting the input for the ".DimLinePoint" like the original "dimlinear" command?  Keeping the dimension ortho to the ucs?
  2. The first question will answer my immediate issue, but my second question is in AutoCAD 2016 how does the new command "DIM" work that it dynamically changes from dimlinear and dimaligned depending on where the user's cursor is before selecting the ".DimLinePoint"?  If someone can point me in the right direction or what to research would be really helpful. This would be a neet feature to use, rather than creating two different commands for linear vs aligned dimensions.

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
        }

    }
    
}
8 REPLIES 8
Message 2 of 9

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
        }
    }

}
Message 3 of 9

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...

Message 4 of 9
_gile
in reply to: James.Pascual


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.

 



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

Message 5 of 9
James.Pascual
in reply to: _gile

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.

Message 6 of 9
_gile
in reply to: James.Pascual

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;
            }
        }


Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

Message 7 of 9
James.Pascual
in reply to: _gile

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.

Message 8 of 9
_gile
in reply to: James.Pascual

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:

  • Editor prompt methods work in current UCS.
  • JigPrompts methods work in WCS.
  • Entities properties are defined in WCS (except for Polyline vertices which are ECS (or OCS) 2D points).

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;
            }
        }

 

 



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

Message 9 of 9
James.Pascual
in reply to: _gile

Awesome thanks! This is exactly what I needed, thanks for saving me the trouble of more research. Changing this to the accepted solution

Can't find what you're looking for? Ask the community or share your knowledge.

Post to forums  

Technology Administrators


Autodesk Design & Make Report