こちらの続きです。
板状に分割したい2 - C#ATIA
もうちょっと取り組みました。
こんな感じで、完全中空では無く一部開放している形状でも
対応出来るようにしました。
・・・ん~完全では無く、エラーになるものがあるのですが、
スクリプト自体は途中で止まらないようにはしています。
# Fusion360API Python script import traceback import adsk.fusion import adsk.core def run(context): ui = adsk.core.UserInterface.cast(None) try: app: adsk.core.Application = adsk.core.Application.get() ui = app.userInterface msg: str = 'ボディを選択してください' selFilter: str = 'Bodies' sel: adsk.core.Selection = selectEnt(msg, selFilter) if not sel: return targetBody: adsk.fusion.BRepBody = sel.entity execDivided(targetBody) except: if ui: ui.messageBox('Failed:\n{}'.format(traceback.format_exc())) def execDivided( body: adsk.fusion.BRepBody) -> list: comp: adsk.fusion.Component = body.parentComponent # ****** def getVector( geo: adsk.core.Surface, point: adsk.core.Point3D) -> adsk.core.Vector3D: if hasattr(geo, 'normal'): return geo.normal eva: adsk.core.SurfaceEvaluator = geo.evaluator _, vec = eva.getNormalAtPoint(point) return vec def getPairFaces(shell: adsk.fusion.BRepShell): registeredList = [] # 組み合わせ済み pairFaces =[] hitPoints: adsk.core.ObjectCollection = adsk.core.ObjectCollection.create() face: adsk.fusion.BRepFace for face in shell.faces: # 既に組み合わせ済みか? if face.entityToken in registeredList: continue pnt: adsk.core.Point3D = face.pointOnFace geo: adsk.core.Plane = face.geometry vec: adsk.core.Vector3D = getVector(geo, pnt) revVec: adsk.core.Vector3D = vec.copy() revVec.scaleBy(-1) vecs = [ revVec, vec, ] # 候補の面取得 tempFaces = [] for vec in vecs: hitPoints.clear() res = comp.findBRepUsingRay( pnt, vec, adsk.fusion.BRepEntityTypes.BRepFaceEntityType, -1.0, True, hitPoints ) if res.count < 1: continue # 面と距離 - 向きが平行出ないものは除外 tempFaces.extend( [(f, pnt.distanceTo(p)) for f, p in zip(res, hitPoints) if vec.isParallelTo(getVector(f.geometry, p))] ) if len(tempFaces) < 1: continue # 近いものが組み合わせ相手 同じボディか?ってチェック入れるべき? nearFace: adsk.fusion.BRepFace = min(tempFaces, key=lambda x: x[1])[0] if nearFace.entityToken in registeredList: continue pairFaces.append( ( face, nearFace ) ) # 登録 registeredList.extend( [ face.entityToken, nearFace.entityToken ] ) return pairFaces def isAllPlanarFace(body: adsk.fusion.BRepBody) -> bool: planeType = adsk.core.Plane.classType() if all([f.geometry.classType() == planeType for f in body.faces]): return True return False # ******* # 全て平面かチェック if not isAllPlanarFace(body): return # 完全な中空形状チェック # if not body.shells.count == 2: # return # 外側 これ要らないかも・・・ outer: adsk.fusion.BRepShell = max(body.shells, key=lambda x: x.area) # 外内面の組み合わせ pairFaces = getPairFaces(outer) # LoftFeatures loftFeats: adsk.fusion.LoftFeatures = comp.features.loftFeatures # 外内面でロフト bodies = [] for faces in pairFaces: loftFeatIpt: adsk.fusion.LoftFeatureInput = loftFeats.createInput( # adsk.fusion.FeatureOperations.NewBodyFeatureOperation adsk.fusion.FeatureOperations.NewComponentFeatureOperation ) loftFeatIpt.isSolid = True loftFeatIpt.isClosed = False loftSections: adsk.fusion.LoftSections = loftFeatIpt.loftSections [loftSections.add(f) for f in faces] try: # エラーが出るので苦肉の策・・・ loftFeat: adsk.fusion.LoftFeature = loftFeats.add(loftFeatIpt) bodies.append(loftFeat.bodies[0]) except: adsk.core.Application.get().log( 'Failed:\n{}'.format(traceback.format_exc()) ) return bodies def selectEnt( msg: str, filterStr: str) -> adsk.core.Selection: try: app: adsk.core.Application = adsk.core.Application.get() ui: adsk.core.UserInterface = app.userInterface sel = ui.selectEntity(msg, filterStr) return sel except: return None
"全て平らな面" と言う条件を無くしたいと思い、全て曲面
(フォームで作成しシェルしたボディ)も試しました。
頑張ってそれっぽく出来上がるものもあるのですが、
今年のF1のサイド・ポンツーンよりえぐれてそうな
ムリムリな形状も出来ます。
なので諦めました。