Leader jig with variable start and end points

Leader jig with variable start and end points

SRSDS
Advisor Advisor
1,026 Views
8 Replies
Message 1 of 9

Leader jig with variable start and end points

SRSDS
Advisor
Advisor

I've modified several jig codes that I've found but I still really don't know what I'm doing.

I'd like a jig that creates a leader starting from the nearest point to a line to the last mouse position.

Needless to say it's not working.

Below is what I have fumbled together. Hope someone can help.

 

    <CommandMethod("AA", CommandFlags.UsePickSet Or CommandFlags.Redraw Or CommandFlags.Modal Or CommandFlags.NoBlockEditor Or CommandFlags.Session)>
    Sub LabelJig()
        Using docLock As DocumentLock = Application.DocumentManager.MdiActiveDocument.LockDocument()
            Using trans As Transaction = Application.DocumentManager.MdiActiveDocument.TransactionManager.StartTransaction : trcnt = trcnt + 1
                Dim RJC As nsLabel_Range.RangeLabelJig2 = New nsLabel_Range.RangeLabelJig2
                RJC.AddLabel(trans) 'LabelType supposed to be "Range"
                trans.Commit() : trcnt = trcnt - 1 : If trcnt > 0 Then MsgBox(Reflection.MethodBase.GetCurrentMethod.Name() + " - TRCNT>0")
            End Using
        End Using
    End Sub
Imports Autodesk.AutoCAD.ApplicationServices
Imports Autodesk.AutoCAD.DatabaseServices
Imports Autodesk.AutoCAD.EditorInput
Imports Autodesk.AutoCAD.Runtime
Imports Autodesk.AutoCAD.Geometry

Namespace nsLabel_Range
    Public Class RangeLabelJig2
        Public Shared mt_RotationUCS As Double, mt_Height As Integer, vector As Vector2d
        Public Shared ml_angleUCS As Double, ml_angleWCS As Double, ml_dogleglength As Double
        Public Shared myLine As Line
        Public Sub AddLabel(ByRef trans As Transaction)
            Dim ed As Editor = Application.DocumentManager.MdiActiveDocument.Editor
            Dim db As Database = Application.DocumentManager.MdiActiveDocument.Database
            Dim btr As BlockTableRecord = trans.GetObject(db.CurrentSpaceId, OpenMode.ForWrite, False)

            myLine = New Line(New Point3d(0, 0, 0), New Point3d(1000, 0, 0))

            Dim jig As New MLeaderJig(" ", LabelTxtStyleID, trans)
            Dim dragres As PromptResult = ed.Drag(jig)
            If dragres.Status = PromptStatus.OK Then
                Dim bt As BlockTable = DirectCast(trans.GetObject(db.BlockTableId, OpenMode.ForRead, False), BlockTable)
                Try
                    Dim ent As Entity = jig.GetEntity
                    btr.AppendEntity(ent)
                    trans.AddNewlyCreatedDBObject(ent, True)
                Catch ex As Exception
                    MsgBox(Reflection.MethodBase.GetCurrentMethod.Name() + " Exception: " + ex.Message)
                End Try
            End If
        End Sub
        Private Class MLeaderJig
            Inherits EntityJig
            'Private m_pts As Point3dCollection
            Private lastMousePosition As Point3d
            Private m_contents As String
            Private m_leaderIndex As Integer
            Private m_leaderLineIndex As Integer
            Public Sub New(ByVal contents As String, ByVal txtId As ObjectId, ByVal Trans As Transaction)
                MyBase.New(New MLeader())
                m_contents = contents
                Dim ml As MLeader = TryCast(Entity, MLeader)
                ml.SetDatabaseDefaults()
                m_leaderIndex = ml.AddLeader()
                m_leaderLineIndex = 0
            End Sub
            Protected Overrides Function Sampler(ByVal prompts As JigPrompts) As SamplerStatus
                Dim jigOpt As New JigPromptPointOptions()
                jigOpt.UserInputControls = UserInputControls.Accept3dCoordinates Or UserInputControls.AnyBlankTerminatesInput Or UserInputControls.GovernedByOrthoMode Or UserInputControls.GovernedByUCSDetect Or UserInputControls.UseBasePointElevation Or UserInputControls.InitialBlankTerminatesInput Or UserInputControls.NullResponseAccepted
                Dim ed As Editor = Application.DocumentManager.MdiActiveDocument.Editor
                jigOpt.Message = vbLf & "Label End Point: "
                Dim res As PromptPointResult = prompts.AcquirePoint(jigOpt)
                If res.Value = lastMousePosition Then
                    Return SamplerStatus.NoChange
                ElseIf res.Status = PromptStatus.OK Then
                    lastMousePosition = res.Value
                    Return SamplerStatus.OK
                End If
                Return SamplerStatus.Cancel
            End Function
            Protected Overrides Function Update() As Boolean
                Dim ed As Editor = Application.DocumentManager.MdiActiveDocument.Editor
                ed.WriteMessage(vbLf + "lastMousePosition=" & lastMousePosition.X & "," & lastMousePosition.Y)
                Try
                    Dim AngleBetweenUCSandWCS As Double = GetAngleBetweenUCSandWCS()
                    Dim ml As MLeader = TryCast(Entity, MLeader)
                    m_leaderLineIndex = ml.AddLeaderLine(m_leaderIndex)
                    Dim m_labelOrigin As Point3d = myLine.GetClosestPointTo(lastMousePosition, False)
                    ml.AddFirstVertex(m_leaderLineIndex, m_labelOrigin)
                    ml.AddLastVertex(m_leaderLineIndex, New Point3d(0, 0, 0))
                    ml.SetLastVertex(m_leaderLineIndex, lastMousePosition)
                Catch ex As Exception
                    Dim doc As Document = Application.DocumentManager.MdiActiveDocument
                    doc.Editor.WriteMessage(vbLf & "MLeader Jig Exception: " & ex.Message)
                    Return False
                End Try
                Return True
            End Function
            Public Function GetEntity() As Entity
                Return Entity
            End Function
        End Class
    End Class
