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

Jigging text block along selected polyline.

14 REPLIES 14
SOLVED
Reply
Message 1 of 15
Anonymous
3476 Views, 14 Replies

Jigging text block along selected polyline.

Hi,

 

My requirement is, I will select a polyline on drawing and enter some text, on OK click I have to move the text along the polyline. I am able to jig along polyline and place at selected point along the polyline. But my issue is, the text block rotation is not according to the polyline angle when moving along it. Could you please help me in this.

I used the below link for reference to jig along the polyline.

https://drive-cad-with-code.blogspot.com/2012/03/moving-entity-along-curve.html

Thanks in advance for your suggestions

Tejaswini.

14 REPLIES 14
Message 2 of 15
_gile
in reply to: Anonymous

You should get some inspiration from this one.

 

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


Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

Message 3 of 15
Anonymous
in reply to: _gile

Hi,

Thanks for your solution, But my requirement is moving a block having attribute value as text. I have to move my block along the selected polyline, aligning with angle of polyline. and the block should jig below the polyline, not above the polyline. And I have both the polyline and block entities present with me.

Please help me in this regard.

Thanks in advance.

Tejaswini.

Message 4 of 15
_gile
in reply to: Anonymous

This is NOT your first requirement.

In the first maeesage you said: "I will select a polyline on drawing and enter some text, on OK click I have to move the text along the polyline."

By respect to those who try to help you, please do not change the requirements in the same thread.

From the upper code and this one in another post of yours, you should be able to achieve what you want.



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

Message 5 of 15
_gile
in reply to: Anonymous

Try this.

 

        [CommandMethod("JIGBLOCK")]
        public static void JigBlockAlongPolyline()
        {
            var doc = AcAp.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 the block name: ");
            var stringResult = ed.GetString(stringOptions);
            if (stringResult.Status != PromptStatus.OK)
                return;
            var blockName = stringResult.StringResult;

            using (var tr = db.TransactionManager.StartTransaction())
            {
                var bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead);
                if (!bt.Has(blockName))
                    return;
                var pline = (Polyline)tr.GetObject(entityResult.ObjectId, OpenMode.ForRead);
                var curSpace = (BlockTableRecord)tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite);

                var btrId = bt[blockName];
                var br = new BlockReference(Point3d.Origin, btrId);
                curSpace.AppendEntity(br);
                tr.AddNewlyCreatedDBObject(br, true);

                var btr = (BlockTableRecord)tr.GetObject(btrId, OpenMode.ForRead);
                var attInfos = new Dictionary<AttributeReference, TextInfo>();
                foreach (ObjectId id in btr)
                {
                    if (id.ObjectClass.Name == "AcDbAttributeDefinition")
                    {
                        var attDef = (AttributeDefinition)tr.GetObject(id, OpenMode.ForRead);
                        AttributeReference attRef = new AttributeReference();
                        attRef.SetAttributeFromBlock(attDef, br.BlockTransform);
                        br.AttributeCollection.AppendAttribute(attRef);
                        tr.AddNewlyCreatedDBObject(attRef, true);
                        attInfos.Add(attRef, new TextInfo(attDef));
                    }
                }

                var jig = new BlockJig(br, pline, attInfos);
                var pr = ed.Drag(jig);
                if (pr.Status != PromptStatus.OK)
                    br.Erase();
                tr.Commit();
            }
        }

        class TextInfo
        {
            public Point3d Position { get; }

            public Point3d Alignment { get; }

            public bool IsAligned { get; }

            public double Rotation { get; }

            public TextInfo(DBText text)
            {
                Position = text.Position;
                IsAligned = text.Justify != AttachmentPoint.BaseLeft;
                Alignment = text.AlignmentPoint;
                Rotation = text.Rotation;
            }
        }

        class BlockJig : EntityJig
        {
            BlockReference br;
            Polyline pline;
            Point3d dragPt;
            Plane plane;
            Dictionary<AttributeReference, TextInfo> attInfos;

            public BlockJig(BlockReference br, Polyline pline, Dictionary<AttributeReference, TextInfo> attInfos) : base(br)
            {
                this.br = br;
                this.pline = pline;
                this.attInfos = attInfos;
                plane = new Plane(Point3d.Origin, pline.Normal);
            }

            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);
                br.Position = point;
                br.Rotation = angle;
                foreach (var entry in attInfos)
                {
                    var att = entry.Key;
                    var info = entry.Value;
                    att.Position = info.Position.TransformBy(br.BlockTransform);
                    att.Rotation = info.Rotation + angle;
                    if (info.IsAligned)
                    {
                        att.AlignmentPoint = info.Alignment.TransformBy(br.BlockTransform);
                        att.AdjustAlignment(br.Database);
                    }
                    if (att.IsMTextAttribute)
                    {
                        att.UpdateMTextAttribute();
                    }
                }
                return true;
            }
        }


Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

Message 6 of 15
Anonymous
in reply to: _gile

I am able to jig my block along my polyline, claculate the rotation
also...from the references you gave..but the only thing left is when i
click to leave the moving block it is taking the rotation. While i am
dragging along polyline it is only in horizontal Direction..i am using draw
jig for my requirements...it would be helpful if you suggest something
regarding this.. previous post also i mentioned text block where my text is
an attribute to block.
Thanks in advance for any inputs.
Message 7 of 15
_gile
in reply to: Anonymous

