文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

C语言如何实现绘制LoveBeat爱心曲线

2023-07-05 10:20

关注

这篇文章主要讲解了“C语言如何实现绘制LoveBeat爱心曲线”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“C语言如何实现绘制LoveBeat爱心曲线”吧!

心形曲线

给出心形曲线参数方程如下:

x = sin^3(θ)

y = (13 * cos(θ) - 5 * cos(2θ) - 3 * cos(3θ) - cos(4θ)) / 16

对 x, y 同时乘以半径 R,即可对其放大

通过上述方程可得到若干在曲线上的点,记为集合 S

曲线内点的生成

对于内部的点,我们则将S向内扩散,使其符合指数分布,得到S'

令 e ∈ [m, n] 且 e ~ E(λ)

对 P (x, y) ∈ S 作向内扩散得到点 P' ∈ S':

P' = (x, y) * e

扩散程度取决于参数 m, n, λ

曲线外点的生成

对于外部的点,我们则将S向外扩散,使其符合均匀分布,得到S''

令 u ~ U [1, 1 + b]

对 P (x, y) ∈ S 作向外扩散得到点 P'' ∈ S'':

P'' = (x, y) * u

扩散程度取决于参数 b

制作动画

有了上述三个点集合后,就可以描述一个静态的心形图案

现在,我们为其添加周期动画效果

首先引入时间参数 t 和周期函数 T(t) = sin^2(t) (可以是其他周期函数,视效果而定)

对于 P ∈ S U S'

其周期缩放程度与其到原点的距离 d 成反比,可用 R/d 来衡量 (R为心形曲线的半径)

为其添加阶数 i 来扩大距离对缩放程度的影响 (R/d)^i

我们可以得到如下函数

d' = d * (1 + a * T(t) * (R/d)^i)

外部的点在内部点收缩到最小值时,到达最大值,所以和上式相差一个相位

我们可以还做一些额外的处理:

示例代码

// 环境:Visual Studio 2022 C++ 20// EasyX版本:EasyX 2022-9-1 #include <random>#include <unordered_set>#include <graphics.h>#include <cmath> #define PINK LIGHTRED | 0x6055ff#define LIGHTPINK LIGHTRED | 0x6655ff#define DRAW(vecs, color) for(auto& vec : vecs)Draw(vec, color, distribution(engine)) using namespace std; constexpr float Pi = 3.1416f;constexpr float Rad = Pi / 180;constexpr int ScreenWidth = 800;constexpr int ScreenHeight = 600;constexpr int OX = ScreenWidth / 2;constexpr int OY = ScreenHeight / 2; static default_random_engine engine; struct Vec2{float X = .0f;float Y = .0f; Vec2() {}Vec2(float x, float y) { X = x; Y = y; } int GetX() const { return static_cast<int>(X); }int GetY() const { return static_cast<int>(Y); }float Magnitude() const { return sqrt(X * X + Y * Y); }Vec2 operator*(float num) const{ return Vec2(X * num, Y * num); } struct VecHash{size_t operator()(const Vec2& vec) const noexcept{return std::hash<float>()(vec.X) ^ std::hash<float>()(vec.Y);}}; struct VecCompare{bool operator()(const Vec2& vec1, const Vec2& vec2) const noexcept{return fabsf(vec1.X - vec2.X) < 1e-2f && fabsf(vec1.Y - vec2.Y) < 1e-2f;}};};using VecSet = unordered_set<Vec2, Vec2::VecHash, Vec2::VecCompare>;  float CalculateX(float t){ return powf(sin(t), 3.0f); }float CalculateY(float t){ return -(13 * cosf(t) - 5 * cosf(2 * t) - 2 * cosf(3 * t) - cosf(4 * t)) / 16.0f; }  VecSet InitHeart(float startAngle, float endAngle, float radius, size_t count){VecSet set;float rad = startAngle * Rad;float step = (endAngle - startAngle) * Rad / count;float endRad = endAngle * Rad; for (; rad < endRad; rad += step)        set.insert(Vec2(CalculateX(rad) * radius, CalculateY(rad) * radius)); return set;}  VecSet BuildInside(const VecSet& set, size_t frequency, float lambda, float range, float min){VecSet retSet;exponential_distribution<float> distribution(lambda); for (size_t i = 0; i < frequency; i++){for (auto& vec : set){float pX = distribution(engine);float scalarX = (pX < 1.0 ? 1.0f - pX : 1.0f) * range + min; float pY = distribution(engine);float scalarY = (pY < 1.0 ? 1.0f - pY : 1.0f) * range + min; retSet.insert(Vec2(vec.X * scalarX, vec.Y * scalarY));}} return retSet;}  VecSet BuildOutside(const VecSet& set, size_t frequency, float max){VecSet retSet;uniform_real_distribution<float> distribution(1.0f, max); for (size_t i = 0; i < frequency; i++){for (auto& vec : set)            retSet.insert(Vec2(vec.X * distribution(engine), vec.Y *  distribution(engine)));} return retSet;}  VecSet Undulate(const VecSet& set, float radius){VecSet retSet;uniform_real_distribution<float> distribution(-radius, radius); for (auto& vec : set)retSet.insert(Vec2(vec.X + distribution(engine), vec.Y + distribution(engine))); return retSet;}  VecSet Zoom(const VecSet& set, float factor, float radius, float t, float idx){VecSet retSet; for (auto& vec : set)        retSet.insert(vec * (1.0f + factor * sin(t * Pi) * powf((radius / vec.Magnitude()), idx))); return retSet;}  void Draw(const Vec2& vec, COLORREF color, int radius){putpixel(vec.GetX() + OX, vec.GetY() + OY, color); if(radius >= 2)putpixel(vec.GetX() + OX + 1, vec.GetY() + OY, color); if(radius >= 3)putpixel(vec.GetX() + OX, vec.GetY() + OY + 1, color);} int main(){float radius = 160.0f;auto border = InitHeart(0, 360, radius, 480);auto inside = BuildInside(border, 30, 5.0f, 0.85f, 0.15f); initgraph(ScreenWidth, ScreenHeight);BeginBatchDraw(); float t = .0f;float tStep = 0.05f;uniform_int_distribution<int> distribution(1, 3);ExMessage msg{}; while(!peekmessage(&msg, EX_KEY)){auto ps1 = Zoom(border, 0.1f, radius, t, 1.3f);auto ps2 = Undulate(Zoom(inside, 0.1f, radius, t, 1.3f), 3.0f);auto ps3 = Undulate(BuildOutside(border, 10 - static_cast<size_t>(sin(t) * 5), 1.35f - sin(t) * 0.15f), 3.0f); DRAW(ps1, LIGHTPINK);DRAW(ps2, LIGHTPINK);DRAW(ps3, PINK); FlushBatchDraw();Sleep(40); t += tStep;if (t > 1.0f)t = .0f; cleardevice();} EndBatchDraw();closegraph(); return 0;}

感谢各位的阅读,以上就是“C语言如何实现绘制LoveBeat爱心曲线”的内容了,经过本文的学习后,相信大家对C语言如何实现绘制LoveBeat爱心曲线这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是编程网,小编将为大家推送更多相关知识点的文章,欢迎关注!

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     807人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     351人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     314人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     433人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     221人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