【学Rust写CAD】14线性插值函数(加入color.rs)

lerp 函数源码

/// 颜色线性插值/// t 取值范围 0..256,0 表示完全使用当前颜色(self),256 表示完全使用目标颜色(end)#[inline]pub fn lerp(self, end: Color, t: u32) -> Color {let mask = 0xff00ff;// 提取目标颜色的蓝色和红色分量let brb = end.0 & 0xff00ff;// 提取目标颜色的alpha和绿色分量let bag = (end.0 >> 8) & 0xff00ff;// 提取当前颜色的蓝色和红色分量let arb = self.0 & 0xff00ff;// 提取当前颜色的alpha和绿色分量let aag = (self.0 >> 8) & 0xff00ff;// 计算分量差值let drb = brb.wrapping_sub(arb);let dag = bag.wrapping_sub(aag);// 应用插值系数let drb = drb.wrapping_mul(t) >> 8;let dag = dag.wrapping_mul(t) >> 8;// 计算最终分量值let rb = arb + drb;let ag = aag + dag;// 组合并返回结果颜色Color((rb & mask) | ((ag << 8) & !mask))}

颜色线性插值(Lerp)解释

这段代码实现了两个颜色之间的线性插值(linear interpolation),通常称为lerp。这是一种在两个值之间进行平滑过渡的技术,在这里用于颜色过渡。

工作原理
  1. 输入参数:
  • self: 起始颜色

  • end: 目标颜色

  • t: 插值系数,范围0-256(0=完全使用起始颜色,256=完全使用目标颜色)

  1. 颜色分量分离:
  • 将颜色值拆分为蓝色/红色分量和alpha/绿色分量

使用掩码0xff00ff来提取这些分量(因为颜色通常以ARGB格式存储)

  1. 差值计算:

计算目标颜色和起始颜色在各分量上的差值

  • 使用wrapping_sub处理可能的溢出
  1. 应用插值系数:
  • 将差值乘以插值系数t,然后右移8位(相当于除以256)

  • 这实现了按比例混合两个颜色

  1. 组合结果:
  • 将插值后的分量重新组合成最终颜色

  • 使用掩码确保各分量在正确的位置

为什么这样实现

这种实现方式有几个优点:

  • 使用位操作而不是浮点运算,效率更高

  • 同时处理两个颜色分量(蓝色/红色和alpha/绿色),减少操作次数

  • 使用包装算术(wrapping)避免溢出检查,提高性能

示例

如果起始颜色是红色(0xFF0000),目标颜色是蓝色(0x0000FF),当t=128时:

结果会是紫色(0x800080),正好在红色和蓝色中间

这种技术广泛应用于图形渲染、动画过渡和颜色渐变等场景。

测试代码

测试代码包括多种边界情况和典型场景的测试:

#[cfg(test)]
mod tests {use super::Color;#[test]fn test_lerp() {// 测试相同颜色插值let white = Color(0xFFFFFFFF);for i in 0..=256 {assert_eq!(white.lerp(white, i).0, 0xFFFFFFFF, "相同颜色插值失败,i={}", i);}// 测试从黑到白插值let black = Color(0xFF000000);let white = Color(0xFFFFFFFF);assert_eq!(black.lerp(white, 0).0, 0xFF000000, "t=0应返回起始颜色");assert_eq!(black.lerp(white, 256).0, 0xFFFFFFFF, "t=256应返回目标颜色");assert_eq!(black.lerp(white, 128).0, 0xFF7F7F7F, "中间值不正确");// 测试红色到蓝色插值let red = Color(0xFFFF0000);let blue = Color(0xFF0000FF);assert_eq!(red.lerp(blue, 0).0, 0xFFFF0000);assert_eq!(red.lerp(blue, 256).0, 0xFF0000FF);assert_eq!(red.lerp(blue, 128).0, 0xFF7F007F);// 测试透明度变化let opaque = Color(0xFF123456);let transparent = Color(0x00123456);assert_eq!(opaque.lerp(transparent, 128).0, 0x7F123456);// 测试边界情况let color1 = Color(0x12345678);let color2 = Color(0x87654321);assert_eq!(color1.lerp(color2, 0).0, color1.0);assert_eq!(color1.lerp(color2, 256).0, color2.0);// 测试所有分量同时变化let start = Color(0x00000000);let end = Color(0x01020304);assert_eq!(start.lerp(end, 64).0, 0x00404040); // 1/4 of end color}#[test]fn test_lerp_edge_cases() {// 测试t值超出范围的情况(虽然参数是u32,但实际只使用低9位)let c1 = Color(0x00000000);let c2 = Color(0xFFFFFFFF);assert_eq!(c1.lerp(c2, 257).0, c1.lerp(c2, 1).0); // 257 & 0xFF = 1assert_eq!(c1.lerp(c2, 512).0, c1.lerp(c2, 0).0); // 512 & 0xFF = 0// 测试颜色值溢出情况let low = Color(0x00000000);let high = Color(0xFFFFFFFF);assert_eq!(low.lerp(high, 255).0, 0xFFFEFEFE);}
}
测试说明
  1. 基本测试:
  • 相同颜色插值结果应该不变

  • 从黑到白插值的边界和中间值

  • 从红到蓝插值的典型场景

  1. 透明度测试:
  • 测试alpha通道的插值是否正确

