from __future__ import annotations

import dataclasses
import enum
from typing import Any, ClassVar, Protocol, Self, overload, runtime_checkable  # type: ignore

import numpy as np
import numpy.typing as npt

# Every pyclass in this module exposes ``__dataclass_fields__`` as a
# class-level attribute so frameworks like ``orjson``, ``msgspec``, and
# ``pydantic`` treat instances as dataclasses for native (de)serialization.
_DataclassFields = ClassVar[dict[str, dataclasses.Field[Any]]]

class EulerRot(enum.Enum):
    ZYX = "ZYX"
    ZXY = "ZXY"
    YXZ = "YXZ"
    YZX = "YZX"
    XYZ = "XYZ"
    XZY = "XZY"
    ZYZ = "ZYZ"
    ZXZ = "ZXZ"
    YXY = "YXY"
    YZY = "YZY"
    XYX = "XYX"
    XZX = "XZX"
    ZYXEx = "ZYXEx"
    ZXYEx = "ZXYEx"
    YXZEx = "YXZEx"
    YZXEx = "YZXEx"
    XYZEx = "XYZEx"
    XZYEx = "XZYEx"
    ZYZEx = "ZYZEx"
    ZXZEx = "ZXZEx"
    YXYEx = "YXYEx"
    YZYEx = "YZYEx"
    XYXEx = "XYXEx"
    XZXEx = "XZXEx"

class Vec2:
    __dataclass_fields__: _DataclassFields

    ZERO: Vec2
    ONE: Vec2
    NEG_ONE: Vec2
    X: Vec2
    Y: Vec2
    NEG_X: Vec2
    NEG_Y: Vec2
    INFINITY: Vec2
    NEG_INFINITY: Vec2
    NAN: Vec2

    def __init__(self, x: float, y: float) -> None: ...
    @staticmethod
    def splat(v: float) -> Vec2: ...
    @staticmethod
    def from_array(a: tuple[float, float]) -> Vec2: ...
    @staticmethod
    def from_numpy(a: npt.ArrayLike) -> Vec2: ...
    @property
    def x(self) -> float: ...
    @property
    def y(self) -> float: ...
    def with_x(self, x: float) -> Vec2: ...
    def with_y(self, y: float) -> Vec2: ...
    def to_array(self) -> tuple[float, float]: ...
    def to_list(self) -> list[float]: ...
    def to_numpy(self) -> npt.NDArray[np.float64]: ...
    def extend(self, z: float) -> Vec3: ...
    def dot(self, rhs: Vec2) -> float: ...
    def perp(self) -> Vec2: ...
    def perp_dot(self, rhs: Vec2) -> float: ...
    def length(self) -> float: ...
    def length_squared(self) -> float: ...
    def length_recip(self) -> float: ...
    def distance(self, rhs: Vec2) -> float: ...
    def distance_squared(self, rhs: Vec2) -> float: ...
    def normalize(self) -> Vec2: ...
    def try_normalize(self) -> Vec2 | None: ...
    def normalize_or(self, fallback: Vec2) -> Vec2: ...
    def normalize_or_zero(self) -> Vec2: ...
    def normalize_and_length(self) -> tuple[Vec2, float]: ...
    def is_normalized(self) -> bool: ...
    def rotate(self, rhs: Vec2) -> Vec2: ...
    def project_onto(self, rhs: Vec2) -> Vec2: ...
    def reject_from(self, rhs: Vec2) -> Vec2: ...
    def project_onto_normalized(self, rhs: Vec2) -> Vec2: ...
    def reject_from_normalized(self, rhs: Vec2) -> Vec2: ...
    def reflect(self, normal: Vec2) -> Vec2: ...
    def refract(self, normal: Vec2, eta: float) -> Vec2: ...
    def lerp(self, rhs: Vec2, s: float) -> Vec2: ...
    def move_towards(self, rhs: Vec2, d: float) -> Vec2: ...
    def midpoint(self, rhs: Vec2) -> Vec2: ...
    def min(self, rhs: Vec2) -> Vec2: ...
    def max(self, rhs: Vec2) -> Vec2: ...
    def clamp(self, min: Vec2, max: Vec2) -> Vec2: ...
    def min_element(self) -> float: ...
    def max_element(self) -> float: ...
    def min_position(self) -> int: ...
    def max_position(self) -> int: ...
    def clamp_length(self, min: float, max: float) -> Vec2: ...
    def clamp_length_max(self, max: float) -> Vec2: ...
    def clamp_length_min(self, min: float) -> Vec2: ...
    def element_sum(self) -> float: ...
    def element_product(self) -> float: ...
    def copysign(self, rhs: Vec2) -> Vec2: ...
    def powf(self, n: float) -> Vec2: ...
    def sin_cos(self) -> tuple[Vec2, Vec2]: ...
    def mul_add(self, a: Vec2, b: Vec2) -> Vec2: ...
    def step(self, rhs: Vec2) -> Vec2: ...
    def div_euclid(self, rhs: Vec2) -> Vec2: ...
    def rem_euclid(self, rhs: Vec2) -> Vec2: ...
    def angle_to(self, rhs: Vec2) -> float: ...
    def rotate_towards(self, rhs: Vec2, max_angle: float) -> Vec2: ...
    def abs(self) -> Vec2: ...
    def signum(self) -> Vec2: ...
    def floor(self) -> Vec2: ...
    def ceil(self) -> Vec2: ...
    def round(self) -> Vec2: ...
    def trunc(self) -> Vec2: ...
    def fract(self) -> Vec2: ...
    def fract_gl(self) -> Vec2: ...
    def exp(self) -> Vec2: ...
    def exp2(self) -> Vec2: ...
    def ln(self) -> Vec2: ...
    def log2(self) -> Vec2: ...
    def sqrt(self) -> Vec2: ...
    def recip(self) -> Vec2: ...
    def cos(self) -> Vec2: ...
    def sin(self) -> Vec2: ...
    def saturate(self) -> Vec2: ...
    def is_finite(self) -> bool: ...
    def is_nan(self) -> bool: ...
    def abs_diff_eq(self, rhs: Vec2, max_abs_diff: float) -> bool: ...
    @overload
    def __add__(self, other: Vec2) -> Vec2: ...
    @overload
    def __add__(self, other: float) -> Vec2: ...
    @overload
    def __radd__(self, other: Vec2) -> Vec2: ...
    @overload
    def __radd__(self, other: float) -> Vec2: ...
    @overload
    def __sub__(self, other: Vec2) -> Vec2: ...
    @overload
    def __sub__(self, other: float) -> Vec2: ...
    @overload
    def __rsub__(self, other: Vec2) -> Vec2: ...
    @overload
    def __rsub__(self, other: float) -> Vec2: ...
    @overload
    def __mul__(self, other: Vec2) -> Vec2: ...
    @overload
    def __mul__(self, other: float) -> Vec2: ...
    @overload
    def __rmul__(self, other: Vec2) -> Vec2: ...
    @overload
    def __rmul__(self, other: float) -> Vec2: ...
    @overload
    def __truediv__(self, other: Vec2) -> Vec2: ...
    @overload
    def __truediv__(self, other: float) -> Vec2: ...
    @overload
    def __rtruediv__(self, other: Vec2) -> Vec2: ...
    @overload
    def __rtruediv__(self, other: float) -> Vec2: ...
    @overload
    def __mod__(self, other: Vec2) -> Vec2: ...
    @overload
    def __mod__(self, other: float) -> Vec2: ...
    def __neg__(self) -> Vec2: ...
    def __pos__(self) -> Vec2: ...
    def __eq__(self, other: object) -> bool: ...
    def __ne__(self, other: object) -> bool: ...
    def __len__(self) -> int: ...
    def __getitem__(self, idx: int) -> float: ...
    def __repr__(self) -> str: ...
    def __str__(self) -> str: ...
    def __getnewargs_ex__(self) -> tuple[tuple[()], dict[str, bytes]]: ...
    def __array__(self) -> npt.NDArray[np.float64]: ...
    def __hash__(self) -> int: ...

