xdata/reactor length of lines

xdata/reactor length of lines

enescil
Contributor Contributor
3,874 Views
24 Replies
Message 1 of 25

xdata/reactor length of lines

enescil
Contributor
Contributor

Dears,

I have a lot of lines that I need a length, like in attached file. At this moment I do it with a vba  that put fields in all lines.

The problems:

1) fields makes drawing slow to regen or after I modify line.

2) fields not follow lines slopes and position, if I stretch or move one end point of line. Text must be in middle of line.

 

So I thinking use reactors .

I tried reactor but I don't have much experience in lisp and I am having problems with persistent reactors, after I close file and open again, load lisp. Reactor not continue persistent. 

This is a test that I tried. Works only for one line.

 

 

(defun print-align-text ( owner reactor lst / sp ep a d )

(setq sp (vlax-curve-getstartpoint line1))
(setq ep (vlax-curve-getendpoint line1))
(setq a (angle sp ep))
(setq d (distance sp ep))
'(vla-put-textstring mytext (rtos d 2 0))
(vla-put-alignment mytext acalignmentbottomcenter)
(vla-put-textalignmentpoint mytext (vlax-3d-point (mapcar '/ (mapcar '+ sp ep) (list 2.0 2.0 2.0))))
(vla-put-rotation mytext a)

 

)

(defun c:pp ( / sp ep a d )
(vl-load-com)


(setq line1 (car (entsel "\nSelect line: ")))
(setq texto(car (entsel "\nSelect text: ")))


(setq sp (cdr (assoc 10 (entget line1))))
(setq ep (cdr (assoc 11 (entget line1))))

(setq line1 (vlax-ename->vla-object line1))
(setq mytext(vlax-ename->vla-object texto))

(setq a (angle sp ep))
(setq d (distance sp ep))

 


(vla-put-alignment mytext acalignmentbottomcenter)
(vla-put-textalignmentpoint mytext (vlax-3d-point (mapcar '/ (mapcar '+ sp ep) (list 2.0 2.0 2.0))))
(vla-put-rotation mytext a)

