Creating Construction Geometry in Assemblies in Inventor

I was working on answering a question recently and put together a bit of code to make sure my answer was correct and thought it might be useful to some others so I want to share it here.

The initial question was a good one. The question was how to create an offset work plane in an assembly using the API. The obvious thing is to use the AddByPlaneAndOffset method of the WorkPlanes collection but if you try it, it will fail and if you look at the help it will tell you that it’s not supported in assemblies, but it also doesn’t say how to do it.

Assemblies and construction geometry are a bit strange. Working interactively with Inventor, work geometry seems to work just that same as when working in a part, but if you look close you’ll see a big difference. If you create an offset work plane using the UI in an assembly and then look at the result in the browser you’ll see the work plane in the browser just like you would in a part, except in an assembly the work plane browser node can be expanded and then you’ll see that there’s a flush constraint.  Work geometry in a part has intelligence within itself to know what it’s related to and how it’s related so if that geometry is modified it can correctly re-compute itself.  Work geometry in an assembly isn’t intelligent at all.  It just exists in space and the intelligence to position it is done by adding constraints. 

The assembly work geometry commands have a lot of intelligence in them and will create the work geometry and automatically add the needed constraints to get the desired behavior.  The API doesn’t do this. You can create a work plane in space but then you need to add the flush constraint as a separate step. In an assembly, the only way you can create work geometry is to use the AddFixed methods on each of the work geometry collections.

Below is the VBA code I wrote to test this. It demonstrates getting a selected face and then creating a work plane on that face. I’m using an offset of 0, but any offset could be used.  A fair amount of the code is just figuring out the orientation of the work plane.  Although the orientation doesn’t really matter except for looks.  To get a logical orientation it uses the longest linear edge on the selected face and if there aren’t any linear edges then it aligns it with one of the primary model axes. The UI command also does some additional work to size the created work plane to fit the geometry, which the API and this sample doesn’t do.  The API does support setting the size of a work plane but I haven’t attempted that here.

Public Sub CreateWorkPlane()    Dim asmDoc As AssemblyDocument    Set asmDoc = ThisApplication.ActiveDocument        Dim asmDef As AssemblyComponentDefinition    Set asmDef = asmDoc.ComponentDefinition        ' Have a planar face selected.    Dim selFace As Face    Set selFace = ThisApplication.CommandManager.Pick(kPartFacePlanarFilter, "Select planar face")        ' Get the underlying plane geometry from the face.    Dim facePlane As Plane    Set facePlane = selFace.Geometry        Dim tg As TransientGeometry    Set tg = ThisApplication.TransientGeometry        ' Find the longest linear edge on the face and use it as the X axis.    Dim testEdge As Edge    Dim longDir As UnitVector    Dim longLength As Double    longLength = 0    For Each testEdge In selFace.Edges        If testEdge.GeometryType = kLineSegmentCurve Then            Dim lengthVec As Vector            Set lengthVec = testEdge.StartVertex.Point.VectorTo(testEdge.StopVertex.Point)            If lengthVec.length > longLength Then                longLength = lengthVec.length                Set longDir = lengthVec.AsUnitVector            End If        End If    Next        Dim xVec As UnitVector    Dim yVec As UnitVector    Dim pi As Double    pi = Atn(1) * 4    If Not longDir Is Nothing Then        ' Use the longest edge as the x direction for the work plane.        Set xVec = longDir        Set yVec = facePlane.Normal.CrossProduct(xVec)    Else        ' No linear edges was found so calculate another axis to use as the x axis.        ' Use the model x, y, or z axis depending on which one is closest to 90 deg from the normal.        Dim angleDiff As Double        Dim testVec As UnitVector        Set testVec = tg.CreateUnitVector(1, 0, 0)        angleDiff = Abs((pi / 2) - facePlane.Normal.AngleTo(testVec))        Set xVec = testVec                Set testVec = tg.CreateUnitVector(0, 1, 0)        If Abs((pi / 2) - facePlane.Normal.AngleTo(testVec)) < angleDiff Then            angleDiff = Abs((pi / 2) - facePlane.Normal.AngleTo(testVec))            Set xVec = testVec        End If                Set testVec = tg.CreateUnitVector(0, 0, 1)        If Abs((pi / 2) - facePlane.Normal.AngleTo(testVec)) < angleDiff Then            angleDiff = Abs((pi / 2) - facePlane.Normal.AngleTo(testVec))            Set xVec = testVec        End If                Set yVec = facePlane.Normal.CrossProduct(xVec)        Set xVec = yVec.CrossProduct(facePlane.Normal)    End If        ' Create the "fixed" work plane.    Dim wp As WorkPlane    Set wp = asmDef.WorkPlanes.AddFixed(facePlane.RootPoint, xVec, yVec)        ' Create a flush constraint between the face and the workplane with an offset of 0.    Dim flush As FlushConstraint    Set flush = asmDef.Constrain
ts.AddFlushConstraint(selFace, wp, 0, facePlane.RootPoint, facePlane.RootPoint)End Sub

-Brian


Comments

Leave a Reply

Discover more from Autodesk Developer Blog

Subscribe now to keep reading and get access to the full archive.

Continue reading