• 任意多边形的几何变换


    一、实验目的

    1.几何变换的原理的掌握;

    2.通过几何变换实现任意复杂的几何变换。

    二、实验内容

    1. 编写程序,实现多边形五种基本几何变换。绕任意一点(Cx,Cy)逆时针旋转theta几何变换,并在屏幕中进行绘制。

    要求显示图形的坐标系原点在屏幕中心,画出坐标轴,在屏幕上用鼠标选点绘制多边形,并实现多边形的变换。

    三、实验步骤

    (一)多边形的五种基本几何变换

    1.算法思路:

    二维几何变换矩阵T是一个3×3的方阵,简称为二维变换矩阵。

     

    从功能上可以把二维变换矩阵T分为4个子矩阵。其中   是对图形进行比例变换、旋转变换、反射变换和错切变换; 是对图形进行平移变换;       是对图形进行投影变换;    是对图形进行整体比例变换。

    (1)   平移变换

    平移变换的坐标表示为:

    二维平移变换矩阵:

    (2)   比例变换

    比例变换的坐标表示为:

    二维比例变换矩阵:

    (3)   旋转变换

    旋转变换的坐标表示为:

    二维旋转变换矩阵:

    (4)   反射变换   

    1. 关于原点反射的坐标表示为:

    变换矩阵:

    1. 关于x轴的二维反射变换矩阵为 :
    2. 关于y轴的二维反射变换矩阵为 :

    (5)   错切变换

    a.沿x,y方向的错切变换的坐标表示为:

    沿x,y两个方向的二维错切变换矩阵为:

    其中b、c为错切参数。

    b. 沿x方向的二维错切变换矩阵为:

    c. 沿y方向的二维错切变换矩阵为:

    (二)代码如下:

    在GeometricTransformationView.h 文件中添加:

     
    #include <vector>
    
    using std::vector;
    
    #include<math.h>

    添加一个成员变量:   vector<CPoint>  points;

    添加事件处理函数:

    void CGeometricTransformationView::OnPaint() 
    {
        CPaintDC dc(this); // device context for painting
        draw();
        // TODO: Add your message handler code here
        
        // Do not call CView::OnPaint() for painting messages
    }
    
    void CGeometricTransformationView::OnLButtonUp(UINT nFlags, CPoint point) 
    {
        // TODO: Add your message handler code here and/or call default
        CRect rect;
        GetClientRect(rect);
        points.push_back(CPoint(point.x - rect.Width()/2, point.y - rect.Height()/2));
        CView::OnLButtonUp(nFlags, point);
    }
    
    void CGeometricTransformationView::OnRButtonUp(UINT nFlags, CPoint point) 
    {
        // TODO: Add your message handler code here and/or call default
        draw();
        CView::OnRButtonUp(nFlags, point);
    }
    
    void CGeometricTransformationView::OnMButtonUp(UINT nFlags, CPoint point) 
    {
        // TODO: Add your message handler code here and/or call default
        points.clear();
    
        CView::OnMButtonUp(nFlags, point);
    }

    编写一个draw()函数:

    void CGeometricTransformationView::draw()
    {
        CDC *dc = GetDC();
        CRect rect;
        dc->GetClipBox(rect);
        dc->SetViewportOrg(rect.Width()/2, rect.Height()/2);
    
        // 绘制坐标轴
        dc->MoveTo(-rect.Width()/2, 0);
        dc->LineTo(rect.Width()/2, 0);
        dc->MoveTo(0, -rect.Height()/2);
        dc->LineTo(0, rect.Height()/2);
    
        if (points.size() < 3) {
            return;
        }
         int i;
        //绘制多边形
        dc->MoveTo(points[0].x, points[0].y);
        for (  i = 1; i < points.size(); i++) {
            dc->LineTo(points[i].x, points[i].y);
        }
        dc->LineTo(points[0].x, points[0].y);
    
        //向下平移300个单位
        dc->MoveTo(points[0].x, points[0].y+100);
        for (  i = 1; i < points.size(); i++) {
            dc->LineTo(points[i].x, points[i].y+100);
        }
        dc->LineTo(points[0].x, points[0].y+100);
    
        // 2倍放大后的多边形
        dc->MoveTo(2*points[0].x, 2*points[0].y);
        for ( i = 1; i < points.size(); i++) {
            dc->LineTo(2*points[i].x, 2*points[i].y);
        }
        dc->LineTo(2*points[0].x, 2*points[0].y);
    
        // 绕原点旋转60度
        double r = sqrt(points[0].x*points[0].x + points[0].y*points[0].y);
        double pi = acos(-1);
        double angle = pi*60/180;
        int x, y;
        x = points[0].x;
        y = points[0].y;
        dc->MoveTo(x*cos(angle)-y*sin(angle), x*sin(angle)+y*cos(angle));
        for ( i = 1; i < points.size(); i++) {
            x = points[i].x;
            y = points[i].y;
            dc->LineTo(x*cos(angle)-y*sin(angle), x*sin(angle)+y*cos(angle));
        }
        x = points[0].x;
        y = points[0].y;
        dc->LineTo(x*cos(angle)-y*sin(angle), x*sin(angle)+y*cos(angle));
    
        // 关于y轴反射变换
        dc->MoveTo(-points[0].x, points[0].y);
        for ( i = 1; i < points.size(); i++) {
            dc->LineTo(-points[i].x, points[i].y);
        }
        dc->LineTo(-points[0].x, points[0].y);
    
        // 错切变换
        double k = -2.3;
        dc->MoveTo(points[0].x + k*points[0].y, points[0].y);
        for ( i = 1; i < points.size(); i++) {
            dc->LineTo(points[i].x + k*points[i].y, points[i].y);
        }
        dc->LineTo(points[0].x + k*points[0].y, points[0].y);
    
        // 绕(-100, 120)旋转30度
        int ox = -100;
        int oy = 120;
        angle = pi*30/180;
        x = points[0].x;
        y = points[0].y;
        dc->MoveTo((x-ox)*cos(angle)-(y-oy)*sin(angle)+ox, (x-ox)*sin(angle)+(y-oy)*cos(angle)+oy);
        for ( i = 1; i < points.size(); i++) {
            x = points[i].x;
            y = points[i].y;
            dc->LineTo((x-ox)*cos(angle)-(y-oy)*sin(angle)+ox, (x-ox)*sin(angle)+(y-oy)*cos(angle)+oy);
        }
        x = points[0].x;
        y = points[0].y;
        dc->LineTo((x-ox)*cos(angle)-(y-oy)*sin(angle)+ox, (x-ox)*sin(angle)+(y-oy)*cos(angle)+oy);

    (三)运行结果截图:

     
     
     

    参见源码:https://github.com/shenxiaolinZERO/Resources/tree/master/Resources/Computer-Graphics/GeometricTransformation

  • 相关阅读:
    springmvc 路由
    springMVC 流程
    SqlServer中Sql语句的逻辑执行顺序
    中小型公司静态资源管理部署方案
    浅谈SQL Server中的三种物理连接操作
    Zclip复制页面内容到剪贴板兼容各浏览器
    C#中如何利用操作符重载和转换操作符
    类型构造器(静态构造函数)的执行时机你知道多少?
    容器云技术选择之kubernetes和swarm对比
    kafka入门
  • 原文地址:https://www.cnblogs.com/shenxiaolin/p/5529962.html
Copyright © 2020-2023  润新知