(setq myreactor (vlr-object-reactor (list line1) "Object Reactor : " '((:vlr-modified . print-align-text))))


(vlr-pers myreactor)

(princ)
)

 

 

I have read that is better store data using XData. But I have no idea to start.

 

In VBA I tried construct class module withevents, without any sucess.

My knowledge in VBA is basic.

 

Anyone could you give some directions to study best way to do it?

I can't use any kind of dimension.

Thanks

Claudio

 

 

 

0 Likes
Accepted solutions (1)
3,875 Views
24 Replies
Replies (24)
Message 21 of 25

truss_85
Advocate
Advocate

Unfortunatly I could not think of any other. But overall we can run faster. I am currious about in the first place how did you add fields ? Manually or via VBA if it is VBA I think we can run program at least 2 times faster. If it is not, I mean you add fields manually, you can easly do it with vba I can help with that too.

0 Likes
Message 22 of 25

enescil
Contributor
Contributor

Truss,

I will finish my code and test.

Thanks.

 

Do you know when autodesk will remove VBA? My code has thousands lines and I will need to start to study .NET.

I am a civil engineer (bridge designer) and at free times I develop vba tools to improve drawings/drafters performance.

 

 

This is how I place fields, this is a part of code.

 

 

For Each objent In objmodel        ' for each line in layer 5
    With objent
        If .Layer = "5" Or .Layer = "C-5" Then layerferro = 1
    
        If StrComp(.EntityName, "AcDbline", 1) = 0 And layerferro = 1 And .Layer = "5" Then
                        
            TextId = objent.objectID
            text = "%<\AcObjProp Object(%<\_ObjId " & TextId & ">%).Length \f ""%lu2%pr0%ps[,]"">%"
            

            a = objent.StartPoint ' this is to align text field to line, constraint was not good solution
            b = objent.EndPoint
            
            X = (a(0) + b(0)) / 2
            y = (a(1) + b(1)) / 2
            If b(0) - a(0) = 0 Then angulo = 3.14159265358979 / 2 Else angulo = Atn((b(1) - a(1)) / (b(0) - a(0)))
            
            Call createpoint(X, y, 0)
            Set te = doc.ModelSpace.AddText(text, pt, alttexto)
            te.Alignment = acAlignmentBottomCenter: te.TextAlignmentPoint = pt: te.Rotation = angulo
            te.Layer = 3
            If temctexto = 1 Then
                te.StyleName = "ARIAL"
                te.Layer = "C-TEXTO"
            End If
            te.Update

.....

 

 

 

0 Likes
Message 23 of 25

truss_85
Advocate
Advocate
Accepted solution

I really do not know when does it happen. Every year I waited to autodesk did not support any more. Converting to .NET is important because vba runs very slow. Sometimes it can not be bearable.

 

I see we are colleagues. When ever you need help ?

 

Kind Regards...

0 Likes
Message 24 of 25

enescil
Contributor
Contributor
Yes, sure. Thanks.
0 Likes
Message 25 of 25

Hallex
Advisor
Advisor

Try this command, just change layer names on whatever you need

    //__________________________C#_________________________// 

      // Add fields to lines in the model space
        // The following layers: Layer1,Layer2,Text_Layer might be exist before
        [CommandMethod("adf", CommandFlags.UsePickSet | CommandFlags.Redraw)]
        public void testAddFieldsToLines()
        {

            Document doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument;

            Editor ed = doc.Editor;

            Database db = doc.Database;

            BlockTableRecord btr;

            MText txtObj;
            bool result = true;
            string fieldText = string.Empty;
            Point3d spt;
            Point3d ept;
            double ang = 0;
            double x = 0;
            double y = 0;
            Point3d pt;
            ObjectId txtStyleId = ObjectId.Null;

            doc.TransactionManager.EnableGraphicsFlush(true);

            try
            {
                Transaction tr = db.TransactionManager.StartTransaction();

                using (tr)
                {
                    BlockTable bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead);

                    btr = (BlockTableRecord)tr.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForWrite);

                    TextStyleTable txttb = (TextStyleTable)tr.GetObject(db.TextStyleTableId, OpenMode.ForRead);

                    if (txttb.Has("ARIAL"))
                    {

                        txtStyleId = txttb["ARIAL"];
                    }
                    else
                    {
                        txtStyleId = txttb["Standard"];
                    }

                    TypedValue[] tpv = new TypedValue[] {
                        new TypedValue(0, "line"), 
                        new TypedValue(8, "Layer1,Layer2"),// the layers, you interesting in, separated by commas
                        new TypedValue(410, "Model") };

                    SelectionFilter filt = new SelectionFilter(tpv);

                    PromptSelectionResult resSel = ed.SelectAll(filt);

                    if (resSel.Status != PromptStatus.OK)
                    {
                        Autodesk.AutoCAD.ApplicationServices.Application.ShowAlertDialog("Nothing selected");

                        return;
                    }

                    SelectionSet selSet = resSel.Value;

                    foreach (SelectedObject selObj in selSet)
                    {
                        ObjectId id = selObj.ObjectId;

                        Entity ent = (Entity)tr.GetObject(id, OpenMode.ForRead);

                        if (ent != null)
                        {

                            Line ln = (Line)ent as Line;

                            string oidStr = id.ToString().Trim(new char[] { '(', ')' });

                            fieldText = "%<\\AcObjProp Object(%<\\_ObjId " + oidStr + ">%).Length \\f \"%lu2%pr2%ps[,]\">%";// metric, precision 2 decimals

                            spt = ln.StartPoint;

                            ept = ln.EndPoint;

                            x = (spt.X + ept.X) / 2;

                            y = (spt.Y + ept.Y) / 2;

                            if (ept.X - spt.X == 0)
                            {
                                ang = Math.PI / 2;
                            }
                            else
                            {
                                ang = Math.Atan((ept.Y - spt.Y) / (ept.X - spt.X));
                            }

                            pt = new Point3d(x, y, 0.0);

                            txtObj = new MText();

                            txtObj.SetDatabaseDefaults();

                            txtObj.Location = pt;

                            txtObj.Height = 3.0;

                            txtObj.Contents = "Length:";// dummy text

                            txtObj.Rotation = ang;

                            txtObj.TextStyleId = txtStyleId;

                            txtObj.Layer = "Text_Layer";// Text_Layer might be exist

                            txtObj.Attachment = AttachmentPoint.BottomCenter;

                            txtObj.SetAttachmentMovingLocation(txtObj.Attachment);

                            btr.AppendEntity(txtObj);

                            tr.AddNewlyCreatedDBObject(txtObj, true);

                            tr.TransactionManager.QueueForGraphicsFlush();

                            Autodesk.AutoCAD.DatabaseServices.Field fileldObj = new Autodesk.AutoCAD.DatabaseServices.Field();

                            fileldObj.EvaluationOption = FieldEvaluationOptions.Automatic;

                            fileldObj.Evaluate((int)(FieldEvaluationOptions.Automatic), db);

                            fileldObj.SetFieldCode(fieldText);

                            txtObj.SetField(fileldObj);

                            tr.AddNewlyCreatedDBObject(fileldObj, true);

                            ed.WriteMessage("Point\t{0}", txtObj.ObjectId);

                            tr.TransactionManager.QueueForGraphicsFlush();

                            txtObj.Width = txtObj.ActualWidth;

                        }
                    }
                    doc.TransactionManager.FlushGraphics();

                    tr.Commit();

                    ed.Regen();
                }

            }

            catch (Autodesk.AutoCAD.Runtime.Exception ex)
            {
                result = false;

                Autodesk.AutoCAD.ApplicationServices.Application.ShowAlertDialog(ex.Message + "\n" + ex.StackTrace);
            }
            finally
            {

                if (result)
                {
                    ed.WriteMessage("\nThe command executed successfully\n");
                }
            }
        }