class Vec3:
    __dataclass_fields__: _DataclassFields

    ZERO: Vec3
    ONE: Vec3
    NEG_ONE: Vec3
    X: Vec3
    Y: Vec3
    Z: Vec3
    NEG_X: Vec3
    NEG_Y: Vec3
    NEG_Z: Vec3
    INFINITY: Vec3
    NEG_INFINITY: Vec3
    NAN: Vec3

    def __init__(self, x: float, y: float, z: float) -> None: ...
    @staticmethod
    def splat(v: float) -> Vec3: ...
    @staticmethod
    def from_array(a: tuple[float, float, float]) -> Vec3: ...
    @staticmethod
    def from_numpy(a: npt.ArrayLike) -> Vec3: ...
    @staticmethod
    def from_homogeneous(v: Vec4) -> Vec3: ...
    @property
    def x(self) -> float: ...
    @property
    def y(self) -> float: ...
    @property
    def z(self) -> float: ...
    def with_x(self, x: float) -> Vec3: ...
    def with_y(self, y: float) -> Vec3: ...
    def with_z(self, z: float) -> Vec3: ...
    def to_array(self) -> tuple[float, float, float]: ...
    def to_list(self) -> list[float]: ...
    def to_numpy(self) -> npt.NDArray[np.float64]: ...
    def extend(self, w: float) -> Vec4: ...
    def truncate(self) -> Vec2: ...
    def to_homogeneous(self) -> Vec4: ...
    def dot(self, rhs: Vec3) -> float: ...
    def cross(self, rhs: Vec3) -> Vec3: ...
    def length(self) -> float: ...
    def length_squared(self) -> float: ...
    def length_recip(self) -> float: ...
    def distance(self, rhs: Vec3) -> float: ...
    def distance_squared(self, rhs: Vec3) -> float: ...
    def normalize(self) -> Vec3: ...
    def try_normalize(self) -> Vec3 | None: ...
    def normalize_or(self, fallback: Vec3) -> Vec3: ...
    def normalize_or_zero(self) -> Vec3: ...
    def normalize_and_length(self) -> tuple[Vec3, float]: ...
    def is_normalized(self) -> bool: ...
    def project_onto(self, rhs: Vec3) -> Vec3: ...
    def reject_from(self, rhs: Vec3) -> Vec3: ...
    def project_onto_normalized(self, rhs: Vec3) -> Vec3: ...
    def reject_from_normalized(self, rhs: Vec3) -> Vec3: ...
    def reflect(self, normal: Vec3) -> Vec3: ...
    def refract(self, normal: Vec3, eta: float) -> Vec3: ...
    def lerp(self, rhs: Vec3, s: float) -> Vec3: ...
    def slerp(self, rhs: Vec3, s: float) -> Vec3: ...
    def move_towards(self, rhs: Vec3, d: float) -> Vec3: ...
    def midpoint(self, rhs: Vec3) -> Vec3: ...
    def min(self, rhs: Vec3) -> Vec3: ...
    def max(self, rhs: Vec3) -> Vec3: ...
    def clamp(self, min: Vec3, max: Vec3) -> Vec3: ...
    def min_element(self) -> float: ...
    def max_element(self) -> float: ...
    def min_position(self) -> int: ...
    def max_position(self) -> int: ...
    def clamp_length(self, min: float, max: float) -> Vec3: ...
    def clamp_length_max(self, max: float) -> Vec3: ...
    def clamp_length_min(self, min: float) -> Vec3: ...
    def element_sum(self) -> float: ...
    def element_product(self) -> float: ...
    def copysign(self, rhs: Vec3) -> Vec3: ...
    def powf(self, n: float) -> Vec3: ...
    def sin_cos(self) -> tuple[Vec3, Vec3]: ...
    def mul_add(self, a: Vec3, b: Vec3) -> Vec3: ...
    def step(self, rhs: Vec3) -> Vec3: ...
    def div_euclid(self, rhs: Vec3) -> Vec3: ...
    def rem_euclid(self, rhs: Vec3) -> Vec3: ...
    def angle_between(self, rhs: Vec3) -> float: ...
    def rotate_x(self, angle: float) -> Vec3: ...
    def rotate_y(self, angle: float) -> Vec3: ...
    def rotate_z(self, angle: float) -> Vec3: ...
    def rotate_axis(self, axis: Vec3, angle: float) -> Vec3: ...
    def rotate_towards(self, rhs: Vec3, max_angle: float) -> Vec3: ...
    def any_orthogonal_vector(self) -> Vec3: ...
    def any_orthonormal_vector(self) -> Vec3: ...
    def any_orthonormal_pair(self) -> tuple[Vec3, Vec3]: ...
    def abs(self) -> Vec3: ...
    def signum(self) -> Vec3: ...
    def floor(self) -> Vec3: ...
    def ceil(self) -> Vec3: ...
    def round(self) -> Vec3: ...
    def trunc(self) -> Vec3: ...
    def fract(self) -> Vec3: ...
    def fract_gl(self) -> Vec3: ...
    def exp(self) -> Vec3: ...
    def exp2(self) -> Vec3: ...
    def ln(self) -> Vec3: ...
    def log2(self) -> Vec3: ...
    def sqrt(self) -> Vec3: ...
    def recip(self) -> Vec3: ...
    def cos(self) -> Vec3: ...
    def sin(self) -> Vec3: ...
    def saturate(self) -> Vec3: ...
    def is_finite(self) -> bool: ...
    def is_nan(self) -> bool: ...
    def abs_diff_eq(self, rhs: Vec3, max_abs_diff: float) -> bool: ...
    @overload
    def __add__(self, other: Vec3) -> Vec3: ...
    @overload
    def __add__(self, other: float) -> Vec3: ...
    @overload
    def __radd__(self, other: Vec3) -> Vec3: ...
    @overload
    def __radd__(self, other: float) -> Vec3: ...
    @overload
    def __sub__(self, other: Vec3) -> Vec3: ...
    @overload
    def __sub__(self, other: float) -> Vec3: ...
    @overload
    def __rsub__(self, other: Vec3) -> Vec3: ...
    @overload
    def __rsub__(self, other: float) -> Vec3: ...
    @overload
    def __mul__(self, other: Vec3) -> Vec3: ...
    @overload
    def __mul__(self, other: float) -> Vec3: ...
    @overload
    def __rmul__(self, other: Vec3) -> Vec3: ...
    @overload
    def __rmul__(self, other: float) -> Vec3: ...
    @overload
    def __truediv__(self, other: Vec3) -> Vec3: ...
    @overload
    def __truediv__(self, other: float) -> Vec3: ...
    @overload
    def __rtruediv__(self, other: Vec3) -> Vec3: ...
    @overload
    def __rtruediv__(self, other: float) -> Vec3: ...
    @overload
    def __mod__(self, other: Vec3) -> Vec3: ...
    @overload
    def __mod__(self, other: float) -> Vec3: ...
    def __neg__(self) -> Vec3: ...
    def __pos__(self) -> Vec3: ...
    def __eq__(self, other: object) -> bool: ...
    def __ne__(self, other: object) -> bool: ...
    def __len__(self) -> int: ...
    def __getitem__(self, idx: int) -> float: ...
    def __repr__(self) -> str: ...
    def __str__(self) -> str: ...
    def __getnewargs_ex__(self) -> tuple[tuple[()], dict[str, bytes]]: ...
    def __array__(self) -> npt.NDArray[np.float64]: ...
    def __hash__(self) -> int: ...

