6 齐次坐标模块(homogen.rs)

embedded/2025/2/1 19:05:06/

homogen.rs代码定义了一个名为 HomogeneousVector 的结构体,它是用于表示三维空间中的齐次向量。齐次向量常用于计算机图形学和几何学中,特别是在处理投影和变换时。下面是对这段代码的详细解释和一些关键的代码片段分析:

一、homogen.rs文件源码

rust">use crate::point::{Point2D, Point3D};
use crate::vector::{Vector2D, Vector3D};use crate::num::{One, Zero};#[cfg(feature = "bytemuck")]
use bytemuck::{Pod, Zeroable};
use core::cmp::{Eq, PartialEq};
use core::fmt;
use core::hash::Hash;
use core::marker::PhantomData;
use core::ops::Div;
#[cfg(feature = "serde")]
use serde;/// Homogeneous vector in 3D space.
#[repr(C)]
pub struct HomogeneousVector<T, U> {pub x: T,pub y: T,pub z: T,pub w: T,#[doc(hidden)]pub _unit: PhantomData<U>,
}impl<T: Copy, U> Copy for HomogeneousVector<T, U> {}impl<T: Clone, U> Clone for HomogeneousVector<T, U> {fn clone(&self) -> Self {HomogeneousVector {x: self.x.clone(),y: self.y.clone(),z: self.z.clone(),w: self.w.clone(),_unit: PhantomData,}}
}#[cfg(feature = "serde")]
impl<'de, T, U> serde::Deserialize<'de> for HomogeneousVector<T, U>
whereT: serde::Deserialize<'de>,
{fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>whereD: serde::Deserializer<'de>,{let (x, y, z, w) = serde::Deserialize::deserialize(deserializer)?;Ok(HomogeneousVector {x,y,z,w,_unit: PhantomData,})}
}#[cfg(feature = "serde")]
impl<T, U> serde::Serialize for HomogeneousVector<T, U>
whereT: serde::Serialize,
{fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>whereS: serde::Serializer,{(&self.x, &self.y, &self.z, &self.w).serialize(serializer)}
}#[cfg(feature = "arbitrary")]
impl<'a, T, U> arbitrary::Arbitrary<'a> for HomogeneousVector<T, U>
whereT: arbitrary::Arbitrary<'a>,
{fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> {let (x, y, z, w) = arbitrary::Arbitrary::arbitrary(u)?;Ok(HomogeneousVector {x,y,z,w,_unit: PhantomData,})}
}#[cfg(feature = "bytemuck")]
unsafe impl<T: Zeroable, U> Zeroable for HomogeneousVector<T, U> {}#[cfg(feature = "bytemuck")]
unsafe impl<T: Pod, U: 'static> Pod for HomogeneousVector<T, U> {}impl<T, U> Eq for HomogeneousVector<T, U> where T: Eq {}impl<T, U> PartialEq for HomogeneousVector<T, U>
whereT: PartialEq,
{fn eq(&self, other: &Self) -> bool {self.x == other.x && self.y == other.y && self.z == other.z && self.w == other.w}
}impl<T, U> Hash for HomogeneousVector<T, U>
whereT: Hash,
{fn hash<H: core::hash::Hasher>(&self, h: &mut H) {self.x.hash(h);self.y.hash(h);self.z.hash(h);self.w.hash(h);}
}impl<T, U> HomogeneousVector<T, U> {/// Constructor taking scalar values directly.#[inline]pub const fn new(x: T, y: T, z: T, w: T) -> Self {HomogeneousVector {x,y,z,w,_unit: PhantomData,}}
}impl<T: Copy + Div<T, Output = T> + Zero + PartialOrd, U> HomogeneousVector<T, U> {/// Convert into Cartesian 2D point.////// Returns `None` if the point is on or behind the W=0 hemisphere.#[inline]pub fn to_point2d(self) -> Option<Point2D<T, U>> {if self.w > T::zero() {Some(Point2D::new(self.x / self.w, self.y / self.w))} else {None}}/// Convert into Cartesian 3D point.////// Returns `None` if the point is on or behind the W=0 hemisphere.#[inline]pub fn to_point3d(self) -> Option<Point3D<T, U>> {if self.w > T::zero() {Some(Point3D::new(self.x / self.w,self.y / self.w,self.z / self.w,))} else {None}}
}impl<T: Zero, U> From<Vector2D<T, U>> for HomogeneousVector<T, U> {#[inline]fn from(v: Vector2D<T, U>) -> Self {HomogeneousVector::new(v.x, v.y, T::zero(), T::zero())}
}impl<T: Zero, U> From<Vector3D<T, U>> for HomogeneousVector<T, U> {#[inline]fn from(v: Vector3D<T, U>) -> Self {HomogeneousVector::new(v.x, v.y, v.z, T::zero())}
}impl<T: Zero + One, U> From<Point2D<T, U>> for HomogeneousVector<T, U> {#[inline]fn from(p: Point2D<T, U>) -> Self {HomogeneousVector::new(p.x, p.y, T::zero(), T::one())}
}impl<T: One, U> From<Point3D<T, U>> for HomogeneousVector<T, U> {#[inline]fn from(p: Point3D<T, U>) -> Self {HomogeneousVector::new(p.x, p.y, p.z, T::one())}
}impl<T: fmt::Debug, U> fmt::Debug for HomogeneousVector<T, U> {fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {f.debug_tuple("").field(&self.x).field(&self.y).field(&self.z).field(&self.w).finish()}
}#[cfg(test)]
mod homogeneous {use super::HomogeneousVector;use crate::default::{Point2D, Point3D};#[test]fn roundtrip() {assert_eq!(Some(Point2D::new(1.0, 2.0)),HomogeneousVector::from(Point2D::new(1.0, 2.0)).to_point2d());assert_eq!(Some(Point3D::new(1.0, -2.0, 0.1)),HomogeneousVector::from(Point3D::new(1.0, -2.0, 0.1)).to_point3d());}#[test]fn negative() {assert_eq!(None,HomogeneousVector::<f32, ()>::new(1.0, 2.0, 3.0, 0.0).to_point2d());assert_eq!(None,HomogeneousVector::<f32, ()>::new(1.0, -2.0, -3.0, -2.0).to_point3d());}
}

