Skip to content

kumiki.triangles

Flat import path

kumiki/__init__.py re-exports everything on this page via from kumiki import *, so every name below is also available directly as kumiki.TRIANGLES_FLOAT_DIGITS -- you do not need to import from the submodule path shown in the heading above.

kumiki.triangles

Triangle meshing and raw raycasting for CutCSG.

This module is the float-boundary adapter between the exact symbolic CutCSG model and trimesh. All SymPy-to-float conversion happens here.

TRIANGLES_FLOAT_DIGITS module-attribute

TRIANGLES_FLOAT_DIGITS = 8

TRIANGLES_PRISM_INFINITE_EXTENT module-attribute

TRIANGLES_PRISM_INFINITE_EXTENT = 1000.0

TRIANGLES_HALF_SPACE_INFINITE_EXTENT module-attribute

TRIANGLES_HALF_SPACE_INFINITE_EXTENT = TRIANGLES_PRISM_INFINITE_EXTENT * 10.0

TRIANGLES_CYLINDER_SECTIONS module-attribute

TRIANGLES_CYLINDER_SECTIONS = 32

TRIANGLES_RAY_EPSILON module-attribute

TRIANGLES_RAY_EPSILON = 1e-08

TRIANGLES_TINY_COMPONENT_VOLUME_RATIO module-attribute

TRIANGLES_TINY_COMPONENT_VOLUME_RATIO = 0.0001

TRIANGLES_TINY_COMPONENT_MIN_ABS_VOLUME module-attribute

TRIANGLES_TINY_COMPONENT_MIN_ABS_VOLUME = 1e-10

TRIANGLES_PATH_TESSELLATION_TOLERANCE module-attribute

TRIANGLES_PATH_TESSELLATION_TOLERANCE = 0.0005

Float3 module-attribute

Float3 = Tuple[float, float, float]

MeshableTarget module-attribute

MeshableTarget = Union[TriangleMesh, CutCSG]

TriangleMesh dataclass

TriangleMesh(mesh: Trimesh, face_sources: Optional[Tuple[str, ...]] = None)

mesh instance-attribute

mesh: Trimesh

face_sources class-attribute instance-attribute

face_sources: Optional[Tuple[str, ...]] = None

vertices property

vertices: ndarray

faces property

faces: ndarray

face_normals property

face_normals: ndarray

RaycastHit dataclass

RaycastHit(position: Float3, normal: Float3, distance: float, face_index: int, triangle: Tuple[Float3, Float3, Float3])

position instance-attribute

position: Float3

normal instance-attribute

normal: Float3

distance instance-attribute

distance: float

face_index instance-attribute

face_index: int

triangle instance-attribute

triangle: Tuple[Float3, Float3, Float3]

triangulate_cutcsg

triangulate_cutcsg(csg: CutCSG) -> TriangleMesh
Source code in kumiki/triangles.py
def triangulate_cutcsg(csg: CutCSG) -> TriangleMesh:
    return _triangulate_with_label(csg, label=type(csg).__name__)

mesh_cutcsg

mesh_cutcsg(csg: CutCSG) -> TriangleMesh
Source code in kumiki/triangles.py
def mesh_cutcsg(csg: CutCSG) -> TriangleMesh:
    return triangulate_cutcsg(csg)

raw_raycast_first

raw_raycast_first(target: MeshableTarget, origin: V3, direction: V3) -> Optional[RaycastHit]
Source code in kumiki/triangles.py
def raw_raycast_first(target: MeshableTarget, origin: V3, direction: V3) -> Optional[RaycastHit]:
    hits = raw_raycast_all(target, origin, direction)
    if not hits:
        return None
    return hits[0]

raw_raycast_all

raw_raycast_all(target: MeshableTarget, origin: V3, direction: V3) -> list[RaycastHit]
Source code in kumiki/triangles.py
def raw_raycast_all(target: MeshableTarget, origin: V3, direction: V3) -> list[RaycastHit]:
    triangle_mesh = target if isinstance(target, TriangleMesh) else triangulate_cutcsg(target)
    mesh = triangle_mesh.mesh

    origin_array = _vector3_to_numpy(origin)
    direction_array = _vector3_to_numpy(direction)
    direction_norm = np.linalg.norm(direction_array)
    if direction_norm <= TRIANGLES_RAY_EPSILON:
        raise ValueError("Ray direction must be non-zero")
    direction_unit = direction_array / direction_norm

    triangles = np.asarray(mesh.triangles, dtype=float)
    normals = np.asarray(mesh.face_normals, dtype=float)

    hits: list[RaycastHit] = []
    for face_index, triangle in enumerate(triangles):
        hit = _ray_intersect_triangle(origin_array, direction_unit, triangle)
        if hit is None:
            continue
        distance, position = hit
        hits.append(
            RaycastHit(
                position=_tuple3(position),
                normal=_tuple3(normals[face_index]),
                distance=round(float(distance), TRIANGLES_FLOAT_DIGITS),
                face_index=face_index,
                triangle=(
                    _tuple3(triangle[0]),
                    _tuple3(triangle[1]),
                    _tuple3(triangle[2]),
                ),
            )
        )

    hits.sort(key=lambda item: item.distance)
    return hits