趣味编程:心形曲线
目录
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) 初始化一个指定宽度和高度(由前面宏定义 WIDTH 和HEIGHT 确定)。接着调用 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
模式,并且更新lastX
和lastY
为当前绘制的心形线点坐标,用于下一次循环绘制时作为上一个点的坐标。
4. 小结
以上便是本篇博客的所有内容了,最后,祝大家新的一年,愿你我笑容灿烂如花,生活甜蜜如蜜糖。过去的遗憾就让它过去,未来的美好我们一同迎接。跨年之夜,祝你我岁岁平安,事事顺心,步步高升。
相关文章:

趣味编程:心形曲线
目录 1.序言 2.代码展示 3.代码详解 3.1 头文件包含 3.2 绘制坐标轴函数 3.3 main 函数主体部分 4. 小结 1.序言 2025年的第一篇博客就用这个笛卡尔心形图开篇吧,寓意着新年大家能够有心有所属,祝诸位程序猿 / 程序媛 能够早点遇到自己的另一半。…...
C# 设计模式(结构型模式):享元模式
C# 设计模式(结构型模式):享元模式 (Flyweight Pattern) 在软件开发中,尤其是在处理大量对象时,我们常常会面临内存和性能上的挑战。当多个对象具有相似的状态时,通常会占用大量的内存资源,从而…...

计算机毕业设计Django+Tensorflow音乐推荐系统 音乐可视化 卷积神经网络CNN LSTM音乐情感分析 机器学习 深度学习 Flask
温馨提示:文末有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:文末有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:文末有 CSDN 平台官方提供的学长联系方式的名片! 作者简介:Java领…...
mysql 死锁案例及简略分析
准备数据 # 创一个测试表,存储引擎使用 innodb create table test_lock (id int primary key auto_increment,name varchar(20),age int )engine innodb;insert into test_lock (name,age) values (ionc001,10); insert into test_lock (name,age) values (ionc00…...

