Community
Inventor Programming - iLogic, Macros, AddIns & Apprentice
Inventor iLogic, Macros, AddIns & Apprentice Forum. Share your knowledge, ask questions, and explore popular Inventor topics related to programming, creating add-ins, macros, working with the API or creating iLogic tools.
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

How to copy a sketch to a new part in the same location as the source?

16 REPLIES 16
SOLVED
Reply
Message 1 of 17
fredform
536 Views, 16 Replies

How to copy a sketch to a new part in the same location as the source?

Hi,

 

I am working on a iLogic configurator that makes use of Transient BRep's and boolean operations to quickly output complex geometry. I am nearing a MVP of this project but I am currently stuck at this problem of copying a sketch (containing text for sheet metal marking) and pasting it in the output file, at the exact same location as the source file.

 

The code so far works to copy the sketch and paste it, but I have not managed to figure out how to get the necessary input variables to get the exact location from the source file. As a result, running the code on this particular output file (where the sketch face has been changed by a boolean operation) the sketch objects ends up in the wrong place and the mark feature fails.

 

Dim sourceDoc As PartDocument = ThisApplication.Documents.ItemByName("C:\temp\iLogicTest\Part1.ipt")
Dim sourceDef As ComponentDefinition = sourceDoc.ComponentDefinition

Dim newPartDoc As PartDocument = ThisApplication.ActiveDocument
Dim newPartDef As PartComponentDefinition = newPartDoc.ComponentDefinition

'Find the sketch to copy
Dim oSketch As PlanarSketch = Nothing
For Each oSketch In sourceDef.Sketches
    If oSketch.Name = "MarkingSketch" Then
        Exit For
    End If
	oSketch = Nothing
Next

If oSketch Is Nothing Then
    MsgBox("Sketch not found. Exiting rule")
    Return
End If

Dim body As SurfaceBody = newPartDef.SurfaceBodies.Item(1)
Dim assocID As Integer = -1

'Find the face to copy the sketch to
For Each oFace As Face In body.Faces
    If oFace.AssociativeID = assocID Then
        Dim oEdge As Edge = oFace.Edges.Item(2)
        Dim oVertex As Vertex = oEdge.StartVertex
		
        Dim newSketch As PlanarSketch = newPartDef.Sketches.AddWithOrientation(oFace, oEdge, oSketch.NaturalAxisDirection, oSketch.AxisIsX, oVertex)
		'Dim newSketch As PlanarSketch = newPartDef.Sketches.Add(oFace)
        
		oSketch.CopyContentsTo(newSketch)
        newSketch.TextBoxes.Item(1).Text = "some other text"

        Dim sketchObjects As ObjectCollection = ThisApplication.TransientObjects.CreateObjectCollection
        'Get all entities in the sketch
        For Each sketchText As Inventor.TextBox In newSketch.TextBoxes
            sketchObjects.Add(sketchText)
        Next

        Dim oMarkFeatures As MarkFeatures = newPartDef.Features.MarkFeatures
        'Get mark style
        Dim oMarkStyle As MarkStyle = newPartDoc.MarkStyles.Item(1)
        'Create mark definition
        Dim oMarkDef As MarkDefinition = oMarkFeatures.CreateMarkDefinition(sketchObjects, oMarkStyle)
        'Create a mark feature
        Dim oMarkFeature As MarkFeature = oMarkFeatures.Add(oMarkDef)

        Exit For
    End If
Next

 

I am using Inventor Pro 2024. 

 

Best regards,

Fredrik

 

 

16 REPLIES 16
Message 2 of 17
earl_cody
in reply to: fredform

Hi @fredform,

 

If you're looking for a quick answer, the following changes worked for me to locate the sketch in Part2:

Dim oEdge As Edge = oFace.Edges.Item(4)    
Dim oVertex As Vertex = oEdge.StopVertex 
Dim newSketch As PlanarSketch = newPartDef.Sketches.AddWithOrientation(oFace, oEdge, True, True, oVertex)

 

Screenshot 2024-04-20 161010.png

 

https://help.autodesk.com/view/INVNTOR/2024/ENU/?guid=PlanarSketches_AddWithOrientation 

 

You can reference the sketch's coordinate system from Part1 to determine which geometry (the edge, and vertex in this case) to define the copied sketch to (from the user interface or the VBA editor [object tree, or using the document object's SelectSet.Select method]) (there are also multiple ways of doing this if, for some reason, you wanted to use a vertical edge as a Y-axis instead).

 

