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

源代码

// 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) -> OwhereO: 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
whereA: 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仿射变换操作基础,适合用于图形引擎、物理模拟等需要精确数学计算的领域。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/75244.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Spring Boot @RequestParam 解析参数时的常见问题及解决方案

1&#xff0c;遇到的问题&#xff1a;将后端接口写完后我想通过PostMan进行简单的测试一下&#xff0c;一不小心就遇到了这样的情况&#xff1a; org.springframework.web.bind.MissingServletRequestParameterException: Required Integer parameter contractId is not prese…

Golang中间件的原理与实现

一. 什么是 Middleware&#xff1f; 中间件&#xff08;Middleware&#xff09; 是一种 高阶函数&#xff0c;它接受一个函数作为输入&#xff0c;并返回一个经过增强的函数。它的核心思想是通过函数的递归嵌套&#xff0c;动态地为函数添加功能。在 Golang 中&#xff0c;中间…

算法设计学习3

实验目的及要求&#xff1a; 1.加强对结构体的应用。 2.熟悉字符计数排序。 实验设备环境&#xff1a; 1.微型计算机 2.DEV C(或其他编译软件) 实验步骤&#xff1a; 任务&#xff1a;要求使用自定义函数来实现 输入一段文本&#xff0c;统计每个字符出现的次数&#xff0c;按…

Vue2和3的vue-router:生命周期、懒加载

Vue2 vue-router 在 Vue 2 中使用 vue-router 可以方便地管理单页面应用&#xff08;SPA&#xff09;中的路由。理解 vue-router 的生命周期和懒加载机制对于构建高效的 Vue 应用至关重要。以下是一些关键点和示例代码来帮助你理解这些概念。 Vue Router 的生命周期 vue-rou…

【408--考研复习笔记】计算机网络----知识点速览

目录 一、计算机网络体系结构 1.计算机网络的定义与功能&#xff1a; 2.网络体系结构相关概念&#xff1a; 3.OSI 七层模型与 TCP/IP 模型&#xff1a; 4.通信方式与交换技术&#xff1a; 电路交换 报文交换 分组交换 5.端到端通信和点到点通信&#xff1a; 6.计算机…

MySQL-- 多表查询的分类,SQL92与SQL99,7种JOIN的实现,SQL99语法的新特性

目录 一&#xff0c;多表查询的分类 角度1&#xff1a;等值连接 vs 非等值连接 角度2&#xff1a;自连接 vs 非自连接 角度3&#xff1a;内连接 vs 外连接 二&#xff0c;SQL92语法实现内连接&#xff1a;见上&#xff0c;略SQL92语法实现外连接&#xff1a;使用 -…

时间轮算法:原理、演进与应用实践指南

目录 1. 时间轮算法基础 1.1 什么是时间轮算法&#xff1f; 1.2 核心组成部分 2. 基本时间轮的实现机制 2.1 时间轮的构成要素 2.2 工作原理详解 3. 基本时间轮的局限性 3.1 时间范围限制问题 3.2 简单解决方案及其缺陷 4. 时间轮算法的演进 4.1 Round机制&#xff…

Unity 常见报错 定位和查找方法

1.控制台 直接看报错信息 2.打log 例子&#xff1a; for(int i 0;i < 8;i) {Debug.Log(i);//这是打的log,看看到底i是几的时候出问题gameObject.name strs[i];} 3.断点调试 &#xff08;1&#xff09;在你想打断点的行&#xff0c;左边空白处点击可以打断点&#xff…

第十八章:Python实战专题:北京市水资源数据可视化与图书馆书籍管理应用开发

今天我要和大家分享两个非常有趣的Python实战项目&#xff1a;一个是北京市2001-2017年水资源数据的可视化分析&#xff0c;另一个是图书馆书籍管理应用程序的开发。这两个项目都使用了Python的主流库&#xff0c;比如Pandas、Matplotlib和Tkinter&#xff0c;非常适合初学者学…

音视频基础(音视频的录制和播放原理)

文章目录 一、录制原理**1. 音视频数据解析****2. 音频处理流程****3. 视频处理流程****4. 同步控制****5. 关键技术点****总结** 二、播放原理**1. 音视频数据解析****2. 音频处理流程****3. 视频处理流程****4. 同步控制****5. 关键技术点****总结** 一、录制原理 这张图展示…