二、结构体定义

rust">#[repr(C)]
pub struct HomogeneousVector<T, U> {pub x: T,pub y: T,pub z: T,pub w: T,#[doc(hidden)]pub _unit: PhantomData<U>,
}
  • #[repr©] 属性确保了结构体在内存中的布局是连续的,这对于与C语言接口或者特定的内存对齐需求很有用。
  • T 是向量的坐标类型,它可以是任何数值类型,比如 f32 或 f64。
  • U 是一个类型参数,通过 PhantomData 被引入,通常用于表示一些与结构体相关的额外信息,比如单位或维度,但不占用实际的内存空间。
  • _unit 字段被标记为文档隐藏,意味着在生成的文档中不会显示这个字段。

三、实现特性

  • Copy 和 Clone:由于 HomogeneousVector 持有的是泛型 T,只有当 T 实现 Copy 或 Clone 时,HomogeneousVector 才能相应地实现 Copy 或 Clone。
  • serde 序列化/反序列化:当启用了 serde 功能时,HomogeneousVector 可以被序列化和反序列化,前提是它的类型参数 T 也支持 serde。
  • From 实现:提供了从 Vector2D、Vector3D、Point2D 和 Point3D 到 HomogeneousVector 的转换方法。这些转换方法将源数据转换为齐次坐标形式,例如,二维点转换为齐次坐标时,w 分量被设置为 1,而 z 分量(对于2D点来说不存在)被设置为 0。

四、示例代码片段分析

从 Vector2D 转换到 HomogeneousVector

rust">impl<T: Zero, U> From<Vector2D<T, U>> for HomogeneousVector<T, U> {#[inline]fn from(v: Vector2D<T, U>) -> Self {HomogeneousVector::new(v.x, v.y, T::zero(), T::zero())}
}

这里假设 Vector2D 是一个二维向量结构体,T::zero() 返回类型 T 的零值。此实现将二维向量的 x 和 y 分量转换为齐次向量的前两个分量,并将 z 和 w 分量都设置为零。