class Vec4:
    __dataclass_fields__: _DataclassFields

    ZERO: Vec4
    ONE: Vec4
    NEG_ONE: Vec4
    X: Vec4
    Y: Vec4
    Z: Vec4
    W: Vec4
    NEG_X: Vec4
    NEG_Y: Vec4
    NEG_Z: Vec4
    NEG_W: Vec4
    INFINITY: Vec4
    NEG_INFINITY: Vec4
    NAN: Vec4

    def __init__(self, x: float, y: float, z: float, w: float) -> None: ...
    @staticmethod
    def splat(v: float) -> Vec4: ...
    @staticmethod
    def from_array(a: tuple[float, float, float, float]) -> Vec4: ...
    @staticmethod
    def from_numpy(a: npt.ArrayLike) -> Vec4: ...
    @property
    def x(self) -> float: ...
    @property
    def y(self) -> float: ...
    @property
    def z(self) -> float: ...
    @property
    def w(self) -> float: ...
    def with_x(self, x: float) -> Vec4: ...
    def with_y(self, y: float) -> Vec4: ...
    def with_z(self, z: float) -> Vec4: ...
    def with_w(self, w: float) -> Vec4: ...
    def to_array(self) -> tuple[float, float, float, float]: ...
    def to_list(self) -> list[float]: ...
    def to_numpy(self) -> npt.NDArray[np.float64]: ...
    def truncate(self) -> Vec3: ...
    def dot(self, rhs: Vec4) -> float: ...
    def length(self) -> float: ...
    def length_squared(self) -> float: ...
    def length_recip(self) -> float: ...
    def distance(self, rhs: Vec4) -> float: ...
    def distance_squared(self, rhs: Vec4) -> float: ...
    def normalize(self) -> Vec4: ...
    def try_normalize(self) -> Vec4 | None: ...
    def normalize_or(self, fallback: Vec4) -> Vec4: ...
    def normalize_or_zero(self) -> Vec4: ...
    def normalize_and_length(self) -> tuple[Vec4, float]: ...
    def is_normalized(self) -> bool: ...
    def project_onto(self, rhs: Vec4) -> Vec4: ...
    def reject_from(self, rhs: Vec4) -> Vec4: ...
    def project_onto_normalized(self, rhs: Vec4) -> Vec4: ...
    def reject_from_normalized(self, rhs: Vec4) -> Vec4: ...
    def reflect(self, normal: Vec4) -> Vec4: ...
    def refract(self, normal: Vec4, eta: float) -> Vec4: ...
    def lerp(self, rhs: Vec4, s: float) -> Vec4: ...
    def move_towards(self, rhs: Vec4, d: float) -> Vec4: ...
    def midpoint(self, rhs: Vec4) -> Vec4: ...
    def min(self, rhs: Vec4) -> Vec4: ...
    def max(self, rhs: Vec4) -> Vec4: ...
    def clamp(self, min: Vec4, max: Vec4) -> Vec4: ...
    def min_element(self) -> float: ...
    def max_element(self) -> float: ...
    def min_position(self) -> int: ...
    def max_position(self) -> int: ...
    def clamp_length(self, min: float, max: float) -> Vec4: ...
    def clamp_length_max(self, max: float) -> Vec4: ...
    def clamp_length_min(self, min: float) -> Vec4: ...
    def element_sum(self) -> float: ...
    def element_product(self) -> float: ...
    def copysign(self, rhs: Vec4) -> Vec4: ...
    def powf(self, n: float) -> Vec4: ...
    def sin_cos(self) -> tuple[Vec4, Vec4]: ...
    def mul_add(self, a: Vec4, b: Vec4) -> Vec4: ...
    def step(self, rhs: Vec4) -> Vec4: ...
    def div_euclid(self, rhs: Vec4) -> Vec4: ...
    def rem_euclid(self, rhs: Vec4) -> Vec4: ...
    def abs(self) -> Vec4: ...
    def signum(self) -> Vec4: ...
    def floor(self) -> Vec4: ...
    def ceil(self) -> Vec4: ...
    def round(self) -> Vec4: ...
    def trunc(self) -> Vec4: ...
    def fract(self) -> Vec4: ...
    def fract_gl(self) -> Vec4: ...
    def exp(self) -> Vec4: ...
    def exp2(self) -> Vec4: ...
    def ln(self) -> Vec4: ...
    def log2(self) -> Vec4: ...
    def sqrt(self) -> Vec4: ...
    def recip(self) -> Vec4: ...
    def cos(self) -> Vec4: ...
    def sin(self) -> Vec4: ...
    def saturate(self) -> Vec4: ...
    def is_finite(self) -> bool: ...
    def is_nan(self) -> bool: ...
    def abs_diff_eq(self, rhs: Vec4, max_abs_diff: float) -> bool: ...
    @overload
    def __add__(self, other: Vec4) -> Vec4: ...
    @overload
    def __add__(self, other: float) -> Vec4: ...
    @overload
    def __radd__(self, other: Vec4) -> Vec4: ...
    @overload
    def __radd__(self, other: float) -> Vec4: ...
    @overload
    def __sub__(self, other: Vec4) -> Vec4: ...
    @overload
    def __sub__(self, other: float) -> Vec4: ...
    @overload
    def __rsub__(self, other: Vec4) -> Vec4: ...
    @overload
    def __rsub__(self, other: float) -> Vec4: ...
    @overload
    def __mul__(self, other: Vec4) -> Vec4: ...
    @overload
    def __mul__(self, other: float) -> Vec4: ...
    @overload
    def __rmul__(self, other: Vec4) -> Vec4: ...
    @overload
    def __rmul__(self, other: float) -> Vec4: ...
    @overload
    def __truediv__(self, other: Vec4) -> Vec4: ...
    @overload
    def __truediv__(self, other: float) -> Vec4: ...
    @overload
    def __rtruediv__(self, other: Vec4) -> Vec4: ...
    @overload
    def __rtruediv__(self, other: float) -> Vec4: ...
    @overload
    def __mod__(self, other: Vec4) -> Vec4: ...
    @overload
    def __mod__(self, other: float) -> Vec4: ...
    def __neg__(self) -> Vec4: ...
    def __pos__(self) -> Vec4: ...
    def __eq__(self, other: object) -> bool: ...
    def __ne__(self, other: object) -> bool: ...
    def __len__(self) -> int: ...
    def __getitem__(self, idx: int) -> float: ...
    def __repr__(self) -> str: ...
    def __str__(self) -> str: ...
    def __getnewargs_ex__(self) -> tuple[tuple[()], dict[str, bytes]]: ...
    def __array__(self) -> npt.NDArray[np.float64]: ...
    def __hash__(self) -> int: ...

