Hallo,
I want to create jig to insert hallow slab (polyline) everything works fine until I am trying to use an added keyword for rotation then Autocad crashes really bad (no error inforamtion). Can anyone tell me what I am doing wrong? Here is a code, in comment place where program crashes.
Thanks
Ps: I've already been on through the interface and tried to use text jig but no result in my case ๐
Imports System Imports Autodesk.AutoCAD.Runtime Imports Autodesk.AutoCAD.ApplicationServices Imports Autodesk.AutoCAD.DatabaseServices Imports Autodesk.AutoCAD.Geometry Imports Autodesk.AutoCAD.EditorInput Namespace AutoCAD_VB_plug_in1 Public Class MyCommands Inherits Autodesk.AutoCAD.EditorInput.DrawJig Dim BasePt As Point3d Dim angle As Double Dim myPR As PromptPointResult Function StartJig() As PromptPointResult Dim ed As Editor = Application.DocumentManager.MdiActiveDocument.Editor myPR = ed.Drag(Me) Do Select Case myPR.Status Case PromptStatus.OK Return myPR Exit Do End Select Loop While myPR.Status <> PromptStatus.Cancel Return myPR End Function Protected Overrides Function Sampler(ByVal prompts As Autodesk.AutoCAD.EditorInput.JigPrompts) As Autodesk.AutoCAD.EditorInput.SamplerStatus Dim po As New JigPromptPointOptions(vbLf & "Position of slab") po.SetMessageAndKeywords(vbLf & "Specify position of slab or " & "[Rotate]", "R") myPR = prompts.AcquirePoint(po) If myPR.Status = PromptStatus.Keyword Then Select Case myPR.StringResult Case "R" angle = angle + 90 * Math.PI / 180 'Program crash here Exit Select End Select Return SamplerStatus.OK ElseIf myPR.Status = PromptStatus.OK Then If myPR.Value.IsEqualTo(BasePt) Then Return SamplerStatus.NoChange End If BasePt = myPR.Value Return SamplerStatus.OK End If Return SamplerStatus.Cancel End Function Protected Overrides Function WorldDraw(ByVal draw As Autodesk.AutoCAD.GraphicsInterface.WorldDraw) As Boolean Dim x As Integer = BasePt.X Dim y As Integer = BasePt.Y Dim c As Integer = 2 Dim l As Integer = 600 Dim b As Integer = 150 Dim bk As Integer = 26 Dim lk1 As Integer = 100 Dim so As Integer = 10 Dim acPoly As Polyline = New Polyline() acPoly.SetDatabaseDefaults() acPoly.AddVertexAt(0, New Point2d(x, y - c), 0, 0, 0) acPoly.AddVertexAt(1, New Point2d(x + bk / 2 + c, y - c), 0, 0, 0) acPoly.AddVertexAt(2, New Point2d(x + bk / 2 + c, y + lk1 + so), 0, 0, 0) acPoly.AddVertexAt(3, New Point2d(x + b / 2, y + lk1 + so), 0, 0, 0) acPoly.AddVertexAt(4, New Point2d(x + b / 2, y - l + lk1 + so), 0, 0, 0) acPoly.AddVertexAt(5, New Point2d(x - b / 2, y - l + lk1 + so), 0, 0, 0) acPoly.AddVertexAt(6, New Point2d(x - b / 2, y + lk1 + so), 0, 0, 0) acPoly.AddVertexAt(7, New Point2d(x - bk / 2 - c, y + lk1 + so), 0, 0, 0) acPoly.AddVertexAt(8, New Point2d(x - bk / 2 - c, y - c), 0, 0, 0) acPoly.Closed = True Dim curUCSMatrix As Matrix3d = Application.DocumentManager.MdiActiveDocument.Editor.CurrentUserCoordinateSystem Dim curUCS As CoordinateSystem3d = curUCSMatrix.CoordinateSystem3d acPoly.TransformBy(Matrix3d.Rotation(angle, curUCS.Zaxis, BasePt)) draw.Geometry.Polyline(acPoly, 1, 8) End Function <CommandMethod("DoJigA")> Sub DoJigA() StartJig() End Sub End Class End Namespace
From your Jig class, it is hard to tell what the purpose of the jig. if you are to draw a polyline from nothing, using EntityJig might be better option. DrawJig is usually used for presenting a visual clue of how an existing entity would be transformed. But for your case, I guess you use Jig to get the start point and a rotation angle for a fixed sized polyline to be drawn.
From your code I can see 2 issues:
1. The code crash when user select keywork "R", while moving cursor is OK. You may want to try a loop to enclose the prompts.AcquirePoint(), so that user enters keywork, the code set variable "angle" and loop back to prompts.AcquirePoint(). It only breaks out the loop the PromptResult is OK or Cancel. Something like:
Protected Overrides Function Sampler(ByVal prompts As Autodesk.AutoCAD.EditorInput.JigPrompts) As Autodesk.AutoCAD.EditorInput.SamplerStatus
Do
Dim po As New JigPromptPointOptions(vbLf & "Position of slab")
po.SetMessageAndKeywords(vbLf & "Specify position of slab or " & "[Rotate]", "R")
myPR = prompts.AcquirePoint(po)
If myPR.Status = PromptStatus.Keyword Then
Select Case myPR.StringResult
Case "R"
angle = angle + 90 * Math.PI / 180
'Program crash here
Exit Select
End Select
''Remove this
''Return SamplerStatus.OK
ElseIf myPR.Status = PromptStatus.OK Then
If myPR.Value.IsEqualTo(BasePt) Then
Return SamplerStatus.NoChange
End If
BasePt = myPR.Value
Return SamplerStatus.OK
End If
Loop While (True)
Return SamplerStatus.Cancel
End Function
I guess the crash has something to do with the fact that in your code, if user enter keywork R, the sSampler()method still returns samplerStatus.OK, which triggers WorldDraw(), but somehow, the BasePt is unchanged, thus some calculation in the WorldDraw() cannot go ahead (I did not looked into, though).
2. The biggest issue I can see is taht in the WorldDraw() method, your code actaully create many (or too many) polyline objects without dispose them. With minor move of the mouse, the WorldDraw(0 is triggered, and a polyline object is created, and only used for rendering a visual image and yoru code leave it behind. If user drag the Jig for a few seconds, there could be hundreds of thousands of polyline being created in the memory.
You shold create a polyline at class level, and only update/transform it in WordDraw() for the changed location/angle. And at the end of the Jig, you either add this Polylne into database (that is why I suggest to use EntityJig), or retrieve the points/angle to update existing polylne and dispose the polyline iin the Jig class (you may implement IDisposable interface).
Norman Yuan
Hallo Thanks for your feedback and your time. The problem was in StartJig function I didn't protected case when PromptStatus is Keyword. The correct code for this function is:
Function StartJig() As PromptPointResult Dim ed As Editor = Application.DocumentManager.MdiActiveDocument.Editor Dim stat As PromptStatus = PromptStatus.Keyword While stat = PromptStatus.Keyword Dim res = ed.Drag(Me) stat = res.Status If stat <> PromptStatus.OK AndAlso stat <> PromptStatus.Keyword Then Return myPR End If End While Return myPR End Function
I have got two more questions.
1. Like you mentioned before I don't know how to dispose DrawJig, (debbuger asks me Forgot to Dispose?). How should I use or where I can learn about IDisposable interface
2. EntityJig will be better for my function. Still I am learing how to do it. When I finish it i will paste a code, maybe it will be helpful to someone
You are new-ing a Polyline in your worldDraw, this is what you need to dispose. Basically you need to dispose any AutoCAD entity that is NOT added to the database, because AutoCAD won't do it for you. The worldDraw callback is invoked quite often during the jig, which will lead to non neglectible leak in your code.
An easy way to do it is to use the "using" keyword along the Polyline you are creating.
There are many examples of Jigs on our blogs, please take a look if you are not familiar with it:
http://adndevblog.typepad.com/autocad/2012/10/autocadnet-lesson-7-jig.html
Regards,
Philippe.
Can't find what you're looking for? Ask the community or share your knowledge.