【学Rust写CAD】17 通用2D仿射变换矩阵结构体(matrix/generic.rs)

发布于:2025-04-03 ⋅ 阅读:(35) ⋅ 点赞:(0)

源代码

// matrix.rs
use std::ops::{Add, Mul};

use std::ops::{Add, Mul};

/// 通用2D仿射变换矩阵(元素仅需Copy)
#[derive(Clone, Copy, Debug, PartialEq)]
pub struct Matrix<X, Y, Xx, Xy, Yx, Yy> {
    pub x: X, pub y: Y,
    pub xx: Xx, pub xy: Xy,
    pub yx: Yx, pub yy: Yy,
}

impl<X, Y, Xx, Xy, Yx, Yy> Matrix<X, Y, Xx, Xy, Yx, Yy> {
    /// 通用二元运算接口
    #[inline]
    fn binary_op<A, B, C, D, O>(a: A, b: B, c: C, d: D) -> O
    where
        O: From<(A, B, C, D)>
    {
        O::from((a, b, c, d))
    }
}

/// 线性组合运算转换器
pub struct LinearCombination<A, B, C, D>(pub A, pub B, pub C, pub D);

impl<A, B, C, D> From<(A, B, C, D)> for LinearCombination<A, B, C, D> {
    fn from(t: (A, B, C, D)) -> Self {
        LinearCombination(t.0, t.1, t.2, t.3)
    }
}

impl<A, B, C, D, AB, CD> From<LinearCombination<A, B, C, D>> for <AB as Add<CD>>::Output
where
    A: Mul<B, Output = AB>,
    C: Mul<D, Output = CD>,
    AB: Add<CD>
{
    fn from(lc: LinearCombination<A, B, C, D>) -> Self {
        lc.0 * lc.1 + lc.2 * lc.3
    }
}

impl<
    X1, Y1, Xx1, Xy1, Yx1, Yy1,
    X2, Y2, Xx2, Xy2, Yx2, Yy2,
> Mul<Matrix<X2, Y2, Xx2, Xy2, Yx2, Yy2>> 
    for Matrix<X1, Y1, Xx1, Xy1, Yx1, Yy1>
where
    // 基础约束(仅Copy)
    X1: Copy, Y1: Copy, 
    Xx1: Copy, Xy1: Copy, Yx1: Copy, Yy1: Copy,
    X2: Copy, Y2: Copy, 
    Xx2: Copy, Xy2: Copy, Yx2: Copy, Yy2: Copy,

    // 平移运算约束(不限制Output类型)
    Xx2: Mul<X1>,
    Xy2: Mul<Y1>,
    Yx2: Mul<X1>,
    Yy2: Mul<Y1>,

    // 线性变换约束(不限制Output类型)
    Xx1: Mul<Xx2>,
    Xx1: Mul<Yx2>,
    Xy1: Mul<Xy2>,
    Xy1: Mul<Yy2>,
    Yx1: Mul<Xx2>,
    Yx1: Mul<Yx2>,
    Yy1: Mul<Xy2>,
    Yy1: Mul<Yy2>,

    // 加法约束(自动推导)
    <Xx1 as Mul<Xx2>>::Output: Add<<Xy1 as Mul<Yx2>>::Output>,
    <Xx1 as Mul<Xy2>>::Output: Add<<Xy1 as Mul<Yy2>>::Output>,
    <Yx1 as Mul<Xx2>>::Output: Add<<Yy1 as Mul<Yx2>>::Output>,
    <Yx1 as Mul<Xy2>>::Output: Add<<Yy1 as Mul<Yy2>>::Output>,
{
    type Output = Matrix<
        <X1 as Add<<Xx2 as Mul<X1>>::Output>>::Output,  // X
        <Y1 as Add<<Yy2 as Mul<Y1>>::Output>>::Output,  // Y
        <<Xx1 as Mul<Xx2>>::Output as Add<<Xy1 as Mul<Yx2>>::Output>>::Output, // Xx
        <<Xx1 as Mul<Xy2>>::Output as Add<<Xy1 as Mul<Yy2>>::Output>>::Output, // Xy
        <<Yx1 as Mul<Xx2>>::Output as Add<<Yy1 as Mul<Yx2>>::Output>>::Output, // Yx
        <<Yx1 as Mul<Xy2>>::Output as Add<<Yy1 as Mul<Yy2>>::Output>>::Output  // Yy
    >;

    fn mul(self, rhs: Matrix<X2, Y2, Xx2, Xy2, Yx2, Yy2>) -> Self::Output {
        Matrix {
            // 平移计算(完全自由类型推导)
            x: self.x + rhs.x * self.xx + rhs.y * self.yx,
            y: self.y + rhs.x * self.xy + rhs.y * self.yy,
            
            // 通过转换器计算线性变换
            xx: Self::binary_op::<_, _, _, _, _>(
                self.xx, rhs.xx, self.xy, rhs.yx
            ),
            xy: Self::binary_op::<_, _, _, _, _>(
                self.xx, rhs.xy, self.xy, rhs.yy
            ),
            yx: Self::binary_op::<_, _, _, _, _>(
                self.yx, rhs.xx, self.yy, rhs.yx
            ),
            yy: Self::binary_op::<_, _, _, _, _>(
                self.yx, rhs.xy, self.yy, rhs.yy
            ),
        }
    }
}

