- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report
The attached part displays some odd behavior (see the embedded VBA macro T2). The size of the part and the flat pattern extents (40mm x 558.8mm) are reported correctly in Inventor's internal flat pattern properties, but the rangebox information for both the folded and flat model is wildly innacurate for the X value. This seems directly related to the spline based edge on the part.
What spline data is causing the disparity? I know that the rangebox object is only guaranteed to contain the body, but with such a large error it makes the use of the rangebox for any body based on spline geometry pretty much useless.
How is Inventor calculating extents internally? Is it a ray based approach, or a study of edge data? From a programming perspective, how can we get a result that will always return a reasonably accurate description of the size of the part?
Neil
Solved! Go to Solution.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report
RangBox is an ortho box that can exactly cover a shape in WCS coordination. While it is true it looks the X value of a box is not same to what is measured manually when a spline is applied in the sketch. While Y or Z direction works well.
I will need to discuss with our engineer team about this.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report
The RangeBox call is intended to be as fast as possible to be used as a quick way to eliminate or add an object to set of objects for further, more expensive processing. I'm fairly certain that the range box for any spline based geometry is based on the control polygon of the spline so in most cases it will be larger than the actual curve or surface. It would take me a while to dig into how Inventor is getting the size of the sheet metal part, but obviously it's doing a more expensive calculation to get a tight range box.
A way to get an accurate bounding box is to calculate your own based on a mesh representation of the body. This may seem complicated but it's really not. Below is a VBA implementation I just put together quickly to illustrate.
Public Sub t2()
Dim doc As PartDocument
Set doc = ThisDocument
Dim xWidth As Double
Dim yLength As Double
doc.ObjectVisibility.AllWorkFeatures = False
doc.ObjectVisibility.ConstructionSurfaces = False
doc.ObjectVisibility.SketchDimensions = False
doc.ObjectVisibility.Sketches = False
doc.ObjectVisibility.Sketches3D = False
Dim boundingBox As Box
Set boundingBox = doc.ComponentDefinition.SurfaceBodies.Item(1).RangeBox
xWidth = Round(Abs(boundingBox.MaxPoint.X - boundingBox.MinPoint.X), 3)
yLength = Round(Abs(boundingBox.MaxPoint.Y - boundingBox.MinPoint.Y), 3)
Debug.Print "X = " & xWidth
Debug.Print "Y = " & yLength
Set boundingBox = TightRangeBox(doc.ComponentDefinition.SurfaceBodies.Item(1))
xWidth = Round(Abs(boundingBox.MaxPoint.X - boundingBox.MinPoint.X), 3)
yLength = Round(Abs(boundingBox.MaxPoint.Y - boundingBox.MinPoint.Y), 3)
Debug.Print "Tight"
Debug.Print "X = " & xWidth
Debug.Print "Y = " & yLength
End Sub
Public Function TightRangeBox(Body As Inventor.SurfaceBody) As Inventor.Box
' Get the existing mesh of the highest resolution.
Dim tolCount As Long
Dim tols() As Double
Call Body.GetExistingFacetTolerances(tolCount, tols)
Dim i As Integer
Dim bestTol As Double
bestTol = tols(0)
For i = 1 To tolCount - 1
If tols(i) < bestTol Then
bestTol = tols(i)
End If
Next
Dim vertexCount As Long
Dim facetCount As Long
Dim vertexCoords() As Double
Dim normalVectors() As Double
Dim vertexIndices() As Long
Call Body.GetExistingFacets(bestTol, vertexCount, facetCount, vertexCoords, normalVectors, vertexIndices)
' Loop through the vertices and build up the range box.
Dim minX As Double
Dim maxX As Double
Dim minY As Double
Dim maxY As Double
Dim minZ As Double
Dim maxZ As Double
minX = vertexCoords(0)
maxX = vertexCoords(0)
minY = vertexCoords(1)
maxY = vertexCoords(1)
minZ = vertexCoords(2)
maxZ = vertexCoords(2)
For i = 1 To vertexCount - 1
If vertexCoords(i * 3) < minX Then
minX = vertexCoords(i * 3)
End If
If vertexCoords(i * 3) > maxX Then
maxX = vertexCoords(i * 3)
End If
If vertexCoords(i * 3 + 1) < minY Then
minY = vertexCoords(i * 3 + 1)
End If
If vertexCoords(i * 3 + 1) > maxY Then
maxY = vertexCoords(i * 3 + 1)
End If
If vertexCoords(i * 3 + 2) < minZ Then
minZ = vertexCoords(i * 3 + 2)
End If
If vertexCoords(i * 3 + 2) > maxZ Then
maxZ = vertexCoords(i * 3 + 2)
End If
Next
Dim newBox As Box
Set newBox = ThisApplication.TransientGeometry.CreateBox()
newBox.MinPoint = ThisApplication.TransientGeometry.CreatePoint(minX, minY, minZ)
newBox.MaxPoint = ThisApplication.TransientGeometry.CreatePoint(maxX, maxY, maxZ)
Set TightRangeBox = newBox
End Function
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report
Brian,
Although I can easily work around this, using this method on a surfacebody obtained from the flat pattern fails (Doc.ComponentDefinition.FlatPattern.SurfacBodies[1]). The flat pattern surfacebody appears to be a valid surfacebody object, but the GetExistingFacets() method returns no information. The vertexCount and facetCount both = 0, and the returned arrays have no elements other than what was required to initialize the array.
The method works great for a surfacebody object obtained from the ComponentDefintion object.
Neil
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report
I spoke a bit too soon. It does fail when using it with a transient surface body. If I can get a case number I can share some code that demonstrates the issue.
Neil
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report
That's actually expected because the code is getting the mesh being used for the display of the body. For a transient body, there isn't a display mesh. Instead you can calculate a new mesh. Theres a CalculateFacets method that can be used instead, but when I was testing it, it's failing to, which is a bug. However, there is also a CalculateFacetsWithOptions method and that is working. Here's the modified version of the function.
Public Function TightRangeBox(Body As Inventor.SurfaceBody) As Inventor.Box
' Calculate a new mesh.
Dim vertexCount As Long
Dim facetCount As Long
Dim vertexCoords() As Double
Dim normalVectors() As Double
Dim vertexIndices() As Long
Dim options As NameValueMap
Set options = ThisApplication.TransientObjects.CreateNameValueMap
Call Body.CalculateFacetsWithOptions(0.005, options, vertexCount, facetCount, vertexCoords, normalVectors, vertexIndices)
'Call Body.CalculateFacets(0.005, vertexCount, facetCount, vertexCoords, normalVectors, vertexIndices)
' Loop through the vertices and build up the range box.
Dim minX As Double
Dim maxX As Double
Dim minY As Double
Dim maxY As Double
Dim minZ As Double
Dim maxZ As Double
minX = vertexCoords(0)
maxX = vertexCoords(0)
minY = vertexCoords(1)
maxY = vertexCoords(1)
minZ = vertexCoords(2)
maxZ = vertexCoords(2)
Dim i As Integer
For i = 1 To vertexCount - 1
If vertexCoords(i * 3) < minX Then
minX = vertexCoords(i * 3)
End If
If vertexCoords(i * 3) > maxX Then
maxX = vertexCoords(i * 3)
End If
If vertexCoords(i * 3 + 1) < minY Then
minY = vertexCoords(i * 3 + 1)
End If
If vertexCoords(i * 3 + 1) > maxY Then
maxY = vertexCoords(i * 3 + 1)
End If
If vertexCoords(i * 3 + 2) < minZ Then
minZ = vertexCoords(i * 3 + 2)
End If
If vertexCoords(i * 3 + 2) > maxZ Then
maxZ = vertexCoords(i * 3 + 2)
End If
Next
Dim newBox As Box
Set newBox = ThisApplication.TransientGeometry.CreateBox()
newBox.MinPoint = ThisApplication.TransientGeometry.CreatePoint(minX, minY, minZ)
newBox.MaxPoint = ThisApplication.TransientGeometry.CreatePoint(maxX, maxY, maxZ)
Set TightRangeBox = newBox
End Function
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report
Hi Brian,
Great. I did think that might be the approach. I'll have to work around it for pre 2017 support but that is OK. Thanks again for the great support.
Neil
