Read a TEXT given the a TEXT closed to it, VB.NET

Read a TEXT given the a TEXT closed to it, VB.NET

Anonymous
Not applicable
2,203 Views
12 Replies
Message 1 of 13

Read a TEXT given the a TEXT closed to it, VB.NET

Anonymous
Not applicable

I want I have a CAD file with DRAWING NUMBER is "HELLO WORLD".  Assume that I do not know what the drawing number is "HELLOW WORLD" and I want to get it programmingly, how do I do it?  With the help of the community members, I now can search for "DRAWING NUMBER", I have a thought on how to get the "HELLOW WORLD" but not how to translate my thought into code 

 

Thought:

- after I have the TEXT DRAWING NUMBER 's location, I will find the next TEXT below it to get "HELLO WORLD"

 

Capture.PNG

 

  Dim doc = Application.DocumentManager.MdiActiveDocument
        Dim db = doc.Database
        Dim ed = doc.Editor

        Using tr = db.TransactionManager.StartTransaction()
            Dim model = DirectCast(tr.GetObject(
                    SymbolUtilityServices.GetBlockModelSpaceId(db), OpenMode.ForRead), BlockTableRecord)
            For Each id As ObjectId In model
                Select Case id.ObjectClass.DxfName
                    Case "TEXT"
                        Dim text = DirectCast(tr.GetObject(id, OpenMode.ForRead), DBText)
                        If text.TextString = "DRAWING NUMBER" Then
                            'Do another loop-search below DRAWING NUMBER
                        End If
                        Exit Select
                End Select

            Next
            tr.Commit()
        End Using

 

0 Likes
Accepted solutions (1)
2,204 Views
12 Replies
Replies (12)
Message 2 of 13

DirtyDanLand
Enthusiast
Enthusiast

is the drawing number in your filename at all?

0 Likes
Message 3 of 13

Anonymous
Not applicable
Unfortunately, the file name does not contain it
0 Likes
Message 4 of 13

_gile
Consultant
Consultant

What are the reliable criteria for finding the text "HELLO WORLD" by knowing the text "DRAWING NUMBER"?
For example, is the vector from one text position to another always the same?

 

 



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

0 Likes
Message 5 of 13

Anonymous
Not applicable

The words "DRAWING NUMBER" and "HELLO WORLD" are always bounded by a box (created by lines). The world "HELLO WORLD" is always below the word "DRAWING NUMBER".

 

Sorry for the typos in the original question, should be "HELLO WORLD" - not ""HELLOW WORLD

0 Likes
Message 6 of 13

_gile
Consultant
Consultant

So, once you found the "DRAWING NUMBER", you'd be able to use the Editor.TraceBoundary() method to get the enclosing box polyline and use it to build a selection set wich would contain both texts.



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

0 Likes
Message 7 of 13

Anonymous
Not applicable

I just want to display the words : "Hello World" after I found the word "Drawing Number". The bounded box (created by lines) is already there.

Bascially, I do not want to create any new object, I just would like to find out what the drawing number is (in this example, it is "HELLO WORLD")

0 Likes
Message 8 of 13

_gile
Consultant
Consultant
Accepted solution

UL2 a écrit :

I just want to display the words : "Hello World" after I found the word "Drawing Number". The bounded box (created by lines) is already there.

Bascially, I do not want to create any new object, I just would like to find out what the drawing number is (in this example, it is "HELLO WORLD")


Creating a boundary with Editor.TraceBoundary just help us to find this boundary from a single point (the "DRAWING NUMBER" text position) and use this boundary to found the other text.

We do not need to add the newly created boudary to the database, we'll dispose it after using.

 

Here's a commented C# example. I let you convert it to VB if you really have to*.

 

 

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

            using (var tr = db.TransactionManager.StartTransaction())
            {
                var model = (BlockTableRecord)tr.GetObject(
                    SymbolUtilityServices.GetBlockModelSpaceId(db), OpenMode.ForRead);
                // iterate through model space
                foreach (ObjectId id in model)
                {
                    // looking for a text
                    if (id.ObjectClass.DxfName == "TEXT")
                    {
                        var text = (DBText)tr.GetObject(id, OpenMode.ForRead);
                        // which text string is "DRAWING NUMBER"
                        if (text.TextString == "DRAWING NUMBER")
                        {
                            // get the transformation matrix from WCS to UCS 
                            // because Editor methods work with UCS coordinates
                            var wcs2ucs = ed.CurrentUserCoordinateSystem.Inverse();

                            // use COM API with late binding to perform a zoom extents
                            // which insure boundary and selection work
                            dynamic acadApp = Application.AcadApplication;
                            acadApp.ZoomExtents();

                            // get the boundary aroun "DRAWING NUMBER" text
                            var boundary = ed.TraceBoundary(text.Position.TransformBy(wcs2ucs), false);

                            // check for boundary validity
                            if (boundary.Count == 1 && boundary[0] is Polyline)
                            {
                                // get the boundary vertices 
                                var polygon = new Point3dCollection();
                                using (var pline = (Polyline)boundary[0])
                                {
                                    for (int i = 0; i < pline.NumberOfVertices; i++)
                                    {
                                        polygon.Add(pline.GetPoint3dAt(i).TransformBy(wcs2ucs));
                                    }
                                }

                                // perform a window polygon selection using the boundary vertices
                                var filter = new SelectionFilter(new[] { new TypedValue(0, "TEXT") });
                                var selection = ed.SelectWindowPolygon(polygon, filter);
                                acadApp.ZoomPrevious();

                                // check for the selection validity
                                if (selection.Status != PromptStatus.OK || selection.Value.Count != 2)
                                    return;

                                // look for the selected text which is not "DRAWING NUMBER"
                                foreach (SelectedObject so in selection.Value)
                                {
                                    if (so.ObjectId != id)
                                    {
                                        var txt = (DBText)tr.GetObject(so.ObjectId, OpenMode.ForRead);
                                        Application.ShowAlertDialog(txt.TextString);
                                    }
                                }
                            }
                            break;
                        }
                    }
                }
                tr.Commit();
            }
        }

 