3.边界测试:

  • 确保t=0和t=256时返回正确的颜色

  • 测试t值超出范围时的行为(虽然参数是u32,但实现只使用低9位)

  1. 分量测试:
  • 测试所有颜色分量同时变化的情况

  • 测试颜色值溢出的处理

  1. 特殊场景:
  • 测试包装算术(wrapping)的正确性

这些测试覆盖了正常使用场景和边界情况,可以验证lerp方法的正确性。

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

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

相关文章

函数:链式访问

链式访问是将函数的返回值当作回传值就是链式访问 这是原本的字符数回传代码 int main() {int len strlen("seig heil");printf("%d", len);return 0; } 运行结果&#xff1a; 这是链式访问的代码&#xff1a; int main() {printf("%d\n",s…

C++ map容器总结

map基本概念 简介&#xff1a; map中所有元素都是pair pair中第一个元素为key&#xff08;键值&#xff09;&#xff0c;起到索引作用&#xff0c;第二个元素为value&#xff08;实值&#xff09; 所有元素都会根据元素的键值自动排序 本质&#xff1a; map/multimap属于关…

23种设计模式-代理(Proxy)设计模式

代理设计模式 &#x1f6a9;什么是代理设计模式&#xff1f;&#x1f6a9;代理设计模式的特点&#x1f6a9;代理设计模式的结构&#x1f6a9;代理设计模式的优缺点&#x1f6a9;代理设计模式的Java实现&#x1f6a9;代码总结&#x1f6a9;总结 &#x1f6a9;什么是代理设计模式…

UE4学习笔记 FPS游戏制作29 更换武器时更换武器的图标

文章目录 制作物体图标UI添加获取武器图标的方法使用事件分发器&#xff0c;通知UI要换枪定义事件分发器调用事件分发器注册事件分发器 制作物体图标UI 在Fpp-UI上添加一个图片&#xff0c;改名为五weaponIcon&#xff0c;勾选SizeToContent,锚点放在右下角&#xff0c;对齐改…

Chrome 开发环境快速屏蔽 CORS 跨域限制!

Chrome 开发环境快速屏蔽 CORS 跨域限制【详细教程】 ❓ 为什么需要临时屏蔽 CORS&#xff1f; 在前后端开发过程中&#xff0c;我们经常会遇到 跨域请求被浏览器拦截 的问题。例如&#xff0c;你在 http://localhost:3000 调用 https://api.example.com 时&#xff0c;可能会…

【RAG综述系列】之 RAG 相关背景和基本原理

系列文章&#xff1a; 【RAG综述系列】之 RAG 相关背景和基本原理 【RAG综述系列】之 RAG 特点与挑战以及方法与评估 【RAG综述系列】之 RAG 先进方法与综合评估 【RAG综述系列】之 RAG 应用和未来方向 正文&#xff1a; 检索增强生成&#xff08;Retrieval-Augmented Gen…

德昂观点:如何看待MicroStrategy改名为Strategy?

2025年2月&#xff0c;纳斯达克上市公司MicroStrategy&#xff08;股票代码&#xff1a;MSTR&#xff09;宣布更名为“Strategy”&#xff0c;并同步启用全新品牌标识与橙色主视觉。这不仅是品牌形象的更新&#xff0c;更是公司战略方向的明确宣示。德昂作为MSTR中国区BI合作伙…

计算机视觉算法实战——手术导航:技术、应用与未来

✨个人主页欢迎您的访问 ✨期待您的三连 ✨ ✨个人主页欢迎您的访问 ✨期待您的三连 ✨ ✨个人主页欢迎您的访问 ✨期待您的三连✨ ​​​ ​​​​​​​​​ ​​ 1. 手术导航中的计算机视觉&#xff1a;领域介绍 计算机视觉在手术导航领域的应用代表了现代医学与人工智…

Java全栈面试宝典:内存模型与Spring设计模式深度解析

目录 一、JVM内存模型进阶篇 &#x1f525; 问题13&#xff1a;堆与栈的六大维度对比 内存结构对比图 核心差异对照表 &#x1f525; 问题14&#xff1a;三区联动内存模型解析 代码内存分配图解 三区协作流程图 二、Spring设计模式全景解析 &#x1f31f; Spring框架七…

