【计算机图形学】图形变换(以任意直线为对称轴的对称变换)

模块3-2 图形变换

一 实验目的

  1. 编写图形各种变换的算法

二 实验内容

1:任意直线的对称变换。要求将变换矩阵写在实验报告中,并与代码匹配。求对任意直线Ax+By+C=0的对称变换矩阵。

实验结果如下图所示:


1:预设图形初始化


2:鼠标左键点击直线起点


3:鼠标右键点击直线终点


4:继续添加对称情况

求对任意直线Ax+By+C=0的对称变换矩阵:

对于任意直线Ax + By + C = 0,对称变换矩阵为M = (1-2A^2/(A^2+B^2), -2AB/(A^2+B^2), -2AC/(A^2+B^2); -2AB/(A^2+B^2), 1-2B^2/(A^2+B^2), -2BC/(A^2+B^2); 0, 0, 1),其中A和B不同时为0。

1-2A^2/(A^2+B^2)

-2AB/(A^2+B^2)

-2AC/(A^2+B^2)

-2AB/(A^2+B^2)

1-2B^2/(A^2+B^2)

-2BC/(A^2+B^2)

0

0

1

三 程序说明

最终的实验代码如下表所示:

1

//

// 程序名称:任意直线对称变换

// 功    能:实现图形以任意直线为基准的对称变换

// 编译环境:VS2019,EasyX_20220116

// 最后修改:2022-4-7

#include <graphics.h>

#include <conio.h>

#include <iostream>

#include <math.h>

using namespace std;

double points[4][2] = { {150,150},{150,300},{300,300},{300,150} };

const double newpoints[4][2] = { {150,150},{150,300},{300,300},{300,150} };

int num = 4, dimension = 3;

#define PI 3.1415927

//旋转变换

void rotate(double degree);

//平移变换

void trans(double tx, double ty);

//矩阵乘法

void mutiply(double a[5][5], int ar, int ac, double b[5][5], int br, int bc);

//画图函数

void paint();

//任意对称变换

void anysymmetry(int x1, int y1, int x2, int y2);

//坐标轴对称变换

void symmetry(int flag);

void anysymmetry(int x1, int y1, int x2, int y2) {

    double k = 0, b = 0;

    if (x1 == x2) {

         trans(-x1, 0);

         symmetry(1);

         trans(x1, 0);

    }

    else if (y1 == y2) {

         trans(0, -y1);

         symmetry(0);

         trans(0, y1);

    }

    else {

         k = 1.0 * (y1 - y2) / (x1 - x2);

         b = y1 - k * x1;

         trans(0, -b);

         rotate(-atan(k) * 180 * 1.0 / PI);

         symmetry(0);

         rotate(atan(k) * 180 * 1.0 / PI);

         trans(0, b);

    }

}

void symmetry(int flag) {

    int i;

    if (flag == 0) {

         for (i = 0; i < num; i++) {

             points[i][1] = -points[i][1];

         }

    }

    else if (flag == 1) {

         for (i = 0; i < num; i++) {

             points[i][0] = -points[i][0];

         }

    }

    else {

         return;

    }

}

void paint() {

    for (int i = 0; i < num; i++) {

         if (i == num - 1) {

             line(int(points[i][0]), int(points[i][1]), int(points[0][0]), int(points[0][1]));

             break;

         }

         line(int(points[i][0]), int(points[i][1]), int(points[i + 1][0]), int(points[i + 1][1]));

    }

}

void rotate(double degree) {

    double sita = 1.0 * degree / 180 * PI;

    double R[5][5] = { {cos(sita),-sin(sita),0},{sin(sita),cos(sita),0},{0,0,1.0} };

    double point[5][5];

    int i;

    for (i = 0; i < num; i++) {

         point[0][0] = 1.0 * points[i][0];

         point[1][0] = 1.0 * points[i][1];

         point[2][0] = 1;

         mutiply(R, dimension, dimension, point, dimension, 1);

         points[i][0] = point[0][0];

         points[i][1] = point[1][0];

    }

}

void trans(double tx, double ty) {

    double T[5][5] = { {1,0,tx},{0,1,ty},{0,0,1} };

    double point[5][5];

    int i;

    for (i = 0; i < num; i++) {

         point[0][0] = 1.0 * points[i][0];

         point[1][0] = 1.0 * points[i][1];

         point[2][0] = 1;

         mutiply(T, dimension, dimension, point, dimension, 1);

         points[i][0] = point[0][0];

         points[i][1] = point[1][0];

    }

}

void mutiply(double a[5][5], int ar, int ac, double b[5][5], int br, int bc) {

    int i, j, k;

    double c[5][5];

    for (i = 0; i < ar; i++) {

         for (j = 0; j < bc; j++) {

             c[i][j] = 0;

         }

    }

    for (i = 0; i < ar; i++) {

         for (j = 0; j < bc; j++) {

             for (k = 0; k < ac; k++) {

                  c[i][j] += 1.0 * a[i][k] * b[k][j];

             }

         }

    }

    for (i = 0; i < ar; i++) {

         for (j = 0; j < bc; j++) {

             b[i][j] = c[i][j];

         }

    }

}