Screenshot 2024-04-20 155219.pngScreenshot 2024-04-20 155216.png

 

As for making this more transportable, you could implement a few loops to parse all the faces where it's vertices and normal vector match a specified condition or something like that for example (although a little difficult since the B-rep object changes and the face becomes altered, but doable if you know the context). Another thought, potentially, being that you could create the sketch on a work plane. 

 

Best,

Cody

Message 3 of 17
fredform
in reply to: earl_cody

Hi Cody!

 

Your quick answer works in this particular case but I suspect it won’t hold up if the source sketch orientation changes? What I am after is more what you describe in referencing the coordinate system of the sketch in Part1. That way no matter how or where the marking sketch is placed in the source file, it can be copied and placed at the same coordinates and orientation in the output file. For my use case, the output file is used only as a basis for DXF and STP export and is discarded once the export is done.

 

Do you know how to get the necessary edge from the "MarkingSketch" in Part1 to use as input for the sketch in Part2? Would it be easier if geometry or projected geometry exists in the MarkingSketch to act as a helper for the reference (if that makes sense)?

 

 

Best,

Fredrik

Message 4 of 17
WCrihfield
in reply to: fredform

Hi @fredform.  I notices that you seem to be using a 'hidden' property of the Face object within your code (Face.AssociativeID).  I (and Autodesk, see Please Note) usually advise against that practice.  Plus, when I just created a new part, created a new PlanarSketch with a rectangle, extruded it, then uses a simple rule to Pick, then inspect its faces with that property, I get the same value for two of them.  When the Type of the value that is to be returned is undefined, the top and bottom face both return zero, and also when I define it as Integer, I still get zero for those two faces.  A more stable tool to use for identification may be to assign an Attribute to the Face.  That is what the NamedEntities system does behind the scenes also, but with very specific names for the AttributeSet & Attribute objects it creates.

Also, just a few more links that may help:

PlanarSketch.AxisEntity 

PlanarSketch.AxisEntityGeometry 

PlanarSketch.AxisIsX 

PlanarSketch.NaturalAxisDirection 

PlanarSketch.NaturalAxisDirection Sample 

PlanarSketch.OriginPoint 

PlanarSketch.OriginPointGeometry 

PlanarSketch.PlanarEntity 

PlanarSketch.PlanarEntityGeometry 

Wesley Crihfield

EESignature

(Not an Autodesk Employee)

Message 5 of 17
fredform
in reply to: WCrihfield

Hi @WCrihfield,

Thank you for that information. It is unfortunate that AssociativeID falls in this category as it is the only way I managed to make my program work.

Now, this is somewhat off-topic for this thread but my setup is like this:

  1. I have an assembly with a bunch of parts used as "blanks" and a bunch of parts representing "tools" (really the hole geometry to be cut in the blanks)
  2. A Transient BRep body is created for each "blank" component
  3. All the tool components are added to a collection and iterated over to perform boolean operations on the "blank" body
  4. Once complete, a new document is created and the processed "blank" body is added to it

In order to add the marking feature described in this thread and/or determine which face to use as A-side (if the source is Sheet Metal) I need to be able to reference the original faces. I tried reference keys, transient keys and Attributes but nothing worked to tie back to the original face that persisted once the processed body was added to the new part. I checked several sources/samples on these topics but could not get any of them to work. 😞

 

If you have some suggestions on a better approach I would happily discuss it in more detail and send you the code I have so far.

 

Best,

Fredrik

Message 6 of 17
earl_cody
in reply to: fredform

Hi @fredform,

 

Something to try... I wrote a few nested if statements/filters while iterating all of the faces to find the correct sketch face by:

  • Getting a face with same surface type
    • Getting a face with the same normal vector
      • Getting a face that contains the same vertex as the Part1 sketch origin

