Get plane-aligned flatbox of a triangular mesh face in GHPython?


I’m purposfully trying to get the plane-aligned flatbox (bounding box of no volume) of a triangular mesh face. This turned out to be far more challenging than expected! :slight_smile:

import Rhino.Geometry as rg

def get_face_edges(face_vertices):
    """Returns edges as lines for a list of face vertices."""
    edges = []
    for i in range(len(face_vertices) - 2):
        edges.append(rg.Line(face_vertices[i], face_vertices[i + 1]))
    edges.append(rg.Line(face_vertices[-1], face_vertices[0]))
    return edges

if __name__ == "__main__": 
    # Mesh and fIndex are GHPython component inputs
    face = Mesh.Faces[fIndex]  # triangular face
    vertices = [rg.Point3d(v.X, v.Y, v.Z) for v in Mesh.Faces.GetFaceVertices(fIndex)[1:]]

    edge = get_face_edges(vertices)[0] 
    normal = Mesh.FaceNormals[fIndex]

    yaxis = edge.UnitTangent
    xaxis = rg.Vector3d.CrossProduct(yaxis, normal)
    plane = rg.Plane(edge.From, xaxis, yaxis)
    fmesh = rg.Mesh()
    for i in range(len(vertices)):
    fmesh.Faces.AddFace(0, 1, 2) 
    xform = rg.Transform.ChangeBasis(rg.Plane.WorldXY, plane)
    bbox = fmesh.GetBoundingBox(xform)
    plane_to_world = rg.Transform.ChangeBasis(plane, rg.Plane.WorldXY)
    bbox.Transform(plane_to_world) # inflates the previously flatbox to a 3D bounding box ?
    # Output
    a = bbox 

In the WorldXY-plane, the correct flat bounding box appears at the world origin, however when I try to transform it back to the plane of the face, it gets inflated to 3D?

Why is the Transform() method of Rhino.Geometry.BoundingBox different from that of other geometry?

Merry christmas everybody! :santa: (9.3 KB)

This is how I usually get a plane-aligned bounding box. It looks quite similar and not sure if it’ll work with a flat box though. But hey, it might help (edit: looks like I cast to Box before applying the transform):

import Rhino as rc

def alignedBoundingBox(geometry,plane):
    """ Get geometry bounding box aligned to plane """
    worldPl = rc.Geometry.Plane.WorldXY
    worldToPlane = rc.Geometry.Transform.ChangeBasis(worldPl,plane)
    bb = geometry.GetBoundingBox(worldToPlane)
    planeToWorld = rc.Geometry.Transform.ChangeBasis(plane,worldPl)
    box = rc.Geometry.Box(bb)
    return box

Merry Christmas :christmas_tree:

1 Like

Thank you, Anders!!! :slight_smile:
Works like a charm!

It seems like converting the bounding box to a simple box makes it work. The Transform() method of Rhino.Geometry.BoundingBox does something else somehow. It’s even stated in the documentation.

Thanks again! Happy holidays.

1 Like