Find Sketches which contain broken projections

Find Sketches which contain broken projections

emanuel.c
Collaborator Collaborator
415 Views
12 Replies
Message 1 of 13

Find Sketches which contain broken projections

emanuel.c
Collaborator
Collaborator

Hi,

 

There is code to find and delete broken projections in sketches. But I would simply like to know which sketches contain such projections. Sometimes I may have many sketches in a part and would like to just get a message box list or something of those sketches that have issues. (like the sketch shown below).

 

Could someone help me with this? 

Thanks a lot!

 

emanuelc_0-1743613044421.png

 

0 Likes
416 Views
12 Replies
Replies (12)
Message 2 of 13

emanuel.c
Collaborator
Collaborator

Here is some code, but it isn't finding any broken projections, though there are indeed sketches with broken projections...

Sub Main

	Dim oPartDoc As PartDocument = ThisApplication.ActiveDocument
	If oPartDoc Is Nothing Then
		MsgBox("No part document is currently active.", vbExclamation, "Error")
		Exit Sub
	End If
	
	Dim oBrokenSketches As New ArrayList
	
	For Each oSketch As Sketch In oPartDoc.ComponentDefinition.Sketches
		If HasBrokenProjections(oSketch) Then
			oBrokenSketches.Add(oSketch.Name)
		End If
	Next
	
	If oBrokenSketches.Count > 0 Then
		Dim sMessage As String = "The following sketches have broken projections:" & vbCrLf
		For Each sSketchName As String In oBrokenSketches
			sMessage = sMessage & "- " & sSketchName & vbCrLf
		Next
			MsgBox(sMessage, vbExclamation, "Broken Projections Found")
		Else
			MsgBox("No sketches with broken projections were found.", vbInformation, "No Broken Projections")
	End If

End Sub

Function HasBrokenProjections(oSketch As Sketch) As Boolean

	For Each oCurve As SketchEntity In oSketch.SketchEntities
		If TypeOf oCurve Is SketchLine Then
			Dim oLine As SketchLine = oCurve
			Try
				Dim oPropertyInfo As System.Reflection.PropertyInfo = GetType(SketchLine).GetProperty("ReferenceKey")
				If oPropertyInfo IsNot Nothing Then
					Dim referenceKey As String = CStr(oPropertyInfo.GetValue(oLine, Nothing))
					If Not String.IsNullOrEmpty(referenceKey) Then
						Try
							' Attempt to resolve the reference.  If it fails, it's broken.
							Dim oRefEnt As Object = ThisApplication.TransientObjects.CreateObject(referenceKey)
							Catch ex As Exception
							' If an exception occurs, the projection is broken
							Return True
						End Try
					End If
				End If
			Catch ex As Exception
			End Try
	
		ElseIf TypeOf oCurve Is SketchArc Then
			Dim oArc As SketchArc = oCurve
			Try
				Dim oPropertyInfo As System.Reflection.PropertyInfo = GetType(SketchArc).GetProperty("ReferenceKey")
				If oPropertyInfo IsNot Nothing Then
					Dim referenceKey As String = CStr(oPropertyInfo.GetValue(oArc, Nothing))
					If Not String.IsNullOrEmpty(referenceKey) Then
						Try
							Dim oRefEnt As Object = ThisApplication.TransientObjects.CreateObject(referenceKey)
							Catch ex As Exception
							Return True
						End Try
					End If
				End If
				Catch ex As Exception
			End Try
	
		ElseIf TypeOf oCurve Is SketchCircle Then
			Dim oCircle As SketchCircle = oCurve
			Try
				Dim oPropertyInfo As System.Reflection.PropertyInfo = GetType(SketchCircle).GetProperty("ReferenceKey")
				If oPropertyInfo IsNot Nothing Then
					Dim referenceKey As String = CStr(oPropertyInfo.GetValue(oCircle, Nothing))
					If Not String.IsNullOrEmpty(referenceKey) Then
						Try
							Dim oRefEnt As Object = ThisApplication.TransientObjects.CreateObject(referenceKey)
							Catch ex As Exception
							Return True
						End Try
					End If
				End If
				Catch ex As Exception
			End Try
			
		ElseIf TypeOf oCurve Is SketchEllipse Then
			Dim oEllipse As SketchEllipse = oCurve
			Try
				Dim oPropertyInfo As System.Reflection.PropertyInfo = GetType(SketchEllipse).GetProperty("ReferenceKey")
				If oPropertyInfo IsNot Nothing Then
					Dim referenceKey As String = CStr(oPropertyInfo.GetValue(oEllipse, Nothing))
					If Not String.IsNullOrEmpty(referenceKey) Then
						Try
							Dim oRefEnt As Object = ThisApplication.TransientObjects.CreateObject(referenceKey)
							Catch ex As Exception
							Return True
						End Try
					End If
				End If 
				Catch ex As Exception
			End Try
	
		ElseIf TypeOf oCurve Is SketchSpline Then
			Dim oSpline As SketchSpline = oCurve
			Try
				Dim oPropertyInfo As System.Reflection.PropertyInfo = GetType(SketchSpline).GetProperty("ReferenceKey")
				If oPropertyInfo IsNot Nothing Then
					Dim referenceKey As String = CStr(oPropertyInfo.GetValue(oSpline, Nothing))
					If Not String.IsNullOrEmpty(referenceKey) Then
						Try
							Dim oRefEnt As Object = ThisApplication.TransientObjects.CreateObject(referenceKey)
							Catch ex As Exception
							Return True
						End Try
					End If
				End If
				Catch ex As Exception
			End Try
		End If
	Next
	
	Return False

