Community
Fusion API and Scripts
Got a new add-in to share? Need something specialized to be scripted? Ask questions or share what you’ve discovered with the community.
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Batch import multiple splines of csv files. And adding a loft between those splines.

4 REPLIES 4
Reply
Message 1 of 5
tomas_kramer
247 Views, 4 Replies

Batch import multiple splines of csv files. And adding a loft between those splines.

It's my first time using the Fusion API. I am using Windows 10 and Python. I want to import multiple splines into the Fusion (which currently works nicely with the "ImportSplineCSV" sample script), but I find it tedious to do for every csv.file. I was wondering if there was a way to select multiple csv files and create a spline for each seperate one.

In this thread i found a solution, i think, but couldnt get the batch import to work.

https://forums.autodesk.com/t5/fusion-api-and-scripts/trouble-with-batch-import-and-loft-of-csv-file... 

 

 

#Author-Autodesk Inc.

#Description-Import spline from csv file

import adsk.core, adsk.fusion, tracebac
import io

def run(context):
    ui = None
    try:
        app = adsk.core.Application.get()
        ui  = app.userInterface
        # Get all components in the active design.
        product = app.activeProduct
        design = adsk.fusion.Design.cast(product)
        rootComp = design.rootComponent
        title = 'Import Spline csv'
        if not design:
            ui.messageBox('No active Fusion design', title)
            return
       
        dlg = ui.createFileDialog()
        dlg.title = 'Open CSV File'
        dlg.filter = 'Comma Separated Values (*.csv);;All Files (*.*)'
        if dlg.showOpen() != adsk.core.DialogResults.DialogOK :
            return
       
        filename = dlg.filename

        sketches = []
        for i in range(1,202‌‌#Loop for csv import
            filename = 'C:/*privacy*/layer{}.csv'.format(i)

            with io.open(filename, 'r', encoding='utf-8-sig') as f:
                points = adsk.core.ObjectCollection.create()
                line = f.readline()
                data = []
                while line:
                    pntStrArr = line.split(',')
                    for pntStr in pntStrArr:
                        try:
                            data.append(float(pntStr))
                        except:
                            break
               
                    if len(data) >= 3 :
                        point = adsk.core.Point3D.create(data[0], data[1], data[2])
                        points.add(point)
                    line = f.readline()
                    data.clear()            
            if points.count:
                sketch = design.rootComponent.sketches.add(design.rootComponent.xYConstructionPlane)
                sketch.sketchCurves.sketchFittedSplines.add(points)
                sketches.append(sketch)
            else:
                ui.messageBox('No valid points', title)            
       
        loftFeats = rootComp.features.loftFeatures
        loftInput = loftFeats.createInput(adsk.fusion.FeatureOperations.NewBodyFeatureOperation)
        loftSectionsObj = loftInput.loftSections

        for sketch in skethes:
            profile = sketch.profiles.item(0)
            loftSectionsObj.add(profile)
       
        loftFeats = rootComp.features.loftFeatures
        loftInput = loftFeats.createInput(adsk.fusion.FeatureOperations.NewBodyFeatureOperation)
        loftSectionsObj = loftInput.loftSections

        for j in range(0,100‌‌#Loop for selecting the scetch profiles for the loft
           
         profile = design.rootComponent.sketches.add(rootComp.xYConstructionPlane).profiles.item(j)
         loftSectionsObj.add(profile)
         
     

        loftInput.isSolid = False

        # Create loft feature
        loftFeats.add(loftInput)



#design.rootComponent.sketches.add(rootComp.xZConstructionPlane).profiles.item(0)
    except:
        if ui:
            ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))

 

 

After importing the splines, I want to create a loft between the splineprofiles, i wonder if that can be done in the same script. I am working on a propeller and im generating the sectioncurves using openprop v3.3.4. in matlab:

tomas_kramer_0-1714666883056.png

After using the import spline script 20 times i get one blade of the propeller:

tomas_kramer_1-1714667264098.png

Since its always the same process for each propeller, i wonder if its possible to automate the whole process to create a propeller. With the solid loft function iIwant to create a blade. Than i import the hub component and combine the components together. After using a fillet i get a nice transistion between the blades and the hub. With the c-pattern i want to copy the blade with the fillet to the other side.

tomas_kramer_2-1714667558311.png

 

Thank you in advance and have a nice day,

Tomas

