趣味编程:心形曲线

目录

 1.序言

2.代码展示

3.代码详解

3.1 头文件包含

3.2 绘制坐标轴函数 

3.3 main 函数主体部分

4. 小结


 1.序言

2025年的第一篇博客就用这个笛卡尔心形图开篇吧,寓意着新年大家能够有心有所属,祝诸位程序猿 / 程序媛 能够早点遇到自己的另一半。 

2.代码展示

#define _CRT_SECURE_NO_WARNINGS#include <graphics.h>
#include <conio.h>
#include <math.h>#define WIDTH	640					// 窗口宽度
#define HEIGHT	480					// 窗口高度
#define PI		3.14159265			// π
#define DISPLAY 3					// 展示出来动圆与定圆的交点及心脏线当前所在点的尺寸
#define ARROW	5					// 箭头的尺寸
#define COPIES	600					// 份数,看要获得心形线上的多少个点
#define SECONDS 5					// 跑完一圈的秒数
using namespace std;// 画坐标抽
void drawCoordinateAxis()
{setlinecolor(DARKGRAY);line(WIDTH / 2, HEIGHT / 10, WIDTH / 2, HEIGHT / 10 * 9);line(WIDTH / 2, HEIGHT / 10, WIDTH / 2 + ARROW, HEIGHT / 10 + ARROW);line(WIDTH / 2, HEIGHT / 10, WIDTH / 2 - ARROW, HEIGHT / 10 + ARROW);line(WIDTH / 5, HEIGHT / 2, WIDTH / 5 * 4, HEIGHT / 2);line(WIDTH / 5 * 4, HEIGHT / 2, WIDTH / 5 * 4 - ARROW, HEIGHT / 2 - ARROW);line(WIDTH / 5 * 4, HEIGHT / 2, WIDTH / 5 * 4 - ARROW, HEIGHT / 2 + ARROW);
}int main()
{initgraph(WIDTH, HEIGHT);BeginBatchDraw();setlinecolor(BLUE);// 画坐标轴,定圆double r = min(WIDTH, HEIGHT) / 9;circle(WIDTH / 2, HEIGHT / 2, r);drawCoordinateAxis();setrop2(R2_XORPEN);double lastX = WIDTH / 2.0, lastY = HEIGHT / 2 - r;					// 上一个心形线的点的 x,y 值,初始值为 y 轴正方向上距原点 a 个单位长度的点for (double a = 0; !_kbhit(); a += PI / COPIES * 2)					// a 为当前弧度{double x = cos(3.0 / 2.0 * PI + a) * 2 * r + WIDTH / 2;			// 动圆这一个循环的圆心的 x 值double y = sin(3.0 / 2.0 * PI + a) * 2 * r + HEIGHT / 2;		// 动圆这一个循环的圆心的 y 值double FixedPoint_X = cos(PI / 2.0 + a * 2) * r + x;			// 当前循环动圆的定点对应的 x 值double FixedPoint_Y = sin(PI / 2.0 + a * 2) * r + y;			// 当前循环动圆的定点对应的 y 值double Contact_X = cos(PI / 2.0 + a) * r + x;					// 当前循环两圆切点在动圆上对应的 x 值double Contact_Y = sin(PI / 2.0 + a) * r + y;					// 当前循环两圆切点在动圆上对应的 y 值// 画出心形线,只用画这一个循环的点和上一个循环的点的线就行setrop2(R2_COPYPEN);setlinecolor(YELLOW);line(lastX, lastY, FixedPoint_X, FixedPoint_Y);setrop2(R2_XORPEN);lastX = FixedPoint_X;lastY = FixedPoint_Y;// 动圆与定圆的切点setfillcolor(GREEN);solidcircle(Contact_X, Contact_Y, DISPLAY);// 心形线当前点setfillcolor(LIGHTRED);solidcircle(lastX, lastY, DISPLAY);// 动圆setlinecolor(BLUE);circle(x, y, r);FlushBatchDraw();Sleep((double)(1000 * SECONDS) / (double)COPIES + 0.5);// 消除动圆setlinecolor(BLUE);circle(x, y, r);// 消除动圆与定圆的交点setfillcolor(GREEN);solidcircle(Contact_X, Contact_Y, DISPLAY);// 消除心形线当前所在点setfillcolor(LIGHTRED);solidcircle(lastX, lastY, DISPLAY);}_getch();EndBatchDraw();return 0;
}

3.代码详解

3.1 头文件包含
  • 包含了<graphic.h>头文件,这是用于图形绘制相关操作的库
  • <conio.h>头文件提供了一些控制台输入输出相关的函数,例如:_kbit_getch 等,用于检测键盘输入以及获取字符等操作。
  • <math.h>头文件包含数学相关的函数,像 sin ,cos 等三角函数在这里都会被用到。

