Jigging MTEXT Includes coordinates .. along selected polyline.

Jigging MTEXT Includes coordinates .. along selected polyline.

hosneyalaa
Advisor Advisor
2,220 Views
9 Replies
Message 1 of 10

Jigging MTEXT Includes coordinates .. along selected polyline.

hosneyalaa
Advisor
Advisor

Hello all
Hello ... Mr 

 
Is it possible to modify the code he wrote   Mr 
in the page  forums.autodesk.com/t5/net/jigging-text-block-along-selected-polyline/td-p/8403298
To read as in the attached picture

 

 

 

 [CommandMethod("JIGTEXT")]
        public static void JigTextAlonPpolyline()
        {
            var doc = Application.DocumentManager.MdiActiveDocument;
            var db = doc.Database;
            var ed = doc.Editor;

            var entityOptions = new PromptEntityOptions("\nSelect polyline: ");
            entityOptions.SetRejectMessage("\nmust be a Polyline.");
            entityOptions.AddAllowedClass(typeof(Polyline), true);

            var entityResult = ed.GetEntity(entityOptions);

            if (entityResult.Status != PromptStatus.OK)
                return;

            var stringOptions = new PromptStringOptions("\nEnter a text: ");

            stringOptions.AllowSpaces = true;
            var stringResult = ed.GetString(stringOptions);


            if (stringResult.Status != PromptStatus.OK)
                return;

            using (var tr = db.TransactionManager.StartTransaction())
            {
                var pline = (Polyline)tr.GetObject(entityResult.ObjectId, OpenMode.ForRead);
                using (var text = new DBText())
                {
                    text.SetDatabaseDefaults();
                    text.Normal = pline.Normal;
                    text.Justify = AttachmentPoint.BottomCenter;
                    text.AlignmentPoint = Point3d.Origin;
                    text.TextString = stringResult.StringResult;

                    var jig = new TextJig(text, pline);
                    var result = ed.Drag(jig);


                    if (result.Status == PromptStatus.OK)
                    {
                        var currentSpace = (BlockTableRecord)tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite);
                        currentSpace.AppendEntity(text);
                        tr.AddNewlyCreatedDBObject(text, true);
                    }
                }
                tr.Commit();
            }
        }

        class TextJig : EntityJig
        {
            DBText text;
            Polyline pline;
            Point3d dragPt;
            Plane plane;
            Database db;

            public TextJig(DBText text, Polyline pline)
                : base(text)
            {
                this.text = text;
                this.pline = pline;
                plane = new Plane(Point3d.Origin, pline.Normal);
                db = HostApplicationServices.WorkingDatabase;
            }

            protected override SamplerStatus Sampler(JigPrompts prompts)
            {
                var options = new JigPromptPointOptions("\nSpecicfy insertion point: ");
                options.UserInputControls =
                    UserInputControls.Accept3dCoordinates |
                    UserInputControls.UseBasePointElevation;
                var result = prompts.AcquirePoint(options);
                if (result.Value.IsEqualTo(dragPt))
                    return SamplerStatus.NoChange;
                dragPt = result.Value;
                return SamplerStatus.OK;
            }

            protected override bool Update()
            {
                var point = pline.GetClosestPointTo(dragPt, false);
                var angle = pline.GetFirstDerivative(point).AngleOnPlane(plane);
                text.AlignmentPoint = point;
                text.Rotation = angle;
                text.AdjustAlignment(db);
                return true;
            }
        }

 

 

 

Thank you so much

ezgif.com-gif-maker.gif

 

0 Likes
Accepted solutions (2)
2,221 Views
9 Replies
Replies (9)
Message 2 of 10

_gile
Consultant
Consultant
Accepted solution

Hi,

 

