Find and use the correct ProfilePath to extrude

Raider_71
Collaborator

Find and use the correct ProfilePath to extrude

Raider_71
Collaborator
Collaborator

Hi all,

 

I have been trying to get this right but seem to have run into a brick wall. Please see an image of a sketch with some geometry below. Basically two concentric circles and two line segments.

2025-01-17_13-30-00.png

 

I am trying to extrude the region indicated by the arrow. Here is what I have so far:

Dim oPartDoc As PartDocument = oApp.ActiveDocument
Dim oCompdef As PartComponentDefinition = oPartDoc.ComponentDefinition

Dim oSketch As PlanarSketch = oCompdef.Sketches.Item(1)
Dim oProfile As Profile

If oSketch.Profiles.Count = 0 Then
    oProfile = oSketch.Profiles.AddForSolid()
Else
    oProfile = oSketch.Profiles.Item(1)
End If

Dim oProfileEntity As ProfileEntity
Dim oDeleteProfile As Boolean
For Each oProfilePath As ProfilePath In oProfile
    oDeleteProfile = True
    
    For Each oProfileEntity In oProfilePath
        If oProfileEntity.CurveType = Curve2dTypeEnum.kLineSegmentCurve2d Then
            oDeleteProfile = False
        End If        
    Next

    If oDeleteProfile Then
        oProfilePath.Delete()
    End If
    
    Next

    Dim oExtrudeDef As ExtrudeDefinition
oExtrudeDef = oCompdef.Features.ExtrudeFeatures.CreateExtrudeDefinition(oProfile, PartFeatureOperationEnum.kJoinOperation)

oExtrudeDef.SetDistanceExtent(1, PartFeatureExtentDirectionEnum.kNegativeExtentDirection)

Dim oExtrude As ExtrudeFeature
oExtrude = oCompdef.Features.ExtrudeFeatures.Add(oExtrudeDef)

 

2025-01-17_13-35-52.png

 

As you can see its not what I want.

 

Any idea as to how I can specify the correct area to extrude?

 

Thanks!

0 Likes
Reply
Accepted solutions (1)
166 Views
6 Replies
Replies (6)

WCrihfield
Mentor
Mentor

Hi @Raider_71.  That's a pretty tough one to explain, and I don't have a lot of time, but I did take the time to create new part document, create a sketch that looks like that in it, then create an internal iLogic rule within that document that will only extrude that smallest internal area that you are pointing to, using a series of logical checks, some feedback to the iLogic Log window, and a little good old fashioned trial & error testing.

 

That code example is below, and the test part file, containing that rule, is attached.  Before you run it, make sure your iLogic Log tab is showing (does not need to be the 'active' tab though).  Then after you run it, look in that window to see the feedback.

Dim oPDoc As PartDocument = ThisDoc.Document
Dim oPDef As PartComponentDefinition = oPDoc.ComponentDefinition
Dim oSketch As PlanarSketch = oPDef.Sketches.Item(1)
'enabling single entry in UNDO List for all following actions
Dim oTrans As Inventor.Transaction
oTrans = ThisApplication.TransactionManager.StartTransaction(oPDoc, "Extrude Specific Prifile")
'create data/feedback recorder
Dim oReport As New System.Text.StringBuilder()
oReport.AppendLine("Before:  Profiles Count = " & oSketch.Profiles.Count)
Dim oProfile As Inventor.Profile = Nothing
Try
	oProfile = oSketch.Profiles.AddForSolid()
Catch oEx As Exception
	Logger.Error(oEx.ToString)
	oTrans.Abort()
End Try

oReport.AppendLine("After:  Profiles Count = " & oSketch.Profiles.Count)
oReport.AppendLine("Profile Created Has " & oProfile.Count & " ProfilePaths.")

