C#ATIA

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

軸に対して最大距離方向の断面を作る

こちらの続きです。
軸に対して最大距離になるポイントを取得する - C#ATIA

色々あったり、悩んだり。

Z軸(青)からボディに対して最大距離方向に断面のサーフェスを作ります。

# 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)

    resBody: adsk.fusion.BRepBody = get_inter_section_temp_face(body, axis, maxPoint)

    dump_bodies([resBody])


def get_inter_section_temp_face(
    body: adsk.fusion.BRepBody,
    axis: adsk.core.InfiniteLine3D, 
    point: adsk.core.Point3D) -> adsk.fusion.BRepBody:

    interPoint: adsk.core.Point3D = get_intersect_point_from_Infinite(point, axis)
    vec: adsk.core.Vector3D = interPoint.vectorTo(point)
    plane: adsk.core.Plane = adsk.core.Plane.create(
        interPoint,
        axis.direction.crossProduct(vec)
    )

    tmpMgr: adsk.fusion.TemporaryBRepManager = adsk.fusion.TemporaryBRepManager.get()
    wireBody: adsk.fusion.BRepBody = tmpMgr.planeIntersection(body, plane)
    faceBody: adsk.fusion.BRepBody = tmpMgr.createFaceFromPlanarWires([wireBody])
    largeBody: adsk.fusion.BRepBody = get_large_face(axis, point)

    tmpMgr.booleanOperation(
        faceBody,
        largeBody,
        adsk.fusion.BooleanTypes.IntersectionBooleanType
    )

    return faceBody


def get_large_face(
    axis: adsk.core.InfiniteLine3D, 
    point: adsk.core.Point3D) -> adsk.fusion.BRepBody:

    largeValue = 10000000000
    vec: adsk.core.Vector3D = axis.direction.copy()
    points = []

    vec.scaleBy(largeValue)
    p: adsk.core.Point3D = point.copy()
    p.translateBy(vec)
    points.append(p)

    vec.scaleBy(-1)
    p: adsk.core.Point3D = point.copy()
    p.translateBy(vec)
    points.append(p)

    points.append(get_intersect_point_from_Infinite(points[1], axis))
    points.append(get_intersect_point_from_Infinite(points[0], axis))
    points.append(points[0])

    lines = [adsk.core.Line3D.create(p1, p2) for p1, p2 in zip(points, points[1:])]
    print(f'Line Count:{len(lines)}')

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

    wireBody: adsk.fusion.BRepBody = None
    wireBody, _ = tmpMgr.createWireFromCurves(lines)

    # create face
    return tmpMgr.createFaceFromPlanarWires([wireBody])


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 dumpWire(wire: adsk.fusion.BRepWire):
    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)  
    sktFixs: adsk.fusion.SketchFixedSplines = skt.sketchCurves.sketchFixedSplines

    for e in wire.edges:
        geo = e.geometry
        adsk.core.Line3D.asNurbsCurve
        if hasattr(geo, 'asNurbsCurve'):
            geo = geo.asNurbsCurve

        sktFixs.addByNurbsCurve(geo)


def dump_bodies(bodyLst: list):
    app: adsk.core.Application = adsk.core.Application.get()
    des: adsk.fusion.Design = app.activeProduct
    root: adsk.fusion.Component = des.rootComponent

    baseFeat: adsk.fusion.BaseFeature = None
    if des.designType == adsk.fusion.DesignTypes.ParametricDesignType:
        baseFeat = root.features.baseFeatures.add()

    bodies: adsk.fusion.BRepBodies = root.bRepBodies
    if baseFeat:
        baseFeat.startEdit()
        [bodies.add(body, baseFeat) for body in bodyLst]
        baseFeat.finishEdit()
    else:
        [bodies.add(body) for body in bodyLst]


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)

def dumpPlane(plane: adsk.core.Plane) -> adsk.fusion.ConstructionPlanes:
    app: adsk.core.Application = adsk.core.Application.get()
    des: adsk.fusion.Design = app.activeProduct
    root: adsk.fusion.Component = des.rootComponent


    baseFeat: adsk.fusion.BaseFeature = None
    if des.designType == adsk.fusion.DesignTypes.ParametricDesignType:
        baseFeat = root.features.baseFeatures.add()

    if baseFeat:
        baseFeat.startEdit()

    constPlanes: adsk.fusion.ConstructionPlanes = root.constructionPlanes
    planeIpt: adsk.fusion.ConstructionPlaneInput = constPlanes.createInput()
    planeIpt.setByPlane(plane)
    constPlane: adsk.fusion.ConstructionPlane = constPlanes.add(planeIpt)

    if baseFeat:
        baseFeat.finishEdit()

    return constPlane

def draw_cg_body(body: adsk.fusion.BRepBody):
    app: adsk.core.Application = adsk.core.Application.get()
    des: adsk.fusion.Design = app.activeProduct
    root: adsk.fusion.Component = des.rootComponent

    cgGroup: adsk.fusion.CustomGraphicsGroup = root.customGraphicsGroups.add()
    cgBody:adsk.fusion.CustomGraphicsBRepBody = cgGroup.addBRepBody(body)

単に断面を作るのでは無く、Z軸より最大距離方向だけです。
最大距離の反対方向には断面を作らないようにしています。

何故か? 軸で回転させたいからです・・・。(今、悩んでいる所)