Is it possible to get the nearest text ?

Is it possible to get the nearest text ?

Anonymous
Not applicable
2,054 Views
7 Replies
Message 1 of 8

Is it possible to get the nearest text ?

Anonymous
Not applicable

When I specify a start point and end point of line, how to get text on the top side or left side of the line ?

 

Any help would be greatly appreciated.

 

line.png

0 Likes
Accepted solutions (2)
2,055 Views
7 Replies
Replies (7)
Message 2 of 8

SENL1362
Advisor
Advisor

it's not too difficult but:

1. what did you do so far;

2. what restrictions, i.e. angle of text== angle of line, what layer, what text specs, what is the max distance, etc.

 

 

0 Likes
Message 3 of 8

Anonymous
Not applicable

Thanks for your reply.

 

Assume that we don't consider the layer and text specs , but angle of text== angle of line,  the max distance is 100mm, how to get the nearest text ?

0 Likes
Message 4 of 8

TiStars
Advisor
Advisor

I usually will get entities by loop.

Blow is a part of my code for your reference.  I was going to get nearest line to a Text.

 

if (textId.ObjectClass.IsDerivedFrom(textClass))
                {
                    DBText text = (DBText)tr.GetObject(textId, OpenMode.ForRead);
                    var owner = (BlockTableRecord)tr.GetObject(text.OwnerId, OpenMode.ForRead);

                    foreach (ObjectId id in owner)
                    {
                        if (id.ObjectClass.IsDerivedFrom(lineClass))
                        {
                            Line tmpline = (Line)tr.GetObject(id, OpenMode.ForRead);
                            double d = text.Position.DistanceTo(tmpline.GetClosestPointTo(text.Position, false));
                            if (d < distance)
                            {
                                distance = d;
                                line = tmpline;
                            }
                        }
                        
                    }
                    
                }

天涯海角的山姆


您认为此帖子是否有用?欢迎为此帖点赞。

您的问题是否已得到解答?请点击“接受解答”按钮。


EESignature



0 Likes
Message 5 of 8

hgasty1001
Advisor
Advisor

Hi,

 

I understand that the OP need to get the closest text to a given line, and your code is getting the closest line to  given text. You also should note that a crossing line from the middle of the given line would fail if the crossing line pass trough the space between letters.

 

A better approach would be to detect the text using a crossing window or crossing polygon: you need to obtain the end points of the line, then use them to get the angle of the line, now create four new points aiming 90°/180° (pi/2, pi) from the angle of the line (using polar coordinates), with those points create a crossing polygon with the points aiming 90°, add a filter to the proper object  and attributes of the text (layer, color, etc) and check if the selection contains the object, if not, repeat with the points aiming 180°.

 

Gasty.

Message 6 of 8

_gile
Consultant
Consultant
Accepted solution

Hi,

 

Inspired by @hgasty1001 method, you could start from this:

 

        [CommandMethod("TEST", CommandFlags.Redraw)]
        public void Test()
        {
            var doc = Application.DocumentManager.MdiActiveDocument;
            var db = doc.Database;
            var ed = doc.Editor;

            var peo = new PromptEntityOptions("\nSelect line: ");
            peo.SetRejectMessage("\nSelected object is not a Line.");
            peo.AddAllowedClass(typeof(Line), true);
            var per = ed.GetEntity(peo);
            if (per.Status != PromptStatus.OK)
                return;

            var wcs2ucs = ed.CurrentUserCoordinateSystem.Inverse();
            dynamic line = per.ObjectId;
            Point3d startPoint = line.StartPoint.TransformBy (wcs2ucs);
            Point3d endPoint = line.EndPoint.TransformBy(wcs2ucs);

            Vector3d vector;
            if (Math.Abs(startPoint.X - endPoint.X) < 1e-9)
            {
                vector = new Vector3d(-100.0, 0.0, 0.0);
            }
            else if (Math.Abs(startPoint.Y - endPoint.Y) < 1e-9)
            {
                vector = new Vector3d(0.0, 100.0, 0.0);
            }
            else
            {
                ed.WriteMessage("\nThe selected line is neither Horizontal nor vertical.");
                return;
            }

            var filter = new SelectionFilter(new[] { new TypedValue(0, "TEXT") });
            Point3dCollection polygon = new Point3dCollection();
            polygon.Add(startPoint);
            polygon.Add(startPoint + vector);
            polygon.Add(endPoint + vector);
            polygon.Add(endPoint);
            var psr = ed.SelectCrossingPolygon(polygon, filter);
            if (psr.Status == PromptStatus.OK)
                ed.SetImpliedSelection(psr.Value);
            else
                ed.WriteMessage("\nNone text found.");
        }


Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

