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: 

How to efficiently process 10000 individual coordinates to build model.

10 REPLIES 10
SOLVED
Reply
Message 1 of 11
rijalkhem187
876 Views, 10 Replies

How to efficiently process 10000 individual coordinates to build model.

I am trying to build a 3D solid model using sweep / extrusion feature. I have collection of more than 100000 individual coordinates. I am taking two points for extrusion/ sweep at a time to to avoid self intersecting lines problem. However it's taking forever to finish building all bodies (whole model). Is there any way to speed up this process efficiently. I could not understand the use of BRep bodies. I do not need intermediary bodies to be saved. I am trying to get whole extruded model. I have few questions.

1) How to combine all bodies to make single entity?

2) How to use revolve feature that joins the empty spaces between to extrusion bodies at angle?

3)How to  find segments untill the intersecting points to use  sweep feature so, it doesn't require to take only two points at a time. 

 

I am very new to scripting and making model in Fusion 360. 

I would really appreciate if you could help me out in this. 

 

Here is my code:  (Any suggestion for improvement would be highly appreciated.)

 

//Screen Shot 2020-02-27 at 9.02.11 PM.pngScreen Shot 2020-02-27 at 9.04.55 PM.pngScreen Shot 2020-02-27 at 9.05.02 PM.png

 

import adsk.core, adsk.fusion, traceback
import io

 

def Extrudeline(spline,distance,radius,rootComp):
path = rootComp.features.createPath(spline)
# create construction plane normal to the spline
planes = rootComp.constructionPlanes
planeInput = planes.createInput()
planeInput.setByDistanceOnPath(path, adsk.core.ValueInput.createByReal(0))
plane = planes.add(planeInput)
extrudes = rootComp.features.extrudeFeatures

sketches = rootComp.sketches
sketch = sketches.add(plane)

center = plane.geometry.origin
center = sketch.modelToSketchSpace(center)
sketch.sketchCurves.sketchCircles.addByCenterRadius(center, radius)
profile = sketch.profiles[0]

#create a extrude input
distances = adsk.core.ValueInput.createByReal(distance)
extrudeInput = extrudes.createInput(profile, adsk.fusion.FeatureOperations.NewBodyFeatureOperation)
extent_distance = adsk.fusion.DistanceExtentDefinition.create(distances)
extrudeInput.setOneSideExtent(extent_distance, adsk.fusion.ExtentDirections.PositiveExtentDirection)
extrude2 = extrudes.add(extrudeInput)
return extrude2

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)
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

filename = '/Users/rizal/Desktop/20mm_cubeCoordinates.txt'

with io.open(filename, 'r',buffering=2000000000,encoding='utf-8-sig') as f:



data = []
line = next(f)

for line in f:
pntStrArr = line.split(',')
try:
data.append([float(pntStr) for pntStr in pntStrArr])
except:
continue

length = len(data)
length=1101
temp =0
radius =0.2


while temp<length - 1:

root = design.rootComponent
sketch = root.sketches.add(root.xYConstructionPlane)
sketch.isComputeDeferred = True
distance = ((data[temp][0]-data[temp+1][0])**2+(data[temp][1]-data[temp+1][1])**2+(data[temp][2]-data[temp+1][2])**2)**0.5
line = sketch.sketchCurves.sketchLines.addByTwoPoints(adsk.core.Point3D.create(data[temp][0], data[temp][1], data[temp][2]),adsk.core.Point3D.create(data[temp+1][0], data[temp+1][1], data[temp+1][2]))

temp += 1

extrude1 = Extrudeline(line,distance,radius,root)
sketch.isComputeDeferred = False


except:
if ui:
ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))

10 REPLIES 10
Message 2 of 11
kandennti
in reply to: rijalkhem187

Hi @rijalkhem187 .

 

I don't understand what we want, but we interpret it as a question about speeding up modeling.
One choice is to use a TemporaryBRepManager Object.
 
I have never used it, but I think fscad created by @JesusFreke  is also good.
 
If it is not limited to Fusion360, OpenSCAD may be an choice.
Message 3 of 11
rijalkhem187
in reply to: kandennti

@kandennti 

 

 

 

 

 

 

def Extrudeline(spline,distance,radius,rootComp):

path = rootComp.features.createPath(spline)
# create construction plane normal to the spline
planes = rootComp.constructionPlanes
planeInput = planes.createInput()
planeInput.setByDistanceOnPath(path, adsk.core.ValueInput.createByReal(0))
plane = planes.add(planeInput)
extrudes = rootComp.features.extrudeFeatures

sketches = rootComp.sketches
sketch = sketches.add(plane)

center = plane.geometry.origin
center = sketch.modelToSketchSpace(center)
sketch.sketchCurves.sketchCircles.addByCenterRadius(center, radius)

profile = sketch.profiles[0]