Did you try the last code I provided?

 

 



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

Message 8 of 15
Anonymous
in reply to: _gile

Hi,

 

Your solutions are really very useful. Sorry to confuse you. I am a fresher and very new to this autocad.net api development. The video you provided is the output I require. But the block should move below the polyline and should get placed below the polyline when clicked. the moving block is my block having attributes in it. Checking the solutions you gave , I modified my code and now I am able to jig my block along the polyline. But not below the polyline. I used block instead of dbtext, used drawjig. Taking reference from your code, I developed it. Please don't take it as I am posting for fun or wasting your time.

My requirement in clear description when I run my command is:

  1. it will ask to select a polyline on drawing
  2. on selection , a windows form will be opened, in that I will enter some value in the text box
  3. On OK click of my windows form, below things happen
  4. the value entered in the text box , is added as an attribute to the existing block, by importing it(readdwgfile)
  5. then this block is moved along the selected polyline(below the polyline), with rotation of polylines angle.
  6. on click it will be dropped at that location below the polyline.

This is the clear requirement. Please do understand that I am serious about my task. Sorry again if I confused you . I am attaching the jig code I am using now. In that I am passing my selected entity, rotating entity . As of now my output is, jigging is not completely below the polyline. and while moving the blocks rotation is not aligned with polylines angle. but once I end moving, it is placed with that segment angle in polyline. Hope you understood my requirement and where I am in my task now. Please let me know your suggestions.

 

Thanks in advance.

Message 9 of 15
_gile
in reply to: Anonymous

I cannot understand why you keep on trying to do it with a DrawJig despite the fact all examples I provided use an EntityJig.

As said before, I think jigging a single entity is simpler with an EntityJig. If you absolutely want to use a DrawJig, do it so but I won't follow you on this route.



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

Message 10 of 15
Anonymous
in reply to: _gile

Hi _gile,

 

Thank you so much for your inputs and guidance. Now I implemented using entity jig with the help of your references. Thanks for the patience you have towards my posts. As I am completely new to this, I took time to get through the things. Now when I use the below code, I am able to move only below the selected polyline. When the direction on polyline is changing, the block is inverted. How can I modify the output to the one I attached as screenshot.

 

Please find the screenshot I attached. Need your suggestions and inputs in this regard.

 

Thanks in advance.

Tejaswini

 

Message 11 of 15
_gile
in reply to: Anonymous

You need to PI radians (180°) to the rotation angle when its cosine is negative (i.e. [90°-270°] range)

 

            protected override bool Update()
            {
                var point = pline.GetClosestPointTo(dragPt, false);
                var angle = pline.GetFirstDerivative(point).AngleOnPlane(plane);
                if (Math.Cos(angle) < 0.0)
                    angle += Math.PI;
                br.Position = point;
                br.Rotation = angle;
                foreach (var entry in attInfos)
                {
                    var att = entry.Key;
                    var info = entry.Value;
                    att.Position = info.Position.TransformBy(br.BlockTransform);
                    att.Rotation = info.Rotation + angle;
                    if (info.IsAligned)
                    {
                        att.AlignmentPoint = info.Alignment.TransformBy(br.BlockTransform);
                        att.AdjustAlignment(br.Database);
                    }
                    if (att.IsMTextAttribute)
                    {
                        att.UpdateMTextAttribute();
                    }
                }
                return true;
            }


Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

Message 12 of 15
Anonymous
in reply to: _gile

Hi _gile,

After jigging and placing my block with attributes, I am getting my block position at top right of attribute value and attribute reference position at bottom left of the attribute value. I want to have the block position on top left and attribute position on bottom left ( both at same Y-position, one on top left and one on bottom left).

In the reference code you provided,

 IsAligned = text.Justify != AttachmentPoint.BaseLeft; ----> at this actually my block(which I am using and giving attribute value) justification is base left for attribute definition, if I give it as equal to , I am getting eNotapplication exception at  below code point.

 if (info.IsAligned) {
  att.AlignmentPoint = info.Alignment.TransformBy(br.BlockTransform);-----> in this line
   att.AdjustAlignment(br.Database);}

Can you please help me in this. Please let me know, if you need more information regarding this.

 

Thanks for any kind of help.

Tejaswini.

Message 13 of 15
_gile
in reply to: Anonymous

Sorry, I cannot understand what you're describing.

English is not my first language (and I guess it's not yours either).

But beyond that, there seems to be a lot of confusion between block, attribute reference, attribute definition...



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

Message 14 of 15
Anonymous
in reply to: _gile

Hi _gile,

 

Thanks for your response, actually I understood where I got deviated. I got the issue fixed.  I calculated a perpendicular point to the block position and gave it to the attribute position, and the issue got fixed.

Thanks a lot for the guidance.Smiley Happy

Teja.

Message 15 of 15
quyenpv
in reply to: Anonymous

@_gile I want when I execute Text movement at the command line to display a prompt in the editor like "Please select [+/-] for [O]ffset | [</>] for [R]otation" to be able to adjust the offset (offset) and rotation of the text during movement

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

Post to forums  

Forma Design Contest


Autodesk Design & Make Report