class Quat:
    __dataclass_fields__: _DataclassFields

    IDENTITY: Quat
    NAN: Quat

    def __init__(self, x: float, y: float, z: float, w: float) -> None: ...
    @staticmethod
    def from_xyzw(x: float, y: float, z: float, w: float) -> Quat: ...
    @staticmethod
    def from_array(a: tuple[float, float, float, float]) -> Quat: ...
    @staticmethod
    def from_numpy(a: npt.ArrayLike) -> Quat: ...
    @staticmethod
    def from_axis_angle(axis: Vec3, angle: float) -> Quat: ...
    @staticmethod
    def from_scaled_axis(v: Vec3) -> Quat: ...
    @staticmethod
    def from_rotation_x(angle: float) -> Quat: ...
    @staticmethod
    def from_rotation_y(angle: float) -> Quat: ...
    @staticmethod
    def from_rotation_z(angle: float) -> Quat: ...
    @staticmethod
    def from_euler(order: EulerRot, a: float, b: float, c: float) -> Quat: ...
    @staticmethod
    def from_rotation_axes(x_axis: Vec3, y_axis: Vec3, z_axis: Vec3) -> Quat: ...
    @staticmethod
    def from_mat3(mat: Mat3) -> Quat: ...
    @staticmethod
    def from_mat4(mat: Mat4) -> Quat: ...
    @staticmethod
    def from_affine3(a: Affine3) -> Quat: ...
    @staticmethod
    def from_rotation_arc(from_: Vec3, to: Vec3) -> Quat: ...
    @staticmethod
    def from_rotation_arc_colinear(from_: Vec3, to: Vec3) -> Quat: ...
    @staticmethod
    def from_rotation_arc_2d(from_: Vec2, to: Vec2) -> Quat: ...
    @staticmethod
    def look_to_lh(dir: Vec3, up: Vec3) -> Quat: ...
    @staticmethod
    def look_to_rh(dir: Vec3, up: Vec3) -> Quat: ...
    @staticmethod
    def look_at_lh(eye: Vec3, center: Vec3, up: Vec3) -> Quat: ...
    @staticmethod
    def look_at_rh(eye: Vec3, center: Vec3, up: Vec3) -> Quat: ...
    @property
    def x(self) -> float: ...
    @property
    def y(self) -> float: ...
    @property
    def z(self) -> float: ...
    @property
    def w(self) -> float: ...
    def conjugate(self) -> Quat: ...
    def inverse(self) -> Quat: ...
    def dot(self, rhs: Quat) -> float: ...
    def length(self) -> float: ...
    def length_squared(self) -> float: ...
    def length_recip(self) -> float: ...
    def normalize(self) -> Quat: ...
    def mul_vec3(self, rhs: Vec3) -> Vec3: ...
    def mul_quat(self, rhs: Quat) -> Quat: ...
    def lerp(self, end: Quat, s: float) -> Quat: ...
    def slerp(self, end: Quat, s: float) -> Quat: ...
    def angle_between(self, rhs: Quat) -> float: ...
    def rotate_towards(self, rhs: Quat, max_angle: float) -> Quat: ...
    def to_axis_angle(self) -> tuple[Vec3, float]: ...
    def to_scaled_axis(self) -> Vec3: ...
    def to_euler(self, order: EulerRot) -> tuple[float, float, float]: ...
    def to_array(self) -> tuple[float, float, float, float]: ...
    def to_numpy(self) -> npt.NDArray[np.float64]: ...
    def xyz(self) -> Vec3: ...
    def is_finite(self) -> bool: ...
    def is_nan(self) -> bool: ...
    def is_normalized(self) -> bool: ...
    def is_near_identity(self) -> bool: ...
    def abs_diff_eq(self, rhs: Quat, max_abs_diff: float) -> bool: ...
    @overload
    def __mul__(self, other: Quat) -> Quat: ...
    @overload
    def __mul__(self, other: Vec3) -> Vec3: ...
    @overload
    def __mul__(self, other: float) -> Quat: ...
    def __rmul__(self, other: float) -> Quat: ...
    def __add__(self, other: Quat) -> Quat: ...
    def __sub__(self, other: Quat) -> Quat: ...
    def __truediv__(self, other: float) -> Quat: ...
    def __neg__(self) -> Quat: ...
    def __eq__(self, other: object) -> bool: ...
    def __ne__(self, other: object) -> bool: ...
    def __repr__(self) -> str: ...
    def __str__(self) -> str: ...
    def __getnewargs_ex__(self) -> tuple[tuple[()], dict[str, bytes]]: ...
    def __array__(self) -> npt.NDArray[np.float64]: ...
    def __hash__(self) -> int: ...

class Mat3:
    __dataclass_fields__: _DataclassFields

    IDENTITY: Mat3
    ZERO: Mat3
    NAN: Mat3

    def __init__(self, x_axis: Vec3, y_axis: Vec3, z_axis: Vec3) -> None: ...
    @staticmethod
    def from_cols(x_axis: Vec3, y_axis: Vec3, z_axis: Vec3) -> Mat3: ...
    @staticmethod
    def from_numpy(a: npt.ArrayLike) -> Mat3: ...
    @staticmethod
    def from_cols_array(m: tuple[float, ...]) -> Mat3: ...
    @staticmethod
    def from_cols_array_2d(
        m: tuple[
            tuple[float, float, float],
            tuple[float, float, float],
            tuple[float, float, float],
        ],
    ) -> Mat3: ...
    @staticmethod
    def from_diagonal(diagonal: Vec3) -> Mat3: ...
    @staticmethod
    def from_quat(rotation: Quat) -> Mat3: ...
    @staticmethod
    def from_axis_angle(axis: Vec3, angle: float) -> Mat3: ...
    @staticmethod
    def from_euler(order: EulerRot, a: float, b: float, c: float) -> Mat3: ...
    @staticmethod
    def from_rotation_x(angle: float) -> Mat3: ...
    @staticmethod
    def from_rotation_y(angle: float) -> Mat3: ...
    @staticmethod
    def from_rotation_z(angle: float) -> Mat3: ...
    @staticmethod
    def from_angle(angle: float) -> Mat3: ...
    @staticmethod
    def from_translation(translation: Vec2) -> Mat3: ...
    @staticmethod
    def from_scale(scale: Vec2) -> Mat3: ...
    @staticmethod
    def from_scale_angle_translation(
        scale: Vec2, angle: float, translation: Vec2
    ) -> Mat3: ...
    @staticmethod
    def from_mat4(m: Mat4) -> Mat3: ...
    @staticmethod
    def from_mat4_minor(m: Mat4, i: int, j: int) -> Mat3: ...
    @staticmethod
    def look_to_lh(dir: Vec3, up: Vec3) -> Mat3: ...
    @staticmethod
    def look_to_rh(dir: Vec3, up: Vec3) -> Mat3: ...
    @property
    def x_axis(self) -> Vec3: ...
    @property
    def y_axis(self) -> Vec3: ...
    @property
    def z_axis(self) -> Vec3: ...
    def col(self, index: int) -> Vec3: ...
    def row(self, index: int) -> Vec3: ...
    def to_cols_array(self) -> tuple[float, ...]: ...
    def to_cols_array_2d(
        self,
    ) -> tuple[
        tuple[float, float, float],
        tuple[float, float, float],
        tuple[float, float, float],
    ]: ...
    def to_numpy(self) -> npt.NDArray[np.float64]: ...
    def diagonal(self) -> Vec3: ...
    def determinant(self) -> float: ...
    def transpose(self) -> Mat3: ...
    def inverse(self) -> Mat3: ...
    def try_inverse(self) -> Mat3 | None: ...
    def inverse_or_zero(self) -> Mat3: ...
    def to_euler(self, order: EulerRot) -> tuple[float, float, float]: ...
    def mul_vec3(self, rhs: Vec3) -> Vec3: ...
    def mul_transpose_vec3(self, rhs: Vec3) -> Vec3: ...
    def transform_point2(self, rhs: Vec2) -> Vec2: ...
    def transform_vector2(self, rhs: Vec2) -> Vec2: ...
    def mul_mat3(self, rhs: Mat3) -> Mat3: ...
    def add_mat3(self, rhs: Mat3) -> Mat3: ...
    def sub_mat3(self, rhs: Mat3) -> Mat3: ...
    def mul_scalar(self, rhs: float) -> Mat3: ...
    def div_scalar(self, rhs: float) -> Mat3: ...
    def mul_diagonal_scale(self, scale: Vec3) -> Mat3: ...
    def abs(self) -> Mat3: ...
    def recip(self) -> Mat3: ...
    def is_finite(self) -> bool: ...
    def is_nan(self) -> bool: ...
    def abs_diff_eq(self, rhs: Mat3, max_abs_diff: float) -> bool: ...
    @overload
    def __mul__(self, other: Mat3) -> Mat3: ...
    @overload
    def __mul__(self, other: Vec3) -> Vec3: ...
    @overload
    def __mul__(self, other: float) -> Mat3: ...
    def __rmul__(self, other: float) -> Mat3: ...
    def __add__(self, other: Mat3) -> Mat3: ...
    def __sub__(self, other: Mat3) -> Mat3: ...
    def __truediv__(self, other: float) -> Mat3: ...
    def __neg__(self) -> Mat3: ...
    def __eq__(self, other: object) -> bool: ...
    def __ne__(self, other: object) -> bool: ...
    def __repr__(self) -> str: ...
    def __getnewargs_ex__(self) -> tuple[tuple[()], dict[str, bytes]]: ...
    def __array__(self) -> npt.NDArray[np.float64]: ...
    def __hash__(self) -> int: ...