I figure that if the face has the same normal vector and contains a vertex with the same coordinates as the Part1 sketch, then it is likely to be the same face (there is probably a configuration where this isn't 100% reliable, but I think that would be unlikely/more complex geometry than presented here). 

 

Video attached of it running where I also add another sketch to Part1 on a different face and copied that to Part2 successfully. 

 

Best,

Cody

 

Code is VBA

Sub Main()
    Dim inv As Inventor.Application
    Set inv = ThisApplication
    
    Dim part1 As Inventor.PartDocument
    Set part1 = inv.Documents(1)
    
    Dim part2 As Inventor.PartDocument
    Set part2 = inv.ActiveDocument
    
    Dim sketchPart1 As Inventor.PlanarSketch
    Set sketchPart1 = part1.ComponentDefinition.Sketches("MarkingSketch")
    
    Dim facePart1Sketch As Inventor.Face
    Set facePart1Sketch = sketchPart1.PlanarEntity
        
    'find the same face in part2
    Dim facePart2 As Inventor.Face
    Dim vertexPart2SketchOrigin As Inventor.Vertex
    
    'iterate through all the faces
    Dim f As Inventor.Face
    For Each f In part2.ComponentDefinition.SurfaceBodies(1).Faces
        
        'highlight the current face in loop
        Call part2.SelectSet.Clear
        Call part2.SelectSet.Select(f)
        
        'if face has the same surface type
        If f.SurfaceType = facePart1Sketch.SurfaceType Then
            Dim plane As Inventor.plane
            Set plane = f.Geometry
            
            'if face's normal vector/direction is the same
            If _
            plane.Normal.X = facePart1Sketch.Geometry.Normal.X And _
            plane.Normal.Y = facePart1Sketch.Geometry.Normal.Y And _
            plane.Normal.Z = facePart1Sketch.Geometry.Normal.Z Then
                
                'if the face has a vertex that matches the Part1 sketch origin point
                Dim v As Inventor.Vertex
                For Each v In f.Vertices
                    If _
                    v.Point.X = sketchPart1.OriginPointGeometry.X And _
                    v.Point.Y = sketchPart1.OriginPointGeometry.Y And _
                    v.Point.Z = sketchPart1.OriginPointGeometry.Z Then
                        
                        'found the face
                        Set facePart2 = f
                        Set vertexPart2SketchOrigin = v
                        Exit For
                    End If
                Next
            End If
        End If
        
        If Not facePart2 Is Nothing Then
            Exit For
        End If
    Next
    
    If facePart2 Is Nothing Then
        MsgBox ("Couldn't find a face in part 2 that matches part 1")
        Exit Sub
    End If
    
    'create new sketch
    Dim sketchPart2 As Inventor.PlanarSketch
    Set sketchPart2 = part2.ComponentDefinition.Sketches.Add(facePart2)
    
    'relocate to same location as Part2 sketch
    sketchPart2.OriginPoint = vertexPart2SketchOrigin
    
    'copy contents
    Call sketchPart1.CopyContentsTo(sketchPart2)
    
    'end message
    MsgBox ("The sketch has been copied.")
End Sub

 

Message 7 of 17
fredform
in reply to: earl_cody

@earl_cody 

Hi again,

 

Wow, thank you so much for taking the time to put that together!

I will give it a try and see if it works as intended and report back.

 

Best,

Fredrik

 

 

Message 8 of 17
fredform
in reply to: earl_cody

Hi Cody,

 

So I've been testing your code and that with some varied results, but it got me thinking and I believe I have found a solution.

 

First I could not get your code to work at all but then I realized the Part2 file I was using had some changes done to it, so using the file that I uploaded here the code worked. However, this approach does not seem very robust as changes to the marking face can make it fail at identifying the face in question (this probably happens at the vertex loop). I tried to provoke this outcome by adding a bunch of cuts which actually didn't break the code until I put a cut to the left of the text (perhaps because it interferes with the sketch origin location?)

 

fredform_0-1713950151620.png

 

 

Instead my solution is this: I used the center point in the marking sketch of Part1 (constrained to the textbox frame) and added a work point to it.

 

fredform_1-1713951442633.png

 

Then I copy this work point to the new part and project it in the new sketch, constraining the two sketch points to move the textbox in place:

 

Sub AddMarkingSketch(blankCompDef As ComponentDefinition, partDoc As PartDocument, partDef As PartComponentDefinition, body As SurfaceBody, i As Integer)
    'Find the sketch to copy
    Dim oSketch As PlanarSketch = Nothing
    For Each oSketch In blankCompDef.Sketches
        If oSketch.Name = "MarkingSketch" Then
            Exit For
        End If
        oSketch = Nothing
    Next

    If oSketch Is Nothing Then
        MsgBox("Sketch not found. Exiting rule")
        Return
    End If

    'Find the "anchor point" for the TextBox
    Dim WP As WorkPoint = Nothing
    For Each WP In blankCompDef.WorkPoints
        If WP.Name = "TextBoxAnchor" Then
            Dim TG As TransientGeometry = ThisApplication.TransientGeometry
            Dim TGpoint As Point = TG.CreatePoint(WP.Point.X, WP.Point.Y, WP.Point.Z)
            'Add the "anchor point" to the new part as a fixed Work Point feature
            WP = partDef.WorkPoints.AddFixed(TGpoint)
            Exit For
        End If
        WP = Nothing
    Next

    If WP Is Nothing Then
        MsgBox("Work Point not found. Exiting rule")
        Return
    End If

    'Find the face to copy the sketch to
    For Each oFace As Face In body.Faces
        If oFace.AssociativeID = i Then
            'Add sketch to face
            Dim newSketch As PlanarSketch = partDef.Sketches.Add(oFace)

            'Copy contents from source sketch
            oSketch.CopyContentsTo(newSketch)
            'Replace text in TextBox
            newSketch.TextBoxes.Item(1).Text = "some other text"

            Dim SP As SketchPoint
            For Each SP In newSketch.SketchPoints
                'Find the "Center Point" attached to the TextBox frame
                If SP.HoleCenter = True Then
                    'Constrain the TextBox to the "anchor point"
                    Dim anchorPoint As SketchPoint = newSketch.AddByProjectingEntity(WP)
                    newSketch.GeometricConstraints.AddCoincident(SP, anchorPoint)
                    Exit For
                End If
            Next

            Dim sketchObjects As ObjectCollection = ThisApplication.TransientObjects.CreateObjectCollection
            'Get all entities in the sketch
            For Each sketchText As Inventor.TextBox In newSketch.TextBoxes
                sketchObjects.Add(sketchText)
            Next

            Dim oMarkFeatures As MarkFeatures = partDef.Features.MarkFeatures
            'Get mark style
            Dim oMarkStyle As MarkStyle = partDoc.MarkStyles.Item(1)
            'Create mark definition
            Dim oMarkDef As MarkDefinition = oMarkFeatures.CreateMarkDefinition(sketchObjects, oMarkStyle)
            'Create a mark feature
            Dim oMarkFeature As MarkFeature = oMarkFeatures.Add(oMarkDef)

            Exit For
        End If
    Next
End Sub

 

 

I believe this solves the problem of copying and positioning the sketch. I should mention that I encountered a bug when adding the mark feature using version 2024.1, it would throw an error for some reason but worked once I upgraded Inventor to version 2024.3 

 

Message 9 of 17
WCrihfield
in reply to: fredform

Hi @fredform.  Sorry for not getting back sooner.  Not only did I have a lot of other stuff going on, but also was not immediately sure how to respond once you said that you had already tried all those tools/methods for tracking a Face.  There was another case that came to mind though, where a part was inserted into an assembly, then more features (holes / cuts / etc.) were added to that assembly component in the assembly.  Then the user wanted to be able to identify/find a Face on that assembly component that had been assigned a name (using NamedEntities system) within the part file.  For quite a while many things were tried, but no luck, because the internal ID of the Face had changed due to the features.  I could be wrong, because I do not recall the link to that discussion, but I believe the 'End of Features' was moved to before those features were added, then the named Face could be found again, then something about it was recorded, or something done to it, then the 'End of Features' was returned to normal position.

Wait...I think I found a couple of the forum posts I was thinking about:

https://forums.autodesk.com/t5/inventor-programming-ilogic/assembly-level-modification-stopping-draw... 

'this one a little less so, but similar issue

https://forums.autodesk.com/t5/inventor-programming-ilogic/auto-dimension-drawing-retrieving-drawing... 

Wesley Crihfield

EESignature

(Not an Autodesk Employee)

Message 10 of 17
fredform
in reply to: WCrihfield

@WCrihfield 

 

I did some more digging into this method of using AssociativeID's to reference specific faces and it seems a little odd to me that this would be a "hidden" part of the API whose use should be avoided. I found this help page from Inventor 2023 that documents the property also showing its been around since 2011.

 

I first encountered the property in this thread with an answer by @BrianEkins where he does mention it is an undocumented part of the API, but then again that was 2013. Perhaps by now it is safe to use?

 

In my experiments I've noticed the following behaviors related to AssociativeID's and faces:

  • The default value seems to be 0
  • Inventor may change the value as a result of features being added/geometry changing
  • A Transient BRep will have all values (faces) set to 0 (even if the source body/face had other values, as set by Inventor)
  • Adding a Transient BRep body as "NonParametricBaseFeatures" sets all AssociativeID's to equal the Face Index (except where manually set values exists...)
  • Manually set AssociativeID's persists thru being a Transient BRep copy, DoBoolean operations and being added to a document as a non parametric base feature

 

Since the AssociativeID values change when the body is added to the new document and, as far as I can tell, only uses positive numbers I decided to use negative values to name the faces I wanted to reference. So far this seems to be a robust way of solving my problem.

 

I have attached an assembly containing a "blank" component, some "tool" components and a rather lengthy code to create the finished processed file. This code will also output the AssociativeID's of all the faces to the iLogic Logger where the behavior above can be observed.

 

fredform_0-1713958864379.png

 

 

If someone from Autodesk could comment on this method and whether it is to be avoided or not I'd be very grateful.

 

Best,

Fredrik

 

Message 11 of 17
WCrihfield
in reply to: fredform

Hi @fredform.  First of all, thank you very much for the very thorough and informational reply.  I definitely learned something today from this, which I always enjoy.  I skipped directly from Inventor Pro 2022 to Inventor Pro 2024, so I never saw that 2023 online help page.  I did check the 2022 and 2024 online help pages, but did not see that Property listed in either of those, and I am usually pretty well versed in what documentation is available in there, because I'm looking at that stuff every day.  It does seem like I had seen that property used at least one or twice before in forum posts, but could not remember where.  I would also like to hear someone from Autodesk chime in on this Property, how it works, and why it was hidden.  I have know about the Face.InternalName Property for many years, and assumed that this was the 'official' ID of each Face object that we (users) should be using.  But I also knew that a Face's InternalName can sometimes be changed by features that effect that face, especially if the Face gets split into multiple Faces by a feature.  That's where the more advanced systems started coming into play, such as the 'ReferenceKey' system, which sounded very powerful, and could essentially store an entire database within the model file that takes a snapshot of all current entity names at that time and state of the model, with a 'key' to retrieve that database at a later date, when the model is in a more advanced state (more features added).  There are lots of forum posts about using that system, and it sounds pretty complicated to use correctly (I never used it much myself), but a few forum posts really explained it in greater detail, which really opened my eyes to how powerful it could be (and how much memory it could use up).  With all that in place, plus being able to assign attributes to objects, and being able to specify that an attribute will be copied to the object it gets copied to, it is hard to believe that such a simple sounding system (with single digit ID's) could really be effectively used to replace or be better than those other systems that seemed so much more advanced / complicated.

 