#create a extrude input
distances = adsk.core.ValueInput.createByReal(distance)
extrudeInput = extrudes.createInput(profile, adsk.fusion.FeatureOperations.JoinFeatureOperation)
extent_distance = adsk.fusion.DistanceExtentDefinition.create(distances)
extrudeInput.setOneSideExtent(extent_distance, adsk.fusion.ExtentDirections.PositiveExtentDirection)
extrude2 = extrudes.add(extrudeInput)

return extrude2

 

 

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)


filename = '/Desktop/20mm_cubeCoordinates.txt'

with io.open(filename, 'r',buffering=2000000000,encoding='utf-8-sig') as f:



data = []
line = next(f)

for line in f:
pntStrArr = line.split(',')
try:
data.append([float(pntStr) for pntStr in pntStrArr])
except:
continue

length = len(data)
#length=676
temp =0
radius =0.035

while temp<length - 1:

root = design.rootComponent
sketch = root.sketches.add(root.xYConstructionPlane)
sketch.isComputeDeferred = False
distance = ((data[temp][0]/10-data[temp+1][0]/10)**2+(data[temp][1]/10-data[temp+1][1]/10)**2+(data[temp][2]/10-data[temp+1][2]/10)**2)**0.5
line = sketch.sketchCurves.sketchLines.addByTwoPoints(adsk.core.Point3D.create(data[temp][0]/10, data[temp][1]/10, data[temp][2]/10),adsk.core.Point3D.create(data[temp+1][0]/10, data[temp+1][1]/10, data[temp+1][2]/10))

temp += 1

extrude1 = Extrudeline(line,distance,radius,root)

except:
if ui:
ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))

Message 4 of 11
kandennti
in reply to: rijalkhem187

Use this to post your code on the forum. Keep indentation.

2.png

Python indentation is important.

 

 

I tried using TemporaryBRepManager Object.
#Fusion360API Python script
import adsk.core, adsk.fusion, traceback
import time

def run(context):
    ui = None
    try:
        # data file path
        path = '/Desktop/20mm_cubeCoordinates.txt'

        app = adsk.core.Application.get()
        ui  = app.userInterface
        
        # new document
        app.documents.add(adsk.core.DocumentTypes.FusionDesignDocumentType)
        des = adsk.fusion.Design.cast(app.activeProduct)

        # direct design
        des.designType = adsk.fusion.DesignTypes.DirectDesignType

        # time
        startTime = time.time()

        # read file
        data = readData(path)

        # point3D
        pnt3D = adsk.core.Point3D
        pnts = [pnt3D.create(x, y, z) for (x, y, z) in data]

        # create cylinder
        radius =0.035
        cylinders = initCylinders(pnts, radius)

        # add bodies
        root = des.rootComponent
        bodies = root.bRepBodies
        [bodies.add(cyl) for cyl in cylinders]

        # fin
        des.designType = adsk.fusion.DesignTypes.ParametricDesignType
        msg = '-- Done --\nBodyCount : {}\nTime : {} s'.format(
            len(cylinders),time.time() - startTime)
        ui.messageBox(msg)

    except:
        if ui:
            ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))

def initCylinders(
    pnts :list,
    radius :float
    ) -> list:

    tmpMgr = adsk.fusion.TemporaryBRepManager.get()
    vec = adsk.core.Vector3D.create(1.0, 1.0, 1.0)
    cyls = []
    for idx in range(len(pnts) - 1):
        cyl = tmpMgr.createEllipticalCylinderOrCone(
            pnts[idx], radius, radius, pnts[idx + 1], radius, vec)

        if cyl:
            cyls.append(cyl)
    
    return cyls

def readData(
    path :str
    ) -> list:

    with open(path, 'r', buffering = -1, encoding = 'utf-8-sig') as f:
        lst = f.readlines()
    
    data = [s.replace('\n', '').split(',') for s in lst]

    app  :adsk.core.Application = adsk.core.Application.get()
    des  :adsk.fusion.Design = app.activeProduct
    um = des.unitsManager
    conv = um.convert(1, um.defaultLengthUnits, um.internalUnits)

    return [(float(x) * conv, float(y) * conv, float(z) * conv) for (x,y,z) in data]

The PC at home was low performance, but could be processed in about 90 seconds.

1.png

Message 5 of 11
rijalkhem187
in reply to: kandennti

Hi @kandennti 

Thank you for helping me out with this. 

I was able to successfully to get the expected result with your help. However, When I try to take 10,000 point, the Fusion crashes and closes by itself due to segmentation error. 

 

I have got into a new problem with this. I would really appreciate it if you could help to.

1) I am combining the bodies so that  I can use the revolve feature. But after combining two bodies I am not being able to select the face that I want to revolve. In the

#Fusion360API Python script
import adsk.core, adsk.fusion, traceback
import time