For Each oPP As Inventor.ProfilePath In oProfile
	Dim iPP_Count As Integer = oPP.Count
	Dim bClosed As Boolean = oPP.Closed
	oReport.AppendLine()
	oReport.AppendLine("ProfilePath Data:")
	oReport.AppendLine("Has " & iPP_Count & " ProfileEntities.")
	oReport.AppendLine("Closed = " & bClosed)
	Dim bExcluded As Boolean = False
	Dim bFirstMatchFound = False
	oPP.AddsMaterial = False ' <<< IMPORTANT >>>

	If Not iPP_Count = 4 Then
		bExcluded = True
		Continue For
	End If

	If Not bClosed Then
		bExcluded = True
		Continue For
	End If

	Dim iCircles, iCircArcs, iLines, iLineSegments As Integer
	For Each oPE As Inventor.ProfileEntity In oPP
		If oPE.CurveType = Curve2dTypeEnum.kCircleCurve2d Then
			iCircles += 1
			bExcluded = True
			Exit For
		ElseIf oPE.CurveType = Curve2dTypeEnum.kCircularArcCurve2d Then
			iCircArcs += 1
		ElseIf oPE.CurveType = Curve2dTypeEnum.kLineCurve2d Then
			iLines += 1
		ElseIf oPE.CurveType = Curve2dTypeEnum.kLineSegmentCurve2d Then
			iLineSegments += 1
		Else
			oReport.AppendLine("Found Other CurveType.")
		End If
	Next
	oReport.AppendLine(iCircles & " Complete Circles")
	oReport.AppendLine(iCircArcs & " CircularArcs")
	oReport.AppendLine(iLines & " Lines")
	oReport.AppendLine(iLineSegments & " LineSegments")
	If bExcluded Then Continue For
	If iCircArcs = 2 AndAlso (iLines = 2 Or iLineSegments = 2) Then
		oReport.AppendLine("Match Found!")
		If Not bFirstMatchFound Then
			bFirstMatchFound = True
			oPP.AddsMaterial = True ' <<< IMPORTANT >>>
		Else
			oPP.AddsMaterial = False
		End If
	End If
Next
Dim oExtFeats As ExtrudeFeatures = oPDef.Features.ExtrudeFeatures
Dim oExtDef As ExtrudeDefinition = Nothing
Dim oExtFeat As ExtrudeFeature = Nothing
Try
	oExtDef = oExtFeats.CreateExtrudeDefinition(oProfile, PartFeatureOperationEnum.kNewBodyOperation)
	oExtDef.SetDistanceExtent("1 in", PartFeatureExtentDirectionEnum.kPositiveExtentDirection)
	oExtFeat = oExtFeats.Add(oExtDef)
	oTrans.End()
	Logger.Info(vbCrLf & oReport.ToString)
Catch oEx As Exception
	Logger.Error(oEx.ToString)
	oTrans.Abort()
End Try

If this solved your problem, or answered your question, please click ACCEPT SOLUTION .
Or, if this helped you, please click (LIKE or KUDOS) 👍.

Wesley Crihfield

EESignature

(Not an Autodesk Employee)

0 Likes

Raider_71
Collaborator
Collaborator

Hi @WCrihfield ,

 

Thank you for replaying. I am having a hard time understanding the logic in terms of how the smaller part of the profile is selected. I have done some testing and it looks like when Inventor creates the ProfilePaths, it always selects the smallest (in terms of region area) profile first when iterating through the profiles. 

I noticed that you declare the iCircles, iCircArcs, iLines, iLineSegments integers inside the loop. What I picked up was that by doing it that way it does not reset the integer values to 0 each time. Was that done on purpose? ...because I don't understand the logic for doing it that way.
The check you have to see if the ProfilePath is the correct one is that it must contain 2 arcs and 2 lines. That is technically the case for two of the ProfilePaths. Since you don't reset the iCircles, iCircArcs, iLines, iLineSegments variables for each loop, the second time it runs through the main loop it adds 2 to the iCircArcs and iLineSegments variables making it 4 and then it obviously does not pass the check you have further down.

