Add Rectangular Pattern Feature to Component

Add Rectangular Pattern Feature to Component

ebunn3
Advocate Advocate
1,161 Views
5 Replies
Message 1 of 6

Add Rectangular Pattern Feature to Component

ebunn3
Advocate
Advocate

Hi,

 

I've pasted a code example below that creates a Rectangular Pattern Feature and adds it to a new document.  I want to re-configure this so it adds the pattern feature to a new component within an active file instead of creating a new file and adding it to that one.  Can someone help me re-configure this example to do this?  

 

I've tried to change by passing in a new component and using it as my root component and get the following error:

Traceback (most recent call last): File "C:/Users/ebunn/AppData/Roaming/Autodesk/Autodesk Fusion 360/API/Scripts/Nesting_True_Type_By_Points_Comp/Nesting_True_Type_By_Points_Comp.py", line 736, in <module> PatternBodies(preN[1],newComp,numX,moveX,numY,moveY) File "C:/Users/ebunn/AppData/Roaming/Autodesk/Autodesk Fusion 360/API/Scripts/Nesting_True_Type_By_Points_Comp/Nesting_True_Type_By_Points_Comp.py", line 683, in PatternBodies rectangularFeature = rectangularPatterns.add(rectangularPatternInput) File "C:\Users/ebunn/AppData/Local/Autodesk/webdeploy/production/8814bf1cdd9624465cbdf7f023becc629a5ffbe5/...", line 28366, in add return _fusion.RectangularPatternFeatures_add(self, input) RuntimeError: 2 : InternalValidationError : Utils::getObjectPath(obj.get(),objPath, nullptr,path)

 

Here is an example of the attempted change.  The new component I am trying to add it to is called newComp.  I am pulling the bodies from another component passed in as comp:

 

def PatternBodies(comp,newComp,quantityOne,distanceOne,quantityTwo,distanceTwo😞
    app = adsk.core.Application.get()
    ui = app.userInterface
    # Create a document.
    # doc = app.documents.add(adsk.core.DocumentTypes.FusionDesignDocumentType)
    product = app.activeProduct
    design = adsk.fusion.Design.cast(product)
    # # Get the root component of the active design.
    rootComp = newComp#design.rootComponent
    #Get  the document units (bookmark:units)
    units = design.unitsManager.defaultLengthUnits

    # Create input entities for rectangular pattern
    inputEntites = adsk.core.ObjectCollection.create()
    for i in comp.bRepBodies:
        inputEntites.add(i)

 

 

import adsk.core, adsk.fusion, traceback

def run(context):
    ui = None
    try:
        app = adsk.core.Application.get()
        ui = app.userInterface
        
        # Create a document.
        doc = app.documents.add(adsk.core.DocumentTypes.FusionDesignDocumentType)
 
        product = app.activeProduct
        design = adsk.fusion.Design.cast(product)

        # Get the root component of the active design.
        rootComp = design.rootComponent
        
        # Create sketch
        sketches = rootComp.sketches
        sketch = sketches.add(rootComp.xZConstructionPlane)
        sketchCircles = sketch.sketchCurves.sketchCircles
        centerPoint = adsk.core.Point3D.create(0, 0, 0)
        sketchCircles.addByCenterRadius(centerPoint, 3.0)
        
        # Get the profile defined by the circle.
        prof = sketch.profiles.item(0)

        # Create an extrusion input
        extrudes = rootComp.features.extrudeFeatures
        extInput = extrudes.createInput(prof, adsk.fusion.FeatureOperations.NewBodyFeatureOperation)
        
        # Define that the extent is a distance extent of 5 cm.
        distance = adsk.core.ValueInput.createByReal(5)
        extInput.setDistanceExtent(False, distance)

        # Create the extrusion.
        ext = extrudes.add(extInput)
        
        # Get the body created by extrusion
        body = ext.bodies.item(0)
        
        # Create input entities for rectangular pattern
        inputEntites = adsk.core.ObjectCollection.create()
        inputEntites.add(body)
        
        # Get x and y axes for rectangular pattern
        xAxis = rootComp.xConstructionAxis
        yAxis = rootComp.yConstructionAxis
        
        # Quantity and distance
        quantityOne = adsk.core.ValueInput.createByString('3')
        distanceOne = adsk.core.ValueInput.createByString('8 cm')
        quantityTwo = adsk.core.ValueInput.createByString('3')
        distanceTwo = adsk.core.ValueInput.createByString('8 cm')
        
        # Create the input for rectangular pattern
        rectangularPatterns = rootComp.features.rectangularPatternFeatures
        rectangularPatternInput = rectangularPatterns.createInput(inputEntites, xAxis, quantityOne, distanceOne, adsk.fusion.PatternDistanceType.SpacingPatternDistanceType)
        
        # Set the data for second direction
        rectangularPatternInput.setDirectionTwo(yAxis, quantityTwo, distanceTwo)
        
        # Create the rectangular pattern
        rectangularFeature = rectangularPatterns.add(rectangularPatternInput)
    except:
        if ui:
            ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))

 

 

 