End Namespace

 

0 Likes
Accepted solutions (1)
1,027 Views
8 Replies
Replies (8)
Message 2 of 9

SRSDS
Advisor
Advisor

Worked it out.

If someone could explain these it would be helpful. Commenting the line out removed one big confusing result.

 

jigOpt.UserInputControls = UserInputControls.Accept3dCoordinates Or UserInputControls.AnyBlankTerminatesInput Or UserInputControls.GovernedByOrthoMode Or UserInputControls.GovernedByUCSDetect Or UserInputControls.UseBasePointElevation Or UserInputControls.InitialBlankTerminatesInput Or UserInputControls.NullResponseAccepted

 

Imports Autodesk.AutoCAD.ApplicationServices
Imports Autodesk.AutoCAD.DatabaseServices
Imports Autodesk.AutoCAD.EditorInput
Imports Autodesk.AutoCAD.Runtime
Imports Autodesk.AutoCAD.Geometry

Namespace nsLabel_Range
    Public Class RangeLabelJig2
        Public Shared mt_RotationUCS As Double, mt_Height As Integer, vector As Vector2d
        Public Shared ml_angleUCS As Double, ml_angleWCS As Double, ml_dogleglength As Double
        Public Shared myLine As Line
        Public Sub AddLabel(ByRef trans As Transaction)
            Dim ed As Editor = Application.DocumentManager.MdiActiveDocument.Editor
            Dim db As Database = Application.DocumentManager.MdiActiveDocument.Database
            Dim btr As BlockTableRecord = trans.GetObject(db.CurrentSpaceId, OpenMode.ForWrite, False)

            myLine = New Line(New Point3d(0, 0, 0), New Point3d(1000, 0, 0))

            Dim jig As New MLeaderJig(" ", LabelTxtStyleID, trans)
            Dim dragres As PromptResult = ed.Drag(jig)
            If dragres.Status = PromptStatus.OK Then
                Dim bt As BlockTable = DirectCast(trans.GetObject(db.BlockTableId, OpenMode.ForRead, False), BlockTable)
                Try
                    Dim ent As Entity = jig.GetEntity
                    btr.AppendEntity(ent)
                    trans.AddNewlyCreatedDBObject(ent, True)
                Catch ex As Exception
                    MsgBox(Reflection.MethodBase.GetCurrentMethod.Name() + " Exception: " + ex.Message)
                End Try
            End If
        End Sub
        Private Class MLeaderJig
            Inherits EntityJig
            Private m_pts As Point3dCollection
            Private lastMousePosition As Point3d
            Private m_contents As String
            Private m_leaderIndex As Integer
            Private m_leaderLineIndex As Integer
            Public Sub New(ByVal contents As String, ByVal txtId As ObjectId, ByVal Trans As Transaction)
                MyBase.New(New MLeader())
                m_contents = contents
                m_pts = New Point3dCollection()
                Dim ml As MLeader = TryCast(Entity, MLeader)
                ml.SetDatabaseDefaults()
                m_leaderIndex = ml.AddLeader()
                m_leaderLineIndex = 0
            End Sub
            Protected Overrides Function Sampler(ByVal prompts As JigPrompts) As SamplerStatus
                Dim jigOpt As New JigPromptPointOptions()
                'jigOpt.UserInputControls = UserInputControls.Accept3dCoordinates Or UserInputControls.AnyBlankTerminatesInput Or UserInputControls.GovernedByOrthoMode Or UserInputControls.GovernedByUCSDetect Or UserInputControls.UseBasePointElevation Or UserInputControls.InitialBlankTerminatesInput Or UserInputControls.NullResponseAccepted
                Dim ed As Editor = Application.DocumentManager.MdiActiveDocument.Editor
                If m_pts.Count = 0 Then
                    AddVertex()
                Else
                    jigOpt.Message = vbLf & "Label End Point: "
                End If
                Dim res As PromptPointResult = prompts.AcquirePoint(jigOpt)
                If res.Value = lastMousePosition Then
                    Return SamplerStatus.NoChange
                ElseIf res.Status = PromptStatus.OK Then
                    lastMousePosition = res.Value
                    Return SamplerStatus.OK
                End If
                Return SamplerStatus.Cancel
            End Function
            Protected Overrides Function Update() As Boolean
                Dim ed As Editor = Application.DocumentManager.MdiActiveDocument.Editor
                ed.WriteMessage(vbLf + "lastMousePosition=" & Math.Round(lastMousePosition.X) & "," & Math.Round(lastMousePosition.Y))
                Try
                    If m_pts.Count > 0 Then
                        Dim ml As MLeader = TryCast(Entity, MLeader)
                        Dim m_labelOrigin As Point3d = myLine.GetClosestPointTo(lastMousePosition, False)
                        'ml.AddFirstVertex(m_leaderLineIndex, m_labelOrigin)
                        ml.SetFirstVertex(m_leaderLineIndex, m_labelOrigin)
                        'ml.AddLastVertex(m_leaderLineIndex, New Point3d(0, 0, 0))
                        ml.SetLastVertex(m_leaderLineIndex, lastMousePosition)
                    End If
                Catch ex As Exception
                    Dim doc As Document = Application.DocumentManager.MdiActiveDocument
                    doc.Editor.WriteMessage(vbLf & "MLeader Jig Exception: " & ex.Message)
                    Return False
                End Try
                Return True
            End Function
            Public Sub AddVertex()
                Dim ml As MLeader = TryCast(Entity, MLeader)
                If m_pts.Count = 0 Then
                    m_leaderLineIndex = ml.AddLeaderLine(m_leaderIndex)
                    ml.AddFirstVertex(m_leaderLineIndex, lastMousePosition)
                    ml.AddLastVertex(m_leaderLineIndex, New Point3d(0, 0, 0))
                End If
                m_pts.Add(lastMousePosition)
            End Sub
            Public Function GetEntity() As Entity
                Return Entity
            End Function
        End Class
    End Class