3.2 绘制坐标轴函数 
// 画坐标抽
void drawCoordinateAxis()
{setlinecolor(DARKGRAY);line(WIDTH / 2, HEIGHT / 10, WIDTH / 2, HEIGHT / 10 * 9);line(WIDTH / 2, HEIGHT / 10, WIDTH / 2 + ARROW, HEIGHT / 10 + ARROW);line(WIDTH / 2, HEIGHT / 10, WIDTH / 2 - ARROW, HEIGHT / 10 + ARROW);line(WIDTH / 5, HEIGHT / 2, WIDTH / 5 * 4, HEIGHT / 2);line(WIDTH / 5 * 4, HEIGHT / 2, WIDTH / 5 * 4 - ARROW, HEIGHT / 2 - ARROW);line(WIDTH / 5 * 4, HEIGHT / 2, WIDTH / 5 * 4 - ARROW, HEIGHT / 2 + ARROW);
}

这个函数的功能是绘制坐标轴。首先通过 setlinecolor(DARKGRAY)设置线条颜色为深灰色,然后绘制纵轴:

  • 从窗口高度的十分之一位置到十分之九位置绘制一条垂直的直线作为纵轴主体(line(WIDTH)/ 2,HEIGHT / 10,HEIGHT / 10 * 9)
  • 接着在纵轴顶端绘制向上和向下的箭头,通过两条斜线来实现

 在绘制横轴:

  • 从窗口的五分之一位置到五分之四位置绘制一条水平的直线作为横轴主体。(line(WIDTH / 5,HEIGHT / 2,WIDTH / 5 *4,HEIGHT / 2))
  • 最后在横轴有段绘制向左或向右的箭头
3.3 main 函数主体部分
  • 初始化图形窗口与相关设置
int main()
{initgraph(WIDTH, HEIGHT);BeginBatchDraw();setlinecolor(BLUE);

首先通过 initgraph(WIDTH,HIGHT) 初始化一个指定宽度和高度(由前面宏定义 WIDTHHEIGHT 确定)。接着调用 BeginBatchDraw() 开始批量绘图模式,这种模式可以减少图形绘制过程中的闪烁现象,提高显示效果。追后通过 setlinecolor(BLUE)设置后续绘制线条的颜色为蓝色。

  • 设置绘图模式与初始化相关变量 
    setrop2(R2_XORPEN);double lastX = WIDTH / 2.0, lastY = HEIGHT / 2 - r;                  // 上一个心形线的点的 x,y 值,初始值为 y 轴正方向上距原点 a 个单位长度的点

通过 setrop2(R2_XORPEN) 设置绘图的光栅操作模式后为异或模式(XOR),这种模式在后续绘制图形是可以方便地实现图形的叠加和擦除效果。然后初始化 lastX lastY ,它们用于记录上一个绘制的心形线点的坐标,初始值设定为在 y 轴正方向上距离原点定圆半径 r 长度的点坐标(也就是心形线起始点在 y轴 正半轴上的情况)。

  • 循环绘制心形线及相关图形
    for (double a = 0;!_kbhit(); a += PI / COPIES * 2)                  // a 为当前弧度{double x = cos(3.0 / 2.0 * PI + a) * 2 * r + WIDTH / 2;          // 动圆这一个循环的圆心的 x 值double y = sin(3.0 / 2.0 * PI + a) * 2 * r + HEIGHT / 2;          // 动圆这一个循环的圆心的 y 值double FixedPoint_X = cos(PI / 2.0 + a * 2) * r + x;              // 当前循环动圆的定点对应的 x 值double FixedPoint_Y = sin(PI / 2.0 + a * 2) * r + y;              // 当前循环动圆的定点对应的 y 值double Contact_X = cos(PI / 2.0 + a) * r + x;                    // 当前循环两圆切点在动圆上对应的 x 值double Contact_Y = sin(PI / 2.0 + a) * r + y;                    // 当前循环两圆切点在动圆上对应的 y 值

这是一个关键的循环,循环条件是!_kbhit(),即只要没有键盘按键按下就一直循环,每次循环中a(代表弧度)按一定的增量(PI / COPIES * 2,也就是将整个圆周按照COPIES份进行细分,每次增加对应的弧度值)增加。
在循环内:

  • 首先根据当前弧度a计算动圆在这一时刻的圆心坐标(x, y),这里利用三角函数结合定圆半径r以及窗口中心坐标来计算,动圆的圆心运动轨迹是围绕着一个特定的路径(从代码中的三角函数表达式可以看出是符合一定规律的圆形轨迹,且与最终要绘制的心形线相关)。
  • 接着计算当前循环下动圆的定点坐标(FixedPoint_X, FixedPoint_Y),这个定点是与绘制心形线相关的一个关键位置点,通过特定的三角函数关系结合动圆圆心坐标和定圆半径计算得出。
  • 然后计算当前循环两圆切点在动圆上对应的坐标(Contact_X, Contact_Y),同样是基于三角函数、动圆圆心坐标以及定圆半径来确定。
        // 画出心形线,只用画这一个循环的点和上一个循环的点的线就行setrop2(R2_COPYPEN);setlinecolor(YELLOW);line(lastX, lastY, FixedPoint_X, FixedPoint_Y);setrop2(R2_XORPEN);lastX = FixedPoint_X;lastY = FixedPoint_Y;

先将绘图模式切换为R2_COPYPEN正常的绘制模式,直接绘制图形),设置线条颜色为黄色,然后通过line函数绘制从上一个心形线点(坐标(lastX, lastY))到当前循环计算出的心形线点(坐标(FixedPoint_X, FixedPoint_Y))的线段,这样逐步绘制线段就可以呈现出心形线的形状。绘制完后再切换回R2_XORPEN模式,并且更新lastXlastY为当前绘制的心形线点坐标,用于下一次循环绘制时作为上一个点的坐标。

