C#ATIA

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

穴テンプレートのトーラスを考える4

こちらの続きです。
穴テンプレートのトーラスを考える3 - C#ATIA

テストする形状を少し複雑にしました。

ザグリ部分に面取り(赤)を付け、面取りの両側にR面(緑)を付けました。
面取り両側のR面は凸ですが、元々付けていた黄色のR面は凹です。
恐らく、これがクリア出来ればさらに複雑になっても、トーラスについては
クリア出来ると思っています。

この3個のトーラスは、穴テンプレートでは上から順にこんな出力になります。

    <segment bottomAngle="0.785398" isConvex="1" isExpanding="Contracting" sweepAngle="-0.785398" topAngle="1.570796" type="Torus"/>
    <segment bottomAngle="0.000000" isConvex="1" isExpanding="Contracting" sweepAngle="-0.785398" topAngle="0.785398" type="Torus"/>
    <segment bottomAngle="4.712389" isConvex="0" isExpanding="Contracting" sweepAngle="1.570796" topAngle="3.141593" type="Torus"/>

前回、角度をVector3D.angleToメソッドで測定すると、近い方の角度を
返してくることが分かっている為、角度の取得はmath.atan2を使う事にし、
マイナス値での取得では無く、あくまで反時計回りでの角度に強制的に
直す事にしました。
又、sweepAngleとisConvexも理解出来たつもりなので、そちらも出力。
ついでに確認しやすいように、ラジアンと共に度でも出力させます。

# Fusion360API Python script

import traceback
import adsk.core as core
import adsk.fusion as fusion
import math

def run(context):
    ui: core.UserInterface = None
    try:
        app: core.Application = core.Application.get()
        ui = app.userInterface

        msg: str = 'Select'
        selFilter: str = 'ToroidalFaces'
        sel: core.Selection = select_ent(msg, selFilter)
        if not sel:
            return

        face: fusion.BRepFace = sel.entity
        eva: core.SurfaceEvaluator = face.evaluator
        prmBox: core.BoundingBox2D = eva.parametricRange()

        for isU in (True, False):
            arc: core.Arc3D = core.Arc3D.cast(
                eva.getIsoCurve(prmBox.minPoint.x, isU)[0]
            )
            if arc: break

        if not arc: return

        torus: core.Torus = face.geometry
        _, origin, _, _, _ = torus.getData()

        # 本当は穴軸の逆ベクトル?
        axis = core.Vector3D.create(0,0,-1)

        pnt: core.Point3D = origin.copy()
        normal: core.Vector3D = axis.copy()
        normal.scaleBy(100)
        pnt.translateBy(normal)
        plane: core.Plane = core.Plane.create(pnt, normal)

        pointDistanceData = []
        measMgr: core.MeasureManager = app.measureManager
        for p in (arc.startPoint, arc.endPoint):
            res: core.MeasureResults = measMgr.measureMinimumDistance(plane, p)
            pointDistanceData.append(
                {
                    "dist": res.value,
                    "point": p,
                }
            )
        pointDistanceData.sort(key = lambda x: x["dist"])
        vec: core.Vector3D = arc.center.vectorTo(origin)
        vec.normalize()

        mat: core.Matrix3D = core.Matrix3D.create()
        axis.normalize()
        axis.scaleBy(-1)
        mat.setWithCoordinateSystem(
            arc.center,
            vec,
            axis,
            vec.crossProduct(axis),
        )
        mat.invert()

        bottom: core.Point3D = pointDistanceData[0]["point"].copy()
        top: core.Point3D = pointDistanceData[1]["point"].copy()
        bottom.transformBy(mat)
        top.transformBy(mat)

        bottomAngle = math.atan2(bottom.y, bottom.x)
        if bottomAngle < 0:
            bottomAngle += (math.pi *2)

        topAngle = math.atan2(top.y, top.x)
        if topAngle < 0:
            topAngle += (math.pi *2)

        sweepAngle = bottomAngle - topAngle

        msg = [
            f"bottomAngle:{round(bottomAngle, 6)} ",
            f"topAngle:{round(topAngle, 6)}",
            f"sweepAngle:{round(sweepAngle, 6)}",
            f"isConvex:{0 if sweepAngle > 0 else 1}",
            f"bottomDeg:{math.degrees(bottomAngle)}deg",
            f"topDeg:{math.degrees(topAngle)}deg",
            f"sweepDeg:{math.degrees(sweepAngle)}deg",
        ]
        app.log(" / ".join(msg))

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


def select_ent(
    msg: str,
    filter: str
) -> core.Selection:

    try:
        app: core.Application = core.Application.get()
        ui: core.UserInterface = app.userInterface
        sel = ui.selectEntity(msg, filter)
        return sel
    except:
        return None

実際にテストした結果は、上から順にこんな感じです。

 bottomAngle:0.785398  / topAngle:1.570796 / sweepAngle:-0.785398 / isConvex:1 / bottomDeg:45.00000000000012deg / topDeg:90.0deg / sweepDeg:-44.99999999999988deg
 bottomAngle:0.0  / topAngle:0.785398 / sweepAngle:-0.785398 / isConvex:1 / bottomDeg:0.0deg / topDeg:45.00000000000012deg / sweepDeg:-45.00000000000012deg
 bottomAngle:4.712389  / topAngle:3.141593 / sweepAngle:1.570796 / isConvex:0 / bottomDeg:270.0deg / topDeg:180.0deg / sweepDeg:90.0deg

出来てます。(自己満足)