基本2D几何变换

基本2D几何变换,第1张

基本2D几何变换
  • 目前进度:多边形的平移、旋转、缩放
一、实验目的
  • 实现线段、圆和多边形的基本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′=[x′y′​],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} {x′−xr​=(x−xr​)cosθ−(y−yr​)sinθy′−yr​=(x−xr​)sinθ+(y−yr​)cosθ​

P ′ = R ⋅ P , R = [ c o s θ − s i n θ s i n θ c o s θ ] P'=Rcdot P,quad R= left[ begin{matrix} {rm cos}theta & -{rm sin}theta \ {rm sin}theta & {rm cos}theta end{matrix} right] P′=R⋅P,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'=xcdot s_x \ y'=ycdot s_y end{cases} {x′=x⋅sx​y′=y⋅sy​​

P ′ = S ⋅ P , S = [ s x 0 0 s y ] P'=Scdot P,quad S= left[ begin{matrix} s_x & 0 \ 0 & s_y end{matrix} right] P′=S⋅P,S=[sx​0​0sy​​]

四、实验结果 五、附录
#include
#include 
#include

#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;

    
    if (!glfwInit())
        return -1;

    
    window = glfwCreateWindow(640, 480, "Hello World", NULL, NULL);
    if (!window)
    {
        glfwTerminate();
        return -1;
    }

    
    glfwMakeContextCurrent(window);

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

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

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

    
    while (!glfwWindowShouldClose(window))
    {
        
        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);

        
        glfwSwapBuffers(window);

        
        glfwPollEvents();
    }

    glfwTerminate();
    return 0;
}

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/zaji/4751787.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-11-08
下一篇 2022-11-08

发表评论

登录后才能评论

评论列表(0条)

保存