def run(context):
    ui = None
    try:
        # data file path
        path = '/Users/rizal/Desktop/20mm_cubeCoordinates.txt'

        app = adsk.core.Application.get()
        ui  = app.userInterface
        
        # new document
        # app.documents.add(adsk.core.DocumentTypes.FusionDesignDocumentType)
        des = adsk.fusion.Design.cast(app.activeProduct)

        # direct design
        des.designType = adsk.fusion.DesignTypes.DirectDesignType

        # time
        startTime = time.time()

        # read file
        data = readData(path)

        # point3D
        pnt3D = adsk.core.Point3D
        pnts = [pnt3D.create(x, y, z) for (x, y, z) in data]

        # create cylinder
        radius =0.035
        cylinders = initCylinders(pnts, radius)

        # add bodies
        root = des.rootComponent
        bodies = root.bRepBodies

        # for i in range(bodies.count-1):

        [bodies.add(cyl) for cyl in cylinders]

    
#################
        #Sketching lines to make axis for revolve 
        sketches = root.sketches
        xyPlane = root.xYConstructionPlane
        sketch = sketches.add(xyPlane)

        lines = sketch.sketchCurves.sketchLines
        axisline = lines.addByTwoPoints(
            adsk.core.Point3D.create(pnts[1].x,pnts[1].y,pnts[1].z),
            adsk.core.Point3D.create(pnts[1].x,pnts[1].y,pnts[1].z+0.5))

        
        
        #Collection object to store bodies for combine operation
        coll = adsk.core.ObjectCollection.create()
        coll.add(bodies.item(1))

        
        combine = root.features.combineFeatures
        combineInput = combine.createInput(bodies.item(0),coll)
    
        body = combine.add(combineInput)

        # face1 = body.faces[2]
        # face2 = body.faces[3]
        
        # revolves = root.features.revolveFeatures
        # revInput = revolves.createInput(face1,axisline,adsk.fusion.FeatureOperations.JoinFeatureOperation)
        # revInput.setOneSideToExtent(face2)

        # ext = revolves.add(revInput)
        # # for i in range(bodies.count-1):



############
        # fin
        des.designType = adsk.fusion.DesignTypes.ParametricDesignType
        msg = '-- Done --\nBodyCount : {}\nTime : {}'.format(
            len(cylinders),time.time() - startTime)
        ui.messageBox(msg)

    except:
        if ui:
            ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))

def initCylinders(
    pnts :list,
    radius :float
    ) -> list:

    tmpMgr = adsk.fusion.TemporaryBRepManager.get()
    cyls = []
    for idx in range(2):
        # creating vector to orient epllipse along the path
        vec = adsk.core.Vector3D.create(pnts[idx].x,pnts[idx].y,pnts[idx].z)

        #creating elliptical cylinder with major radius 0.02 and minor radius 0.01 and direction of vector 
        cyl = tmpMgr.createEllipticalCylinderOrCone(
            pnts[idx],0.02, 0.01, pnts[idx + 1], 0.02, vec)

        if cyl:
            cyls.append(cyl)
    
    return cyls

def readData(
    path :str
    ) -> list:

    with open(path, 'r', buffering = -1, encoding = 'utf-8-sig') as f:
        lst = f.readlines()
    
    data = [s.replace('\n', '').split(',') for s in lst]

    app  :adsk.core.Application = adsk.core.Application.get()
    des  :adsk.fusion.Design = app.activeProduct
    um = des.unitsManager
    conv = um.convert(1, um.defaultLengthUnits, um.internalUnits)

    return [(float(x) * conv, float(y) * conv, float(z) * conv) for (x,y,z) in data]

Two combined bodiesTwo combined bodiesSelecting the face (I want to select with Script )Selecting the face (I want to select with Script )Using revolve (needs to be done with scripting)Using revolve (needs to be done with scripting)user interface, i can select the face and revolve it to starting face of the next body. However, with the script, I am not being able to select the end face of 1st body to revolve. 

 

Could you please look into the updated code and help me to figure out how to solve this issue.

Message 6 of 11
kandennti
in reply to: rijalkhem187

Using sketches is slow.
Therefore, I decided to create a sphere at the end of the cylinder.
 1.png
 
Creating a sphere is everything except the beginning and end.
2.png
 
The combination of all these cylinders and spheres was also handled by the API.
#Fusion360API Python script
import adsk.core, adsk.fusion, traceback
import time