End Function

 

0 Likes
Message 3 of 13

WCrihfield
Mentor
Mentor

Have you tried checking the value of the PlanarSketch.HealthStatus property, which is a variation of the HealthStatusEnum?  You could use a Select Case statement when doing so, which allows multiple possible results to be responded to (acted upon) in one Case, as opposed to using an If...Then statement.  Checking that would avoid iterating through each SketchEntity, if it works.

Wesley Crihfield

EESignature

(Not an Autodesk Employee)

0 Likes
Message 4 of 13

emanuel.c
Collaborator
Collaborator

Hi Wesley, thank you for the input! I used some other codes and got this working - full disclosure, a bit of Gemini in there too 🙂 I wish for it to search 3D sketches also, but have had a hard time with that... It will find Broken Projections in 2D sketches very well, but not in 3D. Would you have any input on this?

Thank you!

Sub Main()

    Dim oDoc As Document = ThisApplication.ActiveDocument

    If oDoc.DocumentType <> Inventor.DocumentTypeEnum.kPartDocumentObject Then
        MessageBox.Show("Hey this code only runs with Part Documents!", "", MessageBoxButtons.OK, MessageBoxIcon.Exclamation)
        Exit Sub
    End If

    Dim oPDef As PartComponentDefinition = oDoc.ComponentDefinition
    Dim brokenSketches As New System.Collections.ArrayList()

    ' Check 2D Sketches
    For Each oSketch As PlanarSketch In oPDef.Sketches
        Dim brokenProjectionFound As Boolean = False
        For Each oSE As SketchEntity In oSketch.SketchEntities
            Try
                If oSE.Reference Then
                    If oSE.ReferencedEntity Is Nothing Then
                        brokenProjectionFound = True ' Found a broken projection
                    End If
                End If
            Catch
            End Try
        Next

        If brokenProjectionFound Then
            brokenSketches.Add(oSketch.Name & " (2D)") ' Add sketch name to the list with type
        End If
    Next

    ' Check 3D Sketches
    For Each o3DSketch As Sketch3D In oPDef.Sketches3D
        Dim brokenProjectionFound As Boolean = False
        Try
            Dim sketch3DEntitiesProperty As System.Reflection.PropertyInfo = o3DSketch.GetType().GetProperty("Sketch3DEntities")
            If sketch3DEntitiesProperty IsNot Nothing Then
                Dim sketch3DEntities As Object = sketch3DEntitiesProperty.GetValue(o3DSketch, Nothing)
                If sketch3DEntities IsNot Nothing Then
                    For Each o3DEntity As Object In CType(sketch3DEntities, System.Collections.IEnumerable)
                        Try
                            If o3DEntity.GetType().Name = "Sketch3DReference" Then
                                Dim referencedEntityProperty As System.Reflection.PropertyInfo = o3DEntity.GetType().GetProperty("ReferencedEntity")
                                If referencedEntityProperty IsNot Nothing Then
                                    Dim referencedEntity As Object = referencedEntityProperty.GetValue(o3DEntity, Nothing)
                                    If referencedEntity Is Nothing Then
                                        brokenProjectionFound = True
                                    End If
                                End If
                            End If
                        Catch
                        End Try
                    Next
                End If
            End If
        Catch
        End Try

        If brokenProjectionFound Then
            brokenSketches.Add(o3DSketch.Name & " (3D)") ' Add 3D sketch name to the list with type
        End If
    Next

    If brokenSketches.Count > 0 Then
        Dim message As String = "The following sketches contain broken projections:" & vbCrLf
        For Each sketchName As String In brokenSketches
            message = message & "- " & sketchName & vbCrLf
        Next
        MessageBox.Show(message, "Broken Projections Found")
    Else
        MessageBox.Show("No broken projections found in any sketches.", "iLogic")
    End If

End Sub

 

0 Likes
Message 5 of 13

J-Camper
Advisor
Advisor

@emanuel.c,

I would just use the HealthStatus property that @WCrihfield mentioned.  Both Planar and 3D sketches have the property and return "kDriverLostHealth" when there are sick projections

Dim pDoc As PartDocument = TryCast(ThisApplication.ActiveDocument, PartDocument)
If pDoc Is Nothing Then Logger.Debug("Not Run In Part Document") : Exit Sub
	
For Each sk As PlanarSketch In pDoc.ComponentDefinition.Sketches
	'Logger.Trace(CType(sk.HealthStatus, HealthStatusEnum).ToString)
	If sk.HealthStatus = HealthStatusEnum.kDriverLostHealth Then Logger.Trace(sk.Name & " has broken Projections")
Next

