How to efficiently process 10000 individual coordinates to build model.

How to efficiently process 10000 individual coordinates to build model.

Anonymous
2,426 Views
10 Replies
Message 1 of 11

How to efficiently process 10000 individual coordinates to build model.

Anonymous
Not applicable

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

0 Likes
Accepted solutions (2)
2,427 Views
10 Replies
Replies (10)
Message 2 of 11

kandennti
Mentor
Mentor

Hi @Anonymous .

 

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.
0 Likes
Message 3 of 11

Anonymous
Not applicable

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

0 Likes
Message 4 of 11

kandennti
Mentor
Mentor
Accepted solution

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

0 Likes
Message 5 of 11

Anonymous
Not applicable

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.

0 Likes
Message 6 of 11

kandennti
Mentor
Mentor
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?
 
0 Likes
Message 7 of 11

Anonymous
Not applicable

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.

0 Likes
Message 8 of 11

Anonymous
Not applicable

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.

0 Likes
Message 9 of 11

kandennti
Mentor
Mentor
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.
0 Likes
Message 10 of 11

kandennti
Mentor
Mentor
Accepted solution
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.
0 Likes
Message 11 of 11

Anonymous
Not applicable

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

0 Likes