See the code below. If I take the variable declaration outside the main for loop and reset the values to 0 each time then it extrudes both parts of the "donut" as per image below.

2025-01-19_10-21-32.png

    Private Sub BtnExtrudeSpecificProfile2_Click(sender As Object, e As EventArgs) Handles BtnExtrudeSpecificProfile2.Click

        Dim oPDoc As PartDocument = oApp.ActiveDocument
        Dim oPDef As PartComponentDefinition = oPDoc.ComponentDefinition
        Dim oSketch As PlanarSketch = oPDef.Sketches.Item(1)
        'enabling single entry in UNDO List for all following actions
        Dim oTrans As Inventor.Transaction
        oTrans = oApp.TransactionManager.StartTransaction(oPDoc, "Extrude Specific Profile")

        Dim oProfile As Inventor.Profile = Nothing
        Try
            oProfile = oSketch.Profiles.AddForSolid()
        Catch oEx As Exception
            oTrans.Abort()
        End Try

        Dim iCircles, iCircArcs, iLines, iLineSegments As Integer

        For Each oProfilePath As Inventor.ProfilePath In oProfile
            iCircles = 0
            iCircArcs = 0
            iLines = 0
            iLineSegments = 0

            Dim iPP_Count As Integer = oProfilePath.Count
            Dim bClosed As Boolean = oProfilePath.Closed

            Dim bExcluded As Boolean = False
            Dim bFirstMatchFound = False
            oProfilePath.AddsMaterial = False ' <<< IMPORTANT >>>

            If Not iPP_Count = 4 Then
                bExcluded = True
                Continue For
            End If

            If Not bClosed Then
                bExcluded = True
                Continue For
            End If

            For Each oPE As Inventor.ProfileEntity In oProfilePath
                If oPE.CurveType = Curve2dTypeEnum.kCircleCurve2d Then
                    iCircles += 1
                    bExcluded = True
                    Exit For
                ElseIf oPE.CurveType = Curve2dTypeEnum.kCircularArcCurve2d Then
                    iCircArcs += 1
                ElseIf oPE.CurveType = Curve2dTypeEnum.kLineCurve2d Then
                    iLines += 1
                ElseIf oPE.CurveType = Curve2dTypeEnum.kLineSegmentCurve2d Then
                    iLineSegments += 1
                Else

                End If
            Next

            If bExcluded Then Continue For
            If iCircArcs = 2 AndAlso (iLines = 2 Or iLineSegments = 2) Then
                If Not bFirstMatchFound Then
                    bFirstMatchFound = True
                    oProfilePath.AddsMaterial = True ' <<< IMPORTANT >>>
                Else
                    oProfilePath.AddsMaterial = False
                End If
            End If
        Next

        Dim oExtFeats As ExtrudeFeatures = oPDef.Features.ExtrudeFeatures
        Dim oExtDef As ExtrudeDefinition = Nothing
        Dim oExtFeat As ExtrudeFeature = Nothing

        Try
            oExtDef = oExtFeats.CreateExtrudeDefinition(oProfile, PartFeatureOperationEnum.kNewBodyOperation)
            oExtDef.SetDistanceExtent("1 in", PartFeatureExtentDirectionEnum.kPositiveExtentDirection)
            oExtFeat = oExtFeats.Add(oExtDef)
            oTrans.End()
        Catch oEx As Exception
            oTrans.Abort()
        End Try
    End Sub

 

So yeah, I am just trying to figure out what the logic is here. I would have checked for the same (must contain 2 arcs and 2 line segments) but both ProfilePaths will have that condition.

Should one not start checking the length of the arcs, for instance, and use the ProfilePath with the shortest arc lengths or something?

 

Your thoughts?

 

0 Likes

WCrihfield
Mentor
Mentor

