Recursive Function

Recursive Function

Leonardo_Czuy
Advocate Advocate
1,177 Views
7 Replies
Message 1 of 8

Recursive Function

Leonardo_Czuy
Advocate
Advocate

Hello

I am trying to create a recursive function to take the code of a piece, find all pieces with that code, and pass them to another layer.

In the 'LookForFather' function, located at line 23, it receives the code 'C123019_PL-EJ-P0005_00.' It compares this code with the father, treating it as a piece ('peca'). If the comparison yields true, it returns true. If false, the function recursively calls itself, passing the parent code 'C123019_PL-EJ-C0002_00,' and the recursion continues, until find or break.

Sub Main
    drawDoc = TryCast(ThisDoc.Document, DrawingDocument)
	
    If (drawDoc Is Nothing) Then
       MessageBox.Show("Esta regra só pode ser executada em um desenho,", "iLogic")
       Return
    End If
	
	peca = InputBox("Digite o código da Peça:", "iLogic")
	If peca = "" Then
		MessageBox.Show("Necessário fornecer o código de uma peça", "iLogic")
		Return
	End If
	

    LookForView()
End Sub

Private drawDoc As DrawingDocument
Private modelDoc As Document
Private peca As String

Function LookForFather(ByVal occ As ComponentOccurrence) As Boolean
    Dim parentComponent As ComponentOccurrence = occ.ParentOccurrence
    If parentComponent Is Nothing Then
        Return False ' Reached top-level component
    End If
	
    Dim FileName As String
    FileName = parentComponent.Name
    Dim partes As String() = FileName.Split(":"c)
    FileName = partes(0).Trim()
	
    If FileName = peca Then
        ' Check if the current parent is the desired grandfather
        Return True
    Else
		'grandFather = parentComponent.ParentOccurrence
		'If grandFather IsNot Nothing Then
			'Return LookForFather(parentComponent)
		'End If

        ' The desired grandfather was not found
        Return False
    End If
End Function

 

Leonardo_Czuy_0-1701455233139.png

 

0 Likes
Accepted solutions (1)
1,178 Views
7 Replies
Replies (7)
Message 2 of 8

Frederick_Law
Mentor
Mentor

Ok.

So?

What's wrong?

0 Likes
Message 3 of 8

Leonardo_Czuy
Advocate
Advocate

Code dont run. Dont work. 

0 Likes
Message 4 of 8

Frederick_Law
Mentor
Mentor

Check the Main.

Are you running LockForView or LookForFather?

Message 5 of 8

WCrihfield
Mentor
Mentor
Accepted solution

Hi @Leonardo_Czuy.  This may be slightly unrelated, but if you just want to find the top level parent component of a lower level component, the easiest way may be to use the ComponentOccurrence.ComponentPath property, which returns a ComponentOccurrencesEnumerator, then just get the first entry within that collection, because they should be in order from top - first, to bottom - last.

Wesley Crihfield

EESignature

(Not an Autodesk Employee)

0 Likes
Message 6 of 8

Leonardo_Czuy
Advocate
Advocate

I call LockForView, after i Call ProcessOccurrences and Call LookForFather

Sub Main
    drawDoc = TryCast(ThisDoc.Document, DrawingDocument)
	
    If (drawDoc Is Nothing) Then
       MessageBox.Show("Esta regra só pode ser executada em um desenho,", "iLogic")
       Return
    End If
	
	peca = InputBox("Digite o código da Peça:", "iLogic")
	If peca = "" Then
		MessageBox.Show("Necessário fornecer o código de uma peça", "iLogic")
		Return
	End If
	

    LookForView()
End Sub

Private drawDoc As DrawingDocument
Private modelDoc As Document
Private peca As String

