To create a point on a curve in CATIA V5 is a pretty simple task. Things get complicated if we need to repeat it in VBA. Although most of the information you need you can find also in CATIA V5 documentation, the lack of examples is a real problem. I would like to try to fill this gap and show you some of the functions you can use when you work with CATIA curves. And because I like when things are moving, we create an animation :).
Wanna see it in action?
A Timer procedure
Since we are going to create a simple animation, we need a timer. Native VBA time-related functions only provide up to seconds accuracy. However, for our animation, we need a higher resolution, ideally milliseconds resolutions.
The Windows API provides several ways to measure elapsed time, the simplest is perhaps the GetTickCount function. This function measures the number of milliseconds that have elapsed since the system was started, up to 49.7 days. According to official Microsoft documentation, the resolution of the GetTickCount function is limited to the resolution of the system timer, which is typically in the range of 10 milliseconds to 16 milliseconds. For more details about this function look here.
The GetTickCount function together with Sleep and DoEvents function provides a good enough ticker for most of the applications. Running them within a loop, we get a simple timer that provides a higher resolution than native VBA and it is not blocking a CATIA user interface. But keep in mind, every computer is different and maybe you need to adjust TIMER_INTERVAL constant or a Sleep parameter (both in milliseconds) if your system is too slow, too fast or nonresponding.
Option Explicit
Private Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
Private Declare Function GetTickCount Lib "kernel32.dll" () As Long
Private myStep As Long
Private counter As Long
Private myShape As Circle2D
Private Const TIMER_INTERVAL As Long = 50
Private Const NUMBER_OF_POINTS As Long = 200
Sub Main()
' get an active view
Dim myView As DrawingView
Set myView = CATIA.ActiveDocument.Sheets.ActiveSheet.Views.ActiveView
' get a curve, first element is axis system
Dim myCurve
Set myCurve = myView.GeometricElements.Item(2)
Dim startTime As Long
startTime = GetTickCount
myStep = 1
' main timer loop
Do
If (GetTickCount - startTime) > TIMER_INTERVAL Then
' draw circle
Draw myView, myCurve
'reset time after redrawing
startTime = GetTickCount
End If
' pause execution
Sleep 5
' process events (do not block UI)
DoEvents
Loop While True
End Sub
A Draw procedure
A Draw procedure takes care of rendering of a moving element(s), circle(s). It is called on every timer tick, it calculates the next point on the curve and draws/redraws a circle in that point. At first, we split the curve into a number of points defined by NUMBER_OF_POINTS constant. On every call of the function, we increase a counter variable and we get the next point from the predefined number of points on the curve.
With a function GetParamExtents we get parametric extents of a curve, which is a parametric equivalent of the end-points. The return value is an array where the first element is the parameter associated with the start point of the curve and the second one is the parameter associated with the end point of the curve.
To get a point lying on a curve we use the function GetPointAtParam. This function returns a point on the curve computed from an input parameter. If the input parameter is a value (Double) within the range defined by parametric extents, as a result, we get a location of the 2D point on the curve in a form of an array with X and Y coordinates of the computed point. A variable param is incrementally increased/decreased on every function call moving constantly between the start point of the curve and the end point.
Finally, we create a circle in the computed point on the curve and we assign it to a module variable myShape. The circle is created only on a first call of the function, on the other calls we just modify the position of the existing one. In the last lines, we control a direction of the movement with a variable myStep, which switches from positive to negative and vice versa when we get outside of the range of the total number of points (when we reach either the start point of the curve or the end point). In the end we increase/decrease the counter variable.
Sub Draw(myView As DrawingView, myCurve)
Dim distanceRatio As Double
distanceRatio = 1 / NUMBER_OF_POINTS * counter
Dim paramExtents(1)
myCurve.GetParamExtents paramExtents
Dim param As Double
param = paramExtents(0) + (paramExtents(1) - paramExtents(0)) * distanceRatio
Dim currPoint(1)
myCurve.GetPointAtParam param, currPoint
Dim fact2D
Set fact2D = myView.Factory2D
If myShape Is Nothing Then
Set myShape = fact2D.CreateClosedCircle(currPoint(0), currPoint(1), 5)
Else
myShape.SetData currPoint(0), currPoint(1), 5
End If
If counter < 0 Or counter > NUMBER_OF_POINTS Then myStep = -myStep
counter = counter + myStep
End Sub
To test it, create and activate a view with the curve as the only element inside. Then copy a source code into a standard module and launch the Main procedure.