class Mat4:
    __dataclass_fields__: _DataclassFields

    IDENTITY: Mat4
    ZERO: Mat4
    NAN: Mat4

    def __init__(
        self, x_axis: Vec4, y_axis: Vec4, z_axis: Vec4, w_axis: Vec4
    ) -> None: ...
    @staticmethod
    def from_cols(x_axis: Vec4, y_axis: Vec4, z_axis: Vec4, w_axis: Vec4) -> Mat4: ...
    @staticmethod
    def from_numpy(a: npt.ArrayLike) -> Mat4: ...
    @staticmethod
    def from_cols_array(m: tuple[float, ...]) -> Mat4: ...
    @staticmethod
    def from_cols_array_2d(
        m: tuple[
            tuple[float, float, float, float],
            tuple[float, float, float, float],
            tuple[float, float, float, float],
            tuple[float, float, float, float],
        ],
    ) -> Mat4: ...
    @staticmethod
    def from_diagonal(diagonal: Vec4) -> Mat4: ...
    @staticmethod
    def from_scale_rotation_translation(
        scale: Vec3, rotation: Quat, translation: Vec3
    ) -> Mat4: ...
    @staticmethod
    def from_rotation_translation(rotation: Quat, translation: Vec3) -> Mat4: ...
    @staticmethod
    def from_quat(rotation: Quat) -> Mat4: ...
    @staticmethod
    def from_mat3(m: Mat3) -> Mat4: ...
    @staticmethod
    def from_mat3_translation(mat3: Mat3, translation: Vec3) -> Mat4: ...
    @staticmethod
    def from_translation(translation: Vec3) -> Mat4: ...
    @staticmethod
    def from_axis_angle(axis: Vec3, angle: float) -> Mat4: ...
    @staticmethod
    def from_euler(order: EulerRot, a: float, b: float, c: float) -> Mat4: ...
    @staticmethod
    def from_rotation_x(angle: float) -> Mat4: ...
    @staticmethod
    def from_rotation_y(angle: float) -> Mat4: ...
    @staticmethod
    def from_rotation_z(angle: float) -> Mat4: ...
    @staticmethod
    def from_scale(scale: Vec3) -> Mat4: ...
    @staticmethod
    def perspective_rh_gl(
        fov_y_radians: float, aspect_ratio: float, z_near: float, z_far: float
    ) -> Mat4: ...
    @staticmethod
    def perspective_lh(
        fov_y_radians: float, aspect_ratio: float, z_near: float, z_far: float
    ) -> Mat4: ...
    @staticmethod
    def perspective_rh(
        fov_y_radians: float, aspect_ratio: float, z_near: float, z_far: float
    ) -> Mat4: ...
    @staticmethod
    def perspective_infinite_lh(
        fov_y_radians: float, aspect_ratio: float, z_near: float
    ) -> Mat4: ...
    @staticmethod
    def perspective_infinite_rh(
        fov_y_radians: float, aspect_ratio: float, z_near: float
    ) -> Mat4: ...
    @staticmethod
    def perspective_infinite_reverse_lh(
        fov_y_radians: float, aspect_ratio: float, z_near: float
    ) -> Mat4: ...
    @staticmethod
    def perspective_infinite_reverse_rh(
        fov_y_radians: float, aspect_ratio: float, z_near: float
    ) -> Mat4: ...
    @staticmethod
    def orthographic_rh_gl(
        left: float, right: float, bottom: float, top: float, near: float, far: float
    ) -> Mat4: ...
    @staticmethod
    def orthographic_lh(
        left: float, right: float, bottom: float, top: float, near: float, far: float
    ) -> Mat4: ...
    @staticmethod
    def orthographic_rh(
        left: float, right: float, bottom: float, top: float, near: float, far: float
    ) -> Mat4: ...
    @staticmethod
    def frustum_rh_gl(
        left: float,
        right: float,
        bottom: float,
        top: float,
        z_near: float,
        z_far: float,
    ) -> Mat4: ...
    @staticmethod
    def frustum_lh(
        left: float,
        right: float,
        bottom: float,
        top: float,
        z_near: float,
        z_far: float,
    ) -> Mat4: ...
    @staticmethod
    def frustum_rh(
        left: float,
        right: float,
        bottom: float,
        top: float,
        z_near: float,
        z_far: float,
    ) -> Mat4: ...
    @staticmethod
    def look_to_lh(eye: Vec3, dir: Vec3, up: Vec3) -> Mat4: ...
    @staticmethod
    def look_to_rh(eye: Vec3, dir: Vec3, up: Vec3) -> Mat4: ...
    @staticmethod
    def look_at_lh(eye: Vec3, center: Vec3, up: Vec3) -> Mat4: ...
    @staticmethod
    def look_at_rh(eye: Vec3, center: Vec3, up: Vec3) -> Mat4: ...
    @property
    def x_axis(self) -> Vec4: ...
    @property
    def y_axis(self) -> Vec4: ...
    @property
    def z_axis(self) -> Vec4: ...
    @property
    def w_axis(self) -> Vec4: ...
    def col(self, index: int) -> Vec4: ...
    def row(self, index: int) -> Vec4: ...
    def to_cols_array(self) -> tuple[float, ...]: ...
    def to_cols_array_2d(
        self,
    ) -> tuple[
        tuple[float, float, float, float],
        tuple[float, float, float, float],
        tuple[float, float, float, float],
        tuple[float, float, float, float],
    ]: ...
    def to_numpy(self) -> npt.NDArray[np.float64]: ...
    def diagonal(self) -> Vec4: ...
    def determinant(self) -> float: ...
    def transpose(self) -> Mat4: ...
    def inverse(self) -> Mat4: ...
    def try_inverse(self) -> Mat4 | None: ...
    def inverse_or_zero(self) -> Mat4: ...
    def to_scale_rotation_translation(self) -> tuple[Vec3, Quat, Vec3]: ...
    def to_euler(self, order: EulerRot) -> tuple[float, float, float]: ...
    def mul_vec4(self, rhs: Vec4) -> Vec4: ...
    def mul_transpose_vec4(self, rhs: Vec4) -> Vec4: ...
    def project_point3(self, rhs: Vec3) -> Vec3: ...
    def transform_point3(self, rhs: Vec3) -> Vec3: ...
    def transform_vector3(self, rhs: Vec3) -> Vec3: ...
    def mul_mat4(self, rhs: Mat4) -> Mat4: ...
    def add_mat4(self, rhs: Mat4) -> Mat4: ...
    def sub_mat4(self, rhs: Mat4) -> Mat4: ...
    def mul_scalar(self, rhs: float) -> Mat4: ...
    def div_scalar(self, rhs: float) -> Mat4: ...
    def mul_diagonal_scale(self, scale: Vec4) -> Mat4: ...
    def abs(self) -> Mat4: ...
    def recip(self) -> Mat4: ...
    def is_finite(self) -> bool: ...
    def is_nan(self) -> bool: ...
    def abs_diff_eq(self, rhs: Mat4, max_abs_diff: float) -> bool: ...
    @overload
    def __mul__(self, other: Mat4) -> Mat4: ...
    @overload
    def __mul__(self, other: Vec4) -> Vec4: ...
    @overload
    def __mul__(self, other: float) -> Mat4: ...
    def __rmul__(self, other: float) -> Mat4: ...
    def __add__(self, other: Mat4) -> Mat4: ...
    def __sub__(self, other: Mat4) -> Mat4: ...
    def __truediv__(self, other: float) -> Mat4: ...
    def __neg__(self) -> Mat4: ...
    def __eq__(self, other: object) -> bool: ...
    def __ne__(self, other: object) -> bool: ...
    def __repr__(self) -> str: ...
    def __getnewargs_ex__(self) -> tuple[tuple[()], dict[str, bytes]]: ...
    def __array__(self) -> npt.NDArray[np.float64]: ...
    def __hash__(self) -> int: ...