For Each sk3d As Sketch3D In pDoc.ComponentDefinition.Sketches3D
	'Logger.Trace(CType(sk3d.HealthStatus, HealthStatusEnum).ToString)
	If sk3d.HealthStatus = HealthStatusEnum.kDriverLostHealth Then Logger.Trace(sk3d.Name & " has broken Projections")
Next

 

JCamper_0-1743638258609.png



I'm not sure what will be returned if there are more issues than just broken projections, so i left the Enumerator report line in.  remove the ' to have it run if you have sketches that should be caught but are not returning "kDriverLostHealth".

0 Likes
Message 6 of 13

Ivan_Sinicyn
Advocate
Advocate

This only works if the Sketch already is informing you that it needs attention. But often it just doesn't tell you anything.

sketch.png

INV 2025.3
0 Likes
Message 7 of 13

emanuel.c
Collaborator
Collaborator

@J-Camperthank you for the code, but indeed as @Ivan_Sinicyn mentioned, it doesn't catch errors when the Sketch doesn't have the warning sign.

 

The code I had works well for 2D sketches, just not for 3D...

 

For that matter, it would be cool to have code that would tell you if anything is broken in a part. This could be run from an Assembly level over all Referenced Documents.

 

I think it's a very dangerous oversight of Inventor to show the "Hospital Sign" for only certain broken issues. I do not want ANY broken issues. For example you can have lost projections on an expensive component and end up with issues down the road, but Inventor kept totally quiet about that 😞

0 Likes
Message 8 of 13

J-Camper
Advisor
Advisor

How often do you get broken projections without the sketch knowing?  Will solving the sketch work to let the sketch know something is broken?

Can you post an example part with undiagnosed broken sketch projections?

0 Likes
Message 9 of 13

emanuel.c
Collaborator
Collaborator

It's not that it's often. One time is too many. If you have one broken constraint, would you let it fly? I doubt it. And yet every broken constraint will shout out via the "hospital sign".

 

The biggest reason why it isn't more of an issue is because I have to keep track of it in my head: "oh, I changed that, and it's related to that, so I need to look into that other part which is derived from it." In my opinion there is no need for this! What exactly is the benefit of allowing broken projections to fly by without notifying the user?

 

For an example, please see the these attached parts. Part 2 is derived from Part 1. Part one has a suppressed features but you would never know it if you didn't personally keep track of it. You can see the model tree is clean, but when you open Sketch2 there are broken projections there.

 

Thanks!

 

emanuelc_0-1743692675949.png

 

emanuelc_1-1743692812417.png

 

 

 

0 Likes
Message 10 of 13

J-Camper
Advisor
Advisor

@emanuel.c,

I see your issue better now.  There was no 3D sketch in the attached part and when i made one it still knew it was broken, so i don't fully know the workflow for getting undiagnosed sick projections.  I did apply your same logic from planar sketches to 3D sketches and it appears to work on the 3D sketch I added:

    ' Check 3D Sketches
    For Each o3DSketch As Sketch3D In oPDef.Sketches3D
        Dim brokenProjectionFound As Boolean = False
		For Each oSE3d As SketchEntity3D In o3DSketch.SketchEntities3D
			Try
                If oSE3d.Reference Then
                    If oSE3d.ReferencedEntity Is Nothing Then
                        brokenProjectionFound = True ' Found a broken projection
                    End If
                End If
            Catch
            End Try
		Next

        If brokenProjectionFound Then
            brokenSketches.Add(o3DSketch.Name & " (3D)") ' Add 3D sketch name to the list with type
        End If
    Next


Full modified rule attached as txt file to save space.

Message 11 of 13

emanuel.c
Collaborator
Collaborator

Wow that's beautiful! Works very well!

 

Ya, even where I tested it on a 3D sketch, those sketches were actually called out as "sick" and Inventor does kind of call them out - at least when an update is being made... Still the code is useful to be able to run from a top level assembly over all referenced parts.

 

I don't know why Autodesk thinks it's OK to allow the flow to move on and not notify the user in such cases. But this will be helpful in catching those broken things.

 

Thank you!

 

 

0 Likes
Message 12 of 13

emanuel.c
Collaborator
Collaborator

The code isn't quite perfect though. I does seem to "catch" errors where there aren't any visible. For example, this sketch was called out, but "Select Broken Projections" is NOT called out and there don't appear to be any other issues... I'm not sure how to trouble shoot that.

 

emanuelc_0-1743695693480.png

 

0 Likes
Message 13 of 13

J-Camper
Advisor
Advisor

If you can post the part with your issue I can try to help, but sometimes i will use a HighlightSet to help troubleshoot.

Here is the HighlistSet code you would need to inject at different locations in your rule:

'Add somewhere earlier one
Dim selectThis As HighlightSet = ThisApplication.ActiveDocument.CreateHighlightSet



'Add Wherever you set the "brokenProjectionFound" Boolean to True
selectThis.AddItem("InsertYourSketchEntityHere")
MessageBox.Show("Pause") 'This should show the sketch entity which appears to be broken.  
selectThis.Clear()

It will pause the rule with a sketch entity highlighted until you close the dialog box.

0 Likes