You could start from this:

 

        [CommandMethod("JIGMTEXT")]
        public static void JigMTextAlongPolyline()
        {
            var doc = Application.DocumentManager.MdiActiveDocument;
            var db = doc.Database;
            var ed = doc.Editor;

            var entityOptions = new PromptEntityOptions("\nSelect curve: ");
            entityOptions.SetRejectMessage("\nMust be a Curve.");
            entityOptions.AddAllowedClass(typeof(Curve), false);

            var entityResult = ed.GetEntity(entityOptions);

            if (entityResult.Status != PromptStatus.OK)
                return;
            using (var tr = db.TransactionManager.StartTransaction())
            {
                var curve = (Curve)tr.GetObject(entityResult.ObjectId, OpenMode.ForRead);
                using (var line = new Line() { ColorIndex = 1 })
                using (var mtext = new MText() { ColorIndex = 2 })
                {
                    var curSpace = (BlockTableRecord)tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite);
                    curSpace.AppendEntity(line);
                    tr.AddNewlyCreatedDBObject(line, true);
                    curSpace.AppendEntity(mtext);
                    tr.AddNewlyCreatedDBObject(mtext, true);
                    var jig = new MTextJig(line, mtext, curve);
                    var promptResult = ed.Drag(jig);
                    if (promptResult.Status != PromptStatus.OK)
                    {
                        line.Erase();
                        mtext.Erase();
                    }
                }
                tr.Commit();
            }
        }

        class MTextJig : DrawJig
        {
            Line line;
            MText mtext;
            Curve curve;
            Point3d startPt, endPt;
            public MTextJig(Line line, MText mtext, Curve curve)
            {
                this.line = line;
                this.mtext = mtext;
                this.curve = curve;
            }
            protected override SamplerStatus Sampler(JigPrompts prompts)
            {
                var options = new JigPromptPointOptions("\nSpecicfy insertion point: ");
                options.UserInputControls =
                    UserInputControls.Accept3dCoordinates |
                    UserInputControls.UseBasePointElevation;
                var result = prompts.AcquirePoint(options);
                if (result.Value.IsEqualTo(startPt))
                    return SamplerStatus.NoChange;
                startPt = result.Value;
                endPt = curve.GetClosestPointTo(startPt, false);
                return SamplerStatus.OK;
            }
            protected override bool WorldDraw(WorldDraw draw)
            {
                WorldGeometry geo = draw.Geometry;
                if (geo != null)
                {
                    line.StartPoint = startPt;
                    line.EndPoint = endPt;
                    geo.Draw(line);

                    mtext.Location = line.StartPoint;
                    mtext.Contents = $@"X = {endPt.X:0.00}\PY = {endPt.Y:0.00}";
                    mtext.Attachment = startPt.X < endPt.X ?
                        AttachmentPoint.MiddleRight :
                        AttachmentPoint.MiddleLeft;
                    geo.Draw(mtext);
                }
                return true;
            }
        }


Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

Message 3 of 10

hosneyalaa
Advisor
Advisor

@_gile 

 

Thank you so much
You are the treasure man in the forum

Thank

 

0 Likes
Message 4 of 10

norman.yuan
Mentor
Mentor
Accepted solution

While as @giles has already showed you how to use "DrawJig", instead of "EntityJig" as you originally thought, to achieve what you want, Jig is a framework mainly meant for user to place new or existing entities dynamically with visual hint. In your particular case, where you only want to show some temporary entities visually for information and no new/existing entity to be changed, you could also use Transient Graphics for these visual temporary entities. You handle Editor.PointMonitor event to trace mouse cursor move and update the Transient Graphics. Following is working code, quite straightforward:

 

 

using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.GraphicsInterface;

namespace GetPartialPolyline
{
    public class CurveTracer
    {
        private readonly Document _dwg;
        private readonly Editor _ed;
        private TransientManager _tsManager = TransientManager.CurrentTransientManager;

        private Line _line = null;
        private MText _mtext = null;
        private Curve _curve = null;

        public CurveTracer(Document dwg)
        {
            _dwg = dwg;
            _ed = dwg.Editor;
        }

        public void TraceCurve()
        {
            var curveId = SelectCurve();
            if (curveId.IsNull)
            {
                _ed.WriteMessage("\n*Cancel*\n");
                return;
            }

            using (var trans = _dwg.TransactionManager.StartTransaction())
            {
                _curve = (Curve)trans.GetObject(curveId, OpenMode.ForRead);
                _curve.Highlight();

                try
                {
                    _ed.PointMonitor += Editor_PointMonitor;

                    var opt = new PromptPointOptions(
                        "\nMove mouse cursor along the selected curve entity:");
                    opt.AllowArbitraryInput = true;
                    opt.AllowNone = true;
                    var res = _ed.GetPoint(opt);
                }
                finally
                {
                    _ed.PointMonitor -= Editor_PointMonitor;
                    ClearGhosts();
                }

                _curve.Unhighlight();
                trans.Commit();
            }
        }