def run(context):
    ui = None
    try:
        # data file path
        path = '/Desktop/20mm_cubeCoordinates.txt'

        app = adsk.core.Application.get()
        ui  = app.userInterface
        
        # new document
        app.documents.add(adsk.core.DocumentTypes.FusionDesignDocumentType)
        des = adsk.fusion.Design.cast(app.activeProduct)

        # direct design
        des.designType = adsk.fusion.DesignTypes.DirectDesignType

        # time
        startTime = time.time()

        # read file
        data = readData(path)

        # point3D
        pnt3D = adsk.core.Point3D
        pnts = [pnt3D.create(x, y, z) for (x, y, z) in data]

        # create cylinder
        radius = 0.035
        cylinders = initCylinders(pnts, radius)

        # create Sphere
        spheres = initSpheres(pnts, radius)

        # union
        body = unionBodies(unionBodies(cylinders[0], cylinders[1:]),spheres)

        # add bodies
        root = des.rootComponent
        bodies = root.bRepBodies
        bodies.add(body)

        # fin
        des.designType = adsk.fusion.DesignTypes.ParametricDesignType
        msg = '-- Done --\nPointCount : {}\nTime : {} s'.format(
            len(pnts),time.time() - startTime)
        ui.messageBox(msg)

    except:
        if ui:
            ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))

def unionBodies(
    body :adsk.fusion.BRepBody,
    bodies :list,
    ) -> adsk.fusion.BRepBody:

    tmpMgr = adsk.fusion.TemporaryBRepManager.get()
    unionBool = adsk.fusion.BooleanTypes.UnionBooleanType
    target :adsk.fusion.BRepBody = body
    for tool in bodies:
        tmpMgr.booleanOperation(target, tool, unionBool)
    
    return target

def initSpheres(
    pnts :list,
    radius :float
    ) -> list:

    tmpMgr = adsk.fusion.TemporaryBRepManager.get()
    sphs = []
    for pnt in pnts[1:-1]:
        sph = tmpMgr.createSphere(pnt, radius)

        if sph:
            sphs.append(sph)
    
    return sphs

def initCylinders(
    pnts :list,
    radius :float
    ) -> list:

    tmpMgr = adsk.fusion.TemporaryBRepManager.get()
    vec = adsk.core.Vector3D.create(1.0, 1.0, 1.0)
    cyls = []
    for idx in range(len(pnts) - 1):
        cyl = tmpMgr.createEllipticalCylinderOrCone(
            pnts[idx], radius, radius, pnts[idx + 1], radius, vec)

        if cyl:
            cyls.append(cyl)
    
    return cyls

def readData(
    path :str
    ) -> list:

    with open(path, 'r', buffering = -1, encoding = 'utf-8-sig') as f:
        lst = f.readlines()
    
    data = [s.replace('\n', '').split(',') for s in lst]

    app  :adsk.core.Application = adsk.core.Application.get()
    des  :adsk.fusion.Design = app.activeProduct
    um = des.unitsManager
    conv = um.convert(1, um.defaultLengthUnits, um.internalUnits)

    return [(float(x) * conv, float(y) * conv, float(z) * conv) for (x,y,z) in data]
 3.png
 
 
 

However, When I try to take 10,000 point, the Fusion crashes and closes by itself due to segmentation error.  

No more ideas. Why not split and process the data?
 
Message 7 of 11
rijalkhem187
in reply to: kandennti

Hi @kandennti ,

 

Thats a great  solution.I tried it and gives a good result if the cylinder is circluar.

 

I am wodering how would you approach if the cylinder is elliptical shape. 

 

For the data, i tried doing it in fractions and adding to component. 

I have another file with 5075 points. My fusion app works untill 5000 points (at single or doing multiple time and combining bodies) however if i add another faraction of 20 points after 5000 my fusion crashes and closes. I dont know why its not being able to 75 more points.

Message 8 of 11
rijalkhem187
in reply to: rijalkhem187

Hi @kandennti , 

 

It's my humble request if you could give an idea if the shape is elliptical. 

 

Would you mind trying another file? One file is a whole object.

 

I would really appreciate it if you could give me feedback on it.

 

new.txt has 5075 points and 

shape.txt has hell loads of points.

Message 9 of 11
kandennti
in reply to: rijalkhem187

Attach f3d file and script file which processed "new.txt".
However, it cannot be determined whether the processing is correct.

"shape.txt" can create BRepBody,
bodies.add(body)
Is a difficult state.
 

From tomorrow, my work may be so busy that I can't afford the time to tackle this problem.
Message 10 of 11
kandennti
in reply to: kandennti

The last one was incorrect.
Attach the slightly improved data.
2.png
I tried "shape.txt", but the data is big and Fusion360 goes down. It can be processed halfway, but ...
1.png
This is the limit for me.
Message 11 of 11
rijalkhem187
in reply to: kandennti

Hi @kandennti , 

 

I would like to express my sincere thanks for your help and time you have spent in finding a solution to the problem I encountered. 

 

Your solution helped me greatly to move forward in my project.

 

Thanks,

Khem Raj Rijal

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

Post to forums  

Autodesk DevCon in Munich May 28-29th


Autodesk Design & Make Report