I have not downloaded your ZIP file though.  Where I work we have very strict system/network security policies/measures in place, so downloading ZIP, or RAR, and other such compressed file types from places like forums is not allowed.  I did download your earlier model files and looked at them yesterday though.  Even that can be dangerous though, with iLogic Event Triggers potentially being involved which can be triggered by simply opening the document.  When we download someone else's Excel file, those can have VBA macros in them too, but at least Microsoft Excel warns us about those, before allowing them to be immediately 'active'.

Wesley Crihfield

EESignature

(Not an Autodesk Employee)

Message 12 of 17
fredform
in reply to: WCrihfield

You're welcome! 🙂 I hope we can all get some clarity on this topic. As I mentioned before, I tried figuring out how to use Reference Keys for this purpose but nothing I tried worked.

 

Good point about the ZIP-file, I only put it there due to the 3 file limit of the forum. If you wanna give the code a try I included it below:

Sub Main()
    'Set references to this assembly
    Dim asmDoc As AssemblyDocument = ThisApplication.ActiveDocument
    Dim asmDef As ComponentDefinition = asmDoc.ComponentDefinition

    'Set references to the "blank" component
    Dim blankComponent As ComponentOccurrence = asmDef.Occurrences.Item(1)
    Dim blankCompDef As ComponentDefinition = blankComponent.Definition
    Dim blankCompDoc As PartDocument = blankCompDef.Document
    Dim SMCD As SheetMetalComponentDefinition = blankCompDoc.ComponentDefinition
    Dim thkParam As Parameter = SMCD.Thickness

    Dim toolCollection As New Collection
    toolCollection.Add(asmDef.Occurrences.Item(2))
    toolCollection.Add(asmDef.Occurrences.Item(3))
    toolCollection.Add(asmDef.Occurrences.Item(4))

    'Print out all the AssociativeIDs of all the faces
    Call GetAssocIDs(blankCompDef.SurfaceBodies.Item(1), "blankComponent")

    'Proxy needed to resolve some bug mentioned somewhere...
    Dim proxy As Object = Nothing
    Call blankComponent.CreateGeometryProxy(blankCompDef.SurfaceBodies.Item(1), proxy)
    Dim bodyProxy As SurfaceBodyProxy = TryCast(proxy, SurfaceBodyProxy)
    'Create a Transient BRep copy of the "blank" component
    Dim blankBody As SurfaceBody = ThisApplication.TransientBRep.Copy(bodyProxy)

    'Marking Face: Find the face index where named attribute exists
    Dim markingFaceIndex As Integer = GetAttributeFaceIndex(blankCompDef.SurfaceBodies.Item(1), "MarkingFace")
    'Set associativeID 
    Dim markingFaceID As Integer = -1
    blankBody.Faces.Item(markingFaceIndex).AssociativeID = markingFaceID

    'A-side Face: Find the face index defined by the A-side feature
    Dim ASideFaceIndex As Integer = GetASideFaceIndex(blankCompDef.SurfaceBodies.Item(1), blankCompDoc)
    'Set associativeID
    Dim ASideFaceID As Integer = -2
    blankBody.Faces.Item(ASideFaceIndex).AssociativeID = ASideFaceID

    'Open and highlight the face(s) found in the blankComponent
    ThisApplication.Documents.Open(blankCompDoc.FullDocumentName, True)
    Dim HS As HighlightSet = blankCompDoc.CreateHighlightSet
    HS.AddItem(blankCompDef.SurfaceBodies.Item(1).Faces.Item(markingFaceIndex))
    HS.AddItem(blankCompDef.SurfaceBodies.Item(1).Faces.Item(ASideFaceIndex))

    'Print out all the AssociateIDs of all the faces 
    Call GetAssocIDs(blankBody, "blankBody")

    'Create matrix to hold the coordinates of the "blank" component relative to its position in the assembly
    Dim trans As Matrix = blankComponent.Transformation
    trans.Invert()

    'Process all "tool" occurrences and perform boolean operations
    For Each toolOcc As ComponentOccurrence In toolCollection
        Dim toolDef As ComponentDefinition = toolOcc.Definition
        'Proxy needed to resolve bug...
        proxy = Nothing
        Call toolOcc.CreateGeometryProxy(toolDef.SurfaceBodies.Item(1), proxy)
        Dim toolBodyProxy As SurfaceBodyProxy = TryCast(proxy, SurfaceBodyProxy)
        Dim toolBody As SurfaceBody = ThisApplication.TransientBRep.Copy(toolBodyProxy)

        'Transform the bodies relative to the "blank" component
        Call ThisApplication.TransientBRep.Transform(toolBody, toolBodyProxy.ContainingOccurrence.Transformation)
        Call ThisApplication.TransientBRep.Transform(toolBody, trans)

        'Subtract the geometry of the "tool" bodies from the "blank" body
        ThisApplication.TransientBRep.DoBoolean(blankBody, toolBody, BooleanTypeEnum.kBooleanTypeDifference)
    Next

    'Print out all the AssociateIDs of all the faces 
    Call GetAssocIDs(blankBody, "blankBody after processing")

    Dim partDoc As PartDocument = ThisApplication.Documents.Add(
        DocumentTypeEnum.kPartDocumentObject, ThisApplication.FileManager.GetTemplateFile(DocumentTypeEnum.kPartDocumentObject), CreateVisible:=True) 'Bugs out when set to False running outside of iLogic
    Dim partDef As PartComponentDefinition = partDoc.ComponentDefinition

    'Create a base feature definition using the inputs below
    Dim nonPrmFeatures As NonParametricBaseFeatures
    nonPrmFeatures = partDef.Features.NonParametricBaseFeatures
    Dim featureDef As NonParametricBaseFeatureDefinition
    featureDef = nonPrmFeatures.CreateDefinition

    Dim transObjs As TransientObjects = ThisApplication.TransientObjects
    Dim col As ObjectCollection = transObjs.CreateObjectCollection
    col.Add(blankBody)
    'Create an non-associative surface body
    featureDef.BRepEntities = col
    featureDef.OutputType = BaseFeatureOutputTypeEnum.kSolidOutputType
    featureDef.IsAssociative = False

    'Add the resulting body
    Dim baseFeature As NonParametricBaseFeature
    'baseFeature = partDef.Features.NonParametricBaseFeatures.Add(blankBody)
    baseFeature = nonPrmFeatures.AddByDefinition(featureDef)

    Dim partBody As SurfaceBody = partDef.SurfaceBodies.Item(1)

    'Print out all the AssociateIDs of all the faces 
    Call GetAssocIDs(partBody, "New Part")

    'Set camera to home view
    ThisApplication.CommandManager.ControlDefinitions.Item("AppViewCubeHomeCmd").Execute()

    'Set face color to show the correct face was located
    Call SetFaceColor(partDoc, partDef.SurfaceBodies.Item(1), markingFaceID)
    Call SetFaceColor(partDoc, partDef.SurfaceBodies.Item(1), ASideFaceID)

    'Convert to sheetmetal: Set thickness value, A-side definition and create Flat Pattern
    Call ProcessSheetMetal(partDoc, thkParam, partBody, ASideFaceID)

    'Copy sketch from blank component, paste to new document and add marking feature
    Call AddMarkingSketch(blankCompDef, partDoc, partDef, partBody, markingFaceID)
	