* If you start learnig .NET, you should learn C# instead of VB because you'll find more help, examples, samples, templates written in C# than in VB.

 



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

Message 9 of 13

Anonymous
Not applicable

😕 I guess I need to study C# instead of VB.NET 🙂 thanks

0 Likes
Message 10 of 13

Anonymous
Not applicable

 

I ran into a problem with a normal CAD file, I received this message

 

Capture.PNG

0 Likes
Message 11 of 13

_gile
Consultant
Consultant

Editor.TraceBoundary() method has some limitation (as the BOUNDARY and HATCH commands).

 

you can try to sole this by replacing the Zoom extents to a zoom around the "DRAWING NUMBER" text which displays the whole boundary but not many much.

 

Here's an example, you can adjust the ZoomScaled scale factor (0.1 here) to suit your needs and uncomment the two ZoomPrevious if you want to reset the zoom previous.

 

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

            using (var tr = db.TransactionManager.StartTransaction())
            {
                var model = (BlockTableRecord)tr.GetObject(
                    SymbolUtilityServices.GetBlockModelSpaceId(db), OpenMode.ForRead);
                // iterate through model space
                foreach (ObjectId id in model)
                {
                    // looking for a text
                    if (id.ObjectClass.DxfName == "TEXT")
                    {
                        var text = (DBText)tr.GetObject(id, OpenMode.ForRead);
                        // which text string is "DRAWING NUMBER"
                        if (text.TextString == "DRAWING NUMBER")
                        {
                            // get the transformation matrix from WCS to UCS 
                            // because Editor methods work with UCS coordinates
                            var wcs2ucs = ed.CurrentUserCoordinateSystem.Inverse();

                            // use COM API with late binding to perform a zoom
                            // which insure boundary and selection work
                            dynamic acadApp = Application.AcadApplication;
                            var exts = text.GeometricExtents;
                            var pt1 = exts.MinPoint.TransformBy(wcs2ucs).ToArray();
                            var pt2 = exts.MaxPoint.TransformBy(wcs2ucs).ToArray();
                            acadApp.ZoomWindow(pt1, pt2);
                            acadApp.ZoomScaled(0.1, 1); // change 0.1 to suit your needs

                            // get the boundary around "DRAWING NUMBER" text
                            var boundary = ed.TraceBoundary(text.Position.TransformBy(wcs2ucs), false);

                            // check for boundary validity
                            if (boundary.Count == 1 && boundary[0] is Polyline)
                            {
                                // get the boundary vertices 
                                var polygon = new Point3dCollection();
                                using (var pline = (Polyline)boundary[0])
                                {
                                    for (int i = 0; i < pline.NumberOfVertices; i++)
                                    {
                                        polygon.Add(pline.GetPoint3dAt(i).TransformBy(wcs2ucs));
                                    }
                                }

                                // perform a window polygon selection using the boundary vertices
                                var filter = new SelectionFilter(new[] { new TypedValue(0, "TEXT") });
                                var selection = ed.SelectWindowPolygon(polygon, filter);

                                // uncomment these lines to reset the previous view
                                //acadApp.ZoomPrevious();
                                //acadApp.ZoomPrevious();

                                // check for the selection validity
                                if (selection.Status != PromptStatus.OK || selection.Value.Count != 2)
                                    return;

                                // look for the selected text which is not "DRAWING NUMBER"
                                foreach (SelectedObject so in selection.Value)
                                {
                                    if (so.ObjectId != id)
                                    {
                                        var txt = (DBText)tr.GetObject(so.ObjectId, OpenMode.ForRead);
                                        Application.ShowAlertDialog(txt.TextString);
                                    }
                                }
                            }
                            break;
                        }
                    }
                }
                tr.Commit();
            }
        }


Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

Message 12 of 13

norman.yuan
Mentor
Mentor

While you can certainly use code to get the result you want (finding a rectangle border that encloses 2 texts of given content, I feel the way of presenting the data (Drawing Number) in AutoCAD drawing itself is flawed and not deserve the effort of complicated code. Why not use a block with attribute, or the drawing number is an attribute of title block? In that case, the code to find the block and update the attribute with whatever drawing number is much more simple and straightforward.

Norman Yuan

Drive CAD With Code

EESignature

Message 13 of 13

Anonymous
Not applicable

I understand but it happens to a number of companies - they might employ some bad CAD standards  and once these bad standards in place, they get carried over and over. To get something changed in big companies, it requires a lot of efforts reasoning, convincing, etc. 

0 Likes