Here’s the VB.Net and C# versions of the VBA program from previous post. To go from that VBA program to this VB.Net version was fairly easy. I just copied and pasted the VBA code into a new VB.Net project. The primary changes that I had to make were primarily to the array declarations. Another change, although it wasn’t required, was to change the error handling from the On Error style to Try Catch. I prefer the Try Catch style of error handling.
The array declaration change is because in .Net declaring an array isn’t enough to initialize it. The VBA version of one of the declarations is here:
Dim startCoord() As Double
Here’s the .Net version of the same array.
Dim startCoord() As Double = {}
Here’s the full VB.Net program. The Inventor Application object is passed in as an argument. The act of pasting the VBA code into a .Net program automatically removed all of the Set statements because they’re not longer needed in .Net, which is nice. I also like to enclose arguments to a method within parentheses. In VBA the parentheses are optional and use have to use the Call statement to have them. In VB.Net parentheses are required and using a Call statement is optional. Other than these minor changes, it’s the same code as the original VBA version.
Public Sub CreateSegmentedCurve(ByVal invApp As Inventor.Application) ' Check to see that a curved sketch entity is selected. Dim entity As SketchEntity Try entity = invApp.ActiveDocument.SelectSet.Item(1) Catch ex As Exception MsgBox("A curved sketch entity must be selected.") Exit Sub End Try 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 = entity.Parent ' Get the evaluator from the associate geometry. Dim curveEval As Curve2dEvaluator = entity.Geometry.Evaluator Dim minU As Double Dim maxU As Double curveEval.GetParamExtents(minU, maxU) ' Determine if the entity is open or closed (circle, ' ellipse, or closed spline) Dim curveIsClosed As Boolean = 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 = invApp.TransientGeometry ' Determine if start point is at the min or max parameter. Dim startPoint As SketchPoint = Nothing Dim endPoint As SketchPoint = Nothing If Not curveIsClosed Then Dim startCoord() As Double = {} Dim endCoord() As Double = {} curveEval.GetEndPoints(startCoord, endCoord) If entity.StartSketchPoint.Geometry.IsEqualTo( _ tg.CreatePoint2d(startCoord(0), startCoord(1))) Then startPoint = entity.StartSketchPoint endPoint = entity.EndSketchPoint Else endPoint = entity.StartSketchPoint startPoint = entity.EndSketchPoint End If End If ' Get the curve length. Dim length As Double 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. Dim trans As Transaction = Nothing Try Dim transMgr As TransactionManager  
; transMgr = invApp.TransactionManager trans = transMgr.StartTransaction( _ invApp.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 ReDim points(segmentCount) Dim currentLength As Double = 0 For i As Integer = 0 To segmentCount Dim currentParam As Double curveEval.GetParamAtLength(minU, currentLength, _ currentParam) currentLength = currentLength + offset Dim params(0) As Double params(0) = currentParam Dim coords() As Double = {} curveEval.GetPointAtParam(params, coords) If i = 0 Then ' Special case for the first point. If Not curveIsClosed Then points(i) = startPoint Else points(i) = sk.SketchPoints.Add( _ tg.CreatePoint2d(coords(0), coords(1)), _ False) endPoint = points(i) End If ElseIf i = segmentCount Then ' Special case for the last point points(i) = endPoint Else points(i) = sk.SketchPoints.Add( _ tg.CreatePoint2d(coords(0), coords(1)), _ False) End If Next ' Connect the points with lines. For i As Integer = 0 To segmentCount - 1 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 originalPoint = points(0).Geometry points(0).MoveTo(tg.CreatePoint2d( _ points(0).Geometry.X + 0.001, _ points(0).Geometry.Y)) points(0).MoveTo(originalPoint) ' Turn off the defer to the sketch will recompute normally. sk.DeferUpdates = False trans.End() Catch ex As Exception sk.DeferUpdates = False If Not trans Is Nothing Then trans.Abort() End If MsgBox("Unexpected error segmenting curve.") End Try End Sub
Here’s a C# version o
f the same program. I’m not going to go into a lot of details now about the differences other than to say that there are several. I’m working on an upcoming post that will describe the various issues when using C# to program Inventor. The majority of this code was created using a VB.Net to C# converter, but there were still significant changes that had to be made after that to get it to run.
static void CreateSegmentedCurve(Inventor.Application invApp) { // Check to see that a curved sketch entity is selected. SketchEntity entity = null; try { entity = (SketchEntity) invApp.ActiveDocument.SelectSet[1]; } catch { MessageBox.Show("A curved sketch entity must be selected."); return; } if (entity is SketchPoint | entity is SketchLine) { MessageBox.Show("A curved sketch entity must be selected."); return; } // Ask for the number of segments to break the curve into. string prompt = null; prompt = "Enter the number of segments for the curve."; int segmentCount = 0; segmentCount = (int) Conversion.Val(Interaction.InputBox(prompt, "Number of Segments", "10", 20, 20)); if (segmentCount == 0) { MessageBox.Show("Invalid segment count."); return; } // Get the parent sketch. Sketch sk = entity.Parent; // Get the geometry associated with the sketch entity. Since // the Geometry property will return one of various types of // objects, we need to use late binding here which C# doesn't // handle very nicely. object geom = entity.GetType().InvokeMember("Geometry", BindingFlags.GetProperty , null, entity, null); // Get the curve evaluator from the geometry. Curve2dEvaluator curveEval = (Curve2dEvaluator) geom.GetType().InvokeMember("Evaluator", BindingFlags.GetProperty, null, geom, null); // Get the evaluator from the associate geometry. double minU = 0; double maxU = 0; curveEval.GetParamExtents(out minU, out maxU); // Determine if the entity is open or closed (circle, // ellipse, or closed spline) bool curveIsClosed = false; if (entity is SketchCircle | entity is SketchEllipse | entity is SketchSpline | entity is SketchOffsetSpline) { if (entity is SketchSpline | entity is SketchOffsetSpline) { bool isClosed = (bool) entity.GetType().InvokeMember( "Closed", BindingFlags.GetProperty, null, entity, null); if (isClosed) { curveIsClosed = true; } } else { curveIsClosed = true; } } TransientGeometry tg = invApp.TransientGeometry; // Determine if start point is at the min or max parameter. SketchPoint startPoint = null; SketchPoint endPoint = null; if (!curveIsClosed) { // Get the start and end sketch points from the curve. SketchPoint tempStartPoint = (SketchPoint) entity.GetType().InvokeMember( "StartSketchPoint", BindingFlags.GetProperty, null, entity, null); SketchPoint tempEndPoint = (SketchPoint) entity.GetType().InvokeMember( "StartSketchPoint", BindingFlags.GetProperty, null, entity, null); // Get the coordinate, as a Point object from // the start sketch point. Point2d tempStartCoord = (Point2d) tempStartPoint.GetType().InvokeMember( "Geometry", BindingFlags.GetProperty, null, tempStartPoint, null); double[] startCoord = {}; double[] endCoord = {}; curveEval.GetEndPoints(ref startCoord, ref endCoord); if (tempStartCoord.IsEqualTo(tg.CreatePoint2d(startCoord[0], startCoord[1]), tg.PointTolerance)) { startPoint = tempStartPoint; endPoint = tempEndPoint; } else { endPoint = tempStartPoint; startPoint = tempEndPoint; } } // Get the curve length. double length = 0; curveEval.GetLengthAtParam(minU, maxU, out length); // Determine the length between segments. double offset = length / segmentCount; // Start a transaction to wrap the sketch creation as a // single undo operation. Transaction trans = null; try { TransactionManager transMgr = null; transMgr = invApp.TransactionManager; trans = transMgr.StartTransaction(invApp.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. SketchPoint[] points = new SketchPoint[segmentCount+1]; double currentLength = 0; for (int i = 0; i

Leave a Reply