Hi @miminguyenps1098 .
If a spline arc approximation is OK, I created it about 4 years ago.
# Fusion360API Python script
import traceback
import adsk.fusion
import adsk.core
# arc-approximation tolerance - Unit is Cm
tolerance = 0.001
def run(context):
ui = adsk.core.UserInterface.cast(None)
try:
app: adsk.core.Application = adsk.core.Application.get()
ui = app.userInterface
# 面選択
msg: str = 'Select curve/ESC-abort'
selFilter: str = 'SketchCurves'
sel: adsk.core.Selection = selectEnt(msg, selFilter)
if not sel:
return
crv = sel.entity
# 点群
points = initPointsOnCurve(crv.geometry, tolerance)
# 円弧近似
threeArcs = []
threeArcs = initThreePointArc(0, len(points)-1, tolerance, points, threeArcs)
if len(threeArcs) < 1:
ui.messageBox('Could not approximate the arc.')
return
# スケッチ作成
des = adsk.fusion.Design.cast(app.activeProduct)
comp = des.rootComponent
skt: adsk.fusion.Sketch = comp.sketches.add(comp.xYConstructionPlane)
skt.name = "ArcApproximation"
# 円弧作成
skt_arcs = skt.sketchCurves.sketchArcs
skt.isComputeDeferred = True
[skt_arcs.addByThreePoints(p1,p2,p3) for (p1,p2,p3) in threeArcs]
skt.isComputeDeferred = False
ui.messageBox(f'{len(threeArcs)} arc created')
except:
if ui:
ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))
# 外心円
def getCircumCircleOFTraiangle(p1,p2,p3):
# 3点ベクトル取得
vec1_2 = adsk.core.Vector3D.cast(p2.asVector())
vec1_2.subtract(p1.asVector())
vec1_2.normalize()
vec2_3 = adsk.core.Vector3D.cast(p3.asVector())
vec2_3.subtract(p2.asVector())
vec2_3.normalize()
# 平行チェック
if vec1_2.isParallelTo(vec2_3):
return None
# P2_P3間 オイラー線
eulerLine = vec2_3.crossProduct(vec1_2.crossProduct(vec2_3))
eulerLine.normalize()
# 中間点
p1_2 = getMidPoint3D(p1,p2)
p2_3 = getMidPoint3D(p2,p3)
# 不明
nv = vec1_2.dotProduct(eulerLine)
t = (vec1_2.dotProduct(p1_2.asVector()) - vec1_2.dotProduct(p2_3.asVector())) / nv
# 外心
center = getCircumCenter(p2_3,eulerLine,t)
# 半径
radius = center.distanceTo(p1)
return (center, radius)
# 外心
def getCircumCenter(p,v,l):
pos = (p.x + v.x * l,
p.y + v.y * l,
p.z + v.z * l)
return adsk.core.Point3D.create(pos[0],pos[1],pos[2])
# 中間点
def getMidPoint3D(p1,p2):
pos = ((p1.x + p2.x) * 0.5,
(p1.y + p2.y) * 0.5,
(p1.z + p2.z) * 0.5)
return adsk.core.Point3D.create(pos[0],pos[1],pos[2])
def isInTolerance(center, radius, tol, points):
dist_lst = [radius - center.distanceTo(p) for p in points]
res = [d for d in dist_lst if d > tol]
return True if len(res) < 1 else False
# 3点円弧 再帰
def initThreePointArc(startIdx, endIdx, tol, points, threeArcs):
if 2 > (endIdx - startIdx):
return threeArcs
# 中間idx
midIdx = int((startIdx + endIdx) * 0.5)
arc = getCircumCircleOFTraiangle(
points[startIdx],
points[midIdx],
points[endIdx]
)
if arc is None:
return threeArcs
# 円弧評価
if isInTolerance(arc[0], arc[1], 0.001, points[startIdx+1:endIdx-1]):
threeArcs.append([points[startIdx],points[midIdx],points[endIdx]])
else:
threeArcs = initThreePointArc(startIdx, midIdx, tol, points, threeArcs)
threeArcs = initThreePointArc(midIdx, endIdx, tol, points, threeArcs)
return threeArcs
# トレランス以内の曲線上の点群
def initPointsOnCurve(geo, tol):
# evaluator
eva = geo.evaluator
# 始点終点
_, startPoint, endPoint = eva.getEndPoints()
_, startPram = eva.getParameterAtPoint(startPoint)
_, endPram = eva.getParameterAtPoint(endPoint)
# トレランス以内の点群
_, pnts = eva.getStrokes(startPram, endPram, tol)
return pnts
# 選択
def selectEnt(
msg: str,
filterStr: str) -> adsk.core.Selection:
try:
app = adsk.core.Application.get()
ui = app.userInterface
sel = ui.selectEntity(msg, filterStr)
return sel
except:
return None