第四届计算机、人工智能与控制工程
第四届计算机、人工智能与控制工程 The 4th International Conference on Computer, Artificial Intelligence and Control Engineering 重要信息 大会官网:www.ic-caice.net 大会时间:2025年1月10-12日 大会地点:中国合肥 (安徽大学磬苑…...

RIP配置实验
RIP配置实验 案例简介 天一公司下属三个分公司,属于不同的地区,三个公司之间用路由器连接,路由器名称分别为分别为 Router0、Router1、Router2,请把一公司的部门pc0,通过二公司路由器,连接三公司的部门pc1,公司之间通…...

C# 整型、浮点型 数值范围原理分析
总目录 前言 一、整型、浮点型 数值范围列表 二、什么是大小、范围 在上面的列表中,每个数据类型都有自己的Range (范围) 和 Size (大小)。 1. 范围 范围好理解,就是对应数据类型的数据范围,如 sbtyte 的数据范围是 -128~127,超…...

Adobe Acrobat Pro DC 2023 下载安装教程,附详细图文
简介: Adobe Acrobat Pro DC 2023 是由 Adobe 公司推出的一款全面的 PDF 编辑、查看和管理软件。这款软件无论是个人用户还是企业级用户,都可以凭借其强大的功能满足不同的需求。作为一款业内领先的 PDF 处理工具,Adobe Acrobat Pro DC 不仅…...

stable diffusion秋叶启动器安装roop插件
方法简洁明了: 第一步:下载秋叶启动器 第二步:输入网址:https://visualstudio.microsoft.com/zh-hans/downloads/,下载vs安装程序,安装开始会自动弹出如下窗口,选择2个环境:Python开…...
7-14 统计工龄
给定公司多名员工的工龄,按输入工龄顺序输出每个工龄段有多少员工。 输入格式: 给出多个整数,即每个员工的工龄,范围在[0, 50]。 输出格式: 按输入工龄顺序输出每个工龄的员工个数,格式为:“工龄:人数”。 每项占一…...

OLED的显示
一、I2C I2C时序:时钟线SCL高电平下:SDA由高变低代表启动信号,开始发送数据;SCL高电平时,数据稳定,数据可以被读走,开始进行读操作,SCL低电平时,数据发生改变࿱…...
本地测试文件解析
PostMapping("/test") public void test() throws IOException {Path csvFile Paths.get("D:\\test/27.csv");//虚拟机退出时删除临时文件csvFile.toFile().deleteOnExit();List<String> list Files.readAllLines(csvFile, Charset.forName("…...

Elasticsearch JavaRestClient版
文章目录 初始化RestHighLeveClient(必要条件)索引库操作1.创建索引库(4步)2.删除索引库(3步)3.判断索引库是否存在(3步)4.总结:四步走 文档操作1.创建文档(4…...

ubuntu 使用s3fs配置自动挂载对象存储
一、环境准备 1.有访问对象存储权限的AKSK 2.服务器、对象存储 二、实施步骤 sudo apt update sudo apt install s3fs echo "AK:SK" >/home/ubuntu/.passwd-s3fs ---位置自定义 chmod 600 /home/ubuntu/.passwd-s3fs ---权限必须要有 mkdir /data sudo s3fs …...

SQL字符串截取函数——Left()、Right()、Substring()用法详解
SQL字符串截取函数——Left()、Right()、Substring()用法详解 1. LEFT() 函数:从字符串的左侧提取指定长度的子字符串。 LEFT(string, length)string:要操作的字符串。length&#x…...

关系分类(RC)模型和关系抽取(RE)模型的区别
目标不同 关系分类模型:对给定的实体对在给定句子中预测其关系类型。两阶段(RC) 关系抽取模型:从句子中识别出所有潜在实体对,并为其预测关系类型。一阶段(NERRE) 训练/预测阶段输入输出数据不…...
什么是索引
在数据库管理系统中,索引是一种数据结构,用于快速定位数据库表中的特定记录。索引类似于一本书的目录,可以帮助数据库引擎迅速找到所需的数据,而不必扫描整个表。 类型:常见的数据库索引类型包括B树索引、哈希索引、全…...

OJ随机链表的复制题目分析
题目内容: 138. 随机链表的复制 - 力扣(LeetCode) 分析: 这道题目,第一眼感觉非常乱,这是正常的,但是我们经过仔细分析示例明白后,其实也并不是那么难。现在让我们一起来分析分析…...

UE5材质节点Distance
Distance可以计算两个物体间的距离,可以用来做过渡效果 当相机和物体距离3000的时候,就会渐渐从蓝过渡到红色,除以500是为了平滑过渡...

OSPF - SPF算法简述
SPF全称最短路径树算法,相信学过数据结构朋友应该看起来很熟悉 在一个区域内的路由器都会产生描述自己网络连接信息的LSA,包括两种信息,有路由信息和拓扑信息,简单的来说拓扑信息就是我连着谁,路由信息就是链路的地址…...

(二)原型模式
原型的功能是将一个已经存在的对象作为源目标,其余对象都是通过这个源目标创建。发挥复制的作用就是原型模式的核心思想。 一、源型模式的定义 原型模式是指第二次创建对象可以通过复制已经存在的原型对象来实现,忽略对象创建过程中的其它细节。 📌 核心特点: 避免重复初…...

跨链模式:多链互操作架构与性能扩展方案
跨链模式:多链互操作架构与性能扩展方案 ——构建下一代区块链互联网的技术基石 一、跨链架构的核心范式演进 1. 分层协议栈:模块化解耦设计 现代跨链系统采用分层协议栈实现灵活扩展(H2Cross架构): 适配层…...
什么是EULA和DPA
文章目录 EULA(End User License Agreement)DPA(Data Protection Agreement)一、定义与背景二、核心内容三、法律效力与责任四、实际应用与意义 EULA(End User License Agreement) 定义: EULA即…...

自然语言处理——Transformer
自然语言处理——Transformer 自注意力机制多头注意力机制Transformer 虽然循环神经网络可以对具有序列特性的数据非常有效,它能挖掘数据中的时序信息以及语义信息,但是它有一个很大的缺陷——很难并行化。 我们可以考虑用CNN来替代RNN,但是…...

IT供电系统绝缘监测及故障定位解决方案
随着新能源的快速发展,光伏电站、储能系统及充电设备已广泛应用于现代能源网络。在光伏领域,IT供电系统凭借其持续供电性好、安全性高等优势成为光伏首选,但在长期运行中,例如老化、潮湿、隐裂、机械损伤等问题会影响光伏板绝缘层…...
Java线上CPU飙高问题排查全指南
一、引言 在Java应用的线上运行环境中,CPU飙高是一个常见且棘手的性能问题。当系统出现CPU飙高时,通常会导致应用响应缓慢,甚至服务不可用,严重影响用户体验和业务运行。因此,掌握一套科学有效的CPU飙高问题排查方法&…...

Python Ovito统计金刚石结构数量
大家好,我是小马老师。 本文介绍python ovito方法统计金刚石结构的方法。 Ovito Identify diamond structure命令可以识别和统计金刚石结构,但是无法直接输出结构的变化情况。 本文使用python调用ovito包的方法,可以持续统计各步的金刚石结构,具体代码如下: from ovito…...
Leetcode33( 搜索旋转排序数组)
题目表述 整数数组 nums 按升序排列,数组中的值 互不相同 。 在传递给函数之前,nums 在预先未知的某个下标 k(0 < k < nums.length)上进行了 旋转,使数组变为 [nums[k], nums[k1], …, nums[n-1], nums[0], nu…...
深入解析 ReentrantLock:原理、公平锁与非公平锁的较量
ReentrantLock 是 Java 中 java.util.concurrent.locks 包下的一个重要类,用于实现线程同步,支持可重入性,并且可以选择公平锁或非公平锁的实现方式。下面将详细介绍 ReentrantLock 的实现原理以及公平锁和非公平锁的区别。 ReentrantLock 实现原理 基本架构 ReentrantLo…...

Java设计模式:责任链模式
一、什么是责任链模式? 责任链模式(Chain of Responsibility Pattern) 是一种 行为型设计模式,它通过将请求沿着一条处理链传递,直到某个对象处理它为止。这种模式的核心思想是 解耦请求的发送者和接收者,…...