Tags (4)
4 REPLIES 4
Message 2 of 5
BrianEkins
in reply to: tomas_kramer

What you're wanting to do is certainly possible. Here's a script I just wrote that creates a spline for each CSV file in a specified folder and then creates a loft through the splines. I've attached the CSV files I used for testing. You should be able to find other posts and examples to add the additional code to insert the hub, mirror the blade, and combine them into a single body. Hopefully, this provides a good start.

def run(context):
    ui = None
    try:
        app = adsk.core.Application.get()
        ui = app.userInterface
        if app.activeProduct.productType != 'DesignProductType':
            ui.messageBox('A Design must be acitve.')
            return

        des: adsk.fusion.Design = app.activeProduct
        root = des.rootComponent

        # Prompt to have the folder containing the csv files selected.
        dlg = ui.createFolderDialog()
        dlg.title = 'Section Curves Folder'
        if dlg.showDialog() != adsk.core.DialogResults.DialogOK :
            return

        sectionFolder = dlg.folder

        # Create a new sketch for the sections.
        sk = root.sketches.add(root.xYConstructionPlane)
        sk.name = 'Section Curves'

        # Get all of the csv files.
        files = [f for f in os.listdir(sectionFolder) if f.endswith('.csv')]
        files.sort()

        sections = []
        for file in files:
            fullFilename = os.path.join(sectionFolder, file)

            points = adsk.core.ObjectCollection.create()
            firstLine = True
            with open(fullFilename, 'r') as file:
                reader = csv.reader(file)
                for row in reader:
                    if firstLine:
                        # Strip off the byte characters at the beginning of the file.
                        row[0] = row[0][3:]
                        firstLine = False
                    points.add(adsk.core.Point3D.create(float(row[0]), float(row[1]), float(row[2])))

            if points.count > 1:
                curve = sk.sketchCurves.sketchFittedSplines.add(points)
                sections.append(curve)
            else:
                point = sk.sketchPoints.add(points[0])
                sections.append(point)

        loftInput = root.features.loftFeatures.createInput(adsk.fusion.FeatureOperations.NewBodyFeatureOperation)
        for section in sections:
            if section.objectType == adsk.fusion.SketchPoint.classType():
                loftSection = loftInput.loftSections.add(section)
                loftSection.setPointTangentEndCondition(adsk.core.ValueInput.createByReal(1))
            else:
                loftInput.loftSections.add(section)

        loft = root.features.loftFeatures.add(loftInput)
    except:
        if ui:
            ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))

 

---------------------------------------------------------------
Brian Ekins
Inventor and Fusion 360 API Expert
Website/Blog: https://EkinsSolutions.com
Message 3 of 5
tomas_kramer
in reply to: tomas_kramer

Files:

Message 4 of 5
tomas_kramer
in reply to: BrianEkins

Thank you so much for your help!

Ive tried the code and I thought it was allready amazing, but than I found out it failed to make a spline:

tomas_kramer_0-1714734038212.png

tomas_kramer_1-1714734055489.png

I've tried to understand how it works, but the code seems fine, so i dont know what the problem is. I've provided my csv files too which i used for testing, maybe it helps

 

 

 

 

#Author-
#Description-

import adsk.core, adsk.fusion, adsk.cam, traceback, os, csv

def run(context):
    ui = None
    try:
        app = adsk.core.Application.get()
        ui = app.userInterface
        if app.activeProduct.productType != 'DesignProductType':
            ui.messageBox('A Design must be acitve.')
            return

        des: adsk.fusion.Design = app.activeProduct
        root = des.rootComponent

        # Prompt to have the folder containing the csv files selected.
        dlg = ui.createFolderDialog()
        dlg.title = 'Section Curves Folder'
        if dlg.showDialog() != adsk.core.DialogResults.DialogOK :
            return

        sectionFolder = dlg.folder

        # Create a new sketch for the sections.
        sk = root.sketches.add(root.xYConstructionPlane)
        sk.name = 'Section Curves'

        # Get all of the csv files.
        files = [f for f in os.listdir(sectionFolder) if f.endswith('.csv')]
        files.sort()

        sections = []
        for file in files:
            fullFilename = os.path.join(sectionFolder, file)

            points = adsk.core.ObjectCollection.create()
            firstLine = True
            with open(fullFilename, 'r') as file:
                reader = csv.reader(file)
                for row in reader:
                    if firstLine:
                        # Strip off the byte characters at the beginning of the file.
                        row[0] = row[0][3:]
                        firstLine = False
                    points.add(adsk.core.Point3D.create(float(row[0]), float(row[1]), float(row[2])))