class Affine3:
    __dataclass_fields__: _DataclassFields

    IDENTITY: Affine3
    ZERO: Affine3
    NAN: Affine3

    def __init__(self, matrix3: Mat3, translation: Vec3) -> None: ...
    @staticmethod
    def from_cols(
        x_axis: Vec3, y_axis: Vec3, z_axis: Vec3, w_axis: Vec3
    ) -> Affine3: ...
    @staticmethod
    def from_numpy(a: npt.ArrayLike) -> Affine3: ...
    @staticmethod
    def from_cols_array(m: tuple[float, ...]) -> Affine3: ...
    @staticmethod
    def from_cols_array_2d(
        m: tuple[
            tuple[float, float, float],
            tuple[float, float, float],
            tuple[float, float, float],
            tuple[float, float, float],
        ],
    ) -> Affine3: ...
    @staticmethod
    def from_scale(scale: Vec3) -> Affine3: ...
    @staticmethod
    def from_quat(rotation: Quat) -> Affine3: ...
    @staticmethod
    def from_axis_angle(axis: Vec3, angle: float) -> Affine3: ...
    @staticmethod
    def from_rotation_x(angle: float) -> Affine3: ...
    @staticmethod
    def from_rotation_y(angle: float) -> Affine3: ...
    @staticmethod
    def from_rotation_z(angle: float) -> Affine3: ...
    @staticmethod
    def from_translation(translation: Vec3) -> Affine3: ...
    @staticmethod
    def from_mat3(mat3: Mat3) -> Affine3: ...
    @staticmethod
    def from_mat3_translation(mat3: Mat3, translation: Vec3) -> Affine3: ...
    @staticmethod
    def from_scale_rotation_translation(
        scale: Vec3, rotation: Quat, translation: Vec3
    ) -> Affine3: ...
    @staticmethod
    def from_rotation_translation(rotation: Quat, translation: Vec3) -> Affine3: ...
    @staticmethod
    def from_mat4(m: Mat4) -> Affine3: ...
    @staticmethod
    def look_to_lh(eye: Vec3, dir: Vec3, up: Vec3) -> Affine3: ...
    @staticmethod
    def look_to_rh(eye: Vec3, dir: Vec3, up: Vec3) -> Affine3: ...
    @staticmethod
    def look_at_lh(eye: Vec3, center: Vec3, up: Vec3) -> Affine3: ...
    @staticmethod
    def look_at_rh(eye: Vec3, center: Vec3, up: Vec3) -> Affine3: ...
    @property
    def matrix3(self) -> Mat3: ...
    @property
    def translation(self) -> Vec3: ...
    def transform_point3(self, rhs: Vec3) -> Vec3: ...
    def transform_vector3(self, rhs: Vec3) -> Vec3: ...
    def inverse(self) -> Affine3: ...
    def to_scale_rotation_translation(self) -> tuple[Vec3, Quat, Vec3]: ...
    def to_cols_array(self) -> tuple[float, ...]: ...
    def to_cols_array_2d(
        self,
    ) -> tuple[
        tuple[float, float, float],
        tuple[float, float, float],
        tuple[float, float, float],
        tuple[float, float, float],
    ]: ...
    def to_numpy(self) -> npt.NDArray[np.float64]: ...
    def is_finite(self) -> bool: ...
    def is_nan(self) -> bool: ...
    def abs_diff_eq(self, rhs: Affine3, max_abs_diff: float) -> bool: ...
    def __mul__(self, other: Affine3) -> Affine3: ...
    def __eq__(self, other: object) -> bool: ...
    def __ne__(self, other: object) -> bool: ...
    def __repr__(self) -> str: ...
    def __getnewargs_ex__(self) -> tuple[tuple[()], dict[str, bytes]]: ...
    def __array__(self) -> npt.NDArray[np.float64]: ...
    def __hash__(self) -> int: ...

@runtime_checkable
class Scalable(Protocol):
    def scaled(self, factor: float) -> Self: ...

@runtime_checkable
class Transformable(Protocol):
    def translated(self, offset: Vec3) -> Self: ...
    def rotated_mat(self, mat: Mat3) -> Self: ...
    def rotated_quat(self, quat: Quat) -> Self: ...
    def transformed(self, mat: Affine3) -> Self: ...

@runtime_checkable
class Bounded(Protocol):
    def broadphase(self) -> Sphere: ...
    def obb(self) -> Cuboid: ...
    def aabb(self) -> Cuboid: ...

@runtime_checkable
class Stretchable(Protocol):
    def stretch(self, translation: Vec3) -> list[Shape]: ...

@runtime_checkable
class Collides(Protocol):
    def collides(self, other: Shape) -> bool: ...

class Shape:
    __dataclass_fields__: _DataclassFields

class Sphere(Shape):
    __dataclass_fields__: _DataclassFields

    def __init__(self, center: Vec3, radius: float) -> None: ...
    @property
    def center(self) -> Vec3: ...
    @property
    def radius(self) -> float: ...
    def scaled(self, factor: float) -> Sphere: ...
    def translated(self, offset: Vec3) -> Sphere: ...
    def rotated_mat(self, mat: Mat3) -> Sphere: ...
    def rotated_quat(self, quat: Quat) -> Sphere: ...
    def transformed(self, mat: Affine3) -> Sphere: ...
    def broadphase(self) -> Sphere: ...
    def obb(self) -> Cuboid: ...
    def aabb(self) -> Cuboid: ...
    def abs_diff_eq(self, rhs: Sphere, max_abs_diff: float) -> bool: ...
    def stretch(self, translation: Vec3) -> list[Shape]: ...
    def collides(self, other: Shape) -> bool: ...
    def __repr__(self) -> str: ...

