计算机图形学:二维图形变换及实现

一、平移变换

1.1 推导

平移变换是将图形在二维平面上按照某个向量 ( Δ x , Δ y ) (\Delta x, \Delta y) (Δx,Δy)进行移动。对于平面上的任意一点 ( x , y ) (x, y) (x,y),平移后的坐标 ( x ′ , y ′ ) (x', y') (x,y)可以通过以下公式计算:

x ′ = x + Δ x y ′ = y + Δ y \begin{aligned} x' = x + \Delta x\\ y' = y + \Delta y \end{aligned} x=x+Δxy=y+Δy

1.2 C++ 代码示例

#include <iostream>
#include <vector>

struct Point {
    double x, y;
};

void translate(std::vector<Point>& points, double dx, double dy) {
    for (auto& p : points) {
        p.x += dx;
        p.y += dy;
    }
}

int main() {
    std::vector<Point> polygon = {{1, 2}, {3, 4}, {5, 1}};
    double dx = 2, dy = 3;
    translate(polygon, dx, dy);
    for (const auto& p : polygon) {
        std::cout << "Translated Point: (" << p.x << ", " << p.y << ")" << std::endl;
    }
    return 0;
}

1.3 Python 代码示例

import matplotlib.pyplot as plt

def translate(points, dx, dy):
    return [(x + dx, y + dy) for x, y in points]

points = [(1, 2), (3, 4), (5, 1)]
dx, dy = 2, 3
translated_points = translate(points, dx, dy)

plt.figure()
plt.plot(*zip(*points), 'bo-', label='Original')
plt.plot(*zip(*translated_points), 'ro-', label='Translated')
plt.axis("equal")
plt.legend()
plt.show()

运行结果如下

平移

二、比例变换(缩放变换)

2.1 推导

比例变换是改变图形的大小的操作。设 k x k_x kx k y k_y ky 分别是沿 x x x轴和 y y y轴的缩放因子,则点 ( x , y ) (x, y) (x,y)缩放后的坐标 ( x ′ , y ′ ) (x', y') (x,y)可以通过以下方式计算:

x ′ = k x ⋅ x y ′ = k y ⋅ y \begin{aligned} x' = k_x \cdot x \\ y' = k_y \cdot y \end{aligned} x=kxxy=kyy

2.2 C++ 代码示例

#include <iostream>
#include <vector>

struct Point {
    double x, y;
};

void scale(std::vector<Point>& points, double kx, double ky) {
    for (auto& p : points) {
        p.x *= kx;
        p.y *= ky;
    }
}

int main() {
    std::vector<Point> polygon = {{1, 2}, {3, 4}, {5, 1}};
    double kx = 2, ky = 3;
    scale(polygon, kx, ky);
    for (const auto& p : polygon) {
        std::cout << "Scaled Point: (" << p.x << ", " << p.y << ")" << std::endl;
    }
    return 0;
}

2.2 Python 代码示例

import matplotlib.pyplot as plt

def scale(points, kx, ky):
    return [(x * kx, y * ky) for x, y in points]

points = [(1, 2), (3, 4), (5, 1)]
kx, ky = 2, 3
scaled_points = scale(points, kx, ky)

plt.figure()
plt.plot(*zip(*points), 'bo-', label='Original')
plt.plot(*zip(*scaled_points), 'ro-', label='Scaled')
plt.axis("equal")
plt.legend()
plt.show()

运行结果如下

缩放

三、旋转变换

3.1 推导

旋转变换是将图形绕原点或某一点旋转一定角度 θ \theta θ(以弧度为单位)。对于平面上的任意一点 ( x , y ) (x, y) (x,y),旋转后的坐标 ( x ′ , y ′ ) (x', y') (x,y) 可以通过以下公式计算:

x ′ = x ⋅ cos ⁡ ( θ ) − y ⋅ sin ⁡ ( θ ) y ′ = x ⋅ sin ⁡ ( θ ) + y ⋅ cos ⁡ ( θ ) \begin{aligned} x' = x \cdot \cos(\theta) - y \cdot \sin(\theta) \\ y' = x \cdot \sin(\theta) + y \cdot \cos(\theta) \end{aligned} x=xcos(θ)ysin(θ)y=xsin(θ)+ycos(θ)

3.2 C++ 代码示例

#include <iostream>
#include <vector>
#include <cmath> // For cos(), sin()

struct Point {
    double x, y;
};