Appreciate the help.

 

Eric

0 Likes
Accepted solutions (1)
1,162 Views
5 Replies
Replies (5)
Message 2 of 6

Jorge_Jaramillo
Collaborator
Collaborator

Hi @ebunn3 ,

 

Please find attached a script for it.

Just to clarify: the bodies created in the rectangular pattern are kept in the source component, so at the end of the function it moves them to the new created component.

 

def PatternBodies(  srcComp: adsk.fusion.Component, 
                    destOccu: adsk.fusion.Occurrence,
                    quantityOne: adsk.core.ValueInput, 
                    distanceOne: adsk.core.ValueInput, 
                    quantityTwo: adsk.core.ValueInput, 
                    distanceTwo: adsk.core.ValueInput):
    try:
        # Create input entities for rectangular pattern
        inputEntites = adsk.core.ObjectCollection.create()
        for i in srcComp.bRepBodies:
            inputEntites.add(i)

        # Get x and y axes for rectangular pattern
        xAxis = srcComp.xConstructionAxis
        yAxis = srcComp.yConstructionAxis

        # Create the input for rectangular pattern
        rectangularPatterns = srcComp.features.rectangularPatternFeatures
        rectangularPatternInput = rectangularPatterns.createInput(inputEntites, xAxis, quantityOne, distanceOne, adsk.fusion.PatternDistanceType.SpacingPatternDistanceType)

        # Set the data for second direction
        rectangularPatternInput.setDirectionTwo(yAxis, quantityTwo, distanceTwo)
        
        # Create the rectangular pattern
        rectangularFeature = rectangularPatterns.add(rectangularPatternInput)

        # move the bodies to the destComp, since the new bodies are created in the same component they belongs
        bodyArray = [body for body in rectangularFeature.bodies]
        # I had to create this body array, because iterating over rectangularFeature.bodies gives an error on item #8.
        for body in bodyArray:
            body.moveToComponent(destOccu)
    except:
        app.log(f'Error in PatternBodies: {traceback.format_exc()}')


def rectangularPattern():
    try:
        #source component to take bodies from
        rootComp = adsk.fusion.Design.cast(app.activeProduct).rootComponent
        srcComp = rootComp

        #create the new component
        matrix = adsk.core.Matrix3D.create()
        destOccu = rootComp.occurrences.addNewComponent(matrix)
        destComp = destOccu.component
        destComp.name = 'newComponent'

        # create ValueInput's for each dimension
        quantityOne = adsk.core.ValueInput.createByString('3')
        distanceOne = adsk.core.ValueInput.createByString('8 cm')
        quantityTwo = adsk.core.ValueInput.createByString('3')
        distanceTwo = adsk.core.ValueInput.createByString('8 cm')

        PatternBodies(srcComp, destOccu, quantityOne, distanceOne, quantityTwo, distanceTwo)
    except:
        app.log(f'Error in rectangularPattern: {traceback.format_exc()}')

 

Hope this help to solve your problem.

 

Regards,

Jorge

 

 

0 Likes
Message 3 of 6

ebunn3
Advocate
Advocate

Walter,

 

See screenshot below.  I want to use the bodies in Component 1:1 and create a new component that will contain the rectangular pattern.

 

Thanks for all of the help.

 

Eric

 

ebunn3_0-1660324368271.png

 

 

0 Likes
Message 4 of 6

Jorge_Jaramillo
Collaborator
Collaborator
Accepted solution

Give a try at this script which worked for me.

If you have two bodies on source component, you will get 18 (= 2 x 3 x 3) in the new component.

def PatternBodies(  srcComp: adsk.fusion.Component, 
                    destOccu: adsk.fusion.Occurrence,
                    quantityOne: adsk.core.ValueInput, 
                    distanceOne: adsk.core.ValueInput, 
                    quantityTwo: adsk.core.ValueInput, 
                    distanceTwo: adsk.core.ValueInput):
    try:
        # Create input entities for rectangular pattern
        inputEntites = adsk.core.ObjectCollection.create()
        for i in srcComp.bRepBodies:
            # copy bodies to dest component
            cpb = destOccu.component.features.copyPasteBodies.add(i)
            inputEntites.add(cpb.bodies[0])

        # Get x and y axes for rectangular pattern
        xAxis = destOccu.component.xConstructionAxis
        yAxis = destOccu.component.yConstructionAxis

        # Create the input for rectangular pattern
        rectangularPatterns = destOccu.component.features.rectangularPatternFeatures
        rectangularPatternInput = rectangularPatterns.createInput(inputEntites, xAxis, quantityOne, distanceOne, adsk.fusion.PatternDistanceType.SpacingPatternDistanceType)

        # Set the data for second direction
        rectangularPatternInput.setDirectionTwo(yAxis, quantityTwo, distanceTwo)

        # Create the rectangular pattern
        rectangularFeature = rectangularPatterns.add(rectangularPatternInput)
    except:
        app.log(f'Error in PatternBodies: {traceback.format_exc()}')