4. 小结

以上便是本篇博客的所有内容了,最后,祝大家新的一年,愿你我笑容灿烂如花,生活甜蜜如蜜糖。过去的遗憾就让它过去,未来的美好我们一同迎接。跨年之夜,祝你我岁岁平安,事事顺心,步步高升。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

安装和配置 Apache 及 PHP

安装和配置 Apache 及 PHP # 1. 停止当前 Apache 服务 sudo apachectl stop# 2. 清除现有的 Apache 配置和文件 sudo rm -rf /etc/apache2 sudo rm -rf /usr/sbin/httpd sudo rm -rf /Library/WebServer# 3. 使用 Homebrew 安装 Apache brew install httpd# 4. 启动 Apache su…

解决uniapp H5页面限制输入框只能输数字问题

工作记录 最最近在做 uniapp 开发的移动端 H5 页面&#xff0c;有个需求是金额输入框只能输入数字&#xff0c;不能输入小数点和其他字符&#xff0c;经过各种尝试&#xff0c;发现其他字符可以通过正则过滤掉&#xff0c;但是输入小数点的话&#xff0c;因为没有触发 input 和…

group by 执行顺序

后面也会持续更新&#xff0c;学到新东西会在其中补充。 建议按顺序食用&#xff0c;欢迎批评或者交流&#xff01; 缺什么东西欢迎评论&#xff01;我都会及时修改的&#xff01; 感谢各位大佬写的文章让我学到很多东西&#xff01;只是在各位大佬的基础加了我自己的思路&a…

通过爬虫方式实现视频号助手发布视频

1、将真实的cookie贴到解压后目录中cookie.txt文件里,修改python代码里的user_agent和video_path, cover_path等变量的值,最后运行python脚本即可; 2、运行之前根据import提示安装一些常见依赖,比如requests等; 3、2025年1月份最新版; 代码如下: import json import…

Docker入门常用命令总结

1.从远程仓库拉取一个纯净的镜像 docker pull docker .io/centos 2.创建并进入容器&#xff08;左外右内&#xff09; docker run --name xxx -dit 镜像id&#xff08;镜像名称:Tag&#xff09; /bin/bash 【参数必须放在镜像ID之前】 -i 让Docker分配一个伪终端&#xff0c;并…

初学stm32 --- FSMC驱动LCD屏

目录 FSMC简介 FSMC框图介绍 FSMC通信引脚介绍 FSMC_NWE 的作用 FSMC_NWE 的时序关系 FSMC_NOE 的含义 FSMC_NOE 的典型用途 FSMC_NOE 的时序关系 使用FSMC驱动LCD FSMC时序介绍 时序特性中的 OE ILI9341重点时序&#xff1a; FSMC地址映射 HADDR与FSMC_A关系 LCD的…

CSS系列(47)-- Animation Timeline详解

前端技术探索系列&#xff1a;CSS Animation Timeline详解 ⏱️ 致读者&#xff1a;探索动画时间线的艺术 &#x1f44b; 前端开发者们&#xff0c; 今天我们将深入探讨 CSS Animation Timeline&#xff0c;这个强大的动画控制特性。 基础概念 &#x1f680; 时间线定义 …

Nginx - 整合lua 实现对POST请求的参数拦截校验(不使用Openresty)

文章目录 概述步骤 1: 安装 Nginx 和 Lua 模块步骤 2: 创建 Lua 脚本用于参数校验步骤 3: 配置 Nginx 使用 Lua 脚本写法二&#xff1a; 状态码写法三 &#xff1a; 返回自定义JSON复杂的正则校验 步骤 4: 测试和验证ngx.HTTP_* 枚举值 概述 一个不使用 OpenResty 的 Nginx 集…

GRAPE——RLAIF微调VLA模型:通过偏好对齐提升机器人策略的泛化能力(含24年具身模型汇总)