Message 7 of 8

SENL1362
Advisor
Advisor
Accepted solution

A slightly more general approach, any Line Angle will do.

 

       [CommandMethod("TestTextNearLine", CommandFlags.Redraw)]
        public static void TestTextNearLine()
        {
            Document doc = null;
            Editor ed = null;
            Database db = null;

            double maxTxtDist = 100;
            double maxAngDiff = Math.PI / 180;

            try
            {
                doc = AcadApp.DocumentManager.MdiActiveDocument;
                ed = doc.Editor;
                db = doc.Database;

                var peo = new PromptEntityOptions("\nSelect Line: ");
                peo.SetRejectMessage("\nLines only");
                peo.AddAllowedClass(typeof(Line), false);
                peo.AllowObjectOnLockedLayer = true;
                peo.AllowNone = true;
                var per = ed.GetEntity(peo);
                if (per.Status != PromptStatus.OK)
                {
                    return;
                }

                using (var tr = db.TransactionManager.StartTransaction())
                {
                    var ln = tr.GetObject(per.ObjectId, OpenMode.ForRead) as Line;
                    var angle = ln.Angle;
                    var btr = (BlockTableRecord)tr.GetObject(ln.OwnerId, OpenMode.ForRead);


                    var dxRange = -maxTxtDist * Math.Sin(angle);
                    var dyRange= +maxTxtDist * Math.Cos(angle);

                    var selRange = new Point3dCollection();
                    selRange.Add(ln.StartPoint);
                    selRange.Add(ln.EndPoint);
                    selRange.Add(new Point3d(ln.EndPoint.X + dxRange, ln.EndPoint.Y + dyRange, ln.StartPoint.Z));
                    selRange.Add(new Point3d(ln.StartPoint.X + dxRange, ln.StartPoint.Y + dyRange, ln.StartPoint.Z));

                    //Just for debugging purposes
                    {
                        var pl = new Polyline();
                        for (int i = 0; i < selRange.Count; i++)
                        {
                            pl.AddVertexAt(i, new Point2d(selRange[i].X, selRange[i].Y), 0, 0, 0);
                        }
                        pl.Closed = true;
                        btr.UpgradeOpen();
                        btr.AppendEntity(pl);
                        tr.AddNewlyCreatedDBObject(pl, true);
                    }

                    var filter = new SelectionFilter(new[] { new TypedValue(0, "TEXT") });
                    var psr = ed.SelectWindowPolygon(selRange, filter);
                    //var psr = ed.SelectCrossingPolygon(selRange, filter);
                    if (psr.Status == PromptStatus.OK)
                    {
                        var selTxtIds = psr.Value.GetObjectIds().ToList();

                        //Skip Text when Angle <> Line Angle within ONE degree
                        foreach (var id in selTxtIds.ToList())
                        {
                            //Find text where Angle==Line Angle (or +180 degrees within ONE degree
                            var txt = tr.GetObject(id, OpenMode.ForRead) as DBText;
                            if (txt != null && !string.IsNullOrWhiteSpace(txt.TextString))
                            {
                                if (Math.Abs(txt.Rotation - ln.Angle) > maxAngDiff && Math.Abs(txt.Rotation + Math.PI - ln.Angle) * 180.0 / Math.PI > maxAngDiff)
                                {
                                    selTxtIds.Remove(id);
                                }
                            }
                        }
                        ed.SetImpliedSelection(selTxtIds.ToArray());
                    }
                    tr.Commit();
                }
            }
            catch (System.Exception ex)
            {
                ed?.WriteMessage($"\n{ex.Message}");
            }
        }

 

textnearline_0.pngtextnearline.png

Message 8 of 8

TiStars
Advisor
Advisor
Thanks Gasty, I have learnt something.

天涯海角的山姆


您认为此帖子是否有用?欢迎为此帖点赞。

您的问题是否已得到解答?请点击“接受解答”按钮。


EESignature



0 Likes