End Sub

Sub AddMarkingSketch(blankCompDef As ComponentDefinition, partDoc As PartDocument, partDef As PartComponentDefinition, body As SurfaceBody, i As Integer)
    'Find the sketch to copy
    Dim oSketch As PlanarSketch = Nothing
    For Each oSketch In blankCompDef.Sketches
        If oSketch.Name = "MarkingSketch" Then
            Exit For
        End If
        oSketch = Nothing
    Next

    If oSketch Is Nothing Then
        MsgBox("Sketch not found. Exiting rule")
        Return
    End If

    'Find the "anchor point" for the TextBox
    Dim WP As WorkPoint = Nothing
    For Each WP In blankCompDef.WorkPoints
        If WP.Name = "TextBoxAnchor" Then
            Dim TG As TransientGeometry = ThisApplication.TransientGeometry
            Dim TGpoint As Point = TG.CreatePoint(WP.Point.X, WP.Point.Y, WP.Point.Z)
            'Add the "anchor point" to the new part as a fixed Work Point feature
            WP = partDef.WorkPoints.AddFixed(TGpoint)
            Exit For
        End If
        WP = Nothing
    Next

    If WP Is Nothing Then
        MsgBox("Work Point not found. Exiting rule")
        Return
    End If

    'Find the face to copy the sketch to
    For Each oFace As Face In body.Faces
        If oFace.AssociativeID = i Then
            'Add sketch to face
            Dim newSketch As PlanarSketch = partDef.Sketches.Add(oFace)

            'Copy contents from source sketch
            oSketch.CopyContentsTo(newSketch)
            'Replace text in TextBox
            newSketch.TextBoxes.Item(1).Text = "some other text"

            Dim SP As SketchPoint
            For Each SP In newSketch.SketchPoints
                'Find the "Center Point" attached to the TextBox frame
                If SP.HoleCenter = True Then
                    'Constrain the TextBox to the "anchor point"
                    Dim anchorPoint As SketchPoint = newSketch.AddByProjectingEntity(WP)
                    newSketch.GeometricConstraints.AddCoincident(SP, anchorPoint)
                    Exit For
                End If
            Next

            Dim sketchObjects As ObjectCollection = ThisApplication.TransientObjects.CreateObjectCollection
            'Get all entities in the sketch
            For Each sketchText As Inventor.TextBox In newSketch.TextBoxes
                sketchObjects.Add(sketchText)
            Next

            Dim oMarkFeatures As MarkFeatures = partDef.Features.MarkFeatures
            'Get mark style
            Dim oMarkStyle As MarkStyle = partDoc.MarkStyles.Item(1)
            'Create mark definition
            Dim oMarkDef As MarkDefinition = oMarkFeatures.CreateMarkDefinition(sketchObjects, oMarkStyle)
            'Create a mark feature
            Dim oMarkFeature As MarkFeature = oMarkFeatures.Add(oMarkDef)

            Exit For
        End If
    Next