#create spline part:
            if points.count > 1:#check if there 2 points to create a spline
                curve = sk.sketchCurves.sketchFittedSplines.add(points)
                sections.append(curve)
            else:# If there's only one point, add it as a sketch point
                point = sk.sketchPoints.add(points[0])
                sections.append(point)

        loftInput = root.features.loftFeatures.createInput(adsk.fusion.FeatureOperations.NewBodyFeatureOperation)
        for section in sections:
            if section.objectType == adsk.fusion.SketchPoint.classType():
                loftSection = loftInput.loftSections.add(section)
                loftSection.setPointTangentEndCondition(adsk.core.ValueInput.createByReal(1))
            else:
                loftInput.loftSections.add(section)

        loft = root.features.loftFeatures.add(loftInput)
    except:
        if ui:
            ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))

 

 

 

 

@BrianEkins 

Message 5 of 5
BrianEkins
in reply to: tomas_kramer

Your files are encoded differently than mine, so it worked for me and not for you. My files, which I created using Excel, had extra characters at the beginning of the file to specify the encoding type used for the file. I was assuming all files had this same encoding, so I was always ignoring the first three characters. I changed the code, so instead of blindly assuming there are encoding characters at the beginning of the file, I now specify the encoding when opening the file and let Python take care of it.

After fixing that, the loft was failing with your data. The problem is that the files must be named alphabetically in the order they're processed. 

They were being processed:

 

SectionCurve1.csv

SectionCurve10.csv

SectionCurve11.csv

SectionCurve12.csv

SectionCurve13.csv

SectionCurve14.csv

SectionCurve15.csv

SectionCurve16.csv

SectionCurve17.csv

SectionCurve18.csv

SectionCurve19.csv

SectionCurve2.csv

SectionCurve3.csv

 

I renamed the single digits, so the first files are now SectionCurve01.csv, SectionCurve02.csv, etc. Now, they're in correct alphabetical order. 

 

Here's the modified program. I've also attached the files for the renamed sections.

 

import adsk.core, adsk.fusion, traceback
import os
import csv

def run(context):
    ui = None
    try:
        app = adsk.core.Application.get()
        ui = app.userInterface
        if app.activeProduct.productType != 'DesignProductType':
            ui.messageBox('A Design must be acitve.')
            return

        des: adsk.fusion.Design = app.activeProduct
        root = des.rootComponent

        # Prompt to have the folder containing the csv files selected.
        dlg = ui.createFolderDialog()
        dlg.title = 'Section Curves Folder'
        if dlg.showDialog() != adsk.core.DialogResults.DialogOK :
            return

        sectionFolder = dlg.folder

        # Create a new sketch for the sections.
        sk = root.sketches.add(root.xYConstructionPlane)
        sk.name = 'Section Curves'

        # Get all of the csv files.
        files = [f for f in os.listdir(sectionFolder) if f.endswith('.csv')]
        files.sort()

        sections = []
        for file in files:
            fullFilename = os.path.join(sectionFolder, file)

            points = adsk.core.ObjectCollection.create()
            with open(fullFilename, 'r', encoding = 'utf-8-sig') as file:
                reader = csv.reader(file)
                for row in reader:
                    points.add(adsk.core.Point3D.create(float(row[0]), float(row[1]), float(row[2])))

            if points.count > 1:
                curve = None
                curve = sk.sketchCurves.sketchFittedSplines.add(points)
                sections.append(curve)
            else:
                point = sk.sketchPoints.add(points[0])
                sections.append(point)

        loftInput = root.features.loftFeatures.createInput(adsk.fusion.FeatureOperations.NewBodyFeatureOperation)
        for section in sections:
            if section.objectType == adsk.fusion.SketchPoint.classType():
                loftSection = loftInput.loftSections.add(section)
                loftSection.setPointTangentEndCondition(adsk.core.ValueInput.createByReal(1))
            else:
                loftInput.loftSections.add(section)

        loft = root.features.loftFeatures.add(loftInput)
    except:
        if ui:
            ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))
---------------------------------------------------------------
Brian Ekins
Inventor and Fusion 360 API Expert
Website/Blog: https://EkinsSolutions.com

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

Post to forums