class Capsule(Shape):
    __dataclass_fields__: _DataclassFields

    def __init__(self, p1: Vec3, p2: Vec3, radius: float) -> None: ...
    @property
    def p1(self) -> Vec3: ...
    @property
    def radius(self) -> float: ...
    @property
    def p2(self) -> Vec3: ...
    def closest_point_to(self, point: Vec3) -> Vec3: ...
    def bounding_sphere(self) -> tuple[Vec3, float]: ...
    def length(self) -> float: ...
    @staticmethod
    def from_center_orientation(
        center: Vec3, orientation: Mat3, length: float, radius: float
    ) -> Capsule: ...
    def scaled(self, factor: float) -> Capsule: ...
    def translated(self, offset: Vec3) -> Capsule: ...
    def rotated_mat(self, mat: Mat3) -> Capsule: ...
    def rotated_quat(self, quat: Quat) -> Capsule: ...
    def transformed(self, mat: Affine3) -> Capsule: ...
    def broadphase(self) -> Sphere: ...
    def obb(self) -> Cuboid: ...
    def aabb(self) -> Cuboid: ...
    def abs_diff_eq(self, rhs: Capsule, max_abs_diff: float) -> bool: ...
    def stretch(self, translation: Vec3) -> list[Shape]: ...
    def collides(self, other: Shape) -> bool: ...
    def __repr__(self) -> str: ...

class Cuboid(Shape):
    __dataclass_fields__: _DataclassFields

    def __init__(
        self,
        center: Vec3,
        axes: tuple[
            tuple[float, float, float],
            tuple[float, float, float],
            tuple[float, float, float],
        ],
        half_extents: tuple[float, float, float],
    ) -> None: ...
    @staticmethod
    def from_aabb(min: Vec3, max: Vec3) -> Cuboid: ...
    @property
    def center(self) -> Vec3: ...
    @property
    def axes(
        self,
    ) -> tuple[
        tuple[float, float, float],
        tuple[float, float, float],
        tuple[float, float, float],
    ]: ...
    @property
    def half_extents(self) -> tuple[float, float, float]: ...
    @property
    def full_extents(self) -> tuple[float, float, float]: ...
    @property
    def axis_aligned(self) -> bool: ...
    @staticmethod
    def from_center_size_orientation(
        center: Vec3, size: tuple[float, float, float], orientation: Mat3
    ) -> Cuboid: ...
    def corners(self) -> list[Vec3]: ...
    def bounding_sphere_radius(self) -> float: ...
    def contains_point(self, point: Vec3) -> bool: ...
    def point_dist_sq(self, point: Vec3) -> float: ...
    def scaled(self, factor: float) -> Cuboid: ...
    def translated(self, offset: Vec3) -> Cuboid: ...
    def rotated_mat(self, mat: Mat3) -> Cuboid: ...
    def rotated_quat(self, quat: Quat) -> Cuboid: ...
    def transformed(self, mat: Affine3) -> Cuboid: ...
    def broadphase(self) -> Sphere: ...
    def obb(self) -> Cuboid: ...
    def aabb(self) -> Cuboid: ...
    def abs_diff_eq(self, rhs: Cuboid, max_abs_diff: float) -> bool: ...
    def stretch(self, translation: Vec3) -> list[Shape]: ...
    def collides(self, other: Shape) -> bool: ...
    def __repr__(self) -> str: ...

class Cylinder(Shape):
    __dataclass_fields__: _DataclassFields

    def __init__(self, p1: Vec3, p2: Vec3, radius: float) -> None: ...
    @property
    def p1(self) -> Vec3: ...
    @property
    def p2(self) -> Vec3: ...
    @property
    def radius(self) -> float: ...
    @property
    def length(self) -> float: ...
    def point_dist_sq(self, point: Vec3) -> float: ...
    def contains_point(self, point: Vec3) -> bool: ...
    def bounding_sphere(self) -> tuple[Vec3, float]: ...
    @staticmethod
    def from_center_orientation(
        center: Vec3, orientation: Mat3, length: float, radius: float
    ) -> Cylinder: ...
    def scaled(self, factor: float) -> Cylinder: ...
    def translated(self, offset: Vec3) -> Cylinder: ...
    def rotated_mat(self, mat: Mat3) -> Cylinder: ...
    def rotated_quat(self, quat: Quat) -> Cylinder: ...
    def transformed(self, mat: Affine3) -> Cylinder: ...
    def broadphase(self) -> Sphere: ...
    def obb(self) -> Cuboid: ...
    def aabb(self) -> Cuboid: ...
    def abs_diff_eq(self, rhs: Cylinder, max_abs_diff: float) -> bool: ...
    def stretch(self, translation: Vec3) -> list[Shape]: ...
    def collides(self, other: Shape) -> bool: ...
    def __repr__(self) -> str: ...

class ConvexPolytope(Shape):
    __dataclass_fields__: _DataclassFields

    def __init__(
        self,
        planes: list[tuple[tuple[float, float, float], float]],
        vertices: list[tuple[float, float, float]],
    ) -> None: ...
    @staticmethod
    def with_obb(
        planes: list[tuple[tuple[float, float, float], float]],
        vertices: list[tuple[float, float, float]],
        obb: Cuboid,
    ) -> ConvexPolytope: ...
    @property
    def planes(self) -> list[tuple[tuple[float, float, float], float]]: ...
    @property
    def vertices(self) -> list[tuple[float, float, float]]: ...
    @property
    def obb(self) -> Cuboid: ...
    def scaled(self, factor: float) -> ConvexPolytope: ...
    def translated(self, offset: Vec3) -> ConvexPolytope: ...
    def rotated_mat(self, mat: Mat3) -> ConvexPolytope: ...
    def rotated_quat(self, quat: Quat) -> ConvexPolytope: ...
    def transformed(self, mat: Affine3) -> ConvexPolytope: ...
    def broadphase(self) -> Sphere: ...
    def aabb(self) -> Cuboid: ...
    def abs_diff_eq(self, rhs: ConvexPolytope, max_abs_diff: float) -> bool: ...
    def stretch(self, translation: Vec3) -> list[Shape]: ...
    def collides(self, other: Shape) -> bool: ...
    def __repr__(self) -> str: ...

class ConvexPolygon(Shape):
    __dataclass_fields__: _DataclassFields

    def __init__(
        self,
        center: Vec3,
        normal: Vec3,
        vertices_2d: list[tuple[float, float]],
    ) -> None: ...
    @staticmethod
    def with_axes(
        center: Vec3,
        normal: Vec3,
        u_axis: Vec3,
        v_axis: Vec3,
        vertices_2d: list[tuple[float, float]],
    ) -> ConvexPolygon: ...
    @property
    def center(self) -> Vec3: ...
    @property
    def normal(self) -> Vec3: ...
    @property
    def u_axis(self) -> Vec3: ...
    @property
    def v_axis(self) -> Vec3: ...
    @property
    def vertices_2d(self) -> list[tuple[float, float]]: ...
    def scaled(self, factor: float) -> ConvexPolygon: ...
    def translated(self, offset: Vec3) -> ConvexPolygon: ...
    def rotated_mat(self, mat: Mat3) -> ConvexPolygon: ...
    def rotated_quat(self, quat: Quat) -> ConvexPolygon: ...
    def transformed(self, mat: Affine3) -> ConvexPolygon: ...
    def broadphase(self) -> Sphere: ...
    def obb(self) -> Cuboid: ...
    def aabb(self) -> Cuboid: ...
    def abs_diff_eq(self, rhs: ConvexPolygon, max_abs_diff: float) -> bool: ...
    def stretch(self, translation: Vec3) -> list[Shape]: ...
    def collides(self, other: Shape) -> bool: ...
    def __repr__(self) -> str: ...

