Files
marf/ifield/data/common/mesh.py
2025-01-09 15:43:11 +01:00

49 lines
1.2 KiB
Python

from math import pi
from trimesh import Trimesh
import numpy as np
import os
import trimesh
import trimesh.transformations as T
DEBUG = bool(os.environ.get("IFIELD_DEBUG", ""))
__doc__ = """
Here are some helper functions for processing data.
"""
def rotate_to_closest_axis_aligned_bounds(
mesh : Trimesh,
order_axes : bool = True,
fail_ok : bool = True,
) -> np.ndarray:
to_origin_mat4, extents = trimesh.bounds.oriented_bounds(mesh, ordered=not order_axes)
to_aabb_rot_mat4 = T.euler_matrix(*T.decompose_matrix(to_origin_mat4)[3])
if not order_axes:
return to_aabb_rot_mat4
v = pi / 4 * 1.01 # tolerance
v2 = pi / 2
faces = (
(0, 0),
(1, 0),
(2, 0),
(3, 0),
(0, 1),
(0,-1),
)
orientations = [ # 6 faces x 4 rotations per face
(f[0] * v2, f[1] * v2, i * v2)
for i in range(4)
for f in faces]
for x, y, z in orientations:
mat4 = T.euler_matrix(x, y, z) @ to_aabb_rot_mat4
ai, aj, ak = T.euler_from_matrix(mat4)
if abs(ai) <= v and abs(aj) <= v and abs(ak) <= v:
return mat4
if fail_ok: return to_aabb_rot_mat4
raise Exception("Unable to orient mesh")