C#ATIA

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

軸に対して最大距離になるポイントを取得する

そろそろ、こちらに取り掛かりたいです。
旋盤用の回転プロファイルをスケッチとして取得したい - Autodesk Community

え~思い付いた処理方法が上手く行くのかどうか不明です。
どんな風に・・・そのうち書きます。

取りあえず処理上、軸に対して目的のボディの最長(大?)位置
となる部分を探し出したいです。
画像で説明するとこんな状態です。


目的の軸は青いものです。ちょっと極端な例ですね。

CADの測定は、最短距離を求める測定機能はあるのですが、
その逆の最大距離を測定する機能ってあまり無いんですよね。
(CATIA V5にはあります)

それを最長位置を求め、スケッチの点を作るスクリプトです。

# 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
        des: adsk.fusion.Design = app.activeProduct
        root: adsk.fusion.Component = des.rootComponent

        body: adsk.fusion.BRepBody = root.bRepBodies[0]
        axis: adsk.core.InfiniteLine3D = root.zConstructionAxis.geometry

        draw_max_point(body, axis)

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


def draw_max_point(
    body: adsk.fusion.BRepBody,
    axis: adsk.core.InfiniteLine3D):

    app: adsk.core.Application = adsk.core.Application.get()

    vec: adsk.core.Vector3D = axis.direction

    bBox: adsk.core.OrientedBoundingBox3D = get_boundingBox(
        body,
        vec,
    )

    interPoint: adsk.core.Point3D = get_intersect_point_from_Infinite(bBox.centerPoint, axis)

    p1, p2 = get_length_range_points(bBox, interPoint)

    tmpRadius = 100000000

    dmyCylinder: adsk.fusion.BRepFace = get_cylinder_face(p1, p2, tmpRadius)
    
    maxPoint: adsk.core.Point3D = get_max_point_from_cylinder(body, dmyCylinder)

    dumpPoints(
        [
            maxPoint
        ]
    )


def get_max_point_from_cylinder(
    targetBody: adsk.fusion.BRepBody,
    cylinder: adsk.fusion.BRepFace) -> adsk.core.Point3D:

    app: adsk.core.Application = adsk.core.Application.get()
    measMgr: adsk.core.MeasureManager = app.measureManager
    res: adsk.core.MeasureResults = measMgr.measureMinimumDistance(
        targetBody,
        cylinder
    )

    return res.positionOne


def get_cylinder_face(
    startPoint: adsk.core.Point3D,
    endPoint: adsk.core.Point3D,
    radius:float) -> adsk.fusion.BRepFace:

    tmpMgr: adsk.fusion.TemporaryBRepManager = adsk.fusion.TemporaryBRepManager.get()

    cylinder: adsk.fusion.BRepBody = tmpMgr.createCylinderOrCone(
        startPoint,
        radius,
        endPoint,
        radius
    )

    return cylinder.faces[0]


def get_intersect_point_from_Infinite(
    point: adsk.core.Point3D,
    inf: adsk.core.InfiniteLine3D) -> adsk.core.Point3D:

    plane: adsk.core.Plane = adsk.core.Plane.create(
        point,
        inf.direction
    )

    inters: adsk.core.ObjectCollection = inf.intersectWithSurface(plane)

    return inters[0]


def get_length_range_points(
    bBox:adsk.core.OrientedBoundingBox3D,
    refPoint: adsk.core.Point3D) -> set:

    half_length = bBox.length * 0.5
    vec: adsk.core.Vector3D = bBox.lengthDirection.copy()

    vec.normalize()
    vec.scaleBy(half_length)
    p1: adsk.core.Point3D = refPoint.copy()
    p1.translateBy(vec)

    vec.normalize()
    vec.scaleBy(-half_length)
    p2: adsk.core.Point3D = refPoint.copy()
    p2.translateBy(vec)

    return (p1, p2)


def get_boundingBox(
    body: adsk.fusion.BRepBody,
    axis: adsk.core.Vector3D) -> adsk.core.OrientedBoundingBox3D:

    app: adsk.core.Application = adsk.core.Application.get()
    measMgr: adsk.core.MeasureManager = app.measureManager

    return measMgr.getOrientedBoundingBox(
        body,
        axis,
        get_orthogonal_vector(axis)
    )


def get_orthogonal_vector(
    vector: adsk.core.Vector3D) -> adsk.core.Vector3D:

    tmpVec: adsk.core.Vector3D = adsk.core.Vector3D.create(1,0,0)
    if vector.isParallelTo(tmpVec):
        tmpVec = adsk.core.Vector3D.create(0,1,0)

    return vector.crossProduct(tmpVec)


def dumpPoints(points):
    app: adsk.core.Application = adsk.core.Application.get()
    des: adsk.fusion.Design = app.activeProduct
    root: adsk.fusion.Component = des.rootComponent
    skt: adsk.fusion.Sketch = root.sketches.add(root.xYConstructionPlane)  
    sktPnts: adsk.fusion.SketchPoints = skt.sketchPoints 

    for p in points:
        sktPnts.add(p)

なっ長くない? たったそれだけの事なのに・・・。

結果はこちらです。

そう、これだけ。もっと効率良いアルゴリズムあるのかな?