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 of 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 <= segmentCount; i++) {
double currentParam = 0;
curveEval.GetParamAtLength(minU, currentLength,
out currentParam);
currentLength = currentLength + offset;
double[] crvParams = new double[1];
crvParams[0] = currentParam;
double[] coords = {};
curveEval.GetPointAtParam(ref crvParams, ref coords);
if (i == 0) {
// Special case for the first point.
if (!curveIsClosed)
{
points[i] = startPoint;
}
else
{
points[i] = sk.SketchPoints.Add(
tg.CreatePoint2d(coords[0],
coords[1]), false);
endPoint = points[i];
}
}
else if (i == segmentCount)
{
// Special case for the last point
points[i] = endPoint;
}
else
{
points[i] = sk.SketchPoints.Add(
tg.CreatePoint2d(coords[0],
coords[1]), false);
}
}
// Connect the points with lines.
for (int i = 0; i <= segmentCount - 1; i++)
{
sk.SketchLines.AddByTwoPoints(points[i], points[i + 1]);
}
// 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.
Point2d originalPoint = default(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 (Exception)
{
sk.DeferUpdates = false;
if ((trans != null))
{
trans.Abort();
}
MessageBox.Show("Unexpected error segmenting curve.");
}
}

Subscribe
Comments