        #region private methods

        private ObjectId SelectCurve()
        {
            var opt = new PromptEntityOptions(
                "\nSelect a curve entity:");
            opt.SetRejectMessage(
                "\nInvalid: not a curve entity!");
            opt.AddAllowedClass(typeof(Curve), false);

            var res = _ed.GetEntity(opt);
            return res.Status == PromptStatus.OK ? res.ObjectId : ObjectId.Null;
        }

        private void Editor_PointMonitor(object sender, PointMonitorEventArgs e)
        {
            ClearGhosts();
            var endPt = e.Context.RawPoint;
            var startPt = _curve.GetClosestPointTo(endPt, false);
            CreateGhosts(startPt, endPt);
        }

        private void ClearGhosts()
        {
            if (_line!=null)
            {
                _tsManager.EraseTransient(_line, new IntegerCollection());
                _line.Dispose();
            }

            if (_mtext != null)
            {
                _tsManager.EraseTransient(_mtext, new IntegerCollection());
                _mtext.Dispose();
            }
        }

        private void CreateGhosts(Point3d startPt, Point3d endPt)
        {
            _line = new Line(startPt, endPt);
            _line.ColorIndex = 1;

            var txt= $@"X = {startPt.X:0.00}\PY = {startPt.Y:0.00}";

            _mtext = new MText()
            {
                ColorIndex = 2,
                TextHeight = 200,
                Contents = txt,
                Location = new Point3d(endPt.X + 100, endPt.Y + 100, endPt.Z)
            };
            _mtext.Attachment = endPt.X < startPt.X ?
                        AttachmentPoint.MiddleRight :
                        AttachmentPoint.MiddleLeft;

            _tsManager.AddTransient(
                _line, TransientDrawingMode.DirectTopmost, 128, new IntegerCollection());

            _tsManager.AddTransient(
                _mtext, TransientDrawingMode.DirectTopmost, 128, new IntegerCollection());

        }

        #endregion
    }
}

 

 The command to run it:

 

        [CommandMethod("TraceCurve")]
        public static void RunCurveTracing()
        {
            var dwg = CadApp.DocumentManager.MdiActiveDocument;
            var tracer = new CurveTracer(dwg);
            tracer.TraceCurve();
        }

 

 

In the code, for simplicity, I just set the MText's TextHeight to fixed height. You can certainly set the TextHeight according to  system variable "SCREENSIZE" so that whether user zooms in or out while moving the mouse cursor, the text height would appear the same relative to the screen.

 

Here is the video clip showing the command running:

 

Hope this also helps.
 

Norman Yuan

Drive CAD With Code

EESignature

Message 5 of 10

hosneyalaa
Advisor
Advisor

HI @norman.yuan 

Thank you very much
Nice code and works well
Yes, you helped me
Thank you again

0 Likes
Message 6 of 10

hosneyalaa
Advisor
Advisor

 

Welcome to your master @norman.yuan 
If you allow Mr. @norman.yuan            another request from you
Is it possible to modify your code?
So that the MText appears  AT mouse  when you move the mouse as in the picture

 

Sorry for the disturbance
Thank you very much

 

 

 

ezgif.com-gif-maker.gif

 

0 Likes
Message 7 of 10

norman.yuan
Mentor
Mentor

Sorry, I do not have time to write the code right now. As I mentioned in my previous reply, the MText's TextHeight could be dynamically changed so that it looks the same when user zoom in/out during mouse moving. The same also applies to the MText location: its offset to mouse cursor center should be changed according to zooning in/out. For the simplicity I hard-coded the TextHeight and MText's location (TextHeight = 200 and Location is 100 offset from the cursor in X and Y direction):

 

_mtext = new MText()
            {
                ColorIndex = 2,
                TextHeight = 200,
                Contents = txt,
                Location = new Point3d(endPt.X + 100, endPt.Y + 100, endPt.Z)
            };

 