前言 24年具身前沿模型大汇总 过去的这两年&#xff0c;工作之余&#xff0c;我狂写大模型与具身的文章&#xff0c;加之具身大火&#xff0c;每周都有各种朋友通过CSDN私我及我司「七月在线」寻求帮助/指导(当然&#xff0c;也欢迎各大开发团队与我司合作共同交付&#xff09…

Appium 2.0:移动自动化测试的革新之旅

关注开源优测不迷路 大数据测试过程、策略及挑战 测试框架原理&#xff0c;构建成功的基石 在自动化测试工作之前&#xff0c;你应该知道的10条建议 在自动化测试中&#xff0c;重要的不是工具 在移动应用开发的领域中&#xff0c;Appium 作为一款强大的自动化测试工具&#xf…

Mysql SQL 超实用的7个日期算术运算实例(10k)

文章目录 前言1. 加上或减去若干天、若干月或若干年基本语法使用场景注意事项运用实例分析说明2. 确定两个日期相差多少天基本语法使用场景注意事项运用实例分析说明3. 确定两个日期之间有多少个工作日基本语法使用场景注意事项运用实例分析说明4. 确定两个日期相隔多少个月或多…

VSCode设置ctrl或alt+mouse(left)跳转

总结&#xff1a; &#xff08;1&#xff09;VSCode初次远程连接服务器时&#xff0c;需要在服务器上下载 python 拓展&#xff0c;然后选择对应的环境 &#xff08;2&#xff09;VSCode设置ctrl或altmouse(left)跳转到定义

VBA 64位API声明语句第005讲

跟我学VBA&#xff0c;我这里专注VBA, 授人以渔。我98年开始&#xff0c;从源码接触VBA已经20余年了&#xff0c;随着年龄的增长&#xff0c;越来越觉得有必要把这项技能传递给需要这项技术的职场人员。希望职场和数据打交道的朋友&#xff0c;都来学习VBA,利用VBA,起码可以提高…

可扩展性设计架构模式——事件驱动架构

事件驱动架构&#xff08;Event-Driven Architecture, EDA&#xff09;是一种可扩展性设计软件架构模式&#xff0c;它通过事件来触发和通信&#xff08;以事件为核心&#xff09;&#xff0c;实现不同系统组件之间的解耦&#xff08;促进应用程序或系统部件之间的松耦合通信&a…

covid-vaccine-availability-using-flask-server

使用烧瓶服务器获得 Covid 疫苗 原文:https://www . geesforgeks . org/co vid-疫苗-可用性-使用-烧瓶-服务器/ 在本文中&#xff0c;我们将使用 Flask Server 构建 Covid 疫苗可用性检查器。 我们都知道&#xff0c;整个世界都在遭受疫情病毒的折磨&#xff0c;唯一能帮助我们…

设计模式从入门到精通之(三)单例模式

单例模式&#xff1a;只留一份独特的存在 在现代软件设计中&#xff0c;有些对象是必须确保"独一无二"的&#xff0c;比如程序中的配置管理器、线程池、数据库连接等。如果允许这些对象被反复创建&#xff0c;不仅会浪费系统资源&#xff0c;还可能导致程序逻辑出错。…

WordPress Crypto 插件 身份认证绕过漏洞复现(CVE-2024-9989)

0x01 产品简介 WordPress Crypto插件是指那些能够为WordPress网站提供加密货币支付、信息显示或交易功能的插件。这些插件通常与WordPress电子商务插件(如WooCommerce)集成,使网站能够接受多种加密货币支付,或展示加密货币实时信息。支持多种加密货币支付,付款直接进入钱…

hashMap追问

HashMap 7/8区别 不同点&#xff1a; &#xff08;1&#xff09;JDK1.7用的是头插法&#xff0c;而JDK1.8及之后使用的都是尾插法&#xff0c;那么他们为什么要这样做呢&#xff1f;因为JDK1.7是用单链表进行的纵向延伸&#xff0c;当采用头插法时会容易出现逆序且环形链表死…

网络安全:路由技术

概述 路由技术到底研究什么内容 研究路由器寻找最佳路径的过程 路由器根据最佳路径转发数据包 知识点&#xff0c;重要OSRF,BGP1.静态路由原理 路由技术分类 静态路由和动态路由技术 静态路由&#xff1a;是第一代路由技术&#xff0c;由网络管理员手工静态写路由/路径告知路…

IIS设置IP+端口号外网无法访问的解决方案

在IIS将站点设置为IP端口访问&#xff0c;假设端口为8080&#xff0c;设好后&#xff0c;服务器上可以访问&#xff0c;外网无法访问。 通常是端口8080没有加入【入站规则】的缘故&#xff0c;将8080端口加入【入站规则】即可&#xff0c;操作如下&#xff1a; 一、ctrlr 输入 …