趣味编程:心形曲线
目录
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,包括两种信息,有路由信息和拓扑信息,简单的来说拓扑信息就是我连着谁,路由信息就是链路的地址…...
AtCoder 第409场初级竞赛 A~E题解
A Conflict 【题目链接】 原题链接:A - Conflict 【考点】 枚举 【题目大意】 找到是否有两人都想要的物品。 【解析】 遍历两端字符串,只有在同时为 o 时输出 Yes 并结束程序,否则输出 No。 【难度】 GESP三级 【代码参考】 #i…...
Auto-Coder使用GPT-4o完成:在用TabPFN这个模型构建一个预测未来3天涨跌的分类任务
通过akshare库,获取股票数据,并生成TabPFN这个模型 可以识别、处理的格式,写一个完整的预处理示例,并构建一个预测未来 3 天股价涨跌的分类任务 用TabPFN这个模型构建一个预测未来 3 天股价涨跌的分类任务,进行预测并输…...

IoT/HCIP实验-3/LiteOS操作系统内核实验(任务、内存、信号量、CMSIS..)
文章目录 概述HelloWorld 工程C/C配置编译器主配置Makefile脚本烧录器主配置运行结果程序调用栈 任务管理实验实验结果osal 系统适配层osal_task_create 其他实验实验源码内存管理实验互斥锁实验信号量实验 CMISIS接口实验还是得JlINKCMSIS 简介LiteOS->CMSIS任务间消息交互…...

多种风格导航菜单 HTML 实现(附源码)
下面我将为您展示 6 种不同风格的导航菜单实现,每种都包含完整 HTML、CSS 和 JavaScript 代码。 1. 简约水平导航栏 <!DOCTYPE html> <html lang"zh-CN"> <head><meta charset"UTF-8"><meta name"viewport&qu…...

全志A40i android7.1 调试信息打印串口由uart0改为uart3
一,概述 1. 目的 将调试信息打印串口由uart0改为uart3。 2. 版本信息 Uboot版本:2014.07; Kernel版本:Linux-3.10; 二,Uboot 1. sys_config.fex改动 使能uart3(TX:PH00 RX:PH01),并让boo…...
Java多线程实现之Thread类深度解析
Java多线程实现之Thread类深度解析 一、多线程基础概念1.1 什么是线程1.2 多线程的优势1.3 Java多线程模型 二、Thread类的基本结构与构造函数2.1 Thread类的继承关系2.2 构造函数 三、创建和启动线程3.1 继承Thread类创建线程3.2 实现Runnable接口创建线程 四、Thread类的核心…...

Reasoning over Uncertain Text by Generative Large Language Models
https://ojs.aaai.org/index.php/AAAI/article/view/34674/36829https://ojs.aaai.org/index.php/AAAI/article/view/34674/36829 1. 概述 文本中的不确定性在许多语境中传达,从日常对话到特定领域的文档(例如医学文档)(Heritage 2013;Landmark、Gulbrandsen 和 Svenevei…...

Golang——7、包与接口详解
包与接口详解 1、Golang包详解1.1、Golang中包的定义和介绍1.2、Golang包管理工具go mod1.3、Golang中自定义包1.4、Golang中使用第三包1.5、init函数 2、接口详解2.1、接口的定义2.2、空接口2.3、类型断言2.4、结构体值接收者和指针接收者实现接口的区别2.5、一个结构体实现多…...
webpack面试题
面试题:webpack介绍和简单使用 一、webpack(模块化打包工具)1. webpack是把项目当作一个整体,通过给定的一个主文件,webpack将从这个主文件开始找到你项目当中的所有依赖文件,使用loaders来处理它们&#x…...

Xcode 16 集成 cocoapods 报错
基于 Xcode 16 新建工程项目,集成 cocoapods 执行 pod init 报错 ### Error RuntimeError - PBXGroup attempted to initialize an object with unknown ISA PBXFileSystemSynchronizedRootGroup from attributes: {"isa">"PBXFileSystemSynchro…...