By Adam Nagy
You can use these two functions to get the tessellated geometry of an Inventor model. If calculated values already exist then you can get the tolerance they are using via GetExistingFacetTolerances. If this gives back some values then you can use them to retrieve the associated facets through GetExistingFacets, where you would pass in the existing tolerance of your choice.
If the existing facets used a tolerance that is not precise enough for you, then you need to use CalculateFacets.
The relationship between the values that GetExistingFacets/CalculateFacets return can be explained using a simple rectangular face as an example - the order of the values could differ from the below example but the relationship between them should be the same. If we called CalculateFacets(Tolerance As Double, VertexCount As Long, FacetCount As Long, VertexCoordinates() As Double, NormalVectors() As Double, VertexIndices() As Long) on the below face, we would get these values:
There are some samples in the API Help file showing how to use these functions, but here is one that can be useful to debug things. This will show if an acceptable tolerance already exists, in which case the lines will be green otherwise red. You can also then examine the result to see if e.g. for some reason the vertices of neighbouring faces do not line up, like here:
When using the same tolerance to retrieve existing facets, then they should line up between neighbouring faces. If not, then regenerating the model should put things right - i.e. PartDocument.Rebuild():
Here is the VBA sample code for vertex checking:
Sub ShowFacetLines( _ vCount As Long, fCount As Long, coords() As Double, _ normals() As Double, indices() As Long, _ oGraphicNode As GraphicsNode, oDataSets As GraphicsDataSets, _ existing As Boolean) Dim oCoordSet As GraphicsCoordinateSet Set oCoordSet = oDataSets.CreateCoordinateSet(oDataSets.count + 1) Call oCoordSet.PutCoordinates(coords) Dim oCoordIndexSet As GraphicsIndexSet Set oCoordIndexSet = oDataSets.CreateIndexSet(oDataSets.count + 1) Dim oColorSet As GraphicsColorSet Set oColorSet = oDataSets.CreateColorSet(oDataSets.count + 1) If existing Then Call oColorSet.Add(1, 0, 255, 0) Else Call oColorSet.Add(1, 255, 0, 0) End If Dim oColorIndexSet As GraphicsIndexSet Set oColorIndexSet = oDataSets.CreateIndexSet(oDataSets.count + 1) Dim i As Integer For i = 0 To fCount - 1 Call oCoordIndexSet.Add( _ oCoordIndexSet.count + 1, indices(i * 3)) Call oCoordIndexSet.Add( _ oCoordIndexSet.count + 1, indices(i * 3 + 1)) Call oCoordIndexSet.Add( _ oCoordIndexSet.count + 1, indices(i * 3 + 1)) Call oCoordIndexSet.Add( _ oCoordIndexSet.count + 1, indices(i * 3 + 2)) Call oCoordIndexSet.Add( _ oCoordIndexSet.count + 1, indices(i * 3 + 2)) Call oCoordIndexSet.Add( _ oCoordIndexSet.count + 1, indices(i * 3)) Call oColorIndexSet.Add(oColorIndexSet.count + 1, 1) Call oColorIndexSet.Add(oColorIndexSet.count + 1, 1) Call oColorIndexSet.Add(oColorIndexSet.count + 1, 1) Next Dim oLine As LineGraphics Set oLine = oGraphicNode.AddLineGraphics oLine.CoordinateSet = oCoordSet oLine.CoordinateIndexSet = oCoordIndexSet oLine.ColorSet = oColorSet oLine.ColorIndexSet = oColorIndexSet End Sub Sub ShowFacets() Dim oDoc As PartDocument Set oDoc = ThisApplication.ActiveDocument Dim oDef As PartComponentDefinition Set oDef = oDoc.ComponentDefinition Dim tol As Double tol = Val(InputBox("Tolerance", "Provide Facet Tolerance", "0.1")) Dim tr As Transaction Set tr = ThisApplication.TransactionManager.StartTransaction( _ oDoc, "ShowFacets") ' Get the object to draw into On Error Resume Next Dim oClientGraphics As ClientGraphics Set oClientGraphics = oDef.ClientGraphicsCollection("MyTest") If Err = 0 Then oClientGraphics.Delete End If Set oClientGraphics = _ oDef.ClientGraphicsCollection.AddNonTransacting("MyTest") ' Create the graphics data sets collection Dim oDataSets As GraphicsDataSets Set oDataSets = oDoc.GraphicsDataSetsCollection("MyTest") If Err = 0 Then oDataSets.Delete End If Set oDataSets = _ oDoc.GraphicsDataSetsCollection.AddNonTransacting("MyTest") On Error GoTo 0 Dim vCount As Long Dim fCount As Long Dim coords() As Double Dim normals() As Double Dim indices() As Long Dim oSurf As SurfaceBody For Each oSurf In oDef.SurfaceBodies Dim oGraphicNode As GraphicsNode Set oGraphicNode = oClientGraphics.AddNode( _ oClientGraphics.count + 1) ' Check if a good enough tolerance already exists Dim tCount As Long Dim tols() As Double Call oSurf.GetExistingFacetTolerances( _ tCount, tols) Dim usedTol As Double usedTol = 0 Dim msg As String msg = "Available tolerances:" + vbCrLf ' They seem to be ordered from ' smallest to biggest Dim i As Integer For i = tCount - 1 To 0 Step -1 msg = msg + str(tols(i)) + vbCrLf If usedTol = 0 And tols(i) <= tol Then usedTol = tols(i) End If Next ' If we found good existing ' tolerance If usedTol > 0 Then Call oSurf.GetExistingFacets( _ usedTol, _ vCount, _ fCount, _ coords, _ normals, _ indices) Call ShowFacetLines( _ vCount, fCount, coords, _ normals, indices, oGraphicNode, oDataSets, True) msg = msg + "Using tolerance: " + str(usedTol) Call MsgBox(msg, vbInformation, "Used existing tolerance") Else Call oSurf.CalculateFacets( _ tol, _ vCount, _ fCount, _ coords, _ normals, _ indices) Call ShowFacetLines( _ vCount, fCount, coords, _ normals, indices, oGraphicNode, oDataSets, False) Call MsgBox(str(tol), vbInformation, "Used new tolerance") End If Next Call tr.End oDoc.Update End Sub