''__________________________VB.NET__________________________''

        ' Add fields to lines in the model space
        ' The following layers: Layer1,Layer2,Text_Layer might be exist before
        <CommandMethod("adf", CommandFlags.UsePickSet Or CommandFlags.Redraw)> _
        Public Sub testAddFieldsToLines()

            Dim doc As Document = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument

            Dim ed As Editor = doc.Editor

            Dim db As Database = doc.Database

            Dim btr As BlockTableRecord

            Dim txtObj As MText
            Dim result As Boolean = True
            Dim fieldText As String = String.Empty
            Dim spt As Point3d
            Dim ept As Point3d
            Dim ang As Double = 0
            Dim x As Double = 0
            Dim y As Double = 0
            Dim pt As Point3d
            Dim txtStyleId As ObjectId = ObjectId.Null

            doc.TransactionManager.EnableGraphicsFlush(True)

            Try
                Dim tr As Transaction = db.TransactionManager.StartTransaction()

                Using tr
                    Dim bt As BlockTable = DirectCast(tr.GetObject(db.BlockTableId, OpenMode.ForRead), BlockTable)

                    btr = DirectCast(tr.GetObject(bt(BlockTableRecord.ModelSpace), OpenMode.ForWrite), BlockTableRecord)

                    Dim txttb As TextStyleTable = DirectCast(tr.GetObject(db.TextStyleTableId, OpenMode.ForRead), TextStyleTable)

                    If txttb.Has("ARIAL") Then

                        txtStyleId = txttb("ARIAL")
                    Else
                        txtStyleId = txttb("Standard")
                    End If

                    ' the layers, you interesting in, separated by commas
                    Dim tpv As TypedValue() = New TypedValue() {New TypedValue(0, "line"), New TypedValue(8, "Layer1,Layer2"), New TypedValue(410, "Model")}

                    Dim filt As New SelectionFilter(tpv)

                    Dim resSel As PromptSelectionResult = ed.SelectAll(filt)

                    If resSel.Status <> PromptStatus.OK Then
                        Autodesk.AutoCAD.ApplicationServices.Application.ShowAlertDialog("Nothing selected")

                        Return
                    End If

                    Dim selSet As SelectionSet = resSel.Value

                    For Each selObj As SelectedObject In selSet
                        Dim id As ObjectId = selObj.ObjectId

                        Dim ent As Entity = DirectCast(tr.GetObject(id, OpenMode.ForRead), Entity)

                        If ent IsNot Nothing Then

                            Dim ln As Line = TryCast(DirectCast(ent, Line), Line)

                            Dim oidStr As String = id.ToString().Trim(New Char() {"("c, ")"c})

                            fieldText = "%<\AcObjProp Object(%<\_ObjId " & oidStr & ">%).Length \f ""%lu2%pr2%ps[,]"">%"
                            ' metric, precision 2 decimals
                            spt = ln.StartPoint

                            ept = ln.EndPoint

                            x = (spt.X + ept.X) / 2

                            y = (spt.Y + ept.Y) / 2

                            If ept.X - spt.X = 0 Then
                                ang = Math.PI / 2
                            Else
                                ang = Math.Atan((ept.Y - spt.Y) / (ept.X - spt.X))
                            End If

                            pt = New Point3d(x, y, 0.0)

                            txtObj = New MText()

                            txtObj.SetDatabaseDefaults()

                            txtObj.Location = pt

                            txtObj.Height = 3.0

                            txtObj.Contents = "Length:"
                            ' dummy text
                            txtObj.Rotation = ang

                            txtObj.TextStyleId = txtStyleId

                            txtObj.Layer = "Text_Layer" ' Text_Layer might be exist

                            txtObj.Attachment = AttachmentPoint.BottomCenter

                            txtObj.SetAttachmentMovingLocation(txtObj.Attachment)

                            btr.AppendEntity(txtObj)

                            tr.AddNewlyCreatedDBObject(txtObj, True)

                            tr.TransactionManager.QueueForGraphicsFlush()

                            Dim fileldObj As New Autodesk.AutoCAD.DatabaseServices.Field()

                            fileldObj.EvaluationOption = FieldEvaluationOptions.Automatic

                            fileldObj.Evaluate(CInt(FieldEvaluationOptions.Automatic), db)

                            fileldObj.SetFieldCode(fieldText)

                            txtObj.SetField(fileldObj)

                            tr.AddNewlyCreatedDBObject(fileldObj, True)

                            ed.WriteMessage("Point" & vbTab & "{0}", txtObj.ObjectId)

                            tr.TransactionManager.QueueForGraphicsFlush()


                            txtObj.Width = txtObj.ActualWidth
                        End If
                    Next
                    doc.TransactionManager.FlushGraphics()

                    tr.Commit()

                    ed.Regen()

                End Using

            Catch ex As Autodesk.AutoCAD.Runtime.Exception
                result = False

                Autodesk.AutoCAD.ApplicationServices.Application.ShowAlertDialog(ex.Message + vbLf + ex.StackTrace)
            Finally

                If result Then
                    ed.WriteMessage(vbLf & "The command executed successfully" & vbLf)
                End If
            End Try
        End Sub

 

_____________________________________
C6309D9E0751D165D0934D0621DFF27919