基本2D几何变换_2021秋季《计算机图形学》_基于《计算机图形学(第四版)》D.H.&M.P.B.&W.R.C.

本文详细介绍了如何使用OpenGL在2D环境中实现多边形的平移、旋转和缩放操作。通过矩阵运算,分别展示了平移向量、旋转角度和缩放比例对多边形的影响,并提供了相应的C++代码示例,包括多边形原始状态的绘制、平移、绕基准点旋转和保持基准点缩放的函数实现。
摘要由CSDN通过智能技术生成
  • 目前进度:多边形的平移、旋转、缩放

一、实验目的

  • 实现线段、圆和多边形的基本2D几何变换
    • 平移
    • 旋转(含基准点)
    • 缩放(含基准点)

二、实验环境

  • Visual Studio 2019
  • Windows 10

三、算法分析与设计

多边形

平移

对于多边形的各顶点添加一段平移距离,
{ x ′ = x + t x y ′ = y + t y \begin{cases} x'=x+tx\\ y'=y+ty \end{cases} {x=x+txy=y+ty
记原多边形顶点为 P P P,平移后的多边形顶点为 P ′ P' P,平移向量为 T T T,则
P = [ x y ] , P ′ = [ x ′ y ′ ] , T = [ t x t y ] P=\left[\begin{matrix} x\\y \end{matrix}\right],P'=\left[\begin{matrix} x'\\y' \end{matrix}\right],T=\left[\begin{matrix} tx\\ty \end{matrix}\right] P=[xy],P=[xy],T=[txty]

P ′ = P + T P'=P+T P=P+T

旋转

对于多边形的各顶点,绕基准点 ( x r , y r ) (x_r,y_r) (xr,yr)逆时针旋转角度 θ \theta θ
{ x ′ − x r = ( x − x r ) c o s θ − ( y − y r ) s i n θ y ′ − y r = ( x − x r ) s i n θ + ( y − y r ) c o s θ \begin{cases} x'-x_r=(x-x_r){\rm cos}\theta-(y-y_r){\rm sin}\theta \\ y'-y_r=(x-x_r){\rm sin}\theta+(y-y_r){\rm cos}\theta \end{cases} {xxr=(xxr)cosθ(yyr)sinθyyr=(xxr)sinθ+(yyr)cosθ

P ′ = R ⋅ P , R = [ c o s θ − s i n θ s i n θ c o s θ ] P'=R\cdot P,\quad R= \left[ \begin{matrix} {\rm cos}\theta & -{\rm sin}\theta \\ {\rm sin}\theta & {\rm cos}\theta \end{matrix} \right] P=RP,R=[cosθsinθsinθcosθ]

缩放

对于多边形的各顶点,保持基准点不动进行缩放,其中 s x , s y s_x,s_y sx,sy x , y x,y x,y方向的缩放比例。
{ x ′ = x ⋅ s x y ′ = y ⋅ s y \begin{cases} x'=x\cdot s_x \\ y'=y\cdot s_y \end{cases} {x=xsxy=ysy

P ′ = S ⋅ P , S = [ s x 0 0 s y ] P'=S\cdot P,\quad S= \left[ \begin{matrix} s_x & 0 \\ 0 & s_y \end{matrix} \right] P=SP,S=[sx00sy]

四、实验结果

五、附录

#include<GL/glew.h>
#include <GLFW/glfw3.h>
#include<bits/stdc++.h>

#define PI acos(-1)

using namespace std;

struct wcPt2D
{
    GLfloat x, y;

};

wcPt2D verts[3];
wcPt2D pivPt;

void getVerts(wcPt2D* verts)
{
    verts[0].x = -0.7;
    verts[0].y = 0.5;
    verts[1].x = -0.5;
    verts[1].y = 0.7;
    verts[2].x = -0.6;
    verts[2].y = 0.7;
}

/*画出原来的多边形*/
void drawOriginalPolygon(wcPt2D* verts, GLint nVerts)
{
    glBegin(GL_POLYGON);
    for (int k = 0; k < nVerts; k++)
    {
        glVertex2f(verts[k].x, verts[k].y);
    }
    glEnd();
}

/*平移多边形*/
void translatePolygon(wcPt2D* verts, GLint nVerts, GLfloat tx, GLfloat ty)
// (tx,ty)为平移向量
{
    wcPt2D* tmp = new wcPt2D[nVerts];
    for (int k = 0; k < nVerts; k++)
    {
        tmp[k].x = verts[k].x + tx;
        tmp[k].y = verts[k].y + ty;
    }
    glBegin(GL_POLYGON);
    for (int k = 0; k < nVerts; k++)
    {
        glVertex2f(tmp[k].x, tmp[k].y);
    }
    glEnd();
}

/*旋转多边形*/
void rotatePolygon(wcPt2D* verts, GLint nVerts, wcPt2D pivPt, GLdouble theta)
// pivPt:基准点;theta:逆时针旋转角度
{
    float xr = pivPt.x;
    float yr = pivPt.y;
    wcPt2D* tmp = new wcPt2D[nVerts];
    for (int k = 0; k < nVerts; k++)
    {
        tmp[k].x = xr + (verts[k].x - xr) * cos(theta) - (verts[k].y - yr) * sin(theta);
        tmp[k].y = yr + (verts[k].x - xr) * sin(theta) + (verts[k].y - yr) * cos(theta);
    }
    glBegin(GL_POLYGON);
    for (int k = 0; k < nVerts; k++)
    {
        glVertex2f(tmp[k].x, tmp[k].y);
    }
    glEnd();
}

/*缩放多边形*/
void scalePolygon(wcPt2D* verts, GLint nVerts, wcPt2D pivPt, GLfloat sx, GLfloat sy)
// pivPt:基准点
{
    float xr = pivPt.x;
    float yr = pivPt.y;
    wcPt2D* tmp = new wcPt2D[nVerts];
    for (int k = 0; k < nVerts; k++)
    {
        tmp[k].x = sx * verts[k].x + (1 - sx) * xr;
        tmp[k].y = sy * verts[k].y + (1 - sy) * yr;
    }
    glBegin(GL_POLYGON);
    for (int k = 0; k < nVerts; k++)
    {
        glVertex2f(tmp[k].x, tmp[k].y);
    }
    glEnd();
}

int main(void)
{
    GLFWwindow* window;

    /* Initialize the library */
    if (!glfwInit())
        return -1;

    /* Create a windowed mode window and its OpenGL context */
    window = glfwCreateWindow(640, 480, "Hello World", NULL, NULL);
    if (!window)
    {
        glfwTerminate();
        return -1;
    }

    /* Make the window's context current */
    glfwMakeContextCurrent(window);

    if (glewInit() != GLEW_OK)
        cout << "Error!" << endl;

    // cout << glGetString(GL_VERSION) << endl;

    getVerts(verts);
    cout << verts[1].x << endl;

    /* Loop until the user closes the window */
    while (!glfwWindowShouldClose(window))
    {
        /* Render here */
        glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
        glClear(GL_COLOR_BUFFER_BIT);

        drawOriginalPolygon(verts,3);
        translatePolygon(verts, 3, 0.5f, 0.0f);
        pivPt.x = 0.0f;
        pivPt.y = 0.0f;
        //pivPt = verts[0];
        rotatePolygon(verts, 3, pivPt, PI / 3);
        scalePolygon(verts, 3, pivPt, 0.5f, 0.5f);

        /* Swap front and back buffers */
        glfwSwapBuffers(window);

        /* Poll for and process events */
        glfwPollEvents();
    }

    glfwTerminate();
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值