Public Sub LookForView()
    ' Process the occurrences, wrapping it in a transaction so the 
    ' entire process can be undone with a single undo operation. 
    Dim trans As Transaction
    trans = ThisApplication.TransactionManager.StartTransaction(drawDoc, "Drawing Layers to Existing")

    Try
        For Each dSheet As Sheet In drawDoc.Sheets
            For Each drawView As DrawingView In dSheet.DrawingViews
                If (drawView.ViewType = DrawingViewTypeEnum.kDraftDrawingViewType) Then Continue For
                
				Dim docDesc As DocumentDescriptor
				docDesc = drawView.ReferencedDocumentDescriptor
				
				If (docDesc Is Nothing) Then Continue For
				If (docDesc.ReferencedDocumentType = DocumentTypeEnum.kAssemblyDocumentObject) Then
					If (docDesc.ReferencedDocument Is Nothing) Then Continue For
					Dim asmDef As AssemblyComponentDefinition
					Dim assemDoc As AssemblyDocument = TryCast(docDesc.ReferencedDocument, AssemblyDocument)
					If (assemDoc) Is Nothing Then Continue For
					asmDef = assemDoc.ComponentDefinition
					If (asmDef Is Nothing) Then Continue For
					If (asmDef.Occurrences Is Nothing) Then Continue For
					ProcessOccurrences(drawView, asmDef.Occurrences)
				ElseIf (docDesc.ReferencedDocumentType = DocumentTypeEnum.kPartDocumentObject) Then
					Dim partDoc As PartDocument = TryCast(docDesc.ReferencedDocument, PartDocument)
					If (partDoc Is Nothing) Then Continue For
						'ProcessPart(drawView, partDoc)
				End If	
            Next
        Next
    Catch
        trans.Abort()
		Return
    End Try
    trans.End()
End Sub

Sub ProcessOccurrences(ByVal drawView As DrawingView, ByVal Occurrences As ComponentOccurrences)
	' Iterate through the current collection of occurrences. 
	Dim occ As ComponentOccurrence
	For Each occ In Occurrences
		If (occ.Suppressed) Then Continue For
		If (occ.Definition Is Nothing) Then Continue For
		If (occ.ReferencedDocumentDescriptor Is Nothing) Then Continue For
		If (occ.ReferencedDocumentDescriptor.ReferenceMissing) Then Continue For
		If occ.DefinitionDocumentType = DocumentTypeEnum.kPartDocumentObject Then
			' ** It's a part, so get the material.
			Dim partDoc As PartDocument = TryCast(occ.Definition.Document, PartDocument)
			If (partDoc Is Nothing) Then Continue For
			
			If LookForFather(occ) = False then Continue For
			' Get all of the curves associated with this occurrence. 
			Dim drawCurves As DrawingCurvesEnumerator = Nothing
			Try
				drawCurves = drawView.DrawingCurves(occ)
			Catch
				drawCurves = Nothing
			End Try
			If (drawCurves IsNot Nothing) Then

				Dim matLayers As New MaterialLayers(drawDoc, partDoc, drawView, drawCurves)
				matLayers.GetOrCreateMainLayer()
				matLayers.SetDrawingCurvesLayer(ThisApplication)
			End If
		Else
			' It's an assembly, so process its contents. 
			Call ProcessOccurrences(drawView, occ.SubOccurrences)
		End If
	Next
End Sub

Function LookForFather(ByVal occ As ComponentOccurrence) As Boolean
    Dim parentComponent As ComponentOccurrence = occ.ParentOccurrence
    If parentComponent Is Nothing Then
        Return False ' Reached top-level component
    End If
	
    Dim FileName As String
    FileName = parentComponent.Name
    Dim partes As String() = FileName.Split(":"c)
    FileName = partes(0).Trim()
	
    If FileName = peca Then
        ' Check if the current parent is the desired grandfather
        Return True
    Else
		grandFather = parentComponent.ParentOccurrence
			
		If grandFather IsNot Nothing Then
			FileName = grandFather.Name
			partes = FileName.Split(":"c)
			FileName = partes(0).Trim()
			
			If FileName = peca Then
			    ' Check if the current parent is the desired grandfather
			    Return True
			End If
		Else
			Return False
		End If
    End If
End Function