void rotate(std::vector<Point>& points, double theta) {
    theta = theta * M_PI / 180.0; // Convert degrees to radians
    for (auto& p : points) {
        double x_temp = p.x;
        p.x = p.x * cos(theta) - p.y * sin(theta);
        p.y = x_temp * sin(theta) + p.y * cos(theta);
    }
}

int main() {
    std::vector<Point> polygon = {{1, 2}, {3, 4}, {5, 1}};
    double theta = 90; // Rotate 90 degrees
    rotate(polygon, theta);
    for (const auto& p : polygon) {
        std::cout << "Rotated Point: (" << p.x << ", " << p.y << ")" << std::endl;
    }
    return 0;
}

3.3 Python 代码示例

import matplotlib.pyplot as plt
import math

def rotate(points, theta):
    theta = math.radians(theta)  # Convert degrees to radians
    return [(x * math.cos(theta) - y * math.sin(theta),
             x * math.sin(theta) + y * math.cos(theta))
            for x, y in points]

points = [(1, 2), (3, 4), (5, 1)]
theta = 90  # Rotate 90 degrees
rotated_points = rotate(points, theta)

plt.figure()
plt.plot(*zip(*points), 'bo-', label='Original')
plt.plot(*zip(*rotated_points), 'ro-', label='Rotated')
plt.axis("equal")
plt.legend()
plt.show()

运行结果如下

旋转

### 计算机图形学中的二维变换概念 在计算机图形学中,二维变换是指对平面内的点、线以及多边等几何对象的位置、大小和方向进行改变的操作。这些变化可以通过一系列数学运算来描述并实现。 #### 向量基础知识与坐标系 向量是表示位置或位移的重要工具,在二维空间里通常用两个分量(x,y)表示一个点的位置;而图形坐标系定义了如何解释这些数值所代表的具体物理意义。常见的有笛卡尔直角坐标系和其他特殊应用下的极坐标系等[^1]。 #### 变换原理概述 二维图变换主要包括平移(T)、比例(S)、旋转(R),它们分别对应着不同类型的矩阵操作: - **平移**:使物体沿某一方向移动一定距离; - **缩放**:调整目标尺寸大小; - **旋转变换**:围绕指定轴心转动给定角度。 对于上述三种基础变换而言,其核心在于构建相应的转换方程,并利用矩阵式表达出来以便于计算处理[^3]。 #### 几何变换具体实施方式 ##### 平移变换 当需要将某一点P=(x0,y0)沿着X轴正向偏移dx单位长度的同时也按Y轴增加dy时,则新的坐标可通过如下公式获得: \[ P' = (x_0 + dx , y_0 + dy ) \] 为了能够把所有的变换都统一到乘法的式下完成,引入了所谓的“齐次坐标”。即原本的二维矢量被扩展至三维,其中第三维固定为1,这样就可以方便地使用单一矩阵来进行多种组合型的变化了。 ```cpp void translate(float &x, float &y, float tx, float ty){ x += tx; y += ty; } ``` ##### 缩放变换 假设要以原点为中心放大/缩小某个状的比例因子分别为sx,sy,则新坐标的求解过程如下所示: \[ P'(x',y')=S(s_x,s_y)\cdot P(x,y)=\begin{bmatrix}s_x&0\\0&s_y\end{bmatrix}\times[x,y]^T \] 这里需要注意的是,如果希望保持纵横比不变的话,那么应该让\(s_x=s_y\)成立。 ```cpp void scale(float &x, float &y, float sx, float sy){ x *= sx; y *= sy; } ``` ##### 旋转变换 绕Z轴逆时针转过θ度后的效果可以写成这样的关系式子: \[ R(\theta):\quad P'=R_{z}(\theta)\cdot P=\left[\begin{array}{cc}\cos{\theta}&-\sin{\theta}\\ \sin{\theta}&\cos{\theta}\end{array}\right]\times [x,y]^T \] 此过程中涉及到三角函数的应用,因此编程时需调用相应库函数来辅助完成具体的数值计算工作。 ```cpp #include <cmath> #define PI 3.14159265 void rotate(float &x, float &y, float angle_degrees){ double radians = angle_degrees * PI / 180.0; // Convert degrees to radians. float cosTheta = std::cos(radians); float sinTheta = std::sin(radians); float newX = x * cosTheta - y * sinTheta; float newY = x * sinTheta + y * cosTheta; x = newX; y = newY; } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

艰默

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值