def rectangularPattern():
    try:
        #source component to take bodies from
        rootComp = adsk.fusion.Design.cast(app.activeProduct).rootComponent
        srcComp = rootComp.occurrences.item(0).component  # <---- bodies from first component under root component; change according to your design

        #create the new component
        matrix = adsk.core.Matrix3D.create()
        destOccu = rootComp.occurrences.addNewComponent(matrix)
        destComp = destOccu.component
        destComp.name = 'newComponent'

        # create ValueInput's for each dimension
        quantityOne = adsk.core.ValueInput.createByString('3')
        distanceOne = adsk.core.ValueInput.createByString('8 cm')
        quantityTwo = adsk.core.ValueInput.createByString('3')
        distanceTwo = adsk.core.ValueInput.createByString('8 cm')

        PatternBodies(srcComp, destOccu, quantityOne, distanceOne, quantityTwo, distanceTwo)
    except:
        app.log(f'Error in rectangularPattern: {traceback.format_exc()}')

 

The change I made is to copy source bodies to new component before making the rect pattern, instead of moving the result bodies at the end.

 

Regards,

Jorge

0 Likes
Message 5 of 6

ebunn3
Advocate
Advocate

Thank you so much!!!  Perfect.

 

Eric

0 Likes
Message 6 of 6

ebunn3
Advocate
Advocate

I've made a few changes to the script allowing a component selection first.  Just wanted to post the final script for anyone else's benefit.  Thanks again to @Jorge_Jaramillo for the great solution.

import adsk.core, adsk.fusion, traceback

def rectangularPattern(srcComp,quantity1,distance1,quantity2,distance2):
    def traverseForBodies(occs,lst):
        """gets all bodies in occurence, including bodies in childOccurences
        lst = list()
        traverseForBodies(product,lst)"""
        if not occs.bRepBodies.count == 0:
            for bod in occs.bRepBodies:
                if bod.isVisible:lst.append(bod)
        #check child occurences
        if occs.childOccurrences:
            occChild = occs.childOccurrences
            for child in occChild:
                traverseForBodies(child,lst)
    def PatternBodies(  srcComp: adsk.fusion.Component, 
                    destOccu: adsk.fusion.Occurrence,
                    quantityOne: adsk.core.ValueInput, 
                    distanceOne: adsk.core.ValueInput, 
                    quantityTwo: adsk.core.ValueInput, 
                    distanceTwo: adsk.core.ValueInput):
        try:
            # Create input entities for rectangular pattern
            inputEntites = adsk.core.ObjectCollection.create()
            lst = list()
            traverseForBodies(srcComp,lst)
            for i in lst:
                # copy bodies to dest component
                cpb = destOccu.component.features.copyPasteBodies.add(i)
                inputEntites.add(cpb.bodies[0])

            # Get x and y axes for rectangular pattern
            xAxis = destOccu.component.xConstructionAxis
            yAxis = destOccu.component.yConstructionAxis

            # Create the input for rectangular pattern
            rectangularPatterns = destOccu.component.features.rectangularPatternFeatures
            rectangularPatternInput = rectangularPatterns.createInput(inputEntites, xAxis, quantityOne, distanceOne, adsk.fusion.PatternDistanceType.SpacingPatternDistanceType)

            # Set the data for second direction
            rectangularPatternInput.setDirectionTwo(yAxis, quantityTwo, distanceTwo)

            # Create the rectangular pattern
            rectangularFeature = rectangularPatterns.add(rectangularPatternInput)
        except:
            app.log(f'Error in PatternBodies: {traceback.format_exc()}')

    try:
        app = adsk.core.Application.get()
        ui  = app.userInterface     
        #source component to take bodies from
        rootComp = adsk.fusion.Design.cast(app.activeProduct).rootComponent

        #create the new component
        matrix = adsk.core.Matrix3D.create()
        destOccu = rootComp.occurrences.addNewComponent(matrix)
        destComp = destOccu.component
        destComp.name = 'Main_Rect_Pattern'

        # create ValueInput's for each dimension quantity1,distance1,quantity2,distance2
        quantityOne = adsk.core.ValueInput.createByString(quantity1)
        distanceOne = adsk.core.ValueInput.createByString(distance1 + ' cm')
        quantityTwo = adsk.core.ValueInput.createByString(quantity2)
        distanceTwo = adsk.core.ValueInput.createByString(distance2 + ' cm')

        PatternBodies(srcComp, destOccu, quantityOne, distanceOne, quantityTwo, distanceTwo)
    except:
        app.log(f'Error in rectangularPattern: {traceback.format_exc()}')



app = adsk.core.Application.get()
ui  = app.userInterface

#Select body
comp = ui.selectEntity('Select a component', 'Occurrences').entity#.component
print("")
bbMin=comp.boundingBox.minPoint
bbMax=comp.boundingBox.maxPoint
prodL = bbMax.x-bbMin.x
prodW = bbMax.y-bbMin.y

quantityOne=str(4)
distanceOne=str(prodL)
quantityTwo=str(4)
distanceTwo=str(prodW)
rectangularPattern(comp,quantityOne,distanceOne,quantityTwo,distanceTwo)

 

Eric