C#ATIA

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

複数の3D点から平面を作成したい3

時間が無いから、とりあえず出来上がったコードです。

# Fusion360API Python script

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

import os
import sys
import inspect
import random

script_path = os.path.abspath(inspect.getfile(inspect.currentframe()))
script_name = os.path.splitext(os.path.basename(script_path))[0]
script_dir = os.path.dirname(script_path)
sys.path.append(script_dir + "/site-packages")

import numpy as np

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

        points = create_sample(200)
        dump_points(points, "sample data")

        create_fit_plane(points)

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


def create_fit_plane(
    pointList: list[core.Point3D]
) -> fusion.ConstructionPlane:

    def fit_plane(pointList: list[core.Point3D]):
        point_cloud = np.array(pointList)

        com = np.sum(point_cloud, axis=0) / len(point_cloud)
        q = point_cloud - com
        Q = np.dot(q.T, q)
        la, vectors = np.linalg.eig(Q)
        plane_v = vectors.T[np.argmin(la)]

        return plane_v, com
    # *************

    normal, origin = fit_plane(
        [p.asArray() for p in pointList]
    )

    app: core.Application = core.Application.get()
    des: fusion.Design = app.activeProduct
    root: fusion.Component = des.rootComponent

    plane: core.Plane = core.Plane.create(
        core.Point3D.create(*origin.tolist()),
        core.Vector3D.create(*normal.tolist()),
    )

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

    planes: fusion.ConstructionPlanes = root.constructionPlanes
    planeIpt: fusion.ConstructionPlaneInput = planes.createInput()
    constPlane: fusion.ConstructionPlane = None
    if baseFeat:
        try:
            baseFeat.startEdit()
            planeIpt.setByPlane(plane)
            constPlane = planes.add(planeIpt)
        except:
            pass
        finally:
            baseFeat.finishEdit()
    else:
        planeIpt.setByPlane(plane)
        constPlane = planes.add(planeIpt)

    return constPlane


def create_sample(
    count: int
) -> list[core.Point3D]:

    return [
        core.Point3D.create(
            random.uniform(-10, 10),
            random.uniform(-10, 10),
            random.uniform(-1, 1),
        )
        for _ in range(count)
    ]


def dump_points(
    points: list,
    name: str = '',
) -> fusion.Sketch:

    app: core.Application = core.Application.get()
    des: fusion.Design = app.activeProduct
    root: fusion.Component = des.rootComponent

    skt: fusion.Sketch = root.sketches.add(
        root.xYConstructionPlane
    )

    if len(name) > 0:
        skt.name = name

    sktPoints: fusion.SketchPoints = skt.sketchPoints

    skt.isComputeDeferred = True
    [sktPoints.add(p) for p in points]
    skt.isComputeDeferred = False

    return skt

numpyが必要です!