I honestly did not spend much of time on it Friday, and did make a few changes to the code shortly before posting it, which I guess changed its functionality unexpectedly without me noticing (same model / visual result, but different feedback in the log, which I apparently did not read the last time).  I always had all 4 Integer variables declared within the ProfilePaths loop (in an attempt to eliminate value carry-over), but they were originally on 4 lines with initial values, but then for some reason (paused to do other stuff, then came back to it later, and was in a rush at that point) I condensed all 4 declarations to one line, which eliminates the ability to set an initial value, and I did not keep in mind that declaration alone (within a loop) without initial value spec, causes value carry-over (that I was originally trying to avoid).

 

I mainly went for the strategy of trying to figure out which ProfilePath to extrude after the 'Profiles.AddForSolid' method call, like you were originally trying to do, but that is often the most difficult way to do something like this.  It 'sucks' that there is no easy way to check area within the individual 'closed' ProfilePath objects (like there is for the Profile objects through Profile.RegionProperties.Area).  Yes, I was also aware of there being two profile paths with the same characteristics, and was starting to test whether it was the first one the code encountered like that, or the second one.  That's when I got called away, and the hasty change was made when I got back, which seemed to cause the model to turn out the way I wanted, and I was apparently too quick to post that result, without doing further testing.  And yes, arc/line inspections were to be the next logical test when going in that overall direction, but I just got more work related stuff to do just before that point, so I posted what I had at that point, then shifted my focus back to that.

 

Normally, if the sketch originated from me, and I knew I was going to create the extrusion by code, I would have prepared the sketch in a way that made it easier to provide only the geometry needed for the extrusion to the Profiles.AddForSolid method, as its 'ProfilePathSegments' input ObjectCollection, even if that meant needing to assign attributes to just those sketch entities, depending on the situation.  There would have been independent arcs between the top and bottom of the two vertical lines, not just the two complete circles.  But I know that would not help the main point of this forum post, because that is not what you described, and not what you wanted to know.  Sorry if my reply was not that helpful.  Due to a couple major changes (one unfortunate) late last year where I work, I have had to shift a lot more of my focus & time away from the Autodesk Community, and back towards my job, which has lead to far less time available to helping folks on this forum out, which I have very much enjoyed doing over the past several years.

Wesley Crihfield

EESignature

(Not an Autodesk Employee)

0 Likes

Raider_71
Collaborator
Collaborator
Accepted solution

Hi @WCrihfield ,

 

Thank you very much for your time and effort. It is really much appreciated. Having this resource and people willing to collaborate is invaluable, so thank you again sir!

 

Please see code below. I think I have managed to work it out, as we both said, the only other way to differentiate between two similar ProfilePaths is to do check the individual geometry of each. ...and yes, I agree, that if there was a RegionProperties.Area option for ProfilePath that would have been great.

 

