manimgeo.math.vectors 源代码

from .base import close, array2float
from logging import getLogger
from typing import Tuple
import numpy as np

logger = getLogger(__name__)

[文档] @array2float def unit_direction_vector(start: np.ndarray, end: np.ndarray) -> np.ndarray: """ 计算单位方向向量 Returns: `np.ndarray`, 单位方向向量 """ start_float = start.astype(float) end_float = end.astype(float) direction_vector = end_float - start_float norm = np.linalg.norm(direction_vector) if close(float(norm), 0): logger.warning("start 与 end 过于接近或差为 0") raise ValueError("start 与 end 过于接近或差为 0") return direction_vector / norm
[文档] @array2float def get_two_vector_from_normal(normal: np.ndarray) -> Tuple[np.ndarray, np.ndarray]: """ 从法向量生成两个正交向量,三个向量互相正交且生成向量长度为 1 向量选取的方向将尽可能保证数值稳定,v1, v2, normal 构成右手系 """ norm_val = np.linalg.norm(normal) if norm_val == 0: logger.warning("法向量不能是零向量") raise ValueError("法向量不能是零向量") # 确保法向量是单位向量 unit_normal = normal / norm_val # 选择一个健壮的参考向量 # 选择参考向量的标准,与法向量的分量比较,选择最小的分量对应的轴 abs_n = np.abs(unit_normal) if abs_n[0] <= abs_n[1] and abs_n[0] <= abs_n[2]: reference = np.array([1.0, 0.0, 0.0]) elif abs_n[1] <= abs_n[0] and abs_n[1] <= abs_n[2]: reference = np.array([0.0, 1.0, 0.0]) else: reference = np.array([0.0, 0.0, 1.0]) # 生成第一个正交向量 v1 = np.cross(reference, unit_normal) v1 = v1 / np.linalg.norm(v1) # 生成第二个正交向量 v2 = np.cross(unit_normal, v1) v2 = v2 / np.linalg.norm(v2) return v1, v2