Class MaterialLayers
	Public MainLayer As Layer
	Public HiddenLayer As Layer

	' The layer for:
	' Solid lines in a plan or projected view:     MaterialName
	' Hidden lines in a plan or projected view:    MaterialName-Hidden
	' Solid lines in any other view:               MaterialName-View
	' Hidden lines in any other view:              MaterialName-View-Hidden

	Private drawDoc As DrawingDocument
	Private partDoc As PartDocument
	Private drawView As DrawingView
	Private drawCurves As DrawingCurvesEnumerator

	Public Sub New(ByRef drawDoc As DrawingDocument, ByVal partDoc As PartDocument, ByVal drawView As DrawingView, ByVal drawCurves As DrawingCurvesEnumerator)
		Me.drawDoc = drawDoc
		Me.partDoc = partDoc
		Me.drawView = drawView
		Me.drawCurves = drawCurves
	End Sub
	
	Sub GetOrCreateMainLayer()
		Dim layers As LayersEnumerator = drawDoc.StylesManager.Layers
		Try
			ContorniLayer = layers.Item("TESTI")
		Catch
		End Try
		
		Try
			NacosteLayer = layers.Item("NASCOSTE")
		Catch
		End Try
		MainLayer = ContorniLayer
		HiddenLayer = NacosteLayer
	End Sub
	
	Sub SetDrawingCurvesLayer(ByVal app As Inventor.Application)
	    If (MainLayer Is Nothing) Then Return
	    If (drawCurves Is Nothing) Then Return
			
	    ' Create empty collections for curves on different layers
	    Dim objColl As ObjectCollection = app.TransientObjects.CreateObjectCollection()
	    Dim hiddenColl As ObjectCollection = Nothing
	    If (HiddenLayer IsNot Nothing) Then
	        hiddenColl = app.TransientObjects.CreateObjectCollection()
	    End If
		
	    ' Iterate through each drawing curve
	    For Each drawCurve As DrawingCurve In drawCurves
	        If (drawCurve.Segments Is Nothing) Then Continue For
				
			drawCurve.Color = MainLayer.Color
			
	        For Each segment As DrawingCurveSegment In drawCurve.Segments
	            If (segment.HiddenLine) Then
	                If (hiddenColl IsNot Nothing) Then
	                    hiddenColl.Add(segment)
	                End If
	            Else
	                ' Add the segment to the collection for visible curves
	                objColl.Add(segment)
	            End If
	        Next
	    Next
	
	    ' Change the layer of visible curves
	    If (objColl.Count > 0) Then
	        drawView.Parent.ChangeLayer(objColl, MainLayer)
	    End If
	
	    ' Change the layer of hidden curves
	    If (hiddenColl IsNot Nothing AndAlso hiddenColl.Count > 0) Then
	        drawView.Parent.ChangeLayer(hiddenColl, HiddenLayer)
	    End If
	End Sub

End Class



0 Likes
Message 7 of 8

Leonardo_Czuy
Advocate
Advocate

Hello @WCrihfield 

Thanks very much. It's work!!!

 

0 Likes
Message 8 of 8

WCrihfield
Mentor
Mentor

OK.  It still might be useful for that task also.  Below is a quickie iLogic rule just for testing the functionality of that ComponentOccurrence.OccurrencePath.  It lets you manually 'pick' a low level component (part only, I think), then it shows you the list of component names in its 'path'.  The list includes the name of the picked component at the bottom of the list, then its parent component above that, and so on, but does not include the name of the 'main' assembly.

 

Dim oOcc As ComponentOccurrence = ThisApplication.CommandManager.Pick(SelectionFilterEnum.kAssemblyLeafOccurrenceFilter, "Pick lower level component")
If oOcc Is Nothing Then Return
Dim oOccPath As ComponentOccurrencesEnumerator = oOcc.OccurrencePath
If oOccPath Is Nothing OrElse oOccPath.Count = 0 Then Return
Dim oOccNames As New List(Of String)
For Each oParentOcc As ComponentOccurrence In oOccPath
	oOccNames.Add(oParentOcc.Name)
Next
Dim sChosenOccName As String = InputListBox("", oOccNames)
Dim sTopOccName As String = oOccNames.Item(0)
MsgBox("Top Level Parent Component Name = " & sTopOccName, vbInformation, "iLogic")

 

You could check if the parent component is within that 'path' collection, by looping its contents and checking their names.  Just one idea, but the recursive idea is also perfectly valid too.

 

Edit: I sent this response before seeing that you edited your last response.  Well I did not really fix your existing code, I just suggested a different way to do it.

Wesley Crihfield

EESignature

(Not an Autodesk Employee)

0 Likes