Approximating a Sketch Curve with Line Segments

Here’s another little VBA macro that I wrote that might be interesting to some of you.  This one takes any sketch curve (circle, arc, spline, ellipse, or elliptical arc) as input, along with the number of segments to break the curve into.  It then creates sketch lines along the curve.  It also sets the original curve to be construction geometry.

This mostly uses the curve geometry query functionality in the API and also demonstrates creating a sketch.  I’ve tried to add comments to the code to help in understanding what it’s doing. 

Public Sub CreateSegmentedCurve()          ' Check to see that a curved sketch entity is selected.              Dim entity As SketchEntity           On Error Resume Next           Set entity = ThisApplication.ActiveDocument.SelectSet.Item(1)           If Err.Number  0 Then               MsgBox "A curved sketch entity must be selected."               Exit Sub           End If           On Error GoTo 0            If TypeOf entity Is SketchPoint Or _                                         TypeOf entity Is SketchLine Then               MsgBox "A curved sketch entity must be selected."               Exit Sub           End If            ' Ask for the number of segments to break the curve into.              Dim prompt As String           prompt = "Enter the number of segments for the curve."           Dim segmentCount As Integer           segmentCount = Val(InputBox(prompt, "Number of Segments", "10"))           If segmentCount = 0 Then               MsgBox "Invalid segment count."               Exit Sub           End If            ' Get the parent sketch.              Dim sk As sketch           Set sk = entity.Parent            ' Get the evaluator from the associate geometry.              Dim curveEval As Curve2dEvaluator           Set curveEval = entity.Geometry.Evaluator           Dim minU As Double           Dim maxU As Double           Call curveEval.GetParamExtents(minU, maxU)            ' Determine if the entity is open or closed (circle,              ' ellipse, or closed spline)               Dim curveIsClosed As Boolean           curveIsClosed = False           If TypeOf entity Is SketchCircle Or _              TypeOf entity Is SketchEllipse Or _              TypeOf entity Is SketchSpline Or _              TypeOf entity Is SketchOffsetSpline Then               If TypeOf entity Is SketchSpline Or _                  TypeOf entity Is SketchOffsetSpline Then                   If entity.Closed Then                       curveIsClosed = True                   End If               Else                   curveIsClosed = True               End If           End If           Dim tg As TransientGeometry           Set tg = ThisApplication.TransientGeometry            ' Determine if start point is at the min or max parameter.              Dim startPoint As SketchPoint           Dim endPoint As SketchPoint           If Not curveIsClosed Then               Dim startCoord() As Double               Dim endCoord() As Double               Call curveEval.GetEndPoints(startCoord, endCoord)               If entity.StartSketchPoint.Geometry.IsEqualTo( _                 tg.CreatePoint2d(startCoord(0), startCoord(1))) Then                   Set startPoint = entity.StartSketchPoint                   Set endPoint = entity.EndSketchPoint               Else                   Set endPoint = entity.StartSketchPoint                   Set startPoint = entity.EndSketchPoint               End If           End If            ' Get the curve length.              Dim length As Double           Call curveEval.GetLengthAtParam(minU, maxU, length)            ' Determine the length between segments.              Dim offset As Double           offset = length / segmentCount            ' Start a transaction to wrap the sketch creation as a              ' single undo operation.               On Error GoTo ErrorFound           Dim transMgr As TransactionManager           Set transMgr = ThisApplication.TransactionManager           Dim trans As Transaction           Set trans = transMgr.StartTransaction( _                           ThisApplication.ActiveDocument, "Segment Curve")            ' Defer updates on the sketch while the sketch entities              ' are being created.  This will significantly improve               ' performance.               sk.DeferUpdates = True            ' Calculate the points and create a sketch              ' point at each position.               Dim points() As SketchPoint       &#160
;   ReDim points(segmentCount)           Dim i As Integer           Dim currentLength As Double           currentLength = 0           For i = 0 To segmentCount               Dim currentParam As Double               Call curveEval.GetParamAtLength(minU, currentLength, _                                               currentParam)               currentLength = currentLength + offset                Dim params(0) As Double               params(0) = currentParam               Dim coords() As Double               Call curveEval.GetPointAtParam(params, coords)                If i = 0 Then                   ' Special case for first point.                      If Not curveIsClosed Then                       Set points(i) = startPoint                   Else                       Set points(i) = sk.SketchPoints.Add( _                              tg.CreatePoint2d(coords(0), coords(1)), False)                       Set endPoint = points(i)                   End If               ElseIf i = segmentCount Then                   ' Special case for last point                      Set points(i) = endPoint               Else                   Set points(i) = sk.SketchPoints.Add( _                              tg.CreatePoint2d(coords(0), coords(1)), False)               End If           Next            ' Connect the points with lines.              For i = 0 To segmentCount - 1               Call sk.SketchLines.AddByTwoPoints(points(i), points(i + 1))           Next            ' Make the selected entity construction geometry.              entity.Construction = True                 ' There's a current problem that when setting the construction              ' property, the display isn't updated to reflect this change               ' until something causes the sketch to recompute.  This performs               ' a change on the sketch to kick a recompute.               Dim originalPoint As Point2d           Set originalPoint = points(0).Geometry           Call points(0).MoveTo(tg.CreatePoint2d( _                                          points(0).Geometry.X + 0.001, _                                          points(0).Geometry.Y))           Call points(0).MoveTo(originalPoint)            ' Turn off the defer to the sketch will recompute normally.              sk.DeferUpdates = False            trans.End           Exit Sub             ErrorFound:           sk.DeferUpdates = False            If Not trans Is Nothing Then               trans.Abort           End If            MsgBox "Unexpected error segmenting curve."       End Sub

Comments

Leave a Reply

Discover more from Autodesk Developer Blog

Subscribe now to keep reading and get access to the full archive.

Continue reading