C#ATIA

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

ポケットを探す2

こちらの続きです。
ポケットを探す1 - C#ATIA

前回の条件
・底面は水平
・側面は垂直
で凹形状となる面を見つけます。つまり、

ここから


これを探し出す って事です。(出来ました)

def find_pocket_faces(
    body: fusion.BRepBody,
    axis: core.Vector3D,
) -> list[fusion.BRepFace]:
    '''
    ポケット面取得
    '''
    def is_pocket_edge(
        edge: fusion.BRepEdge,
        tolerance: float = 0.001,
    ) -> bool:

        if edge.faces.count == 2:
            face1: fusion.BRepFace = edge.faces[0]
            face2: fusion.BRepFace = edge.faces[1]

            edgeEva: core.CurveEvaluator3D = edge.evaluator
            _, minPrm, maxPrm = edgeEva.getParameterExtents()
            midPrm = (minPrm + maxPrm) * 0.5
            _, midPnt = edgeEva.getPointAtParameter(midPrm)

            _, normal1 = face1.evaluator.getNormalAtPoint(midPnt)
            _, normal2 = face2.evaluator.getNormalAtPoint(midPnt)

            normalAngle = normal1.angleTo(normal2)

            if edge.coEdges[0].loop.face == face1:
                coEdge = edge.coEdges[0]
            elif edge.coEdges[1].loop.face == face1:
                coEdge = edge.coEdges[1]

            testPrm = midPrm + ((maxPrm - minPrm) * 0.001)
            _, testPnt = edgeEva.getPointAtParameter(testPrm)
            edgeDir: core.Vector3D = midPnt.vectorTo(testPnt)
            edgeDir.normalize()
            if not coEdge.isOpposedToEdge:
                edgeDir.scaleBy(-1)

            cross: core.Vector3D = normal1.crossProduct(normal2)

            if edgeDir.angleTo(cross) > math.pi * 0.5:
                return False

            return abs(normalAngle - math.pi * 0.5) < tolerance
        else:
            return False
    # **********

    # Plane
    faces = [f for f in body.faces 
        if f.geometry.objectType == core.Plane.classType()] 

    # Normal
    faces = [f for f in faces
        if axis.isParallelTo(f.geometry.normal)]

    # Pocket
    faces = [f for f in faces
        if all([is_pocket_edge(e) for e in f.edges])]

    return faces

公開していなかったのですが、穴の検索はこんな感じです。

def find_hole_faces(
    body: fusion.BRepBody,
    axis: core.Vector3D,
) -> list[fusion.BRepFace]:
    '''
    穴面取得
    '''

    def is_hole(
        face: fusion.BRepFace,
    ) -> bool:
        '''
        穴か軸か
        '''
        point: core.Point3D = face.pointOnFace
        eva: core.SurfaceEvaluator = face.evaluator

        normal: core.Vector3D = None
        _, normal = eva.getNormalAtPoint(point)
        normal.normalize()
        normal.scaleBy(0.001)

        checkPnt: core.Point3D = point.copy()
        checkPnt.translateBy(normal)

        cog: core.Point3D = face.centroid

        return cog.distanceTo(checkPnt) < cog.distanceTo(point)

    # Cylinder
    faces = [f for f in body.faces 
        if f.geometry.objectType == core.Cylinder.classType()] 

    # vextor
    faces = [f for f in faces
        if axis.isParallelTo(f.geometry.axis)]

    # hole
    faces = [f for f in faces if is_hole(f)]

    # remove overlap
    facesDict = {}
    [facesDict.setdefault(f.centroid.asArray(), f) for f in faces]
        
    return list(facesDict.values())

こんな感じの、底面平らな穴形状は、両方にHitしちゃうな。