class Line(Shape):
    __dataclass_fields__: _DataclassFields

    def __init__(self, origin: Vec3, dir: Vec3) -> None: ...
    @staticmethod
    def from_points(a: Vec3, b: Vec3) -> Line: ...
    @property
    def origin(self) -> Vec3: ...
    @property
    def dir(self) -> Vec3: ...
    def scaled(self, factor: float) -> Line: ...
    def translated(self, offset: Vec3) -> Line: ...
    def rotated_mat(self, mat: Mat3) -> Line: ...
    def rotated_quat(self, quat: Quat) -> Line: ...
    def transformed(self, mat: Affine3) -> Line: ...
    def abs_diff_eq(self, rhs: Line, max_abs_diff: float) -> bool: ...
    def stretch(self, translation: Vec3) -> list[Shape]: ...
    def collides(self, other: Shape) -> bool: ...
    def __repr__(self) -> str: ...

class Ray(Shape):
    __dataclass_fields__: _DataclassFields

    def __init__(self, origin: Vec3, dir: Vec3) -> None: ...
    @property
    def origin(self) -> Vec3: ...
    @property
    def dir(self) -> Vec3: ...
    def scaled(self, factor: float) -> Ray: ...
    def translated(self, offset: Vec3) -> Ray: ...
    def rotated_mat(self, mat: Mat3) -> Ray: ...
    def rotated_quat(self, quat: Quat) -> Ray: ...
    def transformed(self, mat: Affine3) -> Ray: ...
    def abs_diff_eq(self, rhs: Ray, max_abs_diff: float) -> bool: ...
    def stretch(self, translation: Vec3) -> list[Shape]: ...
    def collides(self, other: Shape) -> bool: ...
    def __repr__(self) -> str: ...

class LineSegment(Shape):
    __dataclass_fields__: _DataclassFields

    def __init__(self, p1: Vec3, p2: Vec3) -> None: ...
    @property
    def p1(self) -> Vec3: ...
    @property
    def p2(self) -> Vec3: ...
    def bounding_sphere(self) -> tuple[Vec3, float]: ...
    def scaled(self, factor: float) -> LineSegment: ...
    def translated(self, offset: Vec3) -> LineSegment: ...
    def rotated_mat(self, mat: Mat3) -> LineSegment: ...
    def rotated_quat(self, quat: Quat) -> LineSegment: ...
    def transformed(self, mat: Affine3) -> LineSegment: ...
    def broadphase(self) -> Sphere: ...
    def obb(self) -> Cuboid: ...
    def aabb(self) -> Cuboid: ...
    def abs_diff_eq(self, rhs: LineSegment, max_abs_diff: float) -> bool: ...
    def stretch(self, translation: Vec3) -> list[Shape]: ...
    def collides(self, other: Shape) -> bool: ...
    def __repr__(self) -> str: ...

class Plane(Shape):
    __dataclass_fields__: _DataclassFields

    def __init__(self, normal: Vec3, d: float) -> None: ...
    @staticmethod
    def from_point_normal(point: Vec3, normal: Vec3) -> Plane: ...
    @property
    def normal(self) -> Vec3: ...
    @property
    def d(self) -> float: ...
    def scaled(self, factor: float) -> Plane: ...
    def translated(self, offset: Vec3) -> Plane: ...
    def rotated_mat(self, mat: Mat3) -> Plane: ...
    def rotated_quat(self, quat: Quat) -> Plane: ...
    def transformed(self, mat: Affine3) -> Plane: ...
    def abs_diff_eq(self, rhs: Plane, max_abs_diff: float) -> bool: ...
    def stretch(self, translation: Vec3) -> list[Shape]: ...
    def collides(self, other: Shape) -> bool: ...
    def __repr__(self) -> str: ...

class Pointcloud(Shape):
    __dataclass_fields__: _DataclassFields

    def __init__(
        self,
        points: list[tuple[float, float, float]],
        r_range: tuple[float, float],
        point_radius: float,
    ) -> None: ...
    def scaled(self, factor: float) -> Pointcloud: ...
    def translated(self, offset: Vec3) -> Pointcloud: ...
    def rotated_mat(self, mat: Mat3) -> Pointcloud: ...
    def rotated_quat(self, quat: Quat) -> Pointcloud: ...
    def transformed(self, mat: Affine3) -> Pointcloud: ...
    def broadphase(self) -> Sphere: ...
    def obb(self) -> Cuboid: ...
    def aabb(self) -> Cuboid: ...
    def abs_diff_eq(self, rhs: Pointcloud, max_abs_diff: float) -> bool: ...
    def collides(self, other: Shape) -> bool: ...
    @staticmethod
    def from_numpy(
        points: npt.ArrayLike, point_radius: float = 0.033
    ) -> Pointcloud: ...
    @staticmethod
    def from_list(
        points: list[tuple[float, float, float]], point_radius: float = 0.033
    ) -> Pointcloud: ...
    def __repr__(self) -> str: ...

class SphereCollection:
    __dataclass_fields__: _DataclassFields

    def __init__(self) -> None: ...
    @staticmethod
    def with_capacity(cap: int) -> SphereCollection: ...
    @staticmethod
    def from_slice(spheres: list[Sphere]) -> SphereCollection: ...
    def is_empty(self) -> bool: ...
    def push(self, sphere: Sphere) -> None: ...
    def get(self, index: int) -> Sphere: ...
    def clear(self) -> None: ...
    def any_collides_sphere(self, sphere: Sphere) -> bool: ...
    def abs_diff_eq(self, rhs: SphereCollection, max_abs_diff: float) -> bool: ...
    def __len__(self) -> int: ...
    def __repr__(self) -> str: ...

class Collider:
    __dataclass_fields__: _DataclassFields

    def __init__(self) -> None: ...
    def add(self, shape: Shape) -> None: ...
    def collides(self, shape: Shape) -> bool: ...
    def collides_other(self, other: Collider) -> bool: ...
    def include(self, other: Collider) -> None: ...
    def refine_bounding(self) -> None: ...
    def mask(self) -> int: ...
    def capsules(self) -> list[Capsule]: ...
    def cuboids(self) -> list[Cuboid]: ...
    def cylinders(self) -> list[Cylinder]: ...
    def planes(self) -> list[Plane]: ...
    def try_stretch_d(self, translation: Vec3) -> Collider | None: ...
    def polygons(self) -> list[ConvexPolygon]: ...
    def polytopes(self) -> list[ConvexPolytope]: ...
    def lines(self) -> list[Line]: ...
    def rays(self) -> list[Ray]: ...
    def segments(self) -> list[LineSegment]: ...
    def pointclouds(self) -> list[Pointcloud]: ...
    def spheres(self) -> SphereCollection: ...
    def scaled(self, factor: float) -> Collider: ...
    def translated(self, offset: Vec3) -> Collider: ...
    def rotated_mat(self, mat: Mat3) -> Collider: ...
    def rotated_quat(self, quat: Quat) -> Collider: ...
    def transformed(self, mat: Affine3) -> Collider: ...
    def broadphase(self) -> Sphere: ...
    def obb(self) -> Cuboid: ...
    def aabb(self) -> Cuboid: ...
    def __repr__(self) -> str: ...

Quaternion = Quat
Rotation3d = Mat3
Translation3d = Vec3
Transform3d = Affine3
Box3d = Cuboid
Sphere3d = Sphere
Cylinder3d = Cylinder
ObstacleUnion = Collider
PointCloud = Pointcloud