Say, if you want the text height to be always 5% of the height of current screen view, and always offset from the cursor  also to be 5%, you can get the screen size in the drawing unit from system variable "SCREENSIZE", and then do simple math to calculate the TextHeight and offset for the text location. To make things look more professional, you can challenge yourself to place the MText more properly, for example, while it normally is placed at lower-right side of the cursor, but if the cursor is close to the screen edge and the MText could be partially or entirely off screen. In this case, you could place it at lower-left side, or upper-left/right side. That is you need to calculate if the MText is within the screen view. Again, system variable "SCREENSIZE" is the key information for the calculation.

 

 

 

Norman Yuan

Drive CAD With Code

EESignature

Message 8 of 10

hosneyalaa
Advisor
Advisor

HI

@_gile  AND @norman.yuan 

Is it possible to modify the code?
To show a difference between the coordinates between
The base point and the mouse movement

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.Runtime;

using CadApp = Autodesk.AutoCAD.ApplicationServices.Application;
using Autodesk.AutoCAD.ApplicationServices;

using Autodesk.AutoCAD.GraphicsInterface;

using System.Windows.Media.Imaging;
using System.Drawing;




namespace GetPartialPolyline
{
    public class CurveTracer
    {
        [CommandMethod("JIGMTEXT")]
        public static void JigMTextAlongPolyline()
        {
            var doc = Application.DocumentManager.MdiActiveDocument;
            var db = doc.Database;
            var ed = doc.Editor;

           



            var entityOptions = new PromptPointOptions(System.Environment.NewLine + "\nSpecicfy insertion point: ");
           
                     
            var entityResult = ed.GetPoint(entityOptions);


            if (entityResult.Status != PromptStatus.OK)
                return;

            using (var tr = db.TransactionManager.StartTransaction())
            {

                using (var mtext = new MText() { ColorIndex = 2 })
                {
                    var curSpace = (BlockTableRecord)tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite);

                    curSpace.AppendEntity(mtext);
                    tr.AddNewlyCreatedDBObject(mtext, true);

                    var jig = new MTextJig(mtext);

                    var promptResult = ed.Drag(jig);

                    if (promptResult.Status != PromptStatus.OK)
                    {
                        //line.Erase();
                        //mtext.Erase();
                    }

                }
                tr.Commit();
            }

        }

        class MTextJig : DrawJig
        {
            double  sta, dh;
            MText mtext;
            Point3d entityResult;
            Point3d startPt, endPt;
            public MTextJig(MText mtext)
            {
                //this.line = line;
                 this.mtext = mtext;
                //this.curve = curve;
            }
            protected override SamplerStatus Sampler(JigPrompts prompts)
            {
                var options = new JigPromptPointOptions("\nSpecicfy insertion point: ");

                options.UserInputControls =
                    UserInputControls.Accept3dCoordinates |
                    UserInputControls.UseBasePointElevation;

                var result = prompts.AcquirePoint(options);

                if (result.Value.IsEqualTo(startPt))
                    return SamplerStatus.NoChange;

                    startPt = result.Value;
                    endPt = startPt;
                    sta = startPt.X - endPt.X;
                    dh = (startPt.Y - endPt.Y) + 1;

                return SamplerStatus.OK;
            }
            protected override bool WorldDraw(WorldDraw draw)
            {
                WorldGeometry geo = draw.Geometry;
                if (geo != null)
                {
                    
                    mtext.ColorIndex = 2;
                    mtext.Height = 2;
                    mtext.Location = startPt;
                    mtext.Contents = string.Format("X2-X1: {0}\nY2-Y1: {1}", sta, dh);  
                    mtext.Attachment = startPt.X < endPt.X ?
                        AttachmentPoint.MiddleRight :
                        AttachmentPoint.MiddleLeft;
                    geo.Draw(mtext);
                }
                return true;
            }
        }
    }
}
0 Likes
Message 9 of 10

_gile
Consultant
Consultant

Sorry, I cannot understand what you're trying to achieve:

endPt = startPt;
sta = startPt.X - endPt.X;
dh = (startPt.Y - endPt.Y) + 1;

sta will always be equal to 0.0 and dh equal to 1.0...



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

0 Likes
Message 10 of 10

hosneyalaa
Advisor
Advisor

hi @_gile 

Please see this

 

 

22222222222222222222222222.gif

0 Likes