End Sub

Sub ProcessSheetMetal(partDoc As PartDocument, thkParam As Parameter, partBody As SurfaceBody, ASideFaceID As Integer)
    'Make sure the new file is sheetmetal
    If Not TypeOf partDoc.ComponentDefinition Is SheetMetalComponentDefinition Then
        'Convert to sheetmetal
        Try
            partDoc.SubType = "{9C464203-9BAE-11D3-8BAD-0060B0CE6BB4}"
        Catch ex As Exception
            MsgBox("Failed converting new file to Sheet Metal")
            Return
        End Try
    End If

    Dim SMCD As SheetMetalComponentDefinition = partDoc.ComponentDefinition
    'Unlock SheetMetalStyle (untick checkbox "Use Thickness from Rule" to allow editing Thickness parameter)
    SMCD.UseSheetMetalStyleThickness = False
    'Set Thickness from "blank" component
    SMCD.Thickness.Value = thkParam.Value

    'Loop thru faces in the new part document looking for a match
    For Each oFace As Face In partBody.Faces
        If oFace.AssociativeID = ASideFaceID Then
            'Add the A-side definition to the new part document
            SMCD.ASideDefinitions.Add(oFace)
            Exit For
        End If
    Next

    'Create flat pattern
    SMCD.Unfold()
    SMCD.FlatPattern.ExitEdit()
