diff --git a/CatiaNetTest/AssemblyTiers2.vb b/CatiaNetTest/AssemblyTiers2.vb index 2089e30e2f58d6fe7e113a6669fb996b693137dd..cb54f91d2f3f3f38dbac3301948abe0db8938c94 100644 --- a/CatiaNetTest/AssemblyTiers2.vb +++ b/CatiaNetTest/AssemblyTiers2.vb @@ -13,6 +13,7 @@ Public Class AssemblyTiers2 Public intStep As Integer Public dCollSens As Double Public intParts As Integer + Public intNumFaces As Integer Public primaryFasteners As New ArrayList Public secondaryFasteners As New ArrayList Public cAllProducts As New ArrayList @@ -72,13 +73,6 @@ Public Class AssemblyTiers2 oSel.Clear() baseSel.Clear - 'Collision parameters - intStep = 10 - dCollSens = 2 - 'CollisionParams.Show - Debug.Print("Step = " + CStr(intStep)) - Debug.Print("Sensitivity = " + CStr(dCollSens)) - 'Separation of components DeactivateFasteners(document.Product) @@ -87,12 +81,12 @@ Public Class AssemblyTiers2 MsgBox(outputText) 'Distances from global axis system origin to assembly boundary (along global axis) - aAssemblyBoundaries(0) = 0# 'max_X - aAssemblyBoundaries(1) = 0# 'min_X - aAssemblyBoundaries(2) = 0# 'max_Y - aAssemblyBoundaries(3) = 0# 'min_Y - aAssemblyBoundaries(4) = 0# 'max_Z - aAssemblyBoundaries(5) = 0# 'min_Z + aAssemblyBoundaries(0) = -1 / 0 'max_X + aAssemblyBoundaries(1) = 1 / 0 'min_X + aAssemblyBoundaries(2) = -1 / 0 'max_Y + aAssemblyBoundaries(3) = 1 / 0 'min_Y + aAssemblyBoundaries(4) = -1 / 0 'max_Z + aAssemblyBoundaries(5) = 1 / 0 'min_Z 'Global coordinates, of which at least one has to be exceeded by the part origin, for that part to be "disassembled" 'in global axis directions @@ -114,16 +108,29 @@ Public Class AssemblyTiers2 aPartBBGlob(0, 4) = 0# 'z_part_glob_pos aPartBBGlob(0, 5) = 0# 'z_part_glob_neg + 'Initialize aPartBBGlob with safe values + For i = 0 To cRelevantProducts.Count - 1 + aPartBBGlob(i, 0) = -1 / 0 + aPartBBGlob(i, 1) = 1 / 0 + aPartBBGlob(i, 2) = -1 / 0 + aPartBBGlob(i, 3) = 1 / 0 + aPartBBGlob(i, 4) = -1 / 0 + aPartBBGlob(i, 5) = 1 / 0 + Next + Dim BBStartTime As DateTime BBStartTime = Now 'This is used to check whether a product must be moved in current iteration Dim bMoveable(cRelevantProducts.Count - 1) As Boolean + 'Number of faces in assembly represents the geometrical complexity of parts + intNumFaces = 0 + For i = 0 To cRelevantProducts.Count - 1 '########## this won't work if part document name is not = part number ###### - 'Dim partI As Part + ''Dim partI As Part Dim prodI As Product prodI = cRelevantProducts.Item(i) Dim docName As String @@ -133,18 +140,18 @@ Public Class AssemblyTiers2 '############################################################################ 'Determine assembly 's limits - ' Dim partI As Part - ' Dim prodI As Product - ' prodI = cRelevantProducts.Item(i) - ' Dim docName As String - ' docName = prodI.PartNumber + ".CATPart" - ' Dim oPartDoc As PartDocument - ' Dim sPartPath As String - ' sPartPath = prodI.GetMasterShapeRepresentationPathName - ' oPartDoc = CATIA.Documents.Read(sPartPath) - ' Debug.Print ">>> " & docName & " <<<" - 'CATIA.Documents.Item(docName) - ' GenerateBoundingBox oPartDoc, prodI, i + 'Dim partI As Part + 'Dim prodI As Product + 'prodI = cRelevantProducts.Item(i) + 'Dim docName As String + 'docName = prodI.PartNumber + ".CATPart" + 'Dim oPartDoc As PartDocument + 'Dim sPartPath As String + 'sPartPath = prodI.GetMasterShapeRepresentationPathName + 'oPartDoc = CATIA.Documents.Read(sPartPath) + 'Debug.Print(">>> " & docName & " <<<") + ''CATIA.Documents.Item(docName) + 'GenerateBoundingBox(oPartDoc, prodI, i) 'Base component is in cRelevantProducts, but not moveable If productIsInCollection(prodI, cBaseProducts) Then @@ -160,14 +167,21 @@ Public Class AssemblyTiers2 Dim BBSecondsElapsed As Double BBSecondsElapsed = Math.Round(BBMillisecondsElapsed / 1000.0, 2) MsgBox("Bounding box calculation took " & CStr(BBSecondsElapsed) & " seconds") + Debug.Print("Number of faces in assembly: " & CStr(intNumFaces)) - MsgBox("Assembly Boundaries: " & vbNewLine & - "max_X = " & aAssemblyBoundaries(0) & vbNewLine & - "min_X = " & aAssemblyBoundaries(1) & vbNewLine & - "max_Y = " & aAssemblyBoundaries(2) & vbNewLine & - "min_Y = " & aAssemblyBoundaries(3) & vbNewLine & - "max_Z = " & aAssemblyBoundaries(4) & vbNewLine & - "min_Z = " & aAssemblyBoundaries(5)) + 'Collision parameters + Dim dGeomMean As Double + dGeomMean = (aAssemblyBoundaries(0) - aAssemblyBoundaries(1)) * (aAssemblyBoundaries(2) - aAssemblyBoundaries(3)) * (aAssemblyBoundaries(4) - aAssemblyBoundaries(5)) + dGeomMean = dGeomMean ^ (1 / 3) + intStep = Math.Round(dGeomMean / 50, 0) + Debug.Print("Movement step: " & CStr(intStep)) + + dCollSens = 2 + + MsgBox("Assembly dimensions: " & vbNewLine & + "X = " & aAssemblyBoundaries(0) - aAssemblyBoundaries(1) & vbNewLine & + "Y = " & aAssemblyBoundaries(2) - aAssemblyBoundaries(3) & vbNewLine & + "Z = " & aAssemblyBoundaries(4) - aAssemblyBoundaries(5)) 'After the aAssemblyBoundaries and aPartBBGlob are calculated, define aRemovalDistances For i = 0 To cRelevantProducts.Count - 1 @@ -179,15 +193,16 @@ Public Class AssemblyTiers2 aRemovalDistances(i, 5) = aAssemblyBoundaries(5) - aPartBBGlob(i, 4) Next i - MsgBox("Removal distances for " & cRelevantProducts.Item(1).PartNumber & ":" & vbNewLine & - "X_pos = " & aRemovalDistances(0, 0) & vbNewLine & - "X_neg = " & aRemovalDistances(0, 1) & vbNewLine & - "Y_pos = " & aRemovalDistances(0, 2) & vbNewLine & - "Y_neg = " & aRemovalDistances(0, 3) & vbNewLine & - "Z_pos = " & aRemovalDistances(0, 4) & vbNewLine & - "Z_neg = " & aRemovalDistances(0, 5)) + 'MsgBox("Removal distances for " & cRelevantProducts.Item(1).PartNumber & ":" & vbNewLine & + '"X_pos = " & aRemovalDistances(0, 0) & vbNewLine & + '"X_neg = " & aRemovalDistances(0, 1) & vbNewLine & + '"Y_pos = " & aRemovalDistances(0, 2) & vbNewLine & + '"Y_neg = " & aRemovalDistances(0, 3) & vbNewLine & + '"Z_pos = " & aRemovalDistances(0, 4) & vbNewLine & + '"Z_neg = " & aRemovalDistances(0, 5)) '#################### Main algorithm ########################## + Dim intI As Integer 'total number of components in the scene minus base parts Dim intJ As Integer 'number of primary directions (default: global + local) Dim intTier As Integer 'number of current assembly tier @@ -238,25 +253,6 @@ Public Class AssemblyTiers2 Dim cGroups As Groups cGroups = CATIA.ActiveDocument.Product.GetTechnologicalObject("Groups") - 'calculate initial clashes (due to imprecise modelling or STEP file export...) - ' Dim cInitClashes AsCollection - ' Dim oInitClash 'As Clash - ' ' oInitClash = cInitClashes.Add - ' oInitClash.ComputationType = catClashComputationTypeBetweenAll - ' oInitClash.Compute - ' Dim cInitConflicts As Conflicts - ' cInitConflicts = oInitClash.Conflicts - ' Dim numConfl As Integer - ' Dim numClashes As Integer - ' numClashes = 0 - ' For numConfl = 1 To cInitConflicts.Count - ' If cInitConflicts.Item(numConfl).Type = catConflictTypeClash Then - ' cInitClashes.Add cInitConflicts.Item(numConfl) - ' numClashes = numClashes + 1 - ' End If - ' Next numConfl - ' MsgBox CStr(numClashes) & " clashes were detected in the original model." - Dim StartTime As DateTime StartTime = Now @@ -286,14 +282,6 @@ Public Class AssemblyTiers2 bInitPosRecorded(int_i) = True End If - 'For each product, determine whether it is a base product, deactivated or virtual - ' Dim bBaseProduct As Boolean - ' bBaseProduct = productIsInCollection(product1, cBaseProducts) - ' Dim bDeactivated As Boolean - ' bDeactivated = productIsInCollection(product1, cDeactivated) - ' Dim bVirtual As Boolean - ' bVirtual = productIsInCollection(product1, cVirtual) - 'Group that includes our product (needed for collision detection between two selections or groups) Dim group1 As Group group1 = cGroups.Add @@ -305,7 +293,9 @@ Public Class AssemblyTiers2 Dim iStaticProduct As Integer For iStaticProduct = 0 To cRelevantProducts.Count - 1 If iStaticProduct <> int_i And Not bDeactivated(iStaticProduct) Then - group2.AddExplicit(cRelevantProducts.Item(iStaticProduct)) + If BoundingBoxesOverlap(int_i, iStaticProduct) Then + group2.AddExplicit(cRelevantProducts.Item(iStaticProduct)) + End If End If Next iStaticProduct @@ -618,7 +608,6 @@ exitCD: If disassDir(int_i, intAxis) = 1 Then disassDir(int_i, intAxis) = 0 disassDir(int_i, d3.Item(intAxis)) = 1 - Exit For End If Next intAxis Next int_i @@ -835,7 +824,7 @@ exitCD: CATIA.StartCommand("Activate / Deactivate Component") selection1.Clear() intFasteners = intFasteners + 1 - ElseIf InStr(sName, "screw") Or InStr(sName, "schraube") > 0 Then + ElseIf InStr(sName, "screw") > 0 Or InStr(sName, "schraube") > 0 Or (InStr(sName, "iso") > 0 And InStr(sName, "4762") > 0) Or (InStr(sName, "din") > 0 And (InStr(sName, "912") > 0 Or InStr(sName, "933") > 0)) Then Debug.Print(prod.Name + " was identified as a screw") selection1.Add(prod) @@ -862,16 +851,16 @@ exitCD: CATIA.StartCommand("Activate / Deactivate Component") selection1.Clear() intFasteners = intFasteners + 1 - ElseIf InStr(sName, "pin") > 0 Then - Debug.Print(prod.Name + " was identified as a pin") - selection1.Add(prod) + 'ElseIf InStr(sName, "pin") > 0 Then + ' Debug.Print(prod.Name + " was identified as a pin") + ' selection1.Add(prod) - primaryFasteners.Add(prod) + ' primaryFasteners.Add(prod) - CATIA.StartCommand("Activate / Deactivate Component") - selection1.Clear() - intFasteners = intFasteners + 1 - ElseIf InStr(sName, "nut") > 0 Then + ' CATIA.StartCommand("Activate / Deactivate Component") + ' selection1.Clear() + ' intFasteners = intFasteners + 1 + ElseIf InStr(sName, "nut") > 0 Or (InStr(sName, "iso") > 0 And InStr(sName, "4161") > 0) Or (InStr(sName, "din") > 0 And (InStr(sName, "934") > 0 Or InStr(sName, "439") > 0)) Then Debug.Print(prod.Name + " was identified as a nut") selection1.Add(prod) @@ -880,7 +869,7 @@ exitCD: CATIA.StartCommand("Activate / Deactivate Component") selection1.Clear() intFasteners = intFasteners + 1 - ElseIf InStr(sName, "washer") > 0 Then + ElseIf InStr(sName, "washer") > 0 Or (InStr(sName, "din") > 0 And (InStr(sName, "9021") > 0 Or InStr(sName, "125") > 0 Or InStr(sName, "127") > 0)) Then Debug.Print(prod.Name + " was identified as a washer") selection1.Add(prod) @@ -1001,6 +990,7 @@ exitCD: faceSel.Search("Type=Face,sel") Debug.Print("Selected faces: " & CStr(faceSel.Count)) + intNumFaces += faceSel.Count 'Need to check whether Extract crashes given this face and try the next one Dim f As Integer @@ -1714,4 +1704,15 @@ Finish: Return intAns End Function + Function BoundingBoxesOverlap(int_i As Integer, iStaticProduct As Integer) As Boolean + If aPartBBGlob(int_i, 1) >= aPartBBGlob(iStaticProduct, 0) Or aPartBBGlob(int_i, 0) <= aPartBBGlob(iStaticProduct, 1) Then + If aPartBBGlob(int_i, 3) >= aPartBBGlob(iStaticProduct, 2) Or aPartBBGlob(int_i, 2) <= aPartBBGlob(iStaticProduct, 3) Then + If aPartBBGlob(int_i, 5) >= aPartBBGlob(iStaticProduct, 4) Or aPartBBGlob(int_i, 4) <= aPartBBGlob(iStaticProduct, 5) Then + Return False + End If + End If + End If + Return True + End Function + End Class diff --git a/CatiaNetTest/CatiaNetTest.vbproj b/CatiaNetTest/CatiaNetTest.vbproj index 01bf99af4e81a838ef374e743fd3d2a0804ff380..36b6adaf1f53f4d1a70483349b728cc2c2ac1b3c 100644 --- a/CatiaNetTest/CatiaNetTest.vbproj +++ b/CatiaNetTest/CatiaNetTest.vbproj @@ -81,6 +81,7 @@ <DependentUpon>Form1.vb</DependentUpon> <SubType>Form</SubType> </Compile> + <Compile Include="HierarchicalAssemblyTiers.vb" /> <Compile Include="My Project\AssemblyInfo.vb" /> <Compile Include="My Project\Application.Designer.vb"> <AutoGen>True</AutoGen> diff --git a/CatiaNetTest/Form1.Designer.vb b/CatiaNetTest/Form1.Designer.vb index 4b13759686da8538c48bb90b335c925a823b0f8e..c8a93736a9aff1c5b2c76a2b9686ceb6a102e8f3 100644 --- a/CatiaNetTest/Form1.Designer.vb +++ b/CatiaNetTest/Form1.Designer.vb @@ -26,6 +26,10 @@ Partial Class Form1 Me.Button1 = New System.Windows.Forms.Button() Me.Label2 = New System.Windows.Forms.Label() Me.Button2 = New System.Windows.Forms.Button() + Me.Label3 = New System.Windows.Forms.Label() + Me.Button3 = New System.Windows.Forms.Button() + Me.Label4 = New System.Windows.Forms.Label() + Me.Button4 = New System.Windows.Forms.Button() Me.SuspendLayout() ' 'Label1 @@ -49,26 +53,66 @@ Partial Class Form1 'Label2 ' Me.Label2.AutoSize = True - Me.Label2.Location = New System.Drawing.Point(92, 96) + Me.Label2.Location = New System.Drawing.Point(92, 86) Me.Label2.Name = "Label2" - Me.Label2.Size = New System.Drawing.Size(109, 13) + Me.Label2.Size = New System.Drawing.Size(118, 13) Me.Label2.TabIndex = 2 - Me.Label2.Text = "Start collision analysis" + Me.Label2.Text = "Simple collision analysis" ' 'Button2 ' - Me.Button2.Location = New System.Drawing.Point(249, 96) + Me.Button2.Location = New System.Drawing.Point(249, 81) Me.Button2.Name = "Button2" Me.Button2.Size = New System.Drawing.Size(114, 23) Me.Button2.TabIndex = 3 - Me.Button2.Text = "Assembly Tiers 2" + Me.Button2.Text = "Assembly Tiers" Me.Button2.UseVisualStyleBackColor = True ' + 'Label3 + ' + Me.Label3.AutoSize = True + Me.Label3.Location = New System.Drawing.Point(92, 123) + Me.Label3.Name = "Label3" + Me.Label3.Size = New System.Drawing.Size(91, 13) + Me.Label3.TabIndex = 4 + Me.Label3.Text = "Complex products" + ' + 'Button3 + ' + Me.Button3.Location = New System.Drawing.Point(249, 118) + Me.Button3.Name = "Button3" + Me.Button3.Size = New System.Drawing.Size(114, 23) + Me.Button3.TabIndex = 5 + Me.Button3.Text = "Hierarchical" + Me.Button3.UseVisualStyleBackColor = True + ' + 'Label4 + ' + Me.Label4.AutoSize = True + Me.Label4.Location = New System.Drawing.Point(92, 160) + Me.Label4.Name = "Label4" + Me.Label4.Size = New System.Drawing.Size(144, 13) + Me.Label4.TabIndex = 6 + Me.Label4.Text = "AND/OR graph requirements" + ' + 'Button4 + ' + Me.Button4.Location = New System.Drawing.Point(249, 155) + Me.Button4.Name = "Button4" + Me.Button4.Size = New System.Drawing.Size(114, 23) + Me.Button4.TabIndex = 7 + Me.Button4.Text = "LG + MW" + Me.Button4.UseVisualStyleBackColor = True + ' 'Form1 ' Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 13.0!) Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font - Me.ClientSize = New System.Drawing.Size(468, 191) + Me.ClientSize = New System.Drawing.Size(468, 217) + Me.Controls.Add(Me.Button4) + Me.Controls.Add(Me.Label4) + Me.Controls.Add(Me.Button3) + Me.Controls.Add(Me.Label3) Me.Controls.Add(Me.Button2) Me.Controls.Add(Me.Label2) Me.Controls.Add(Me.Button1) @@ -84,4 +128,8 @@ Partial Class Form1 Friend WithEvents Button1 As Button Friend WithEvents Label2 As Label Friend WithEvents Button2 As Button + Friend WithEvents Label3 As Label + Friend WithEvents Button3 As Button + Friend WithEvents Label4 As Label + Friend WithEvents Button4 As Button End Class diff --git a/CatiaNetTest/Form1.vb b/CatiaNetTest/Form1.vb index ac24fb4678e3c0a4e8390a2f371aebf0d2599475..905540142b24b0c93471bb172395ea9b37253cc1 100644 --- a/CatiaNetTest/Form1.vb +++ b/CatiaNetTest/Form1.vb @@ -39,4 +39,19 @@ Public Class Form1 End Try End Sub + + Private Sub Label3_Click(sender As Object, e As EventArgs) Handles Label3.Click + + End Sub + + Private Sub Button3_Click(sender As Object, e As EventArgs) Handles Button3.Click + + Dim hierarchicalAlgorithm As HierarchicalAssemblyTiers = New HierarchicalAssemblyTiers() + + Try + hierarchicalAlgorithm.CatMain() + Catch ex As Exception + + End Try + End Sub End Class diff --git a/CatiaNetTest/HierarchicalAssemblyTiers.vb b/CatiaNetTest/HierarchicalAssemblyTiers.vb new file mode 100644 index 0000000000000000000000000000000000000000..a6dab04571715d2babb81a514eb056f3b946cb5e --- /dev/null +++ b/CatiaNetTest/HierarchicalAssemblyTiers.vb @@ -0,0 +1,1825 @@ +Imports System +Imports HybridShapeTypeLib +Imports INFITF +Imports MECMOD +Imports NavigatorTypeLib +Imports ProductStructureTypeLib +Imports SPATypeLib +Imports PARTITF +Imports Microsoft.Office.Interop.Excel + +Public Class HierarchicalAssemblyTiers + + Public intStep As Integer + Public dCollSens As Double + Public intParts As Integer + Public intNumFaces As Integer + Public primaryFasteners As New ArrayList + Public secondaryFasteners As New ArrayList + Public cAllProducts As New ArrayList + Public cRelevantProducts As New ArrayList + Public cBaseProducts As New ArrayList + Public aRemovalDistances(,) As Double + Public aAssemblyBoundaries(5) As Double + Public aPartBBGlob(,) As Double + Public aInitPos(,) As Double + Public sChosenDirection As String + Public oList As Object + Public CATIA As INFITF.Application + + Sub CatMain() + + CATIA = GetObject(, "CATIA.Application") + If CATIA Is Nothing Then CATIA = CreateObject("CATIA.Application") + + Dim document As ProductDocument + document = CATIA.ActiveDocument + + Dim topProduct As Product + topProduct = document.Product + + AssemblyTiersDetermination(topProduct) + + End Sub + + Sub AssemblyTiersDetermination(theProduct As Product) + + cAllProducts = New ArrayList + cRelevantProducts = New ArrayList + cBaseProducts = New ArrayList + + Debug.Print("========================================================") + + 'Get Products that are one level deeper in the specification tree only (direct children) + Dim oInstances As Collection + oInstances = theProduct.Products + Dim i As Integer + Dim outputText As String + + intParts = oInstances.Count + outputText = "This assembly contains " + CStr(intParts) + " components" + vbNewLine + MsgBox(outputText) + + 'Select the assembly's base components + 'Declare selection + Dim oSel As Selection + Dim baseSel As Object 'to deal with restricted function problem + oSel = CATIA.ActiveDocument.Selection + baseSel = oSel + 'Create an array for CATProducts + Dim strArray(0) + strArray(0) = "Product" + 'Display a messagebox prompting the user to select CATIA parts + MsgBox("Please select the assembly's base product") + Dim sStatus As String + sStatus = baseSel.SelectElement3(strArray, "Select parts or subassemblies", False, INFITF.CATMultiSelectionMode.CATMultiSelTriggWhenUserValidatesSelection, False) + + For i = 1 To baseSel.Count + cBaseProducts.Add(baseSel.Item(i).LeafProduct) + Debug.Print("Added base component: " & baseSel.Item(i).LeafProduct.Name) + Next + + oSel.Clear() + baseSel.Clear + + 'Separation of components + DeactivateFasteners(theProduct) + + 'Display the number of relevant parts + outputText = CStr(cRelevantProducts.Count) + " components are considered in precedence graph generation" + MsgBox(outputText) + + 'Distances from global axis system origin to assembly boundary (along global axis) + aAssemblyBoundaries(0) = 0# 'max_X + aAssemblyBoundaries(1) = 0# 'min_X + aAssemblyBoundaries(2) = 0# 'max_Y + aAssemblyBoundaries(3) = 0# 'min_Y + aAssemblyBoundaries(4) = 0# 'max_Z + aAssemblyBoundaries(5) = 0# 'min_Z + + 'Global coordinates, of which at least one has to be exceeded by the part origin, for that part to be "disassembled" + 'in global axis directions + ReDim aRemovalDistances(cRelevantProducts.Count - 1, 5) + aRemovalDistances(0, 0) = 0# 'X_pos + aRemovalDistances(0, 1) = 0# 'X_neg + aRemovalDistances(0, 2) = 0# 'Y_pos + aRemovalDistances(0, 3) = 0# 'Y_neg + aRemovalDistances(0, 4) = 0# 'Z_pos + aRemovalDistances(0, 5) = 0# 'Z_neg + + 'Store information about secondary BB (6 distances to boundary planes from part origin along global x/y/z directions) - used to define aRemovalDistances + 'Secondary BB: faces parallel to global origin planes and defined by outermost corner points of local BB of this part + ReDim aPartBBGlob(cRelevantProducts.Count - 1, 5) + aPartBBGlob(0, 0) = 0# 'x_part_glob_pos + aPartBBGlob(0, 1) = 0# 'x_part_glob_neg + aPartBBGlob(0, 2) = 0# 'y_part_glob_pos + aPartBBGlob(0, 3) = 0# 'y_part_glob_neg + aPartBBGlob(0, 4) = 0# 'z_part_glob_pos + aPartBBGlob(0, 5) = 0# 'z_part_glob_neg + + Dim BBStartTime As DateTime + BBStartTime = Now + + 'This is used to check whether a product must be moved in current iteration + Dim bMoveable(cRelevantProducts.Count - 1) As Boolean + + 'Number of faces in assembly represents the geometrical complexity of parts + intNumFaces = 0 + + For i = 0 To cRelevantProducts.Count - 1 + + 'Get collection of elementary parts (elements, leaf parts) making up subassembly i + Dim oSubassembly As Product + oSubassembly = cRelevantProducts.Item(i) + Dim cElements As New ArrayList + ExtractProducts(oSubassembly, cElements) + + Debug.Print("Elementary parts: " & CStr(cElements.Count)) + + For j = 0 To cElements.Count - 1 + + '########## this won't work if part document name is not = part number ###### + ''Dim partI As Part + Dim prodI As Product + prodI = cElements.Item(j) + Dim docName As String + docName = prodI.PartNumber + ".CATPart" + Debug.Print(">>> " & docName & " <<<") + GenerateBoundingBox(CATIA.Documents.Item(docName), prodI, i) + '############################################################################ + + 'Determine assembly 's limits + 'Dim partI As Part + 'Dim prodI As Product + 'prodI = cElements.Item(j) + 'Dim docName As String + 'docName = prodI.PartNumber + ".CATPart" + 'Dim oPartDoc As PartDocument + 'Dim sPartPath As String + 'sPartPath = prodI.GetMasterShapeRepresentationPathName + 'oPartDoc = CATIA.Documents.Read(sPartPath) + 'Debug.Print(">>> " & docName & " <<<") + ''CATIA.Documents.Item(docName) + 'GenerateBoundingBox(oPartDoc, prodI, i) + + Next j + + 'Base component is in cRelevantProducts, but not moveable + If productIsInCollection(oSubassembly, cBaseProducts) Then + bMoveable(i) = False + Else + bMoveable(i) = True + End If + + Next i + + Dim BBMillisecondsElapsed As Double + BBMillisecondsElapsed = (Now - BBStartTime).TotalMilliseconds + Dim BBSecondsElapsed As Double + BBSecondsElapsed = Math.Round(BBMillisecondsElapsed / 1000.0, 2) + MsgBox("Bounding box calculation took " & CStr(BBSecondsElapsed) & " seconds") + Debug.Print("Number of faces in assembly: " & CStr(intNumFaces)) + + 'Collision parameters + Dim dGeomMean As Double + dGeomMean = (aAssemblyBoundaries(0) - aAssemblyBoundaries(1)) * (aAssemblyBoundaries(2) - aAssemblyBoundaries(3)) * (aAssemblyBoundaries(4) - aAssemblyBoundaries(5)) + dGeomMean = dGeomMean ^ (1 / 3) + intStep = Math.Round(dGeomMean / 50, 0) + Debug.Print("Movement step: " & CStr(intStep)) + + dCollSens = 2 + + MsgBox("Assembly dimensions: " & vbNewLine & + "X = " & aAssemblyBoundaries(0) - aAssemblyBoundaries(1) & vbNewLine & + "Y = " & aAssemblyBoundaries(2) - aAssemblyBoundaries(3) & vbNewLine & + "Z = " & aAssemblyBoundaries(4) - aAssemblyBoundaries(5)) + + 'After the aAssemblyBoundaries and aPartBBGlob are calculated, define aRemovalDistances + For i = 0 To cRelevantProducts.Count - 1 + aRemovalDistances(i, 0) = aAssemblyBoundaries(0) - aPartBBGlob(i, 1) + aRemovalDistances(i, 1) = aAssemblyBoundaries(1) - aPartBBGlob(i, 0) + aRemovalDistances(i, 2) = aAssemblyBoundaries(2) - aPartBBGlob(i, 3) + aRemovalDistances(i, 3) = aAssemblyBoundaries(3) - aPartBBGlob(i, 2) + aRemovalDistances(i, 4) = aAssemblyBoundaries(4) - aPartBBGlob(i, 5) + aRemovalDistances(i, 5) = aAssemblyBoundaries(5) - aPartBBGlob(i, 4) + Next i + + 'MsgBox("Removal distances for " & cRelevantProducts.Item(1).PartNumber & ":" & vbNewLine & + '"X_pos = " & aRemovalDistances(0, 0) & vbNewLine & + '"X_neg = " & aRemovalDistances(0, 1) & vbNewLine & + '"Y_pos = " & aRemovalDistances(0, 2) & vbNewLine & + '"Y_neg = " & aRemovalDistances(0, 3) & vbNewLine & + '"Z_pos = " & aRemovalDistances(0, 4) & vbNewLine & + '"Z_neg = " & aRemovalDistances(0, 5)) + + '#################### Main algorithm ########################## + + Dim intI As Integer 'total number of components in the scene minus base parts + Dim intJ As Integer 'number of primary directions (default: global + local) + Dim intTier As Integer 'number of current assembly tier + Dim int_i As Integer 'product index in cRelevantProducts + Dim int_i_cycle As Integer 'product counter + Dim int_j As Integer 'primary direction index 1..12 + Dim int_j_temp As Integer 'used to display movement direction once + Dim int_k As Integer 'secondary direction index 1..10 + Dim total_coll As Long 'counter of total collision detections + Dim cDeactivated As New ArrayList 'really deactivated products + Dim cVirtual As Collection 'these funny green parts + Dim precedenceMatrix(cRelevantProducts.Count - 1, cRelevantProducts.Count - 1) As Single + Dim disassDir(cRelevantProducts.Count - 1, 11) + Dim aTiers(cRelevantProducts.Count - 1) As Integer + ReDim aInitPos(cRelevantProducts.Count - 1, 11) 'remember initial positions of the products + Dim bInitPosRecorded(cRelevantProducts.Count - 1) As Boolean + Dim bDeactivated(cRelevantProducts.Count - 1) As Boolean + + intI = cRelevantProducts.Count - 1 'the index of base components will be simply skipped (cRelevantProducts includes cBaseProducts, unlike in the paper!) + intJ = 6 'number of disassembly directions (6 - only global axes, 12 - including local axes) + intTier = 1 'counts current disassembly tier (lower number means earlier disassembly possible) - this gets reversed in the end + int_i = 0 'index of current part in collection of relevant products + int_i_cycle = 0 'counter for the current tier iteration + int_j = 0 'index of disassembly direction + int_j_temp = 0 'used to display movement direction once + total_coll = 0 + + 'map indices to directions (careful, starts from 0 here, but the paper and moveProduct uses 1 as start) + Dim d1 + d1 = CreateObject("Scripting.Dictionary") + d1.Add(0, "Global X+") + d1.Add(1, "Global Y+") + d1.Add(2, "Global Z+") + d1.Add(3, "Global X-") + d1.Add(4, "Global Y-") + d1.Add(5, "Global Z-") + d1.Add(6, "Local X+") + d1.Add(7, "Local Y+") + d1.Add(8, "Local Z+") + d1.Add(9, "Local X-") + d1.Add(10, "Local Y-") + d1.Add(11, "Local Z-") + + 'access the clash technology object + Dim cClashes As Clashes + cClashes = CATIA.ActiveDocument.Product.GetTechnologicalObject("Clashes") + 'access the groups technology object + Dim cGroups As Groups + cGroups = CATIA.ActiveDocument.Product.GetTechnologicalObject("Groups") + + Dim StartTime As DateTime + StartTime = Now + + Do + + 'Processing next Product + Dim product1 As Product + product1 = cRelevantProducts.Item(int_i) + Debug.Print("Processing " & product1.Name & " [tier=" & intTier & ", i_cycle=" & int_i_cycle & ", I=" & intI & "]") + + 'Skip not moveable products + If Not bMoveable(int_i) Then + 'the part is a base component or deactivated + GoTo entry0 + End If + + 'Remember initial position P_i (initPos) + Dim initPos(11) + Dim oPosition1 As Object + oPosition1 = product1.Position + oPosition1.GetComponents(initPos) + If bInitPosRecorded(int_i) = False Then + Dim ip As Integer + For ip = 0 To 11 + aInitPos(int_i, ip) = initPos(ip) + Next ip + bInitPosRecorded(int_i) = True + End If + + 'Group that includes our product (needed for collision detection between two selections or groups) + Dim group1 As Group + group1 = cGroups.Add + group1.AddExplicit(product1) + + 'Create a Group of Products that this product shouldn't collide with + Dim group2 As Group + group2 = cGroups.Add + Dim iStaticProduct As Integer + For iStaticProduct = 0 To cRelevantProducts.Count - 1 + If iStaticProduct <> int_i And Not bDeactivated(iStaticProduct) Then + group2.AddExplicit(cRelevantProducts.Item(iStaticProduct)) + End If + Next iStaticProduct + + Do +entry1: + 'Movement step in a given direction + + 'If it is a movable part (not base component or already deactivated or "virtual" part from higher tier)... + If bMoveable(int_i) = True Then + + 'move component intStep distance in int_j direction + moveProduct(product1, int_j, True) + + 'display current disassembly direction once it changes + If int_j <> int_j_temp Then + Debug.Print("[" & d1.Item(int_j) & "]") + int_j_temp = int_j + End If + + 'collision detection + If collisionDetected(cClashes, group1, group2) Then + + 'check for collisions with higher tier + Dim detConflicts As Conflicts + detConflicts = cClashes.Item(cClashes.Count).Conflicts + + If detConflicts.Count > 0 Then + + Dim oConflict1 As Conflict + Dim ic As Integer + + For ic = 1 To detConflicts.Count + + oConflict1 = detConflicts.Item(ic) + oConflict1.Status = SPATypeLib.CatConflictStatus.catConflictStatusRelevant + + If oConflict1.Type = SPATypeLib.CatConflictType.catConflictTypeClash Then + + If oConflict1.Value < -dCollSens Then + + Dim secProduct As Product + 'get the product we collided with + secProduct = oConflict1.SecondProduct + + 'find the tier of the second product + 'Dim dummyProd As Product + 'Dim iIndex As Integer + 'iIndex = 0 + 'For Each dummyProd In cRelevantProducts + ' If dummyProd.Name = secProduct.Name Then + ' Exit For + ' End If + ' iIndex = iIndex + 1 + 'Next dummyProd + Dim secTier As Integer + Dim iIndex As Integer + iIndex = ParentSubassemblyIndex(secProduct, cRelevantProducts) + secTier = aTiers(iIndex) + + 'as soon as secTier is not the direct higher tier, no reason to move further + If secTier < intTier - 1 Then + GoTo exit1 + End If + + 'if the disassembly tier is 1 lower (attention: tiers get reversed in the end to the assembly tiers!) + If secTier = intTier - 1 And Not (secTier = 0 And intTier = 1) Then + + Debug.Print("Collision with higher tier: " & oConflict1.FirstProduct.Name & " - " & oConflict1.SecondProduct.Name & " = " & oConflict1.Value) + + 'record precedence relation, because secProduct is an obstacle in the way of the current product + precedenceMatrix(int_i, iIndex) = 1 + + 'move the product through the "virtual" part from higher tier + GoTo entry1 + + End If + + End If 'deeper than dCollSens + + End If 'clash + + Next ic 'next conflict + + End If +exit1: + 'move product to initial position + Dim oPosition3 As Object + oPosition3 = product1.Position + oPosition3.SetComponents(initPos) + 'take next direction + int_j = int_j + 1 + 'if not all directions are checked for this product... + If int_j < intJ Then + 'continue movement in primary directions (movement loop) + Else + 'all directions were checked + total_coll = total_coll + intJ + Debug.Print("Disassembly trials: " & total_coll) + int_i = int_i + 1 + int_i_cycle = int_i_cycle + 1 + int_j = 0 + int_j_temp = 0 + + 'if active products remain in this cycle... + If int_i_cycle <= intI - cBaseProducts.Count Then + 'process next product in this cycle + Exit Do + Else + 'all components in this cycle were checked + Dim p As Integer + Dim intItemp As Integer + intItemp = intI + 'record tiers + For p = 0 To cRelevantProducts.Count - 1 + If productIsInCollection(cRelevantProducts.Item(p), cBaseProducts) Then + 'base product always has tier 0 (doesn't get reversed) + aTiers(p) = 0 + Else + 'not a base product + 'product has valid disass. directions and has no tier recorded yet + If productHasValidDisassDir(p, disassDir) And Not aTiers(p) > 0 Then + 'save tier + aTiers(p) = intTier + 'decrease the counter of active products in assembly + intI = intI - 1 + 'change visuals for "virtual" products + Dim virtSelection As Selection + virtSelection = CATIA.ActiveDocument.Selection + virtSelection.Clear() + virtSelection.Add(cRelevantProducts.Item(p)) + Dim visProperties1 As Object + visProperties1 = virtSelection.VisProperties + visProperties1.SetRealColor(80, 255, 160, 1) + virtSelection.Clear() + 'remember virtual green products + 'cVirtual.Add cRelevantProducts.Item(p) + 'fix position + bMoveable(p) = False + 'Deactivate last disassembly tier directly + If intI = cBaseProducts.Count - 1 Then + Dim selektion As Selection + selektion = CATIA.ActiveDocument.Selection + selektion.Clear() + selektion.Add(cRelevantProducts.Item(p)) + CATIA.StartCommand("Activate / Deactivate Component") + selektion.Clear() + cDeactivated.Add(cRelevantProducts.Item(p)) + bDeactivated(p) = True + End If + End If + 'product from higher tier + If productHasValidDisassDir(p, disassDir) And aTiers(p) = intTier - 1 Then + 'deactivate + Dim selection2 As Selection + selection2 = CATIA.ActiveDocument.Selection + selection2.Clear() + selection2.Add(cRelevantProducts.Item(p)) + CATIA.StartCommand("Activate / Deactivate Component") + selection2.Clear() + cDeactivated.Add(cRelevantProducts.Item(p)) + bDeactivated(p) = True + End If + End If + Next p + + 'Notify the user if no parts could be disassembled in this tier + If intI = intItemp Then + Debug.Print("WARNING! No parts could be removed during this cycle." & vbNewLine & "This is usually due to inaccuracies in modelling (e.g. collisions in initial assembly).") + GoTo exitCD + End If + + 'recalculate assembly boundaries and removal distances + RecalculateRemovalDistances(cRelevantProducts, cDeactivated) + + 'if there are still parts to disassemble... + If intI >= cBaseProducts.Count Then + 'increment tier + intTier = intTier + 1 + 'process next cycle of products + int_i = 0 + int_i_cycle = 0 + Exit Do + Else + 'all parts were disassembled + 'end collision detection algorithm + GoTo exitCD + End If + End If + End If + Else + 'no collisions after the movement step + 'check whether part reached final position + If productReachedFinalPosition(product1, int_i) Then + 'store valid disassembly direction + disassDir(int_i, int_j) = 1 + GoTo exit1 + Else + 'continue movement in primary directions (movement loop) + End If + End If + Else +entry0: + 'the part is a base component or deactivated + Debug.Print("Skipping " + product1.Name + " (base component or deactivated)") + int_i = int_i + 1 + 'process next product + Exit Do + End If + Loop 'movement loop + Loop 'product loop + +exitCD: + + Dim SecondsElapsed As Double + Dim MillisecondsElapsed As Double + MillisecondsElapsed = (Now - StartTime).TotalMilliseconds + SecondsElapsed = Math.Round(MillisecondsElapsed / 1000.0, 2) + MsgBox("Collision detection algorithm finished execution after " & CStr(SecondsElapsed) & " seconds") + + 'Return products to their initial positions, activate them + Dim p1 As Integer + For p1 = 0 To cRelevantProducts.Count - 1 + If Not productIsInCollection(cRelevantProducts.Item(p1), cBaseProducts) And bDeactivated(p1) Then + Dim oPosition4 As Object + oPosition4 = cRelevantProducts.Item(p1).Position + Dim aPos(11) + For comp = 0 To 11 + aPos(comp) = aInitPos(p1, comp) + Next comp + oPosition4.SetComponents(aPos) + Dim selection4 As Selection + selection4 = CATIA.ActiveDocument.Selection + selection4.Clear() + selection4.Add(cRelevantProducts.Item(p1)) + CATIA.StartCommand("Activate / Deactivate Component") + selection4.Clear() + End If + Next p1 + + 'Select a single extraction direction in case there are multiple + Dim d2 + d2 = CreateObject("Scripting.Dictionary") + d2.Add("Global X+", 0) + d2.Add("Global Y+", 1) + d2.Add("Global Z+", 2) + d2.Add("Global X-", 3) + d2.Add("Global Y-", 4) + d2.Add("Global Z-", 5) + d2.Add("Local X+", 6) + d2.Add("Local Y+", 7) + d2.Add("Local Z+", 8) + d2.Add("Local X-", 9) + d2.Add("Local Y-", 10) + d2.Add("Local Z-", 11) + 'Inverse axis indices + Dim d3 + d3 = CreateObject("Scripting.Dictionary") + d3.Add(0, 3) + d3.Add(1, 4) + d3.Add(2, 5) + d3.Add(3, 0) + d3.Add(4, 1) + d3.Add(5, 2) + d3.Add(6, 9) + d3.Add(7, 10) + d3.Add(8, 11) + d3.Add(9, 6) + d3.Add(10, 7) + d3.Add(11, 8) + For int_i = 0 To cRelevantProducts.Count - 1 + 'Dim sum As Integer + 'sum = 0 + 'For intAxis = 0 To intJ - 1 + ' sum = sum + disassDir(int_i, intAxis) + 'Next intAxis + ''Only for products with multiple extraction directions + 'If sum > 1 Then + ' 'Add options to ComboBox + ' For intAxis = 0 To intJ - 1 + ' If disassDir(int_i, intAxis) = 1 Then + ' ExtractionDirection.ComboBox1.AddItem(d1.Item(intAxis)) + ' End If + ' Next intAxis + ' 'Highlight the product in CATIA + ' Dim selection5 As Selection + ' selection5 = CATIA.ActiveDocument.Selection + ' selection5.Clear() + ' selection5.Add(cRelevantProducts.Item(int_i + 1)) + ' 'Show dialog + ' ExtractionDirection.Show + ' selection5.Clear() + ' 'Translate chosen axis name back into index 0..11 + ' Dim iChosenDir As Integer + ' iChosenDir = d2.Item(sChosenDirection) + ' 'Set all other disassembly directions to 0 + ' For intAxis = 0 To intJ - 1 + ' If intAxis = iChosenDir Then + ' disassDir(int_i, intAxis) = 1 + ' Else + ' disassDir(int_i, intAxis) = 0 + ' End If + ' Next intAxis + 'End If + 'Reverse tier values + Dim intMaxTier As Integer + intMaxTier = intTier + If aTiers(int_i) <> 0 Then + aTiers(int_i) = intMaxTier + 1 - aTiers(int_i) + End If + 'Reverse disassembly axis (assembly axis = -disass. axis) + For intAxis = 0 To intJ - 1 + If disassDir(int_i, intAxis) = 1 Then + disassDir(int_i, intAxis) = 0 + disassDir(int_i, d3.Item(intAxis)) = 1 + End If + Next intAxis + Next int_i + + 'Association of components belonging to sequential tiers + + Dim cClashes1 As Clashes + Dim oClash1 As Clash + oClash1 = cClashes.Add + oClash1.ComputationType = CatClashComputationType.catClashComputationTypeBetweenAll + oClash1.Compute + Dim cInitConflicts As Conflicts + cInitConflicts = oClash1.Conflicts + Dim initConfl As Conflict + Dim nConfl As Integer + nConfl = 0 + For Each initConfl In cInitConflicts + Dim firstIndex As Integer + Dim secondIndex As Integer + firstIndex = ParentSubassemblyIndex(initConfl.FirstProduct, cRelevantProducts) + secondIndex = ParentSubassemblyIndex(initConfl.SecondProduct, cRelevantProducts) + If aTiers(firstIndex) = aTiers(secondIndex) - 1 Then + precedenceMatrix(firstIndex, secondIndex) = 1 + End If + If aTiers(secondIndex) = aTiers(firstIndex) - 1 Then + precedenceMatrix(secondIndex, firstIndex) = 1 + End If + Next initConfl + + ' For int_i = 1 To cRelevantProducts.Count + ' Dim bNoContacts As Boolean + ' bNoContacts = True + ' 'loop over components from previous tier + ' For int_j = 1 To cRelevantProducts.Count + ' If aTiers(int_j - 1) = aTiers(int_i - 1) - 1 And aTiers(int_i - 1) <> 0 Then + ' 'Test for contact + ' 'define two groups + ' Dim group11 As Group + ' Dim group21 As Group + ' group11 = cGroups.Add + ' group21 = cGroups.Add + ' group11.AddExplicit cRelevantProducts.Item(int_i) + ' group21.AddExplicit cRelevantProducts.Item(int_j) + ' 'create a new clash analysis + ' Dim oClash 'As Clash + ' oClash = cClashes.Add + ' oClash.ComputationType = catClashComputationTypeBetweenTwo + ' oClash.FirstGroup = group11 + ' oClash.SecondGroup = group21 + ' oClash.InterferenceType = catClashInterferenceTypeContact + ' oClash.Compute + ' Dim cConflicts As Conflicts + ' cConflicts = oClash.Conflicts + ' If cConflicts.Count > 0 Then + ' precedenceMatrix(int_j - 1, int_i - 1) = 1 + ' bNoContacts = False + ' End If + ' End If + ' Next int_j + ' Next int_i + + 'Export data to Excel + Dim objExcel As Microsoft.Office.Interop.Excel.Application + objExcel = CreateObject("Excel.Application") + objExcel.Visible = True + objExcel.Workbooks.Add + objExcel.ActiveWorkbook.Sheets.Add.Name = "Precedence Matrix" + Dim objSheet1, objSheet2 As Object + objSheet1 = objExcel.ActiveWorkbook.Worksheets(2) + objSheet1.Name = "Assembly Directions" + objSheet2 = objExcel.ActiveWorkbook.Worksheets(1) + + 'Assembly directions + objSheet1.Cells(1, 1).Value = "Product" + objSheet1.Cells(1, 2).Value = "+X" + objSheet1.Cells(1, 3).Value = "+Y" + objSheet1.Cells(1, 4).Value = "+Z" + objSheet1.Cells(1, 5).Value = "-X" + objSheet1.Cells(1, 6).Value = "-Y" + objSheet1.Cells(1, 7).Value = "-Z" + objSheet1.Cells(1, 8).Value = "Assembly Tier" + For int_i = 0 To cRelevantProducts.Count - 1 + objSheet1.Cells(int_i + 2, 1).Value = cRelevantProducts.Item(int_i).Name + For intAxis = 0 To intJ - 1 + objSheet1.Cells(int_i + 2, 2 + intAxis).Value = disassDir(int_i, intAxis) + Next intAxis + objSheet1.Cells(int_i + 2, intJ + 2).Value = aTiers(int_i) + Next int_i + + 'Precedence relations + For int_i = 0 To cRelevantProducts.Count - 1 + For int_j = 0 To cRelevantProducts.Count - 1 + objSheet2.Cells(int_i + 1, int_j + 1).Value = precedenceMatrix(int_i, int_j) + Next int_j + Next int_i + + 'Save and close excel workbook + Dim xlsFileName As String = theProduct.PartNumber + Dim xlsPath As String = "D:\mikep\Files\RWTH\Master Produktionstechnik\Masterarbeit\Experimente\" + objExcel.ActiveWorkbook.SaveAs(Filename:=xlsPath & xlsFileName & ".xlsx") + objExcel.ActiveWorkbook.Close(SaveChanges:=True) + 'close the excel application + objExcel.Quit() + ReleaseObject(objExcel) + + 'Once we are done on this level, generate precedence diagrams for each subassembly recursively + Dim subassembly As Product + For Each subassembly In cRelevantProducts + Dim leafProducts As New ArrayList + ExtractProducts(subassembly, leafProducts) + If leafProducts.Count > 5 Then + AssemblyTiersDetermination(subassembly) + End If + Next subassembly + + End Sub + Sub ExtractProducts(oCurrentProduct As Product, cElementaryParts As ArrayList) + + Dim oCurrentTreeNode As Product + Dim i As Integer + + If oCurrentProduct.Products.Count = 0 Then + cElementaryParts.Add(oCurrentProduct) + End If + + For i = 1 To oCurrentProduct.Products.Count + oCurrentTreeNode = oCurrentProduct.Products.Item(i) + + 'recursive + If oCurrentTreeNode.Products.Count > 0 Then + ExtractProducts(oCurrentTreeNode, cElementaryParts) + Else + Debug.Print(oCurrentTreeNode.PartNumber & " (" & oCurrentTreeNode.Name & ") is a leaf product") + 'remove special characters from the part number + Dim newPartNo As String + Dim newCharacter As String + newCharacter = " " + newPartNo = oCurrentTreeNode.PartNumber + newPartNo = Replace(newPartNo, "<", newCharacter) + newPartNo = Replace(newPartNo, ">", newCharacter) + newPartNo = Replace(newPartNo, "/", newCharacter) + oCurrentTreeNode.PartNumber = newPartNo + cElementaryParts.Add(oCurrentTreeNode) + End If + + Next + + End Sub + + Sub GetNextNode(oCurrentProduct As Product) + + Dim oCurrentTreeNode As Product + Dim i As Integer + + For i = 1 To oCurrentProduct.Products.Count + oCurrentTreeNode = oCurrentProduct.Products.Item(i) + + If IsPart(oCurrentTreeNode) = True Then + MsgBox(oCurrentTreeNode.PartNumber & " is a part") + ElseIf IsProduct(oCurrentTreeNode) = True Then + MsgBox(oCurrentTreeNode.PartNumber & " is a product") + Else + MsgBox(oCurrentTreeNode.PartNumber & " is a component") + End If + + 'recursive + If oCurrentTreeNode.Products.Count > 0 Then + GetNextNode(oCurrentTreeNode) + End If + + Next + + End Sub + + Function IsPart(objCurrentProduct As Product) As Boolean + + Dim oTestPart As PartDocument + + oTestPart = Nothing + + On Error Resume Next + + oTestPart = CATIA.Documents.Item(objCurrentProduct.PartNumber & ".CATPart") + + If Not oTestPart Is Nothing Then + IsPart = True + Else + IsPart = False + End If + + End Function + + Function IsProduct(objCurrentProduct As Product) As Boolean + + Dim oTestProduct As ProductDocument + + oTestProduct = Nothing + + On Error Resume Next + + oTestProduct = CATIA.Documents.Item(objCurrentProduct.PartNumber & ".CATProduct") + + If Not oTestProduct Is Nothing Then + IsProduct = True + Else + IsProduct = False + End If + + End Function + + Function DeactivateFasteners(objProduct As Product) + + Dim objParts As Collection + 'On the top level of product tree + objParts = objProduct.Products + 'Recursive + 'objParts = cAllProducts + Dim selection1 As Selection + selection1 = CATIA.ActiveDocument.Selection + selection1.Clear() + + Dim intFasteners As Integer + intFasteners = 0 + + For Each prod In objParts + Dim sName As String + Dim primFastSize As Integer + + sName = LCase(prod.PartNumber) + 'Debug.Print sName + If InStr(sName, "bolt") > 0 Then + Debug.Print(prod.Name + " was identified as a bolt") + selection1.Add(prod) + + primaryFasteners.Add(prod) + + CATIA.StartCommand("Activate / Deactivate Component") + selection1.Clear() + intFasteners = intFasteners + 1 + ElseIf InStr(sName, "screw") > 0 Or InStr(sName, "schraube") > 0 Or (InStr(sName, "iso") > 0 And InStr(sName, "4762") > 0) Or (InStr(sName, "din") > 0 And (InStr(sName, "912") > 0 Or InStr(sName, "933") > 0)) Then + Debug.Print(prod.Name + " was identified as a screw") + selection1.Add(prod) + + primaryFasteners.Add(prod) + + CATIA.StartCommand("Activate / Deactivate Component") + selection1.Clear() + intFasteners = intFasteners + 1 + ElseIf InStr(sName, "clip") > 0 Then + Debug.Print(prod.Name + " was identified as a clip") + selection1.Add(prod) + + primaryFasteners.Add(prod) + + CATIA.StartCommand("Activate / Deactivate Component") + selection1.Clear() + intFasteners = intFasteners + 1 + ElseIf InStr(sName, "wedge") > 0 Then + Debug.Print(prod.Name + " was identified as a wedge") + selection1.Add(prod) + + primaryFasteners.Add(prod) + + CATIA.StartCommand("Activate / Deactivate Component") + selection1.Clear() + intFasteners = intFasteners + 1 + 'ElseIf InStr(sName, "pin") > 0 Then + ' Debug.Print(prod.Name + " was identified as a pin") + ' selection1.Add(prod) + + ' primaryFasteners.Add(prod) + + ' CATIA.StartCommand("Activate / Deactivate Component") + ' selection1.Clear() + ' intFasteners = intFasteners + 1 + ElseIf InStr(sName, "nut") > 0 Or (InStr(sName, "iso") > 0 And InStr(sName, "4161") > 0) Or (InStr(sName, "din") > 0 And (InStr(sName, "934") > 0 Or InStr(sName, "439") > 0)) Then + Debug.Print(prod.Name + " was identified as a nut") + selection1.Add(prod) + + secondaryFasteners.Add(prod) + + CATIA.StartCommand("Activate / Deactivate Component") + selection1.Clear() + intFasteners = intFasteners + 1 + ElseIf InStr(sName, "washer") > 0 Or (InStr(sName, "din") > 0 And (InStr(sName, "9021") > 0 Or InStr(sName, "125") > 0 Or InStr(sName, "127") > 0)) Then + Debug.Print(prod.Name + " was identified as a washer") + selection1.Add(prod) + + secondaryFasteners.Add(prod) + + CATIA.StartCommand("Activate / Deactivate Component") + selection1.Clear() + intFasteners = intFasteners + 1 + Else + cRelevantProducts.Add(prod) + End If + Next + + 'CATIA.StartCommand ("Activate / Deactivate Component") + Debug.Print("Deactivated " + CStr(intFasteners) + " fasteners") + intParts = intParts - intFasteners + Debug.Print(CStr(intParts) + " parts to assemble") + MsgBox("Fasteners are deacivated. Press OK to proceed.") + + End Function + + Function GenerateBoundingBox(partDocument1 As PartDocument, objProduct As Product, i As Integer) + 'Processes a single part to extract its origin XYZ, min/max X/Y/Z + + CATIA.DisplayFileAlerts = False + + 'Declare variables + Dim axis + Dim remake + Dim part1 As Part + Dim axisref As Object + Dim shapeFactory1 As ShapeFactory + Dim hybridShapeFactory1 As HybridShapeFactory + Dim sStatus As String + Dim hybridShapeD1, hybridShapeD2, hybridShapeD3 As HybridShapeDirection + Dim a1, a2, a3, a4, a5, a6 'To change the offsets of the box + Dim bodies1 As Bodies + Dim body1 As Body + Dim reference1 As Reference + Dim HybridShapeExtremum1, HybridShapeExtremum2, HybridShapeExtremum3 As HybridShapeExtremum + Dim HybridShapeExtremum4, HybridShapeExtremum5, HybridShapeExtremum6 As HybridShapeExtremum + Dim originCoord(2) + Dim faceSel As Object + + 'Check whether we are processing a Part + If (InStr(partDocument1.Name, ".CATPart")) <> 0 Then + part1 = partDocument1.Part + hybridShapeFactory1 = part1.HybridShapeFactory + + Dim axiscoord(2) + Dim axissyst + + Dim axisSystem As AxisSystem + axisSystem = part1.AxisSystems.Item(1) + + axissyst = axisSystem + axisref = axisSystem + + Dim ref_name_systaxis As String + ref_name_systaxis = axissyst.Name + + axissyst.IsCurrent = 1 + axissyst.Name = "BBoxAxis" + Dim axname As String + axname = axissyst.Name + + 'Get Product's Position (rotation and translation) + '(for now: relative to the parent product!) + Dim PositionArray(11) + Dim oPosition As Object + oPosition = objProduct.Position + oPosition.GetComponents(PositionArray) + + Dim originpoint As HybridShapePointCoord + axissyst.GetOrigin(originCoord) + 'MsgBox "X0 = " & CStr(originCoord(0)) & vbNewLine & "Y0 = " & CStr(originCoord(1)) & vbNewLine & "Z0 = " & CStr(originCoord(2)) + + originpoint = hybridShapeFactory1.AddNewPointCoord(originCoord(0), originCoord(1), originCoord(2)) + axisref = part1.CreateReferenceFromObject(originpoint) + axissyst.GetXAxis(axiscoord) + hybridShapeD1 = hybridShapeFactory1.AddNewDirectionByCoord(axiscoord(0), axiscoord(1), axiscoord(2)) + axissyst.GetYAxis(axiscoord) + hybridShapeD2 = hybridShapeFactory1.AddNewDirectionByCoord(axiscoord(0), axiscoord(1), axiscoord(2)) + axissyst.GetZAxis(axiscoord) + hybridShapeD3 = hybridShapeFactory1.AddNewDirectionByCoord(axiscoord(0), axiscoord(1), axiscoord(2)) + + 'hybridShapeD1&2 are not set yet, but used for line creation (from origin of the axis system) + Dim Plane_line_1 As HybridShapeLinePtDir + Plane_line_1 = hybridShapeFactory1.AddNewLinePtDir(originpoint, hybridShapeD1, 0, 0, False) + Dim Plane_line_2 As HybridShapeLinePtDir + Plane_line_2 = hybridShapeFactory1.AddNewLinePtDir(originpoint, hybridShapeD2, 0, 0, False) + + Dim oBodies As Bodies + oBodies = part1.Bodies + + 'J is defined to make unique names for Axis and the Body for the bounding box + Dim j As Integer + j = oBodies.Count + + 'If the part already contains a "Bounding Box", skip extremum point extraction + Dim partHasBB As Boolean = False + For Each body In part1.Bodies + If InStr(body.Name, "Bounding Box.") > 0 Then + partHasBB = True + Exit For + End If + Next + + 'create references for Points and read coordinates from the references + Dim point_ref11, point_ref12, point_ref13, point_ref14, point_ref5, point_ref6 As Reference + Dim Point1, Point2, Point3, Point4, Point5, Point6 As HybridShapePointCoord + + If partHasBB Then + + For Each body In part1.Bodies + If InStr(body.Name, "Bounding Box.") > 0 Then + Dim hbDefPoints As HybridBody + hbDefPoints = body.HybridBodies.Item("definition_points") + Point1 = hbDefPoints.HybridShapes.Item(7) + point_ref11 = part1.CreateReferenceFromObject(Point1) + Point2 = hbDefPoints.HybridShapes.Item(8) + point_ref12 = part1.CreateReferenceFromObject(Point2) + Point3 = hbDefPoints.HybridShapes.Item(9) + point_ref13 = part1.CreateReferenceFromObject(Point3) + Point4 = hbDefPoints.HybridShapes.Item(10) + point_ref14 = part1.CreateReferenceFromObject(Point4) + Point5 = hbDefPoints.HybridShapes.Item(11) + point_ref5 = part1.CreateReferenceFromObject(Point5) + Point6 = hbDefPoints.HybridShapes.Item(12) + point_ref6 = part1.CreateReferenceFromObject(Point6) + Exit For + End If + Next + + Else + 'Bounding Box hasn't been calculated for this part yet + + 'Add new Body "Bounding Box."j to the Bodies of the current Part + bodies1 = part1.Bodies + body1 = bodies1.Add() + body1.Name = "Bounding Box." & j + + Dim hybridBodies1 As HybridBodies + hybridBodies1 = body1.HybridBodies + Dim hybridBody1 As HybridBody + hybridBody1 = hybridBodies1.Add + hybridBody1.Name = "definition_points" + + 'Pick a face of the part to use for HybridShapeExtract + faceSel = CATIA.ActiveDocument.Selection + faceSel.Clear + 'The current Part is added to the selection + faceSel.Add(part1) + 'The selection gets rewritten by all the Faces of the selected part ("sel") + faceSel.Search("Type=Face,sel") + + Debug.Print("Selected faces: " & CStr(faceSel.Count)) + intNumFaces += faceSel.Count + + 'Need to check whether Extract crashes given this face and try the next one + + reference1 = faceSel.Item(1).Value + Debug.Print(TypeName(reference1)) + + Dim hybridShapeExtract1 As HybridShapeExtract + hybridShapeExtract1 = hybridShapeFactory1.AddNewExtract(reference1) + hybridShapeExtract1.PropagationType = 1 'point continuity + hybridShapeExtract1.ComplementaryExtract = False + hybridShapeExtract1.IsFederated = False + reference1 = hybridShapeExtract1 + + 'Create the 6 Extrenum items for the Solid/Surf. May not be single points, will be solved with next points + HybridShapeExtremum1 = hybridShapeFactory1.AddNewExtremum(reference1, hybridShapeD1, 1) + HybridShapeExtremum2 = hybridShapeFactory1.AddNewExtremum(reference1, hybridShapeD1, 0) + HybridShapeExtremum3 = hybridShapeFactory1.AddNewExtremum(reference1, hybridShapeD2, 1) + HybridShapeExtremum4 = hybridShapeFactory1.AddNewExtremum(reference1, hybridShapeD2, 0) + HybridShapeExtremum5 = hybridShapeFactory1.AddNewExtremum(reference1, hybridShapeD3, 1) + HybridShapeExtremum6 = hybridShapeFactory1.AddNewExtremum(reference1, hybridShapeD3, 0) + + ' Creates Geometrical Set under the Solid, to contain the construction elements + + Dim hybridBody2 As HybridBody + hybridBody2 = hybridBodies1.Item("definition_points") + + hybridBody2.AppendHybridShape(HybridShapeExtremum1) + part1.InWorkObject = HybridShapeExtremum1 + HybridShapeExtremum1.Name = "max_X" + hybridBody2.AppendHybridShape(HybridShapeExtremum2) + part1.InWorkObject = HybridShapeExtremum2 + HybridShapeExtremum2.Name = "min_X" + hybridBody2.AppendHybridShape(HybridShapeExtremum3) + part1.InWorkObject = HybridShapeExtremum3 + HybridShapeExtremum3.Name = "max_Y" + hybridBody2.AppendHybridShape(HybridShapeExtremum4) + part1.InWorkObject = HybridShapeExtremum4 + HybridShapeExtremum4.Name = "min_Y" + hybridBody2.AppendHybridShape(HybridShapeExtremum5) + part1.InWorkObject = HybridShapeExtremum5 + HybridShapeExtremum5.Name = "max_Z" + hybridBody2.AppendHybridShape(HybridShapeExtremum6) + part1.InWorkObject = HybridShapeExtremum6 + HybridShapeExtremum6.Name = "min_Z" + + part1.UpdateObject(HybridShapeExtremum1) + part1.UpdateObject(HybridShapeExtremum2) + part1.UpdateObject(HybridShapeExtremum3) + part1.UpdateObject(HybridShapeExtremum4) + part1.UpdateObject(HybridShapeExtremum5) + part1.UpdateObject(HybridShapeExtremum6) + + 'part1.Update + + ' Creates a 6 single points using the Extrenums as refs, so if the Extrenum was a line or surf, you can still off planes to these points + + Dim Ref1 As Reference + Ref1 = part1.CreateReferenceFromObject(HybridShapeExtremum1) + 'Dim Point1 As HybridShapePointCoord + Point1 = hybridShapeFactory1.AddNewPointCoordWithReference(0, 0, 0, Ref1) + hybridBody2.AppendHybridShape(Point1) + 'Dim point_ref11 As Reference + point_ref11 = part1.CreateReferenceFromObject(Point1) + + Dim Ref2 As Reference + Ref2 = part1.CreateReferenceFromObject(HybridShapeExtremum2) + 'Dim Point2 As HybridShapePointCoord + Point2 = hybridShapeFactory1.AddNewPointCoordWithReference(0, 0, 0, Ref2) + hybridBody2.AppendHybridShape(Point2) + 'Dim point_ref12 As Reference + point_ref12 = part1.CreateReferenceFromObject(Point2) + + Dim Ref3 As Reference + Ref3 = part1.CreateReferenceFromObject(HybridShapeExtremum3) + 'Dim Point3 As HybridShapePointCoord + Point3 = hybridShapeFactory1.AddNewPointCoordWithReference(0, 0, 0, Ref3) + hybridBody2.AppendHybridShape(Point3) + 'Dim point_ref13 As Reference + point_ref13 = part1.CreateReferenceFromObject(Point3) + + Dim Ref4 As Reference + Ref4 = part1.CreateReferenceFromObject(HybridShapeExtremum4) + 'Dim Point4 As HybridShapePointCoord + Point4 = hybridShapeFactory1.AddNewPointCoordWithReference(0, 0, 0, Ref4) + hybridBody2.AppendHybridShape(Point4) + 'Dim point_ref14 As Reference + point_ref14 = part1.CreateReferenceFromObject(Point4) + + Dim Ref5 As Reference + Ref5 = part1.CreateReferenceFromObject(HybridShapeExtremum5) + 'Dim Point5 As HybridShapePointCoord + Point5 = hybridShapeFactory1.AddNewPointCoordWithReference(0, 0, 0, Ref5) + hybridBody2.AppendHybridShape(Point5) + 'Dim point_ref5 As Reference + point_ref5 = part1.CreateReferenceFromObject(Point5) + + Dim Ref6 As Reference + Ref6 = part1.CreateReferenceFromObject(HybridShapeExtremum6) + 'Dim Point6 As HybridShapePointCoord + Point6 = hybridShapeFactory1.AddNewPointCoordWithReference(0, 0, 0, Ref6) + hybridBody2.AppendHybridShape(Point6) + 'Dim point_ref6 As Reference + point_ref6 = part1.CreateReferenceFromObject(Point6) + + part1.UpdateObject(Point1) + part1.UpdateObject(Point2) + part1.UpdateObject(Point3) + part1.UpdateObject(Point4) + part1.UpdateObject(Point5) + part1.UpdateObject(Point6) + + 'part1.Update + + End If 'partHasBB + + axissyst.IsCurrent = 1 + + 'Read extremum coordinates + Dim coord(2) As Object + Dim absCoord(2) As Object + + Dim TheSPAWorkbench As Workbench + TheSPAWorkbench = CATIA.ActiveDocument.GetWorkbench("SPAWorkbench") + + Dim TheMeasurable + + Debug.Print("Extremum coordinates:") + + 'Transform local extrema coordinates into global coordinates and update aAssemblyBoundaries + + 'Distances to Part Bounding Box faces in local coordinates + Dim aBBDistances(5) As Double + '8 corner points of the Part Bounding Box (BB) in local coordinates (8x3 array) + Dim aBBCornersLocal(7, 2) As Double + + 'max_X_loc + TheMeasurable = TheSPAWorkbench.GetMeasurable(point_ref11) + TheMeasurable.GetPoint(coord) + aBBDistances(0) = coord(0) + absCoord = {0.0, 0.0, 0.0} + Call Coord_Transform(coord, absCoord, objProduct, True) + Debug.Print(Point1.Name & " (max_X): [" & absCoord(0) & " " & absCoord(1) & " " & absCoord(2) & "]") + + 'min_X_loc + TheMeasurable = TheSPAWorkbench.GetMeasurable(point_ref12) + TheMeasurable.GetPoint(coord) + aBBDistances(1) = coord(0) + absCoord = {0.0, 0.0, 0.0} + Call Coord_Transform(coord, absCoord, objProduct, True) + Debug.Print(Point2.Name & " (min_X): [" & absCoord(0) & " " & absCoord(1) & " " & absCoord(2) & "]") + + 'max_Y_loc + TheMeasurable = TheSPAWorkbench.GetMeasurable(point_ref13) + TheMeasurable.GetPoint(coord) + aBBDistances(2) = coord(1) + absCoord = {0.0, 0.0, 0.0} + Call Coord_Transform(coord, absCoord, objProduct, True) + Debug.Print(Point3.Name & " (max_Y): [" & absCoord(0) & " " & absCoord(1) & " " & absCoord(2) & "]") + + 'min_Y_loc + TheMeasurable = TheSPAWorkbench.GetMeasurable(point_ref14) + TheMeasurable.GetPoint(coord) + aBBDistances(3) = coord(1) + absCoord = {0.0, 0.0, 0.0} + Call Coord_Transform(coord, absCoord, objProduct, True) + Debug.Print(Point4.Name & " (min_Y): [" & absCoord(0) & " " & absCoord(1) & " " & absCoord(2) & "]") + + 'max_Z_loc + TheMeasurable = TheSPAWorkbench.GetMeasurable(point_ref5) + TheMeasurable.GetPoint(coord) + aBBDistances(4) = coord(2) + absCoord = {0.0, 0.0, 0.0} + Call Coord_Transform(coord, absCoord, objProduct, True) + Debug.Print(Point5.Name & " (max_Z): [" & absCoord(0) & " " & absCoord(1) & " " & absCoord(2) & "]") + + 'min_Z_loc + TheMeasurable = TheSPAWorkbench.GetMeasurable(point_ref6) + TheMeasurable.GetPoint(coord) + aBBDistances(5) = coord(2) + absCoord = {0.0, 0.0, 0.0} + Call Coord_Transform(coord, absCoord, objProduct, True) + Debug.Print(Point6.Name & " (min_Z): [" & absCoord(0) & " " & absCoord(1) & " " & absCoord(2) & "]") + + 'Generate 8 corner points (local coordinates) to the aBBCornersLocal + Dim m, n, k, c As Integer + c = 0 + For m = 0 To 1 + For n = 2 To 3 + For k = 4 To 5 + aBBCornersLocal(c, 0) = aBBDistances(m) + aBBCornersLocal(c, 1) = aBBDistances(n) + aBBCornersLocal(c, 2) = aBBDistances(k) + 'Transform corner point into global coordinates + coord(0) = aBBCornersLocal(c, 0) + coord(1) = aBBCornersLocal(c, 1) + coord(2) = aBBCornersLocal(c, 2) + Call Coord_Transform(coord, absCoord, objProduct, True) + 'Record values to aPartBBGlob + Dim CCC(2) As Double 'Corner Coordinates in axis system Congruent to global but in the part's origin + CCC(0) = absCoord(0) - PositionArray(9) + CCC(1) = absCoord(1) - PositionArray(10) + CCC(2) = absCoord(2) - PositionArray(11) + If CCC(0) > aPartBBGlob(i, 0) Then + aPartBBGlob(i, 0) = CCC(0) + End If + If CCC(0) < aPartBBGlob(i, 1) Then + aPartBBGlob(i, 1) = CCC(0) + End If + If CCC(1) > aPartBBGlob(i, 2) Then + aPartBBGlob(i, 2) = CCC(1) + End If + If CCC(1) < aPartBBGlob(i, 3) Then + aPartBBGlob(i, 3) = CCC(1) + End If + If CCC(2) > aPartBBGlob(i, 4) Then + aPartBBGlob(i, 4) = CCC(2) + End If + If CCC(2) < aPartBBGlob(i, 5) Then + aPartBBGlob(i, 5) = CCC(2) + End If + 'Update aAssemblyBoundaries (global) + If absCoord(0) > aAssemblyBoundaries(0) Then + aAssemblyBoundaries(0) = absCoord(0) + End If + If absCoord(0) < aAssemblyBoundaries(1) Then + aAssemblyBoundaries(1) = absCoord(0) + End If + If absCoord(1) > aAssemblyBoundaries(2) Then + aAssemblyBoundaries(2) = absCoord(1) + End If + If absCoord(1) < aAssemblyBoundaries(3) Then + aAssemblyBoundaries(3) = absCoord(1) + End If + If absCoord(2) > aAssemblyBoundaries(4) Then + aAssemblyBoundaries(4) = absCoord(2) + End If + If absCoord(2) < aAssemblyBoundaries(5) Then + aAssemblyBoundaries(5) = absCoord(2) + End If + c = c + 1 + Next k + Next n + Next m + + part1.Update + + Else + MsgBox("The active document must be a CATPart") + End If + + End Function + + Sub RecalculateRemovalDistances(cRelProd As ArrayList, cDeact As ArrayList) + + Dim aRemovalDistances(cRelProd.Count - 1, 5) + Dim i As Integer + Dim relProd As Product + 'assure that the origin is inside the BB of assembly + aAssemblyBoundaries(0) = 0# + aAssemblyBoundaries(1) = 0# + aAssemblyBoundaries(2) = 0# + aAssemblyBoundaries(3) = 0# + aAssemblyBoundaries(4) = 0# + aAssemblyBoundaries(5) = 0# + + For i = 0 To cRelProd.Count - 1 + relProd = cRelProd.Item(i) + If Not productIsInCollection(relProd, cDeact) Then + If aInitPos(i, 9) + aPartBBGlob(i, 0) > aAssemblyBoundaries(0) Then + aAssemblyBoundaries(0) = aInitPos(i, 9) + aPartBBGlob(i, 0) + End If + If aInitPos(i, 9) + aPartBBGlob(i, 1) < aAssemblyBoundaries(1) Then + aAssemblyBoundaries(1) = aInitPos(i, 9) + aPartBBGlob(i, 1) + End If + If aInitPos(i, 10) + aPartBBGlob(i, 2) > aAssemblyBoundaries(2) Then + aAssemblyBoundaries(2) = aInitPos(i, 10) + aPartBBGlob(i, 2) + End If + If aInitPos(i, 10) + aPartBBGlob(i, 3) < aAssemblyBoundaries(3) Then + aAssemblyBoundaries(3) = aInitPos(i, 10) + aPartBBGlob(i, 3) + End If + If aInitPos(i, 11) + aPartBBGlob(i, 4) > aAssemblyBoundaries(4) Then + aAssemblyBoundaries(4) = aInitPos(i, 11) + aPartBBGlob(i, 4) + End If + If aInitPos(i, 11) + aPartBBGlob(i, 5) < aAssemblyBoundaries(5) Then + aAssemblyBoundaries(5) = aInitPos(i, 11) + aPartBBGlob(i, 5) + End If + End If + Next i + + For i = 0 To cRelProd.Count - 1 + relProd = cRelProd.Item(i) + If Not productIsInCollection(relProd, cDeact) Then + aRemovalDistances(i, 0) = aAssemblyBoundaries(0) - aPartBBGlob(i, 1) + aRemovalDistances(i, 1) = aAssemblyBoundaries(1) - aPartBBGlob(i, 0) + aRemovalDistances(i, 2) = aAssemblyBoundaries(2) - aPartBBGlob(i, 3) + aRemovalDistances(i, 3) = aAssemblyBoundaries(3) - aPartBBGlob(i, 2) + aRemovalDistances(i, 4) = aAssemblyBoundaries(4) - aPartBBGlob(i, 5) + aRemovalDistances(i, 5) = aAssemblyBoundaries(5) - aPartBBGlob(i, 4) + End If + Next i + + End Sub + + 'Public Function ArrayLen(a As Object) As Integer + ' If IsEmpty(a) Then + ' ArrayLen = 0 + ' Else + ' ArrayLen = UBound(a) - LBound(a) + 1 + ' End If + 'End Function + + Function Det3x3(dX11 As Double, dX12 As Double, dX13 As Double, + dX21 As Double, dX22 As Double, dX23 As Double, + dX31 As Double, dX32 As Double, dX33 As Double) As Double + '*********************************************** + '* + '* 3x3 matrix determinant calculation (direct) + '* + '*********************************************** + + Det3x3 = dX11 * dX22 * dX33 + dX12 * dX23 * dX31 + dX21 * dX32 * dX13 - + dX13 * dX22 * dX31 - dX12 * dX21 * dX33 - dX23 * dX32 * dX11 + End Function + Function Inv3x3(dX11 As Double, dX12 As Double, dX13 As Double, + dX21 As Double, dX22 As Double, dX23 As Double, + dX31 As Double, dX32 As Double, dX33 As Double, aInv() As Double) As Double() + '*********************************************** + '* + '* 3x3 matrix inverse calculation (direct) + '* + '*********************************************** + Dim dDet As Double + + ReDim aInv(8) + + dDet = Det3x3(dX11, dX12, dX13, dX21, dX22, dX23, dX31, dX32, dX33) + 'If dDet = 0 Then Exit Function + If dDet = 0 Then Return Nothing + + aInv(0) = (dX22 * dX33 - dX23 * dX32) / Math.Abs(dDet) + aInv(1) = (dX13 * dX32 - dX12 * dX33) / Math.Abs(dDet) + aInv(2) = (dX12 * dX23 - dX13 * dX22) / Math.Abs(dDet) + aInv(3) = (dX23 * dX31 - dX21 * dX33) / Math.Abs(dDet) + aInv(4) = (dX11 * dX33 - dX13 * dX31) / Math.Abs(dDet) + aInv(5) = (dX13 * dX21 - dX11 * dX23) / Math.Abs(dDet) + aInv(6) = (dX21 * dX32 - dX22 * dX31) / Math.Abs(dDet) + aInv(7) = (dX12 * dX31 - dX11 * dX32) / Math.Abs(dDet) + aInv(8) = (dX11 * dX22 - dX12 * dX21) / Math.Abs(dDet) + + Return aInv + + End Function + Sub Coord_Transform(aRel() As Object, aAbs() As Object, oProduct As Product, bRecursively As Boolean) + + Dim vProduct As Object, vCoord(11) + Dim oFatherProduct As Product + Dim aInv(8) As Double + + 'Exit condition, empty object + If oProduct Is Nothing Then Exit Sub + + 'Redim absolute coords matrix + On Error Resume Next + 'aAbs = {0.0, 0.0, 0.0} + On Error GoTo 0 + + 'Calculate product coordinates + vProduct = oProduct + vProduct.Position.GetComponents(vCoord) + + 'Calculate inverse matrix + If IsNothing(Inv3x3(CDbl(vCoord(0)), CDbl(vCoord(1)), CDbl(vCoord(2)), + CDbl(vCoord(3)), CDbl(vCoord(4)), CDbl(vCoord(5)), + CDbl(vCoord(6)), CDbl(vCoord(7)), CDbl(vCoord(8)), aInv)) Then + 'MsgBox "Error, degenerate transformation", vbOKOnly + Exit Sub + Else + aInv = Inv3x3(CDbl(vCoord(0)), CDbl(vCoord(1)), CDbl(vCoord(2)), + CDbl(vCoord(3)), CDbl(vCoord(4)), CDbl(vCoord(5)), + CDbl(vCoord(6)), CDbl(vCoord(7)), CDbl(vCoord(8)), aInv) + End If + + 'Calculate transformation + aAbs(0) = vCoord(9) + aInv(0) * aRel(0) + aInv(1) * aRel(1) + aInv(2) * aRel(2) + aAbs(1) = vCoord(10) + aInv(3) * aRel(0) + aInv(4) * aRel(1) + aInv(5) * aRel(2) + aAbs(2) = vCoord(11) + aInv(6) * aRel(0) + aInv(7) * aRel(1) + aInv(8) * aRel(2) + + 'If recursive option sepecified, search for parents and applies the transformation again + If bRecursively Then + + 'Try to assign parent + oFatherProduct = Nothing + On Error Resume Next + oFatherProduct = oProduct.Parent.Parent + On Error GoTo 0 + + 'If OK, recalculate coords + If oFatherProduct Is Nothing Then + Else + If oFatherProduct.PartNumber + ".CATProduct" = CATIA.ActiveDocument.Name Then + aRel(0) = aAbs(0) + aRel(1) = aAbs(1) + aRel(2) = aAbs(2) + Coord_Transform(aRel, aAbs, oFatherProduct, False) + Else + aRel(0) = aAbs(0) + aRel(1) = aAbs(1) + aRel(2) = aAbs(2) + Coord_Transform(aRel, aAbs, oFatherProduct, True) + End If + End If + + End If + + End Sub + + Function productIsInCollection(objProd As Product, prodColl As ArrayList) As Boolean + Dim dummyObj As Product + productIsInCollection = False + For Each dummyObj In prodColl + If dummyObj.Name = objProd.Name Then + productIsInCollection = True + Exit For + End If + Next + End Function + + Sub moveProduct(objProd As Product, intDir As Integer, bPositive As Boolean) + Dim intS As Integer + If bPositive = True Then + intS = intStep + Else + intS = -intStep + End If + Dim moveArray(11) + moveArray(0) = 1 + moveArray(1) = 0 + moveArray(2) = 0 + moveArray(3) = 0 + moveArray(4) = 1 + moveArray(5) = 0 + moveArray(6) = 0 + moveArray(7) = 0 + moveArray(8) = 1 + moveArray(9) = 0 + moveArray(10) = 0 + moveArray(11) = 0 + + Dim axisArray(11) + + 'movement along global axis + If intDir < 6 Then + 'Attention: for now it is assumed that all products are on the top level of specification tree + If intDir = 0 Then + moveArray(9) = intS + End If + If intDir = 1 Then + moveArray(10) = intS + End If + If intDir = 2 Then + moveArray(11) = intS + End If + If intDir = 3 Then + moveArray(9) = -intS + End If + If intDir = 4 Then + moveArray(10) = -intS + End If + If intDir = 5 Then + moveArray(11) = -intS + End If + Else 'movement along local axis + Dim oPosition As Object + oPosition = objProd.Position + oPosition.GetComponents(axisArray) + If intDir = 6 Then + moveArray(9) = axisArray(0) * intS + moveArray(10) = axisArray(1) * intS + moveArray(11) = axisArray(2) * intS + End If + If intDir = 7 Then + moveArray(9) = axisArray(3) * intS + moveArray(10) = axisArray(4) * intS + moveArray(11) = axisArray(5) * intS + End If + If intDir = 8 Then + moveArray(9) = axisArray(6) * intS + moveArray(10) = axisArray(7) * intS + moveArray(11) = axisArray(8) * intS + End If + If intDir = 9 Then + moveArray(9) = -axisArray(0) * intS + moveArray(10) = -axisArray(1) * intS + moveArray(11) = -axisArray(2) * intS + End If + If intDir = 10 Then + moveArray(9) = -axisArray(3) * intS + moveArray(10) = -axisArray(4) * intS + moveArray(11) = -axisArray(5) * intS + End If + If intDir = 11 Then + moveArray(9) = -axisArray(6) * intS + moveArray(10) = -axisArray(7) * intS + moveArray(11) = -axisArray(8) * intS + End If + End If + Dim prod1nd As Product + prod1nd = objProd + prod1nd.Move.Apply(moveArray) + + End Sub + + Function collisionDetected(cClashes As Clashes, group1 As Group, group2 As Group) As Boolean + 'cRelevantProducts As Collection, cDeactivated As Collection + + collisionDetected = False + + 'define two groups + ' Dim group1 As Group + 'Dim group2 As Group + ' group1 = cGroups.Add + ' group2 = cGroups.Add + ' group1.AddExplicit product1 + ' Dim relevantProduct As Product + ' For Each relevantProduct In cRelevantProducts + ' If Not relevantProduct.Name = product1.Name And Not productIsInCollection(relevantProduct, cDeactivated) Then + ' group2.AddExplicit relevantProduct + ' End If + ' Next relevantProduct + 'create a new clash analysis + Dim oClash As Clash + oClash = cClashes.Add + oClash.ComputationType = SPATypeLib.CatClashComputationType.catClashComputationTypeBetweenTwo + oClash.FirstGroup = group1 + oClash.SecondGroup = group2 + oClash.InterferenceType = SPATypeLib.CatClashInterferenceType.catClashInterferenceTypeClearance + 'oClash.Clearance = dCollSens + oClash.Compute + Dim cConflicts As Conflicts + cConflicts = oClash.Conflicts + If cConflicts.Count > 0 Then + 'MsgBox "Detected a collision: " & product1.Name + 'If at least one conflict value exceeds the collision sensitivity, it is a collision + Dim oConflict As Conflict + Dim c As Integer + For c = 1 To cConflicts.Count + oConflict = cConflicts.Item(c) + oConflict.Status = SPATypeLib.CatConflictStatus.catConflictStatusRelevant + If oConflict.Type = SPATypeLib.CatConflictType.catConflictTypeClash Then + If oConflict.Value < -dCollSens Then + collisionDetected = True + Debug.Print("Clash detected: " & oConflict.FirstProduct.Name & " - " & oConflict.SecondProduct.Name & " = " & oConflict.Value) + Exit For + End If + End If + Next c + End If + End Function + + Function productReachedFinalPosition(objProd As Product, i1 As Integer) As Boolean + productReachedFinalPosition = False + Dim posArray(11) + Dim oPosition As Object + oPosition = objProd.Position + oPosition.GetComponents(posArray) + If posArray(9) > aRemovalDistances(i1, 0) Then + productReachedFinalPosition = True + 'MsgBox "X+ removal distance reached by " & objProd.Name + End If + If posArray(9) < aRemovalDistances(i1, 1) Then + productReachedFinalPosition = True + 'MsgBox "X- removal distance reached by " & objProd.Name + End If + If posArray(10) > aRemovalDistances(i1, 2) Then + productReachedFinalPosition = True + 'MsgBox "Y+ removal distance reached by " & objProd.Name + End If + If posArray(10) < aRemovalDistances(i1, 3) Then + productReachedFinalPosition = True + 'MsgBox "Y- removal distance reached by " & objProd.Name + End If + If posArray(11) > aRemovalDistances(i1, 4) Then + productReachedFinalPosition = True + 'MsgBox "Z+ removal distance reached by " & objProd.Name + End If + If posArray(11) < aRemovalDistances(i1, 5) Then + productReachedFinalPosition = True + 'MsgBox "Z- removal distance reached by " & objProd.Name + End If + End Function + + Function productHasValidDisassDir(i1 As Integer, disassDir(,) As Object) As Boolean + productHasValidDisassDir = False + Dim j As Integer + For j = 0 To 11 + If disassDir(i1, j) = 1 Then + productHasValidDisassDir = True + Exit For + End If + Next j + End Function + + Function Tree(s1, q) + + For Each s2 In s1.Products + Tree(s2, q) + Next + + Dim parentAssy As Object + parentAssy = s1.Parent.Parent + + If StrComp(TypeName(parentAssy), "Product") = 0 Then + parentAssy.ReferenceProduct.Products.Item(s1.Name).Name = CStr(s1.PartNumber) & CStr("." & q) + q = q + 1 + End If + + End Function + + Private Sub RenameSingleLevel(ByRef oCurrentProd As Product) + + On Error Resume Next + + 'More declarations + Dim ItemToRename As Product + Dim ToRenamePartNumber As String + Dim lNumberOfItems As Long + Dim RenameArray(2000) As String + Dim i As Integer + Dim j As Integer + Dim k As Integer + + oCurrentProd = oCurrentProd.ReferenceProduct 'You have to work with the "ReferenceProduct" object + lNumberOfItems = oCurrentProd.Products.Count + + 'For i = 1 To lNumberOfItems 'Clear out the rename array + ' RenameArray(i) = "" 'Don't know if this is necessary + 'Next + + 'Run through this loop once, to set everything to a dummy name, to avoid naming conflicts + For i = 1 To lNumberOfItems 'Cycle through the assembly's children + ItemToRename = oCurrentProd.Products.Item(i) 'Declare which item we are working on + + ToRenamePartNumber = ItemToRename.PartNumber 'Get the Part Number + 'ToRenamePartNumber = ItemToRename.DescriptionRef 'Toggle these two lines for testing + + RenameArray(i) = ToRenamePartNumber 'Building the list of part names for the numbering loop + + k = 0 'Numbering Loop + For j = 1 To i 'This loop checks and sets the instance number + If RenameArray(j) = ToRenamePartNumber Then + k = k + 1 + End If + Next + CATIA.StatusBar = ItemToRename.Name & " > " & ToRenamePartNumber & "." & k + 'MsgBox ItemToRename.Name & " / " & ToRenamePartNumber & "." & k 'This line is for testing only + ItemToRename.Name = ToRenamePartNumber & "TEMP." & k 'Set the new instance name, to a TEMP dummy value + + Next + + 'Run through this loop to set the name finally, then the recursion call + For i = 1 To lNumberOfItems + ItemToRename = oCurrentProd.Products.Item(i) + + ToRenamePartNumber = ItemToRename.PartNumber 'Toggle these two lines for testing + 'ToRenamePartNumber = ItemToRename.DescriptionRef 'Toggle these two lines for testing + + RenameArray(i) = ToRenamePartNumber + + k = 0 + For j = 1 To i + If RenameArray(j) = ToRenamePartNumber Then + k = k + 1 + End If + Next + + CATIA.StatusBar = ItemToRename.Name & " > " & ToRenamePartNumber & "." & k + 'MsgBox ItemToRename.Name & " / " & ToRenamePartNumber & "." & k 'For testing + + ItemToRename.Name = ToRenamePartNumber & "." & k 'Set the new instance name final + + If ItemToRename.Products.Count <> 0 Then 'Recursive Call for version 0.1.2 + If oList.exists(ItemToRename.PartNumber) Then GoTo Finish + If ItemToRename.PartNumber = ItemToRename.ReferenceProduct.Parent.Product.PartNumber Then oList.Add(ItemToRename.PartNumber, 1) + Call RenameSingleLevel(ItemToRename) + End If + +Finish: + Next + + End Sub + + Function GetProductIndex(objProd As Product, cProds As ArrayList) As Integer + Dim produkt As Product + Dim intAns As Integer + intAns = 0 + For Each produkt In cProds + If produkt.Name = objProd.Name Then + GetProductIndex = intAns + Exit Function + End If + intAns = intAns + 1 + Next produkt + Return intAns + End Function + + Function BoundingBoxesOverlap(int_i As Integer, iStaticProduct As Integer) As Boolean + If aPartBBGlob(int_i, 1) >= aPartBBGlob(iStaticProduct, 0) Or aPartBBGlob(int_i, 0) <= aPartBBGlob(iStaticProduct, 1) Then + If aPartBBGlob(int_i, 3) >= aPartBBGlob(iStaticProduct, 2) Or aPartBBGlob(int_i, 2) <= aPartBBGlob(iStaticProduct, 3) Then + If aPartBBGlob(int_i, 5) >= aPartBBGlob(iStaticProduct, 4) Or aPartBBGlob(int_i, 4) <= aPartBBGlob(iStaticProduct, 5) Then + Return False + End If + End If + End If + Return True + End Function + + Function ParentSubassemblyIndex(objProd As Product, cRelProd As ArrayList) As Integer + 'CATIA detects collisions on Part level, but for tier determination we need to know which + 'subassembly the crashed Part belongs to (and get its index, because that's how we retrieve + 'assembly tier quickly + + 'Try to assign parent + Dim oFatherProduct As Product + oFatherProduct = Nothing + On Error Resume Next + oFatherProduct = objProd.Parent.Parent + On Error GoTo 0 + + If oFatherProduct Is Nothing Then + 'Current part or subassembly lies on the top level of the specification tree + ParentSubassemblyIndex = GetProductIndex(objProd, cRelProd) + Else + If productIsInCollection(objProd, cRelProd) Then + 'Part or subassembly is on the same hierarchy level as the moving part + ParentSubassemblyIndex = GetProductIndex(objProd, cRelProd) + Else + 'Have to try recursively on the higher level of assembly structure + ParentSubassemblyIndex(oFatherProduct, cRelProd) + End If + End If + + End Function + + Private Sub ReleaseObject(ByVal obj As Object) + Try + Dim intRel As Integer = 0 + Do + intRel = System.Runtime.InteropServices.Marshal.ReleaseComObject(obj) + Loop While intRel > 0 + 'MsgBox("Final Released obj # " & intRel) + Catch ex As Exception + MsgBox("Error releasing object" & ex.ToString) + obj = Nothing + Finally + GC.Collect() + End Try + End Sub + + +End Class + diff --git a/CatiaNetTest/bin/Debug/CatiaNetTest.exe b/CatiaNetTest/bin/Debug/CatiaNetTest.exe index 94e67f4fff98419dab1bceefbf1eac9e103fa1af..fa991fb5175975f1cdbde8fe6a0c9800d804d76f 100644 Binary files a/CatiaNetTest/bin/Debug/CatiaNetTest.exe and b/CatiaNetTest/bin/Debug/CatiaNetTest.exe differ diff --git a/CatiaNetTest/bin/Debug/CatiaNetTest.pdb b/CatiaNetTest/bin/Debug/CatiaNetTest.pdb index c43d247e2fbedcf6d65a35dde4706f17eb794bbb..5dfd60943eb0b41beaad1d9baf7ba04a2a5823cb 100644 Binary files a/CatiaNetTest/bin/Debug/CatiaNetTest.pdb and b/CatiaNetTest/bin/Debug/CatiaNetTest.pdb differ diff --git a/CatiaNetTest/obj/Debug/CatiaNetTest.exe b/CatiaNetTest/obj/Debug/CatiaNetTest.exe index 94e67f4fff98419dab1bceefbf1eac9e103fa1af..fa991fb5175975f1cdbde8fe6a0c9800d804d76f 100644 Binary files a/CatiaNetTest/obj/Debug/CatiaNetTest.exe and b/CatiaNetTest/obj/Debug/CatiaNetTest.exe differ diff --git a/CatiaNetTest/obj/Debug/CatiaNetTest.pdb b/CatiaNetTest/obj/Debug/CatiaNetTest.pdb index c43d247e2fbedcf6d65a35dde4706f17eb794bbb..5dfd60943eb0b41beaad1d9baf7ba04a2a5823cb 100644 Binary files a/CatiaNetTest/obj/Debug/CatiaNetTest.pdb and b/CatiaNetTest/obj/Debug/CatiaNetTest.pdb differ diff --git a/CatiaNetTest/obj/Debug/CatiaNetTest.vbproj.GenerateResource.Cache b/CatiaNetTest/obj/Debug/CatiaNetTest.vbproj.GenerateResource.Cache index 1a031fdb392ea88d0c7157e6d696f89b5477d744..594ce36497884ed1df0d337248f4c486c2c79d72 100644 Binary files a/CatiaNetTest/obj/Debug/CatiaNetTest.vbproj.GenerateResource.Cache and b/CatiaNetTest/obj/Debug/CatiaNetTest.vbproj.GenerateResource.Cache differ diff --git a/CatiaNetTest/obj/Debug/CatiaNetTest.vbprojAssemblyReference.cache b/CatiaNetTest/obj/Debug/CatiaNetTest.vbprojAssemblyReference.cache index b0030fbd7ec997cca7076394568b815bd1f625f7..98ac912058021e08fe3a1b745a79cf7499d688b6 100644 Binary files a/CatiaNetTest/obj/Debug/CatiaNetTest.vbprojAssemblyReference.cache and b/CatiaNetTest/obj/Debug/CatiaNetTest.vbprojAssemblyReference.cache differ diff --git a/CatiaNetTest/obj/Debug/DesignTimeResolveAssemblyReferences.cache b/CatiaNetTest/obj/Debug/DesignTimeResolveAssemblyReferences.cache index 766eddbc32003fee7eb3f40f30bbdb2a5fe285a6..20323601aaea24770b5ca260161b363f78dd2615 100644 Binary files a/CatiaNetTest/obj/Debug/DesignTimeResolveAssemblyReferences.cache and b/CatiaNetTest/obj/Debug/DesignTimeResolveAssemblyReferences.cache differ