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 create a convex hull by using Python APIs in Fusion 360?

5 REPLIES 5
SOLVED
Reply
Message 1 of 6
jspoh86
1597 Views, 5 Replies

How to create a convex hull by using Python APIs in Fusion 360?

Hi,

 

Is there any way to create a convex hull by using Python APIs in Fusion 360?

 

Thanks,

Ha-An

 

5 REPLIES 5
Message 2 of 6
BrianEkins
in reply to: jspoh86

There's not anything built into the API, but you should be able to either write your own math or find an existing library that would create the set of points that represent a convex hull.  Then it depends on whether it's 2D or 3D and what you're going to use it for that would define what you do next.  For example, if it's 2D you probably want to draw the shape in a sketch.  If it's 3D you can create custom graphics to display the triangles. 

 

It would be a bit painful to create a solid body of the mesh because you would need to draw the outline of each face as sketch geometry and then create a patch feature, and then finally you could stitch them all together.  If there are many polygons, it will take a very long time and would likely fail.

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

Thank you for your answer. I should look up some libraries.

Message 4 of 6
kandennti
in reply to: jspoh86

Hi jspoh86.

 

It was an interesting theme, so I tried it.
A library for 'blender' has been released, I used that library.

 

https://michelanders.blogspot.com/2012/02/3d-convex-hull-in-python.html
https://github.com/varkenvarken/blenderaddons/blob/master/chull.py

 

Therefore, 'chull.py' needs to be in the same folder as the split file.

 

#FusionAPI_python test_ConvexHull3D
#Author-kantoku
#Description-新たなスケッチを作成し、ランダムに3Dな点を作成し、3Dな凸包を作成

import adsk.core, adsk.fusion, traceback
import random, os, sys
this_dir = os.path.dirname(os.path.abspath(__file__))
sys.path.append(this_dir)

#thx-varkenvarken
#chttps://michelanders.blogspot.com/2012/02/3d-convex-hull-in-python.html
#https://github.com/varkenvarken/blenderaddons/blob/master/chull.py
import chull

def run(context):
    #Create Point Count
    p_count = 100
    
    ui = None
    try:
        #extension
        chull.Vertex.toPnt = ToPoint3d
        chull.Face.toSkt = ToSketch
        adsk.core.Point3D.toVec = ToCHullVector
        adsk.fusion.Sketch.initSurf = InitSurface
        
        #preparation
        app = adsk.core.Application.get()
        ui = app.userInterface
        des = app.activeProduct
        root = des.rootComponent
        
        #スケッチと点の作成
        skt = root.sketches.add(root.xYConstructionPlane)
        skt.name = 'points'
        CreateRandomPoint(skt, -10.0, 10.0, p_count)
        
        #time
        import time
        t = time.time()
        
        #coordinate array
        pnts = [p.geometry.asArray() for p in skt.sketchPoints]
        del pnts[0] #remove origin point
        
        #edges sketch
        skt = root.sketches.add(root.xYConstructionPlane)
        skt.name = 'edges'
        
        #ConvexHull
        face_count = InitConvexHull(pnts,skt)
        
        #finish
        ui.messageBox('Point Count:{}\nface Count:{}\ntime:{:.2f}s'
            .format(p_count,face_count,time.time()- t))
        
    except:
        if ui:
            ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))

#ConvexHull
def InitConvexHull(point3d_list,target_sketch):
    if len(point3d_list) < 4: return
    
    #hull
    pnts = [chull.Vector(ary[0],ary[1],ary[2]) for ary in point3d_list]
    hull = chull.Hull(pnts)
    
    #edges
    [f.toSkt(target_sketch) for f in hull.faces]
    
    #faces
    target_sketch.initSurf()
    
    return len(hull.faces)

#RandomPoint
def CreateRandomPoint(skt, low, upp, count):
    pnts = [adsk.core.Point3D.create(
            random.uniform(low,upp),random.uniform(low,upp),random.uniform(low,upp)) 
            for dmy in range(count)]
        
    skt_Pnts = skt.sketchPoints
    [skt_Pnts.add(pnt) for pnt in pnts]

# --- extension method ---
#chull.Vertex
def ToPoint3d(self):
    return adsk.core.Point3D.create(
        self.v.x,self.v.y,self.v.z)

#chull.Face
def ToSketch(self, skt):
    #Vertex
    pnts = skt.sketchPoints
    ps = [pnts.add(p.toPnt()) for p in self.vertex]
    
    #edge
    lins = skt.sketchCurves.sketchLines
    edges =[(ps[0],ps[1]),(ps[1],ps[2]),(ps[2],ps[0])]
    [lins.addByTwoPoints(p0,p1) for p0,p1 in edges]
    
#adsk.core.Point3D
def ToCHullVector(self):
    ary = self.asArray()
    return chull.Vector(ary[0],ary[1],ary[2])
    