调试输出

rust">impl<T: fmt::Debug, U> fmt::Debug for HomogeneousVector<T, U> {fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {f.debug_tuple("").field(&self.x).field(&self.y).field(&self.z).field(&self.w).finish()}
}

当 T 实现了 fmt::Debug 时,HomogeneousVector 也可以被格式化输出,这通常用于调试目的。

五、总结

homogen.rs代码展示了如何在 Rust 中定义和实现一个泛型结构体,以及如何利用 Rust 的类型系统和特性(如 PhantomData、条件编译 #[cfg()]、特性标志等)来增强代码的功能性和灵活性。HomogeneousVector 的设计使其能够灵活地与不同的数值类型和额外的类型信息一起工作,同时支持序列化和从其他几何类型转换。


http://www.ppmy.cn/embedded/158710.html

相关文章

ICSE‘25 LLM Assistance for Memory Safety

不知道从什么时候开始&#xff0c;各大技术社区&#xff0c;技术群聊流行着 “用Rust重写!” &#xff0c;放一张图(笑死… 这不, 随着大模型技术的流行&#xff0c;大家都在探索如何让大模型自动完成仓库级别(全程序)的代码重构&#xff0c;代码变换&#xff08;Refactor&…

Python之百度财务数据可视化分析

Python之百度财务数据可视化分析 &#x1f31f; 嗨&#xff0c;我是LucianaiB&#xff01; &#x1f30d; 总有人间一两风&#xff0c;填我十万八千梦。 &#x1f680; 路漫漫其修远兮&#xff0c;吾将上下而求索。 目录 设计题目设计目的设计任务描述设计要求输入和输出要求…

[Linux]el8安全配置faillock:登录失败达阈值自动锁定账户配置

前言 本篇文章的配置仅使用于el8版本的Linux&#xff0c;目前已在centos8、BCLinux8上验证成功&#xff0c;其他版本系统是否可行还得考查。 el8中管理用户登录失败锁定账户所用的模块是faillock.so&#xff0c;如果想要将配置应用与其他版本的Linux&#xff0c;建议确认Linux…

2025蓝桥杯JAVA编程题练习Day1

1.刑侦科推理试题 题目描述 有以下10道单选题&#xff0c;编程求这10道题的答案。 这道题的答案是&#xff1a; A. A B. B C. C D. D 第5题的答案是&#xff1a; A. C B. D C. A D. B 以下选项中哪一题的答案与其他三项不同&#xff1a; A. 第3题 B. 第6题 C. 第2题 D.…

Python3 【装饰器】避坑指南:常见错误解析

Python3 【装饰器】避坑指南&#xff1a;常见错误解析 在编写或使用 Python 装饰器时&#xff0c;可能会遇到一些典型的错误。以下是 15 种常见错误&#xff0c;分析出错原因并提供纠正方法&#xff0c;同时通过代码示例进行演示和说明。 1. 忘记调用被装饰的函数 错误原因&a…

开源的Text-to-SQL工具WrenAI

WrenAI是一个开源的Text-to-SQL工具&#xff0c;旨在通过自然语言交互界面&#xff0c;帮助用户更便捷地查询数据库。以下是对WrenAI的详细介绍&#xff1a; 一、主要功能 自然语言交互&#xff1a;用户可以通过对话方式提出问题&#xff0c;WrenAI能够理解和解析复杂的查询需…

开源音乐管理软件Melody

本文软件由网友 heqiusheng 推荐。不过好像已经是一年前了 &#x1f602; 简介 什么是 Melody &#xff1f; Melody 是你的音乐精灵&#xff0c;旨在帮助你更好地管理音乐。目前的主要能力是帮助你将喜欢的歌曲或者音频上传到音乐平台的云盘。 主要功能包括&#xff1a; 歌曲…

如何用函数去计算x年x月x日是(C#)

如何用函数去计算x年x月x日是? 由于现在人工智能的普及,我们往往会用计算机去算,或者去记录事情 1.计算某一年某一个月有多少天 2.计算某年某月某日是周几 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threadin…