こちらの続きです。
NURBS面を円筒面に変換する1 - C#ATIA
えーまずNurbs面から円筒面にする面を探し出す必要があるのですが、
難しいです。
こちらに添付されているデータをテストデータにします。
解決済み: STEPからインポートしたデータの面構成を簡単に修正する方法が欲しい - Autodesk Community
本当はもっと色々なデータが必要なのですが、タダでさえ
迷っているので、これが処理できるようにするのが、まず
目標にしておきます。
色々悩みますが、とりあえず軸を見つけたいです。
あちらのデータ(元CATIA)はUVのどちらかが直線だったため、
比較的簡単に軸を見つけられました。
しかし、こちらのスクリプトでNURBS化したものは、
UV両方ともnurbs曲線になってしまいました。
(本気でnurbs化する事を実感)
そこで、面上にランダムな点を作成し、点の位置から
法線と曲率を取得し、点の位置を法線方向にRサイズ(曲率の逆数)
移動させた際の位置が中心軸になるのでは?と感じてます。
(言葉だけだとわかりにくいですね)
説明不足が半端じゃないのですが、こんなスクリプトを作りました。
# Fusion360API Python script import traceback import adsk.core as core import adsk.fusion as fusion import random def run(context): ui: core.UserInterface = None try: app: core.Application = core.Application.get() ui = app.userInterface des: fusion.Design = app.activeProduct root: fusion.Component = des.rootComponent body: fusion.BRepBody = root.bRepBodies[0] nurbss = get_nurbs_faces(body) group = group_by_faces(nurbss) test(group[0], False) except: if ui: ui.messageBox('Failed:\n{}'.format(traceback.format_exc())) def test(faces: list, isAbs: bool): face: fusion.BRepFace = None for face in faces: eva: core.SurfaceEvaluator = face.evaluator # _, prm = eva.getParameterAtPoint( # face.pointOnFace # ) # _, vec, crvMax, crvMin = eva.getCurvature(prm) prmRange: core.BoundingBox2D = eva.parametricRange() prms = [ core.Point2D.create( random.uniform( prmRange.minPoint.x, prmRange.maxPoint.x, ), random.uniform( prmRange.minPoint.y, prmRange.maxPoint.y, ), ) for _ in range(10) ] _, _, crvMaxs, _ = eva.getCurvatures(prms) _, nmls = eva.getNormalsAtParameters(prms) _, pnts = eva.getPointsAtParameters(prms) v: core.Vector3D = None cr: float = -10000 p1: core.Point3D = None pntSets = [] for p1, v, cr in zip(pnts, nmls, crvMaxs): p2: core.Point3D = p1.copy() r = 1/cr if isAbs: r = abs(r) v.normalize v.scaleBy(r) p2.translateBy(v) pntSets.append((p1, p2)) dump_lines(pntSets) def dump_lines(pntSets): app: core.Application = core.Application.get() des: fusion.Design = app.activeProduct root: fusion.Component = des.rootComponent skt: fusion.Sketch = root.sketches.add(root.xYConstructionPlane) sktLines: fusion.SketchLines = skt.sketchCurves.sketchLines [sktLines.addByTwoPoints(p1, p2) for p1, p2 in pntSets] def group_by_faces( faces: list, ) -> list: group = [] face: fusion.BRepFace = None tokens = [face.entityToken for face in faces] for face in faces: if face.entityToken not in tokens: continue tokens.remove(face.entityToken) tangents = col2lst(face.tangentiallyConnectedFaces) if len(tangents) < 1: continue [tokens.remove(f.entityToken) for f in tangents] tangents.append(face) group.append(tangents) return group def get_nurbs_faces( body: fusion.BRepBody, ) -> list: return [f for f in body.faces if f.geometry.objectType == core.NurbsSurface.classType()] def col2lst( col: core.ObjectCollection, ) -> list: return [x for x in col]
ルートコンポーネント内の最初のボディのnurbs面の組み合わせに、
ランダムな点を10個作成し、法線から曲率分移動させた点との
間に直線を作り出します。ね、説明しても無駄でしょ?
実行するとこんな感じです。
あぁ中心に向かっていません。
曲率がマイナスの値になっていた事は気が付いていたので、
ここを修正します。
# test(group[0], False) test(group[0], True)
それっぽく軸の位置に集まりそうです。このデータの場合は
絶対値でOKっぽいです。
続いて、モデルを変更します。 穴では無く、軸っぽくします。
あくまで元の面を活かしたいので、結合の差を使って作りました。
同じようにスクリプトを実行すると
絶対値での場合は望む結果になりませんでした。
最初の状態に戻し試すと
上手く行きました。
結果的に、
・穴: 絶対値
・軸: そのまま
で見つけ出せそうな気はしているのですが、
本当にこれで良いのかな・・・。
穴と軸では処理を変えたい部分があるので、これで
判断して良いのかな・・・。