C#ATIA

↑タイトル詐欺 主にFusion360API 偶にCATIA V5 VBA(絶賛ネタ切れ中)

NURBS面を円筒面に変換する3

こちらの続きです。
NURBS面を円筒面に変換する2 - C#ATIA

前回説明を忘れていましたが、任意の面に接線接続以上の隣接している面を
取得することはAPIで取得可能です。

その組み合わせた面が本当に円筒かどうか判断したいです。
あぁそうか、今気が付いたけどまぁ後のテーマにしよう。

前回同様、面上に10点作成し曲率のばらつきが一定以内であれば
円筒面と判断すれば良い様な気がしています・・・いや、球体も
含まれちゃいますね。

まぁ球体は取りあえず無視して、こんなテストコードを作りました。
記載していない関数は、前回のものと変更ありません。

# Fusion360API Python script

import traceback
import adsk.core as core
import adsk.fusion as fusion
import random
import statistics

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)
        # test(group[0], True)
        for faces in group:
            print(is_cylinder(faces))


    except:
        if ui:
            ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))


def is_cylinder(
    faces: list,
    tolerance: float = 0.0001
) -> bool:

    resLst = []

    face: fusion.BRepFace = None
    for face in faces:
        eva: core.SurfaceEvaluator = face.evaluator

        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)

        resLst.append(statistics.variance(crvMaxs) < tolerance)

    return all(resLst)

数値(今回は曲率)のバラつきは分散で調べました。良いのかな・・・。
そして分散が一定の数値以下でOKとしたいのですが、数値が幾つが
適切だかわからないのですが、”0.0001”としました。
もう、不安しかありません。

念の為ですが、取得している曲率の一例はこんな感じです。

-1.2493772363329765
-1.2486900538177184
-1.2510724277907324
-1.248247343786411
-1.2503424321522778
-1.2510858088348
-1.2498398982937735
-1.2493181971087732
-1.247284520473275
-1.2510953336750845

Rサイズだと

-0.7991990137576473
-0.8007073224079025
-0.7994615674494644
-0.7987661586159905
-0.7992104618851492
-0.8012348166877553
-0.7999450894000383
-0.8011068316351571
-0.8011229784921655
-0.7996670715423259

0.02以内ぐらいでしょうか? 想像していたよりバラツキがあります。

こちらのモデルで、スクリプトを実行した結果はこちらです。

True
True
True
True
True

5か所の穴は全て円筒面として判断出来ました! って
クリアする数値を設定したので、当たり前なんですけどね。

” 0.00001”でもクリアするな・・・平均値の差の二乗だから
こっちの方が良いのかな・・・。