int main() {

    initgraph(1000, 800);

    ExMessage m;

    //绘画初始矩形

    setcolor(WHITE);

    rectangle(points[0][0], points[0][1], points[2][0], points[2][1]);

    int x0, y0, x1, y1;

    while (1) {

         m = getmessage(EX_MOUSE | EX_KEY);

         switch (m.message) {

             case WM_LBUTTONDOWN:

                  x0 = m.x;

                  y0 = m.y;

                  //画直线起点

                  setlinecolor(WHITE);

                  setfillcolor(GREEN);

                  fillrectangle(m.x - 3, m.y - 3, m.x + 3, m.y + 3);

                  break;

             case WM_RBUTTONDOWN:

                  x1 = m.x;

                  y1 = m.y;

                  //画直线终点

                  setlinecolor(WHITE);

                  setfillcolor(GREEN);

                  fillrectangle(m.x - 3, m.y - 3, m.x + 3, m.y + 3);

                  //处理直线

                  line(x0, y0, x1, y1);

                  anysymmetry(x0, y0, x1, y1);

                  paint();

                  for (int i = 0; i < 4; i++) {

                      points[0][0] = newpoints[0][0];

                      points[0][1] = newpoints[0][1];

                      points[1][0] = newpoints[1][0];

                      points[1][1] = newpoints[1][1];

                      points[2][0] = newpoints[2][0];

                      points[2][1] = newpoints[2][1];

                      points[3][0] = newpoints[3][0];

                      points[3][1] = newpoints[3][1];

                  }

                  break;

             case WM_KEYDOWN:

                  if (m.vkcode == VK_ESCAPE) {

                      return 0;

                  }

        }

    }

    _getch();

    closegraph();

    return 0;

}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

数据结构——链表(python版)

一、链表简介 链表是一种在存储单元上非连续、非顺序的存储结构。数据元素的逻辑顺序是通过链表中的指针链接次序实现。链表是由一系列的结点组成&#xff0c;结点可以在运行时动态生成。每个结点包含两部分&#xff1a;数据域与指针域。数据域存储数据元素&#xff0c;指针域…

TCP的三次握手和四次挥手

三次握手 既然我们文章要说的是TCP的三次握手&#xff0c;和四次挥手&#xff0c;那么肯定是说的连接&#xff0c;也不是说的不其他的。那么它这个连接的过程说的是什么呢&#xff1f; 我们还是从图中理解&#xff0c;这样比较好理解&#xff0c; TCP第一次握手&#xff1a;服…

gradle Task 详解

目录 Task定义和配置 Task的执行阶段 Task 的依赖 Task 指定执行顺序 Task 主gradle引入其他的gradle文件 将某一个task挂载到指定的task之后执行 gradle task官网&#xff1a;Task - Gradle DSL Task定义和配置 查看工程下所有的task&#xff0c;使用如下命令 gradle …

【Linux】浅谈eloop机制

目录 1.eloop 机制 2.eloop结构体 2.1.eloop_data结构体 2.2 Socket事件结构体 2.3 Timeout事件结构体 2.4 Signal事件结构体 3.eloop_init 4.eloop_run 4.1 signal事件 4.2 socket事件 4.3 timeout事件 1.eloop 机制 主线程中启动事件监听机制&#xff0c;对不同的…

深度学习模型压缩与优化加速

1. 简介 深度学习&#xff08;Deep Learning&#xff09;因其计算复杂度或参数冗余&#xff0c;在一些场景和设备上限制了相应的模型部署&#xff0c;需要借助模型压缩、系统优化加速、异构计算等方法突破瓶颈&#xff0c;即分别在算法模型、计算图或算子优化以及硬件加速等层…

如何优雅地停掉线程?

很久很久以前&#xff0c;在一个名为“Springboot”的村庄中&#xff0c;住着一群热爱编程的程序员。他们喜欢探索新技术、优化自己的代码&#xff0c;为了打造更好的软件而不断努力着。 在这个村庄中&#xff0c;有一个名叫小明的程序员&#xff0c;他是村庄中最优秀的程序员…

一文打通java中内存泄露

目录 前置知识 内存泄漏&#xff08;memory leak&#xff09; 内存溢出&#xff08;out of memory&#xff09; Java中内存泄露的8种情况 静态集合类 单例模式 内部类持有外部类 各种连接&#xff0c;如数据库连接、网络连接和IO连接等 变量不合理的作用域 改变哈希值 …

第二十八章 React脚手架配置代理

为了更好地理解如何在React应用程序中配置代理&#xff0c;我们需要先了解什么是代理。 代理是一种充当客户端和服务器之间中间人的服务器。当客户端向服务器发送请求时&#xff0c;代理服务器将接收请求并将其转发到服务器。服务器将响应发送回代理服务器&#xff0c;代理服务…

机器视觉工程师职场四点“心态>交流=思路>知行合一”