代码分析

  1. 矩阵布局
    矩阵采用以下布局:

[ 1 x y 0 x x x y 0 y x y y ] \begin{bmatrix}1 & x & y \\ 0 & xx & xy \\ 0 & yx & yy \end{bmatrix} 100xxxyxyxyyy

这种布局的特点是:

  • 平移分量 x 和 y 位于第一行

  • 线性变换部分位于右下2x2子矩阵

  • 左下保持 [0, 0] 以保证是仿射变换

  1. 核心功能
    矩阵乘法
    两个矩阵相乘的结果计算如下:

[ 1 x 1 y 1 0 x x 1 x y 1 0 y x 1 y y 1 ] ∗ [ 1 x 2 y 2 0 x x 2 x y 2 0 y x 2 y y 2 ] = [ 1 x 1 + x 2 ∗ x x 1 + y 2 ∗ y x 1 y 1 + x 2 ∗ x y 1 + y 2 ∗ y y 1 0 x x 1 ∗ x x 2 + x y 1 ∗ y x 2 x x 1 ∗ x y 2 + x y 1 ∗ y y 2 0 y x 1 ∗ x x 2 + y y 1 ∗ y x 2 y x 1 ∗ x y 2 + y y 1 ∗ y y 2 ] \begin{bmatrix}1 & x1 & y1 \\ 0 & xx1 & xy1 \\ 0 & yx1 & yy1 \end{bmatrix} * \begin{bmatrix}1 & x2 & y2 \\ 0 & xx2 & xy2 \\ 0 & yx2 & yy2 \end{bmatrix}= \begin{bmatrix}1 & x1+x2*xx1+y2*yx1 & y1+x2*xy1+y2*yy1 \\ 0 & xx1*xx2+xy1*yx2 & xx1*xy2+xy1*yy2 \\ 0 & yx1*xx2+yy1*yx2 & yx1*xy2+yy1*yy2 \end{bmatrix} 100x1xx1yx1y1xy1yy1 100x2xx2yx2y2xy2yy2 = 100x1+x2xx1+y2yx1xx1xx2+xy1yx2yx1xx2+yy1yx2y1+x2xy1+y2yy1xx1xy2+xy1yy2yx1xy2+yy1yy2

实现特点
  1. 泛型设计:支持不同类型的矩阵元素

  2. trait约束:确保类型安全

  • 乘法约束:Mul trait

  • 加法约束:Add trait

  • 克隆约束:Clone trait

  1. 精确控制:可以控制每种运算的输出类型

  2. 性能优化:使用#[inline]提示编译器优化

使用场景

这种矩阵适用于:

  • 2D图形变换(平移、旋转、缩放、倾斜)

  • 需要高精度计算的场景

  • 需要组合多个变换的场景(通过矩阵乘法)

优势
  1. 灵活性:支持不同的数值类型(f32, f64, 定点数等)

  2. 类型安全:编译时检查所有操作的有效性

  3. 明确语义:矩阵布局更直观反映变换参数

  4. 可组合性:通过矩阵乘法组合多个变换

这个实现提供了强大而类型安全的2D仿射变换操作基础,适合用于图形引擎、物理模拟等需要精确数学计算的领域。


网站公告

今日签到

点亮在社区的每一天
去签到