Hi Autodesk Inventor Community,
Occasionally, the edge object's GetClosestPointTo() method can give spurious results. In the example given, if GetClosestPointTo is called on the point in the middle of the elliptical arc's parameter range, the point at the beginning of the arc is returned. However, a small perturbation in the parameter range either side results in good accuracy. I have attached the part and VBA code to highlight this bug.
Does anybody know a way to ascertain/improve the reliability of calls to this function? And, does anybody know what algorithm is used to calculate it.
Kind Regards,
Aaron
VBA code:
'For the forum
Sub numerical_bug()
'Find the single elliptical edge in the part
Dim oPartDoc As PartDocument
Set oPartDoc = ThisApplication.ActiveDocument
Dim oComponentDefinition As ComponentDefinition
Set oComponentDefinition = oPartDoc.ComponentDefinition
Dim oSurfaceBodies As SurfaceBodies
Set oSurfaceBodies = oComponentDefinition.SurfaceBodies
Dim oSurfaceBody As SurfaceBody
Set oSurfaceBody = oSurfaceBodies(1)
Dim i As Integer
Dim face1 As Face
Dim face2 As Face
Dim ellipticalEdge As Edge
For i = 1 To oSurfaceBody.Edges.count
If (oSurfaceBody.Edges(i).GeometryType = CurveTypeEnum.kEllipticalArcCurve) Then
Set ellipticalEdge = oSurfaceBody.Edges(i)
End If
Next i
'Get the parameter range
Dim minParam As Double
Dim maxParam As Double
Call ellipticalEdge.Evaluator.GetParamExtents(minParam, maxParam)
Dim midParam As Double
midParam = (minParam + maxParam) / 2
Dim paramLength As Double
paramLength = maxParam - minParam
'The issue occurs exactly in the middle of the parameter range. But parameters close to it are well behaved
Const nParams As Integer = 4
Dim paramList(nParams) As Double
paramList(0) = midParam
paramList(1) = midParam + 0.000001 * paramLength
paramList(2) = midParam - 0.000001 * paramLength
paramList(3) = minParam
Dim names(nParams) As String
names(0) = "Middle of Range"
names(1) = "Just above of middle"
names(2) = "Just below middle"
names(3) = "Start of parameter range"
' Create points from evaluator
Dim points(20) As Double
Call ellipticalEdge.Evaluator.GetPointAtParam(paramList, points)
Dim oTG As TransientGeometry
Set oTG = ThisApplication.TransientGeometry
' Initialising for the loop
Dim count As Integer
Dim outputString As String
count = 0
Dim closestPoints(nParams) As point
Dim actualPoints(nParams) As point
Dim errors(nParams) As Double
'Assess Each Point
For i = 1 To nParams
Dim currentPoint As point
Set currentPoint = oTG.CreatePoint(points(count), points(count + 1), points(count + 2))
Set actualPoints(i) = currentPoint
'Find the closest point
Dim closestPoint As point
Set closestPoint = ellipticalEdge.GetClosestPointTo(currentPoint)
Set closestPoints(i) = closestPoint
'Calculate the difference between the closest point and the current point
Dim p As Vector
Set p = closestPoint.VectorTo(currentPoint)
errors(i) = p.Length
outputString = outputString & names(i - 1) & ": " & vbCrLf
outputString = outputString & "Param " & i & ": " & paramList(i - 1) & vbCrLf
outputString = outputString & "Point " & i & ": " & vbCrLf & _
" x = " & currentPoint.x & vbCrLf & _
" y = " & currentPoint.y & vbCrLf & _
" z = " & currentPoint.z & vbCrLf
outputString = outputString & "Closest Point To Point " & i & ": " & vbCrLf & _
" x = " & closestPoint.x & vbCrLf & _
" y = " & closestPoint.y & vbCrLf & _
" z = " & closestPoint.z & vbCrLf
outputString = outputString & "GetClosestPointTo() Error: " & errors(i) & vbCrLf
outputString = outputString & vbCrLf
count = count + 3
Next i
' Notice that the apparent closest point to the midpoint is the same as the start point
If (closestPoints(1).x = actualPoints(4).x And _
closestPoints(1).y = actualPoints(4).y And _
closestPoints(1).z = actualPoints(4).z) Then
outputString = outputString & "Closest point to the midpoint is exactly the same as start point!!" & vbCrLf
End If
outputString = outputString & vbCrLf & "Param Length: " & paramLength & vbCrLf
outputString = outputString & "Param Min: " & minParam & vbCrLf
outputString = outputString & "Param Max: " & maxParam
MsgBox (outputString)
End Sub
Hi Aaron,
I could reproduce the issue and have logged it in our system as CR 1518391.
I guess the only thing you could do is put in an extra check to see if the returned point is closer than the middle point :-s
Sorry about the inconvenience this issue causes.
Cheers,