Have a look and let me know if you feel there is a better way but it seems to work. 

 

 

 

    Private Sub BtnExtrudeSpecificProfile2_Click(sender As Object, e As EventArgs) Handles BtnExtrudeSpecificProfile2.Click

        Dim oPDoc As PartDocument = oApp.ActiveDocument
        Dim oPDef As PartComponentDefinition = oPDoc.ComponentDefinition
        Dim oSketch As PlanarSketch = oPDef.Sketches.Item(1)
        'enabling single entry in UNDO List for all following actions
        Dim oTrans As Inventor.Transaction
        oTrans = oApp.TransactionManager.StartTransaction(oPDoc, "Extrude Specific Profile")

        Dim oProfile As Inventor.Profile = Nothing
        Try
            oProfile = oSketch.Profiles.AddForSolid()
        Catch oEx As Exception
            oTrans.Abort()
        End Try

        Dim iCircles, iCircArcs, iLines, iLineSegments As Integer
        Dim oArc As Arc2d

        Dim oSmallestProfilePath As Inventor.ProfilePath = Nothing

        For Each oProfilePath As Inventor.ProfilePath In oProfile
            iCircles = 0
            iCircArcs = 0
            iLines = 0
            iLineSegments = 0

            Dim iPP_Count As Integer = oProfilePath.Count
            Dim bClosed As Boolean = oProfilePath.Closed

            Dim bExcluded As Boolean = False

            oProfilePath.AddsMaterial = False ' <<< IMPORTANT >>>

            If Not iPP_Count = 4 Then
                bExcluded = True
                Continue For
            End If

            If Not bClosed Then
                bExcluded = True
                Continue For
            End If

            For Each oPE As Inventor.ProfileEntity In oProfilePath
                If oPE.CurveType = Curve2dTypeEnum.kCircleCurve2d Then
                    iCircles += 1
                    bExcluded = True
                    Exit For
                ElseIf oPE.CurveType = Curve2dTypeEnum.kCircularArcCurve2d Then
                    iCircArcs += 1
                ElseIf oPE.CurveType = Curve2dTypeEnum.kLineCurve2d Then
                    iLines += 1
                ElseIf oPE.CurveType = Curve2dTypeEnum.kLineSegmentCurve2d Then
                    iLineSegments += 1
                Else

                End If
            Next

            If bExcluded Then Continue For
            If iCircArcs = 2 AndAlso (iLines = 2 Or iLineSegments = 2) Then

                If oSmallestProfilePath Is Nothing Then
                    oSmallestProfilePath = oProfilePath
                Else
                    If TotalArcLength(oSmallestProfilePath) > TotalArcLength(oProfilePath) Then
                        oSmallestProfilePath = oProfilePath
                    End If
                End If

            End If
        Next

        oSmallestProfilePath.AddsMaterial = True

        Dim oExtFeats As ExtrudeFeatures = oPDef.Features.ExtrudeFeatures
        Dim oExtDef As ExtrudeDefinition = Nothing
        Dim oExtFeat As ExtrudeFeature = Nothing

        Try
            oExtDef = oExtFeats.CreateExtrudeDefinition(oProfile, PartFeatureOperationEnum.kNewBodyOperation)
            oExtDef.SetDistanceExtent("5mm", PartFeatureExtentDirectionEnum.kPositiveExtentDirection)
            oExtFeat = oExtFeats.Add(oExtDef)
            oTrans.End()
        Catch oEx As Exception
            oTrans.Abort()
        End Try
    End Sub

 

 

    Function TotalArcLength(oProfilePath As ProfilePath) As Double

        Dim oListOfArcs As New List(Of Arc2d)

        For Each oPE As Inventor.ProfileEntity In oProfilePath
            If oPE.CurveType = Curve2dTypeEnum.kCircularArcCurve2d Then
                oListOfArcs.Add(CType(oPE.Curve, Arc2d))
            End If
        Next
        Dim dMin As Double, dMax As Double
        Dim dLength As Double
        Dim dTotalLength As Double = 0

        Try

            For Each oArc As Arc2d In oListOfArcs
                oArc.Evaluator.GetParamExtents(dMin, dMax)
                oArc.Evaluator.GetLengthAtParam(dMin, dMax, dLength)
                dTotalLength += dLength
            Next

            Return dTotalLength * 10

        Catch
            Return 0
        End Try

    End Function

 

Thanks again and cheers!

 

WCrihfield
Mentor
Mentor

Finding the ProfilePath that does not include any Circles, and so has the smallest perimeter sounds like a winner.  Looks like it is utilizing a custom Function routine named "TotalArcLength" that must be defined outside of that Sub routine.  A good idea for repeated tasks that you do not want to duplicate the code for.  If you want to mark your last reply as the solution, I would suggest also posting the code used for that Function, so others looking for this solution can reference that resource later, as part of the solution.

Wesley Crihfield

EESignature

(Not an Autodesk Employee)

0 Likes

Raider_71
Collaborator
Collaborator

Hi @WCrihfield ,

 

Ok I added the TotalArcLength function now. 👍

 

Cheers

0 Likes