End Sub

Sub GetAssocIDs(body As SurfaceBody, component As String)
    Dim i As Integer = 1
    For Each face As Face In body.Faces
        Logger.Info(component & ": Index = " & i & " -> ID = " & Face.AssociativeID)
        i += 1
    Next
End Sub

Sub SetFaceColor(doc As PartDocument, body As SurfaceBody, i As Integer)
    doc.Activate()
    Dim style As RenderStyle = doc.RenderStyles("Green")
    For Each face As Face In body.Faces
        If Face.AssociativeID = i Then
            Call Face.SetRenderStyle(StyleSourceTypeEnum.kOverrideRenderStyle, style)
        End If
    Next
End Sub

Function GetASideFaceIndex(body As SurfaceBody, doc As PartDocument) As Integer
    Dim SMCD As SheetMetalComponentDefinition = doc.ComponentDefinition
    Dim i As Integer = 1
    For Each face As Face In body.Faces
        If Face.TransientKey = SMCD.ASideFace.TransientKey Then
            GetASideFaceIndex = i
            Return GetASideFaceIndex
        End If
        i += 1
    Next
    Return Nothing
End Function

Function GetAttributeFaceIndex(body As SurfaceBody, name As String) As Integer
    Dim i As Integer = 1
    For Each face As Face In body.Faces
        Dim AttSets As AttributeSets = Face.AttributeSets
        If AttSets.NameIsUsed("iLogicEntityNameSet") Then
            Dim AttSet As AttributeSet = AttSets.Item("iLogicEntityNameSet")
            For Each Att As Inventor.Attribute In AttSet
                If Att.Value() = name Then
                    GetAttributeFaceIndex = i
                    Return GetAttributeFaceIndex
                End If
            Next
        End If
        i += 1
    Next
    Return Nothing