视觉人机器视觉团队,他们热爱机器视觉行业,爱学习,爱分享。这一路上,首先感谢粉丝们805天一如既往的支持。我想团队拥有这些粉丝,是富有的,也是我们一直创作的动力。 是否记得毕业季,自己的豪言壮语。希望你毕业三年后,无论结果如何,不忘初心,继续前行。 机器视觉工程…

Flutter 中使用 Widgetbook 管理你的组件

Flutter 中使用 Widgetbook 管理你的组件 前言 Flutter 界面开发中我们有几个痛点 &#xff1a; 与设计师协作复用一套设计规范&#xff08;figma&#xff09; 可视化的管理你的组件代码&#xff08;基础组件、业务组件&#xff09; 不同设备尺寸测试你的组件 实时修改你的测试…

python并发编程:什么是并发编程?python对并发编程有哪些支持?

Python并发编程是指同时执行多个任务的编程模式。Python提供了多种实现并发编程的方式&#xff0c;包括多线程、多进程、协程、异步IO等。 为什么要引入并发编程 假设以下两个场景&#xff1a; 场景一: 一个网络爬虫&#xff0c;按顺序爬取花了一个小时&#xff0c;采用并发…

spring-模型数据和视图---视图解析器的说明以及大量代码演示

目录 spring-模型数据 ● 说明 应用实例需求 创建后面所有代码执行成功之后跳转的vote_ok.jsp页面 方式 1: 通过 HttpServletRequest放入 request 域 创建 Master类 创建Pet类 创建model_data.jsp 修改 VoteHandler增加方法 创建vote_ok.jsp, 显示数据 完成测试(Post…

[LeetCode周赛复盘] 第 103 场双周赛20230429

[LeetCode周赛复盘] 第 103 场双周赛20230429 一、本周周赛总结2656. K 个元素的最大和1. 题目描述2. 思路分析3. 代码实现 2657. 找到两个数组的前缀公共数组1. 题目描述2. 思路分析3. 代码实现 2658. 网格图中鱼的最大数目1. 题目描述2. 思路分析3. 代码实现 2659. 将数组清…

Docker consul

目录 一、Docker consul的容器服务和发现 ①服务注册与发现的含义 ②什么是consul 二、服务部署 ①部署consul服务 &#xff08;1&#xff09;查看集群信息 &#xff08;2&#xff09;通过http api获取集群信息 ②部署registrator服务器 &#xff08;1&#xff09;安装…

计算机视觉毕业后找不到工作怎么办?怒刷leetcode,还是另寻他路?

文章目录 一、计算机视觉毕业后找不到工作怎么办&#xff1f;二、大环境&#xff1a;前两年的泡沫太大三、还是要把自己的基本功搞扎实&#xff0c;真正的人才什么时候都紧缺四、转换思路&#xff0c;另投他坑五、要有毅力&#xff0c;心态放平六、最后的建议 一、计算机视觉毕…

应急加固初试(windows sever 2008)

前言 红中(hong_zh0) CSDN内容合伙人、2023年新星计划web安全方向导师、 华为MindSpore截至目前最年轻的优秀开发者、IK&N战队队长、 吉林师范大学网安大一的一名普通学生、搞网安论文拿了回大挑校二、 阿里云专家博主、华为网络安全云享专家、腾讯云自媒体分享计划博主 …

【服务器】威联通NAS文件共享 - 搭建SFTP服务并内网穿透实现在外远程访问

Yan-英杰的主页 悟已往之不谏 知来者之可追 C程序员&#xff0c;2024届电子信息研究生 目录 前言 1. 威联通NAS启用SFTP 2. 测试局域网访问 3. 内网穿透 3.1 威联通安装cpolar内网穿透 3.2 创建隧道 3.3 测试公网远程访问 4. 配置固定公网TCP端口地址 4.1 保留一个固定TCP…

chatGPT+Midjourney制作绘画本

chatGPTMidjourney制作绘画本 灵感来源&#xff1a;https://www.bilibili.com/video/BV1N24y1F7ga/?spm_id_from888.80997.embed_other.whitelist&vd_source6dd97671c42eb7cf111063714216bd0b 最终效果&#xff1a; 绘本故事 故事塑造能力弱的人可以使用chatGPT来帮助编…

JAVAWeb11-服务器渲染技术 -JSP-01-JSP基础

1. 现状 1、JSP 使用情况 2、Thymeleaf 使用情况, 通常和 SpringBoot 结合(也会讲) 3、Vue 使用情况 2. 学 JSP 前&#xff0c;老师要说的几句话 目前主流的技术是 前后端分离 (比如: Spring Boot Vue/React), 我们会讲的.[看一下]JSP 技术使用在逐渐减少&#xff…

C. Maximum Subrectangle(思维 + 考察两个数组相乘得到的矩阵的含义)

Problem - C - Codeforces 给定两个正整数数组 a 和 b&#xff0c;长度分别为 n 和 m。 定义矩阵 c 为一个 nm 的矩阵&#xff0c;其中 ci,jai⋅bj。 你需要在矩阵 c 中找到一个子矩形&#xff0c;使得它的元素之和最多为 x&#xff0c;并且它的面积&#xff08;即元素总数&a…