FALL靶场通关攻略

1&#xff0c;下载好靶机后打开&#xff0c;通过kali扫描靶机ip和端口&#xff0c;得到靶机ip为192.168.50.144 2&#xff0c;扫描目录 3&#xff0c;访问靶机 4&#xff0c;访问扫描到的test.php,得到缺少GET请求参数的提示 5&#xff0c;使用FUZZ来扫出参数为file 6&#xff…

《C++11:bind绑定器与function包装器》

CSTL中提供了bind1绑定器&#xff0c;通常与函数对象一起使用。 函数对象是重载了operator&#xff08;&#xff09;函数的对象。 将二元函数对象operator&#xff08;&#xff09;的第一个参数绑定为固定的x来构造一元函数对象。返回绑定了第一个参数的函数对象。 将二元函数…

JS 防抖与节流

防抖 核心思想&#xff1a;延迟执行&#xff0c;只有在事件触发的频率降低到一定程度后才会执行&#xff0c;而且如果事件持续触发&#xff0c;之前地所有执行都会被取消。 有的操作是高频触发的&#xff0c;但是其实只需要一次触发。比如短时间内多次缩放页面resize&#xff0…

【C/C++算法】从浅到深学习--- 简单模拟算法(图文兼备 + 源码详解)

绪论&#xff1a;冲击蓝桥杯一起加油&#xff01;&#xff01; 每日激励&#xff1a;“不设限和自我肯定的心态&#xff1a;I can do all things。 — Stephen Curry” 绪论​&#xff1a; 本篇是一些简单的模拟算法&#xff0c;其中模拟的本质就是就是根据题目意思进行代码的…

​​解锁 JavaScript DOM:节点操作的核心方法与最佳实践

引言 在当今动态化的 Web 世界中&#xff0c;用户早已不满足于静态的网页展示&#xff0c;而是期待流畅的交互体验——点击按钮弹出菜单、滚动页面加载数据、实时搜索过滤内容……这些功能的背后&#xff0c;都离不开 ​JavaScript DOM&#xff08;文档对象模型&#xff09;操…

Android 12系统源码_系统启动(二)Zygote进程

前言 Zygote&#xff08;意为“受精卵”&#xff09;是 Android 系统中的一个核心进程&#xff0c;负责 孵化&#xff08;fork&#xff09;应用进程&#xff0c;以优化应用启动速度和内存占用。它是 Android 系统启动后第一个由 init 进程启动的 Java 进程&#xff0c;后续所有…

精华贴分享|从不同的交易理论来理解头肩形态,殊途同归

本文来源于量化小论坛策略分享会板块精华帖&#xff0c;作者为孙小迪&#xff0c;发布于2025年2月17日。 以下为精华帖正文&#xff1a; 01 前言 学习了一段时间交易后&#xff0c;我发现在几百年的历史中&#xff0c;不同门派的交易理论对同一种市场特征的称呼不一样&#x…

C++智能指针万字详细讲解(包含智能指针的模拟实现)

在笔试&#xff0c;面试中智能指针经常出现&#xff0c;如果你对智能指针的作用&#xff0c;原理&#xff0c;用法不了解&#xff0c;那么可以看看这篇博客讲解&#xff0c;此外本博客还简单模拟实现了各种指针&#xff0c;在本篇的最后还应对面试题对智能指针的知识点进行了拓…

学习threejs,使用多面体(IcosahedronGeometry、TetrahedronGeometry、OctahedronGeometry等)

&#x1f468;‍⚕️ 主页&#xff1a; gis分享者 &#x1f468;‍⚕️ 感谢各位大佬 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍⚕️ 收录于专栏&#xff1a;threejs gis工程师 文章目录 一、&#x1f340;前言1.1 ☘️THREE.PolyhedronGeometry …

DeepSeek详解:探索下一代语言模型

文章目录 前言一、什么是DeepSeek二、DeepSeek核心技术2.1 Transformer架构2.1.1 自注意力机制 (Self-Attention Mechanism)(a) 核心思想(b) 计算过程(c) 代码实现 2.1.2 多头注意力 (Multi-Head Attention)(a) 核心思想(b) 工作原理(c) 数学描述(d) 代码实现 2.1.3 位置编码 (…

【目标检测】【深度学习】【Pytorch版本】YOLOV1模型算法详解

【目标检测】【深度学习】【Pytorch版本】YOLOV1模型算法详解 文章目录 【目标检测】【深度学习】【Pytorch版本】YOLOV1模型算法详解前言YOLOV1的模型结构YOLOV1模型的基本执行流程YOLOV1模型的网络参数YOLOV1模型的训练方式 YOLOV1的核心思想前向传播阶段网格单元(grid cell)…