End Function

 

Best,

Fredrik

Message 13 of 17
fredform
in reply to: fredform

Anyone from Autodesk care to comment on this approach with AssociativeID's? I would really like to know if this is a valid use of the API or not before proceeding with the project (and accepting the solution to this thread...).

Message 14 of 17
WCrihfield
in reply to: fredform

We probably need to tag one of those Autodesk employees who knows about these types of things, because they are pretty busy, so they may not get a chance to review every forum response that gets posted.  I do not usually like to do this, but when you type the @ symbol in a forum response, it triggers a reaction, expecting you to type in someone's username.  And when you use that technique, there is an optional setting where those folks may get a notification about it, and therefore, they may see that notification and review the response that their username was tagged in.

In this case, Mike Deck is likely the Inventor API expert on the Autodesk side who may know more about this.

@MjDeck 

Can you explain the Face.AssociativeID property in more detail?  If we should use it or should we avoid it?  If we should avoid it, then what is the best alternative?  If we should use it, why was it hidden, and what is it best used for, and not good to use for?

Thanks Mike.

Wesley Crihfield

EESignature

(Not an Autodesk Employee)

Message 15 of 17
MjDeck
in reply to: WCrihfield

Hi @WCrihfield and @fredform - I started looking at this, but I don't know what to recommend at this time.


Mike Deck
Software Developer
Autodesk, Inc.

Message 16 of 17
MjDeck
in reply to: MjDeck

It looks like it's OK to use Face.AssociativeID. It is designed specifically for transient bodies. We might be able to make this API property visible in a future release.


Mike Deck
Software Developer
Autodesk, Inc.

Message 17 of 17
fredform
in reply to: MjDeck

Hello Mike! 

 

Thank you so much for looking into this! And that sounds very promising, for the future release I think this property needs a bit more documentation as well, how it works and how it should be used. Specifically I find the behavior of the AssociativeID seemingly changing to the index number of the face being a bit strange, but perhaps there's some good reason for this.

 

Best,

Fredrik 

Can't find what you're looking for? Ask the community or share your knowledge.

Post to forums  

Autodesk Customer Advisory Groups


Autodesk Design & Make Report