- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report
Hi,
I'm running into an issue when running a rule on a part, accessed at the assembly level.
For context, I'm trying to generate a standard set of custom iProperties (PART_LENGTH, PART_WIDTH, and PART_THICKNESS) in a part file, regardless of whether the original part had those properties. When run at the part level, the rule works as intended, outputting the expected values written as a custom iProperty. However, when the rule is run at the assembly level, half of the parts output the correct value, and half of the parts display the same (incorrect) values: Length= 12 13/16, Width=12 5/16, and Thickness=5 9/16.
To access the external rules, I've been using this rule, run from the assembly:
Imports System.Threading
Sub Main()
Dim asmDoc As AssemblyDocument = ThisApplication.ActiveDocument
ProcessAssembly(asmDoc)
MessageBox.Show("Parts and Subassemblies Updated", " ")
End Sub
Sub ProcessAssembly(asmDoc As AssemblyDocument)
For Each oRefDoc As Document In asmDoc.AllReferencedDocuments
If oRefDoc.DocumentType = DocumentTypeEnum.kPartDocumentObject Then
ProcessPart(oRefDoc)
ElseIf oRefDoc.DocumentType = DocumentTypeEnum.kAssemblyDocumentObject Then
' Open the subassembly document with write permissions
Dim subAsmDoc As AssemblyDocument = ThisApplication.Documents.Open(oRefDoc.FullFileName, False)
' Process the subassembly
ProcessAssembly(subAsmDoc)
' Save and close the subassembly document
subAsmDoc.Save()
subAsmDoc.Close()
End If
Next
End Sub
Sub ProcessPart(partDoc As Document)
' Open the part document with write permissions
partDoc = ThisApplication.Documents.Open(partDoc.FullFileName, False)
' Add a small delay before activation
Thread.Sleep(500)
' Check if the document is already active
If Not partDoc Is ThisApplication.ActiveDocument Then
Try
partDoc.Activate()
' Add a delay to ensure activation
Thread.Sleep(500)
Catch ex As Exception
Debug.Print("Error activating document: " & ex.Message)
End Try
End If
' Log document activation
Debug.Print("Activated document: " & partDoc.FullFileName)
' Add a 500ms delay before running external rules
Thread.Sleep(500)
' Run the external rules
RunExternalRules(partDoc)
' Add a 500ms delay after running external rules
Thread.Sleep(500)
' Save and close the document
partDoc.Save()
partDoc.Close()
' Log document processing completion
Debug.Print("Processed document: " & partDoc.FullFileName)
End Sub
Sub RunExternalRules(partDoc As Document)
Dim ruleNames As String() = {"AUTO_SIZE"}
For Each ruleName As String In ruleNames
Try
iLogicVb.Automation.RunExternalRule(partDoc, ruleName)
Catch ex As Exception
' Handle exceptions if needed
End Try
Next
End Sub
The external rule I'm accessing (AUTO_SIZE) is:
'THIS RULE DETERMINES PART SIZE USING TWO METHODS.
'THE FIRST METHOD MEASURES THE PART AGAINST THE DEFAULT XYZ ORIENTATION.
'THE SECOND METHOD IS USED IF A PART IS NOT ALIGNED WITH THE DEFAULT XYZ AXIS,
'AND IS DEPENDENT ON A USER-DEFINED UCS (WORK FEATURES > UCS).
'THE PART'S MEASUREMENTS ARE OUTPUT AS A SORTED LIST:
'PARTS ARE SORTED BY: "PART_LENGTH" > "PART_WIDTH" > "PART_THICKNESS" AND OUTPUT AS A
'CUSTOM IPROPERTY VALUE ROUNDED TO THE NEAREST 1/16" (ADJUSTABLE, SEE "Dim inc =").
'RULE SHOULD BE RUN IN THE PART ENVIRONMENT
Dim oDoc As Document
oDoc = ThisDoc.Document
Dim oPDef As PartComponentDefinition = oDoc.ComponentDefinition
Dim oUCSs As UserCoordinateSystems = oPDef.UserCoordinateSystems
Dim oUCS As UserCoordinateSystem = Nothing
Dim oA As Double
Dim oB As Double
Dim oC As Double
'DEFINE ROUNDING INCREMENT FOR FRACTIONAL OUTPUT HERE<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
Dim inc = .0625' rounding increment ( .125, .25, .5, etc)
If oUCSs.Count = 0 Then
'IF NO USER-DEFINED UCS, USE DEFAULT PART ORIENTATION
oA = Math.Round(Measure.PreciseExtentsLength, 3)
oB = Math.Round(Measure.PreciseExtentsWidth, 3)
oC = Math.Round(Measure.PreciseExtentsHeight, 3)
Else
'IF USER DEFINED UCS IS PRESENT, MEASURE PART BASED ON THAT
Dim sb As SurfaceBody = oDoc.ComponentDefinition.SurfaceBodies.Item(1) 'get 3d solid
Dim ucs As UserCoordinateSystem = oDoc.ComponentDefinition.UserCoordinateSystems(1)'get custom user coordinate system
Dim vPoints As New List(Of Point) 'create a list of points (for sorting)
Dim mat As Matrix = ucs.Transformation 'get the transformation matrix from the usc (what it takes to translate from user ucs to origin)
mat.Invert() 'invert the matrix (what it takes to translate from origin to user ucs)
For Each vert As Vertex In sb.Vertices 'cycle through all the points
Dim p As Point = vert.Point 'get the Point data From the Vertex
p.TransformBy(mat) 'invert translate the point data (from origin to user ucs)
vPoints.Add(p) 'add translated point to collection
Next
Dim tg = ThisApplication.TransientGeometry 'create empty min and max points
Dim minPoint As Point = tg.CreatePoint(0, 0, 0)
Dim maxPoint As Point = tg.CreatePoint(0, 0, 0)
'sort points based on x values, and get lowest and highest value
vPoints.Sort(Function(x, y) x.X.CompareTo(y.X))
minPoint.X = vPoints.First.X
maxPoint.X = vPoints.Last.X
'sort points based on y values, and get lowest and highest values
vPoints.Sort(Function(x, y) x.Y.CompareTo(y.Y))
minPoint.Y = vPoints.First.Y
maxPoint.Y = vPoints.Last.Y
'sort points based on z values, and get lowest and highest values
vPoints.Sort(Function(x, y) x.Z.CompareTo(y.Z))
minPoint.Z = vPoints.First.Z
maxPoint.Z = vPoints.Last.Z
Dim sizeX As Double = Math.Abs(maxPoint.X - minPoint.X)
Dim sizeY As Double = Math.Abs(maxPoint.Y - minPoint.Y)
Dim sizeZ As Double = Math.Abs(maxPoint.Z - minPoint.Z)
oA = Math.Round(sizeX/2.54, 5)
oB = Math.Round(sizeY/2.54, 5)
oC = Math.Round(sizeZ/2.54, 5)
End If
Dim sortedValues As New List(Of Double) From {oA, oB, oC}
' Sort the values in descending order
sortedValues.Sort(Function(a, b) b.CompareTo(a))
' Now you can access the sorted values
Dim sortedOa As Double = sortedValues(0)
Dim sortedOb As Double = sortedValues(1)
Dim sortedOc As Double = sortedValues(2)
' Use sortedOa, sortedOb, and sortedOc as needed
' THESE STRINGS DETERMINE THE OUTPUT NAME OF THE CUSTOM IPROPERTIES
Dim propLength As String = "PART_LENGTH"
Dim Length As Double = sortedOa
Dim propWidth As String = "PART_WIDTH"
Dim Width As Double = sortedOb
Dim propHeight As String = "PART_THICKNESS"
Dim Height As Double = sortedOc
Dim roundedLength As Double = Math.Round(Length / inc) * inc
Dim roundedWidth As Double = Math.Round(Width / inc) * inc
Dim roundedHeight As Double = Math.Round(Height / inc) * inc
customPropertySet = ThisDoc.Document.PropertySets.Item("Inventor User Defined Properties")
Try
prop = customPropertySet.Item(propLength)
Catch ' Assume error means not found
customPropertySet.Add("", propLength)
End Try
Try
prop = customPropertySet.Item(propWidth)
Catch ' Assume error means not found
customPropertySet.Add("", propWidth)
End Try
Try
prop = customPropertySet.Item(propHeight)
Catch ' Assume error means not found
customPropertySet.Add("", propHeight)
End Try
iProperties.Value("Custom", propLength) = FormatAsFraction(roundedLength)
iProperties.Value("Custom", propWidth) = FormatAsFraction(roundedWidth)
iProperties.Value("Custom", propHeight) = FormatAsFraction(roundedHeight)
I'm not an expert at coding, but there's been a lot of helpful content on here that's gotten me to this point. I'm running out of ideas as to why I'm getting incorrect values when run from the assembly, but running the rule from the part level shows the expected values.
Solved! Go to Solution.