二维旋转变换

求点 P(x1, y1) 绕点 Q(x2, y2) 逆时针旋转 θ 得到的点的坐标

先看绕原点旋转的情况:

在这里插入图片描述

如图所示点 v 绕 原点旋转 θ 角,得到点v’,假设 v点的坐标是(x, y) ,那么可以推导得到 v’点的坐标(x’, y’):

{ x = r ∗ cos ⁡ θ y = r ∗ sin ⁡ θ \left\{ \begin{aligned} x & = r * \cos\theta \\ y & = r * \sin\theta \\ \end{aligned} \right. {xy=rcosθ=rsinθ

{ x ′ = r ∗ cos ⁡ ( ϕ + θ ) y ′ = r ∗ sin ⁡ ( ϕ + θ ) \left\{ \begin{aligned} x' & = r * \cos( \phi + \theta) \\ y' & = r * \sin( \phi + \theta) \\ \end{aligned} \right. {xy=rcos(ϕ+θ)=rsin(ϕ+θ)

展开得:

{ x ′ = r ∗ cos ⁡ ϕ ∗ cos ⁡ θ − r ∗ sin ⁡ ϕ ∗ sin ⁡ θ y ′ = r ∗ sin ⁡ ϕ ∗ cos ⁡ θ + r ∗ cos ⁡ ϕ ∗ sin ⁡ θ \left\{ \begin{aligned} x' & = r * \cos\phi * \cos\theta - r * \sin\phi * \sin\theta \\ y' & = r * \sin\phi * \cos\theta + r * \cos\phi * \sin\theta \\ \end{aligned} \right. {xy=rcosϕcosθrsinϕsinθ=rsinϕcosθ+rcosϕsinθ

带入 x 和 y 的表达式:

{ x ′ = x ∗ cos ⁡ θ − y ∗ sin ⁡ θ y ′ = y ∗ cos ⁡ θ + x ∗ sin ⁡ θ \left\{ \begin{aligned} x' & = x * \cos\theta - y * \sin\theta \\ y' & = y * \cos\theta + x* \sin\theta \\ \end{aligned} \right. {xy=xcosθysinθ=ycosθ+xsinθ

写为矩阵:

[ x ′ y ′ ] = [ cos ⁡ θ − sin ⁡ θ sin ⁡ θ cos ⁡ θ ] ∗ [ x y ] \begin{bmatrix} x'\\ y'\\ \end{bmatrix}= \begin{bmatrix} \cos\theta&-\sin\theta\\ \sin\theta&\cos\theta\\ \end{bmatrix}* \begin{bmatrix} x\\ y\\ \end{bmatrix} [xy]=[cosθsinθsinθcosθ][xy]

于是我们得到旋转变换矩阵 M:

M = [ cos ⁡ θ − sin ⁡ θ sin ⁡ θ cos ⁡ θ ] M = \begin{bmatrix} \cos\theta & -\sin\theta \\ \sin\theta & \cos\theta \end{bmatrix} M=[cosθsinθsinθcosθ]

设旋转后的到的坐标为 P’(x’, y’),类似于平面向量中将起点平移至原点的思想,我们可以将 P 点绕 Q 点旋转的过程看作 PQ 向量旋转得到 P’Q 向量,于是根据 P 和 Q 坐标有:

[ x ′ − x 2 y ′ − y 2 ] = [ cos ⁡ θ − sin ⁡ θ sin ⁡ θ cos ⁡ θ ] ∗ [ x 1 − x 2 y 1 − y 2 ] \begin{bmatrix} x' - x_2\\ y' - y_2\\ \end{bmatrix}= \begin{bmatrix} \cos\theta&-\sin\theta\\ \sin\theta&\cos\theta\\ \end{bmatrix}* \begin{bmatrix} x_1 - x_2\\ y_1 - y_2\\ \end{bmatrix} [xx2yy2]=[cosθsinθsinθcosθ][x1x2y1y2]

于是得到 P’ 坐标为:

[ x ′ y ′ ] = [ cos ⁡ θ − sin ⁡ θ sin ⁡ θ cos ⁡ θ ] ∗ [ x 1 − x 2 y 1 − y 2 ] + [ x 2 y 2 ] \begin{bmatrix} x'\\ y'\\ \end{bmatrix}= \begin{bmatrix} \cos\theta&-\sin\theta\\ \sin\theta&\cos\theta\\ \end{bmatrix}* \begin{bmatrix} x_1 - x_2\\ y_1 - y_2\\ \end{bmatrix} + \begin{bmatrix} x_2\\ y_2\\ \end{bmatrix} [xy]=[cosθsinθsinθcosθ][x1x2y1y2]+[x2y2]

算法实现:

from collections import namedtuple
import mathPoint = namedtuple("Point", ["x", 'y'])def matrix_mul(M: list[list[float]], vec: list[float]) -> list[float]:res = []for row in M:res.append(sum([a * b for (a, b) in zip(row, vec)]))return resdef rotate(p: Point, q: Point, theta: float) -> Point:M = [[math.cos(theta), -math.sin(theta)],[math.sin(theta), math.cos(theta)]]pq = [p.x - q.x, p.y - q.y]t = matrix_mul(M, pq)t[0] += q.xt[1] += q.yreturn Point(t[0], t[1])def main():print(rotate(Point(1.414, 0), Point(0, 0), math.pi / 4), "expect (1, 1)")print(rotate(Point(1, 1), Point(0, 0), -math.pi / 4), "expect (1.414, 0)")print(rotate(Point(2, 2), Point(1, 1), -math.pi / 4), "expect (2.414, 1)")if __name__ == '__main__':main()

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

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

相关文章

JVM主要知识点详解

目录 1. 性能监控和调优 1.1 调优相关参数 1.2 内存泄漏排查 1.3 cpu飙⾼ 2. 内存与垃圾回收 2.1JVM的组成(面试题) 2.2 Java虚拟机栈的组成 2.3 本地方法栈 2.4 堆 2.5 方法区(抽象概念) 2.5.1 方法区和永久代以及元空…

【终于明白为啥有团队禁止使用lombok】

终于明白为啥有团队禁止使用lombok 背景我们的问题难点如何解决是什么东西?最后 背景 团队内部,idea版本不一样,有2021,有2022,有2023。 项目pom中lombok版本过低。 我们的问题 有用较新版本idea的同学,…

计算机组成原理【CO】Ch2 数据的表示和应用

文章目录 大纲2.1 数制与编码2.2 运算方法和运算电路2.3 浮点数的表示和运算 【※】带标志加法器OFSFZFCF计算机怎么区分有符号数无符号数? 【※】存储排列和数据类型转换数据类型大小数据类型转换 进位计数制进制转换2的次幂 各种码的基本特性无符号整数的表示和运算带符号整…

【电控笔记6.2】拉式转换与转移函数

概要 laplace:单输入单输出,线性系统 laplace 传递函数 总结

使用Python模仿文件行为

在Python中,你可以通过文件操作函数(如open()函数)以及模拟输入输出流的库(如io模块)来模拟文件行为。下面是一些示例,展示了如何使用这些工具在Python中模拟文件行为。 1、问题背景 在编写一个脚本时&…

MSQL DML数据操作语言

🌹作者主页:青花锁 🌹简介:Java领域优质创作者🏆、Java微服务架构公号作者😄 🌹简历模板、学习资料、面试题库、技术互助 🌹文末获取联系方式 📝 往期热门专栏回顾 专栏…

随机游走的艺术-图嵌入表示学习

图嵌入引入 机器学习算法: 厨师 样本集: 食材 只有好的食材才能做出好的饭菜 我们需要把数据变成计算机能够读懂的形式(将数据映射成为向量) 图嵌入概述 传统图机器学习 图表示学习 自动学习特征,将…

【Altium Designer 20 笔记】PCB铺铜过程

PCB铺铜步骤 切换到Keep-Out Layer(禁止布线层) 使用shifts键切换单层显示 画禁止布线范围(防止铺铜过大) 切换到需要铺铜的层 选择铺铜网络,通常是地(GND)或某个电源网络 隐藏覆铜:…

leetcode:42.接雨水

单调栈解题思路: 需要知道当前遍历到的元素左边和右边第一个比该元素大的元素。 如果当前遍历到的元素大于栈顶元素,则该元素为栈顶元素右边第一个比它大的元素,此时,栈顶元素的栈内相邻元素是该元素左边第一个比它大的元素。【…

Python 入门指南(一)

原文:zh.annas-archive.org/md5/97bc15629f1b51a0671040c56db61b92 译者:飞龙 协议:CC BY-NC-SA 4.0 前言 这个学习路径帮助你在 Python 的世界中感到舒适。它从对 Python 的全面和实用的介绍开始。你将很快开始在学习路径的第一部分编写程序…

上海人工智能实验室的书生·浦语大模型学习笔记(第二期第四课——上篇)

书生浦语是上海人工智能实验室和商汤科技联合研发的一款大模型,这次有机会参与试用,特记录每日学习情况。 今天就ddl,但这次学习的内容太多,需要很长时间去消化,要抓紧最后时间,不然来不及了 这次记录的是…

02_对象树

#include "mypushbutton.h" #include <QDebug>MyPushButton::MyPushButton(QWidget *parent): QPushButton(parent) {qDebug()<<"我的按钮类构造调用"; }MyPushButton::~MyPushButton() {qDebug()<<"我的按钮类析构调用"; }交…