#adsk.fusion.Sketch
def InitSurface(self,tolerance = 0.001):
    if len(self.profiles) < 1:
        return
        
    newBodyOpe = adsk.fusion.FeatureOperations.NewBodyFeatureOperation
    
    comp = self.parentComponent
    feats = comp.features
    
    objs = adsk.core.ObjectCollection.create()
    [objs.add(v) for v in self.profiles]

    patches = feats.patchFeatures
    pats = patches.add(patches.createInput(objs,newBodyOpe))
    
    objs.clear()
    [objs.add(v) for v in pats.bodies]
    
    tol = adsk.core.ValueInput.createByReal(tolerance)
    stitches = feats.stitchFeatures
    stitches.add(stitches.createInput(objs, tol, newBodyOpe))

 

 

 

Message 5 of 6
kandennti
in reply to: jspoh86

Hi jspoh86.

 

It was an interesting theme, so I tried it.
A library for 'blender' has been released, I used that library.

 

https://github.com/varkenvarken/blenderaddons/blob/master/chull.py

 

Therefore, 'chull.py' needs to be in the same folder as the split file.

 

 

def run(context):
    #Create Point Count
    p_count = 100
    
    ui = None
    try:
        #extension
        chull.Vertex.toPnt = ToPoint3d
        chull.Face.toSkt = ToSketch
        adsk.core.Point3D.toVec = ToCHullVector
        adsk.fusion.Sketch.initSurf = InitSurface
        
        #preparation
        app = adsk.core.Application.get()
        ui = app.userInterface
        des = app.activeProduct
        root = des.rootComponent
        
        #RandomPoint
        skt = root.sketches.add(root.xYConstructionPlane)
        skt.name = 'points'
        CreateRandomPoint(skt, -10.0, 10.0, p_count)
        
        #time
        import time
        t = time.time()
        
        #coordinate array
        pnts = [p.geometry.asArray() for p in skt.sketchPoints]
        del pnts[0] #remove origin point
        
        #edges sketch
        skt = root.sketches.add(root.xYConstructionPlane)
        skt.name = 'edges'
        
        #ConvexHull
        face_count = InitConvexHull(pnts,skt)
        
        #finish
        ui.messageBox('Point Count:{}\nface Count:{}\ntime:{:.2f}s'
            .format(p_count,face_count,time.time()- t))
        
    except:
        if ui:
            ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))

#ConvexHull
def InitConvexHull(point3d_list,target_sketch):
    if len(point3d_list) < 4: return
    
    #hull
    pnts = [chull.Vector(ary[0],ary[1],ary[2]) for ary in point3d_list]
    hull = chull.Hull(pnts)
    
    #edges
    [f.toSkt(target_sketch) for f in hull.faces]
    
    #faces
    target_sketch.initSurf()
    
    return len(hull.faces)

#RandomPoint
def CreateRandomPoint(skt, low, upp, count):
    pnts = [adsk.core.Point3D.create(
            random.uniform(low,upp),random.uniform(low,upp),random.uniform(low,upp)) 
            for dmy in range(count)]
        
    skt_Pnts = skt.sketchPoints
    [skt_Pnts.add(pnt) for pnt in pnts]

# --- extension method ---
#chull.Vertex
def ToPoint3d(self):
    return adsk.core.Point3D.create(
        self.v.x,self.v.y,self.v.z)

#chull.Face
def ToSketch(self, skt):
    #Vertex
    pnts = skt.sketchPoints
    ps = [pnts.add(p.toPnt()) for p in self.vertex]
    
    #edge
    lins = skt.sketchCurves.sketchLines
    edges =[(ps[0],ps[1]),(ps[1],ps[2]),(ps[2],ps[0])]
    [lins.addByTwoPoints(p0,p1) for p0,p1 in edges]
    
#adsk.core.Point3D
def ToCHullVector(self):
    ary = self.asArray()
    return chull.Vector(ary[0],ary[1],ary[2])
    
#adsk.fusion.Sketch
def InitSurface(self,tolerance = 0.001):
    if len(self.profiles) < 1:
        return
        
    newBodyOpe = adsk.fusion.FeatureOperations.NewBodyFeatureOperation
    
    comp = self.parentComponent
    feats = comp.features
    
    objs = adsk.core.ObjectCollection.create()
    [objs.add(v) for v in self.profiles]

    patches = feats.patchFeatures
    pats = patches.add(patches.createInput(objs,newBodyOpe))
    
    objs.clear()
    [objs.add(v) for v in pats.bodies]
    
    tol = adsk.core.ValueInput.createByReal(tolerance)
    stitches = feats.stitchFeatures
    stitches.add(stitches.createInput(objs, tol, newBodyOpe))

 

 

Message 6 of 6
kandennti
in reply to: jspoh86

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