End Namespace
0 Likes
Message 3 of 9

norman.yuan
Mentor
Mentor
Accepted solution

Well, regardless of what "worked it out" means, the code you showed is still a bit problematic.

 

1. Inside the class RangeLabelJig2, why do you need to declare a Shared/static Line object "mLine"? Then in each execution of AddLabel() method, a new Line entity is created but is never added to database/transaction, or it is disposed at the end of the method.

 

2. Inside the real Jig class "MLeaderJig", a new Mleader entity is created. However, what if the user drag the jig and hit ESC? That is, if PromptResult returned by the Jig is not PromptStatus.OK, what happens to the MLeader entity the code created? Obviously, if it is not to be added to Transaction/Database, your code is responsible to dispose it, which the code does not do.

 

You might want to streamline your code for this matter regardless how Jig works.

 

 

Norman Yuan

Drive CAD With Code

EESignature

0 Likes
Message 4 of 9

SRSDS
Advisor
Advisor

Norman,

I had thought about disposing of the line but I didn't give any thought to the leader.

I think I would have taken the code from one of Keans posts. 

Must have accidentally deleted the code that dealt with that.

Thank you.

0 Likes
Message 5 of 9

SRSDS
Advisor
Advisor

Norman,

Can you help me with your second point.

2. Inside the real Jig class "MLeaderJig", a new Mleader entity is created. However, what if the user drag the jig and hit ESC? 

 

Just wondering what might be different to Kean's example that you are pointing out.

https://www.keanw.com/2007/09/creating-a-mult.html

0 Likes
Message 6 of 9

norman.yuan
Mentor
Mentor

OK, I quickly browsed Kean's code. In his code, the jig is used inside a while(){...} loop, which DOES NOT allow user to get out of it unless the jig completes the MLeader, which I think may make a user mad😱! So, in his case, the MLeader would always be added to Transaction/database.

 

If you wan to avoid making user mad and allow them to cancel the jig, then you need to streamline the code to handle the case when Editor.Drag() does not return PromptStatus.OK in order to dispose the entity created in the jig.

 

Norman Yuan

Drive CAD With Code

EESignature

0 Likes
Message 7 of 9

SRSDS
Advisor
Advisor

Bit scared to ask this but can you provide an example of how to dispose of objects created in these types of situations.

Jigs are magical but I'm delving into an art which is one I don't know how to learn.

0 Likes
Message 8 of 9

SRSDS
Advisor
Advisor

I guess more specifically, how do I dispose of objects created in Public Sub New()

 

            Public Sub New(ByVal contents As String, ByVal txtId As ObjectId, ByVal Trans As Transaction)
                MyBase.New(New MLeader())
                Dim ml As MLeader = TryCast(Entity, MLeader)
                Dim mt As MText = New MText()
            End Sub
0 Likes
Message 9 of 9

SRSDS
Advisor
Advisor

I understand now. Thanks for everything.

0 Likes