Nginx多域名HTTPS配置全攻略:从证书生成到客户端安装

一、业务背景 在现代Web开发中&#xff0c;HTTPS已成为保障数据传输安全的标准协议。特别是对于地图类API服务&#xff08;如高德地图&#xff09;&#xff0c;往往需要同时支持多个子域名&#xff08;如webapi.amap.com、restapi.amap.com等&#xff09;的HTTPS访问。传统方式…

Redis原理:rename命令

RENAME key newkey 将一个key重命名为新key&#xff0c;如果key不存在&#xff0c;则会返回异常。如果newKey已经存在&#xff0c;则会被覆盖&#xff0c;其实newKey会被显示的删除&#xff0c;所以如果newKey是一个大key&#xff0c;则会引起延迟。 源码 void renameCommand…

k8s污点与容忍

k8s污点与容忍 k8s污点管理常用命令effect标记值查看污点添加污点删除污点 node污点与容忍污点容忍yaml示例容忍放大基于污点的驱逐驱逐时排除指定服务 设置master调度设置master尽量不调度允许master节点调度pod恢复Master Only状态将node标记为不可调度状态(节点警戒)设置nod…

(BFS)题解:P9425 [蓝桥杯 2023 国 B] AB 路线

题解&#xff1a;P9425 [蓝桥杯 2023 国 B] AB 路线 题目传送门 P9425 [蓝桥杯 2023 国 B] AB 路线 一、题目描述 给定一个NM的迷宫&#xff0c;每个格子标记为A或B。从左上角(1,1)出发&#xff0c;需要移动到右下角(N,M)。移动规则是&#xff1a;必须交替走K个A格子和K个B…

python-leetcode 62.搜索插入位置

题目&#xff1a; 给定一个排序数组和一个目标值&#xff0c;在数组中找到目标值&#xff0c;并返回其索引。如果目标值不存在于数组中&#xff0c;返回它将会被按顺序插入的位置 方法一&#xff1a;二分查找 假设题意是在排序数组中寻找是否存在一个目标值&#xff0c;则可以…

【计网速通】计算机网络核心知识点和高频考点——数据链路层(一)

数据链路层核心知识点&#xff08;一&#xff09; 一、数据链路层概述 1.1 基本概念 数据链路层位于OSI模型的第二层&#xff0c;介于物理层和网络层之间&#xff0c;主要负责在相邻节点之间传输和识别数据帧。 1.2 主要功能 帧同步&#xff1a;识别帧的开始和结束差错控制…

模型部署与调用

目录 部署 ollama下载 模型版本选择 ​编辑 对照表 控制台执行 调用 部署 大模型部署我使用的是Ollama&#xff0c;点击跳转 接下来我将在本地使用ollama就行模型部署的演示 ollama下载 模型版本选择 对照表 大家可以根据自己的显卡配置选择对应的模型版本 控制台执…

Rstudio如何使用Conda环境配置的R

前言 Rstudio作为一款流行的R语言集成开发环境&#xff08;IDE&#xff09;&#xff0c;为用户提供了便捷的编程体验。然而&#xff0c;不同项目可能需要不同版本的R&#xff0c;这就需要我们灵活切换R版本。除了在之前文章中提到的使用 Docker 部署不同版本的 R 的方法之外&am…

C++---RAII模式

一、RAII模式概述 1. 定义 RAII&#xff08;Resource Acquisition Is Initialization&#xff09;即资源获取即初始化&#xff0c;是C中用于管理资源生命周期的一种重要编程模式。其核心在于将资源的获取和释放操作与对象的生命周期紧密绑定。当对象被创建时&#xff0c;资源…

【功能开发】DSP F2837x 检测中断所有函数运行一次的时间

要查看 DSP F28377 的 CPU 在 50 微秒一次的中断内所有程序运行完总共占用了中断多长时间&#xff0c;可以采用硬件定时器测量和软件计时两种常见方法。 方法一&#xff1a;使用硬件定时器测量 原理 利用 DSP 内部的高精度硬件定时器&#xff0c;在中断开始时记录定时器的值…