【C语言实现贝塞尔曲线】无聊人士专用程序,PS钢笔工具最初原形~

2023-05-16

简介

动态演示贝塞尔曲线的绘制过程。

支持任意点数、任意阶次。

点击鼠标右键,在鼠标位置将创建新的点。

按住鼠标左键拖动控制点。

空格键屏幕将清空。

一起来玩一玩吧!

运行效果

 

源码


// 程序名称:贝塞尔曲线
//
#include <math.h>				// sin
#include <stdint.h>				// uint64_t
#include <vector>				// array
#include <graphics.h>			// window

using std::vector;

#define	WIDTH			800		// 宽
#define	HEIGHT			600		// 高

struct Point { double x, y; };

// 初始化控制点
vector<Point> controlPoints;

Point operator+(const Point& a, const Point& b)
{
	return Point({ a.x + b.x, a.y + b.y });
}
Point operator*(double f, const Point& p)
{
	return Point({f*p.x, f*p.y});
}

// 计算二项式系数:C(n, k) = n! / (k!(n-k)!)
// 这里我们不用公式,使用 Pascal's Triangle
// [1],					n = 0
// [1, 1],				n = 1
// [1, 2, 1],			n = 2
// [1, 3, 3, 1],		n = 3
// [1, 4, 6, 4, 1],		n = 4
int C(int n, int k)
{
	vector<int> array(n + 1, 1);
	for (int i = 2; i <= n; i++)
		for (int j = i - 1; j > 0; j--)
			array[j] += array[j - 1];
	return array[k];
}

// 绘制贝塞尔曲线,绘制 t [0 - end_t] 范围
void drawBezier(const vector<Point>& points, double end_t)
{
	if (points.size() <= 1) return;
	int n = points.size() - 1; // 阶次为点数 - 1
	setfillcolor(RED);
	for (double t = 0.0; t <= end_t; t += 0.001)
	{
		Point p{ 0 };
		for (int k = 0; k <= n; k++)
			p = p + C(n, k) * pow(t, k) * pow(1 - t, (double)n - k) * points[k];
		// 位置四舍五入
		p.x += 0.5;
		p.y += 0.5;
		solidcircle((int)p.x, (int)p.y, 3);
	}
}

// 递归获取每一层的控制点
void bezierLevelPoints(vector<vector<Point>>& levels, double t)
{
	vector<Point> &pre = levels.back();
	vector<Point> next;
	int n = pre.size();
	if (n <= 1) return;
	
	for (int i = 0; i < n - 1; i++)
	{
		Point point = (1 - t) * pre[i] + t * pre[i + 1];
		next.push_back(point);
	}
	levels.push_back(next);
	bezierLevelPoints(levels, t);
}

// 处理输入事件
void processInput()
{
	ExMessage msg;
	while (peekmessage(&msg, EM_MOUSE | EM_KEY))
	{
		// 按住左键拖动控制点
		if (WM_MOUSEMOVE == msg.message && msg.lbutton)
		{
			for (auto& p : controlPoints)
			{
				int dx = (int)p.x - msg.x;
				int dy = (int)p.y - msg.y;
				if (dx * dx + dy * dy < 50)
				{
					p.x = msg.x;
					p.y = msg.y;
				}
			}
		}
		// 点击右键,创建控制点
		else if (WM_RBUTTONDOWN == msg.message && msg.rbutton)
		{
			controlPoints.push_back({ (double)msg.x, (double)msg.y });
		}
		// 按空格键清空
		else if (WM_KEYDOWN == msg.message && msg.vkcode == VK_SPACE)
		{
			controlPoints.clear();
		}
	}
}

// 画点、画线
void drawControlLines(vector<vector<Point>>& levels)
	{
	int k = levels.size();
	COLORREF color[8] = { YELLOW, BROWN, CYAN, LIGHTRED, WHITE, GREEN, MAGENTA, RED };
	for (int i = 0; i < k; i++)
	{
		vector<Point> cur = levels[i];
		int n = cur.size();
		setlinecolor(color[i&0XF]);
		setfillcolor(color[i&0XF]);
		for (auto& point : cur)
			solidcircle((int)(point.x + 0.5), (int)(point.y + 0.5), 3);
		if (k <= 2) continue;
		for (int j = 0; j < n - 1; j++)
			line((int)(cur[j].x + 0.5), (int)(cur[j].y + 0.5), \
				(int)(cur[j + 1].x + 0.5), (int)(cur[j + 1].y + 0.5));
	}
}

int main()
{
	TCHAR  buf[32];
	double t = 0.f;
	double time = -1.57079632679489661923;	// pi / 2;
	double deltaTime = 0.f;					// 当前帧和上一帧的时间差
	double lastTime = 0.f;
	double currentTime = 0.f;
	uint64_t start, now, frequency;
	initgraph(WIDTH, HEIGHT);
	BeginBatchDraw();
	QueryPerformanceCounter((LARGE_INTEGER*)&start);
	QueryPerformanceFrequency((LARGE_INTEGER*)&frequency);
	while (1)
	{
		cleardevice();
		QueryPerformanceCounter((LARGE_INTEGER*)&now);
		currentTime = (double)(now - start) / frequency;
		deltaTime = currentTime - lastTime;
		lastTime = currentTime;

		// 保证不同帧率下绘制速度一致
		time += 1.5 * deltaTime;
		t = 0.5 * (1 + sin(time));
		
		// 根据鼠标拖动更新控制点
		processInput();
		// 得到每一层的控制点
		vector<vector<Point>> levels({ controlPoints });
		bezierLevelPoints(levels, t);
		// 绘制控制点、控制线
		drawControlLines(levels);
		// 绘制 0 - t 范围内的贝塞尔曲线
		drawBezier(controlPoints, t);

		// 提示信息
		outtextxy(0,  0, L" Right Mouse Button to Create Points.");
		outtextxy(0, 16, L" Left  Mouse Button to Drag Points.");
		outtextxy(0, 32, L" Press SPACE to Clear.");
		swprintf_s(buf, _T(" t: %.3f"), t);
		outtextxy(0, 48, buf);
		swprintf_s(buf, _T(" time: %.0fms"), 1000 * deltaTime);
		outtextxy(0, 64, buf);
		swprintf_s(buf, _T(" fps: %d"), (int)(1.f / deltaTime));
		outtextxy(0, 80, buf);
		FlushBatchDraw();
	}
	return 0;
}

—————————————————————————————

想学C/C++可以私信我获取粉丝君¥,一起学习交流!

有大把的入门教程、源码资源、大佬解答等等......

—————————————————————————————

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【C语言实现贝塞尔曲线】无聊人士专用程序,PS钢笔工具最初原形~ 的相关文章

  • 经典算法之一:快速排序

    快速排序由于排序效率在同为O N logN 的几种排序方法中效率较高 xff0c 因此经常被采用 xff0c 再加上快速排序思想 分治法也确实实用 xff0c 因此很多软件公司的笔试面试 xff0c 包括像腾讯 xff0c 微软等知名IT公
  • 矩阵乘法测试

    对于时间的函数 gettimeofday 函数使用方法 xff1a http blog csdn net hurmishine article details 60326345 矩阵乘法测试 xff1a 代码 xff1a 1 为了试验简单
  • Python爬虫自动获取CSDN博客收藏文章

    CSDN的Python创意编程活动开始第一天就看到了 xff0c 但是认为自己是菜鸟 xff0c 就向当 吃瓜群众 xff0c 后来看到有好多人的代码是关于爬虫的 xff0c 当初我就是由于对爬虫 感兴趣才自学的Python 现在也打算参加
  • 全网最!详!细!Tarjan算法讲解。

    Tarjan算法讲解的博客网上找到三篇比较好的 现在都转载了 个人只研究了第一篇 正如博主所说 讲的标比较详细 清晰 剩下两篇也可以看一下 卿学姐视频讲解 https www bilibili com video av7330663 以下内
  • MFC计算机图形学(1)

    这学期上了计算机图形学 xff0c 用MFC来绘制简单的图形 下面就简单介绍一下用cv 43 43 来绘制图形 VC 43 43 安装 VC 43 43 我基本不用的 xff0c 平时写C C 43 43 的代码都用Code Blocks
  • MFC计算机图形学(2)

    这里呢 xff0c 先把上一讲的联系讲一下 一般人都用是一个一个的去画 xff0c 但是那样好麻烦 xff0c 计算机的有点就是容易处理重复的事情 xff0c 那就定义成一个画正方形函数吧 xff0c 每次调用就可以了 怎么自定义函数呢 x
  • MFC计算机图形学(3)

    之前我们已经可以画出直线和曲线了 但是算法虽容易理解 xff0c 但是复杂度高 xff0c 今天就介绍比较流行的DDA画线法 xff0c 还有 xff0c 对鼠标进行事件有所响应 xff0c 即 xff0c 在画板上 xff0c 鼠标左键单
  • Ubuntu18.04安装realsense viewer

    一 下载realsense安装包 mkdir p librealsense install cd librealsense install git clone b v2 31 0 https github com IntelRealSens
  • 用D435i录制自己的数据集运行ORBslam2并构建稠密点云

    一 录制rosbag 二 播放rosbag并用rviz查看topic xff0c 记下rgb和depth流话题名 三 用如下脚本 xff08 python2而不是3 xff09 保存rgb和depth图片同时生成rgb txt depth
  • Unrecoverable error: corrupted cluster config file.

    from https www cnblogs com topicjie p 7603227 html 缘起 正在欢乐的逗着孩子玩耍 xff0c 突然间来了一通电话 xff0c 值班人员告诉我误重启了一台服务器 xff0c 是我负责的服务 x
  • 树莓派3B+无屏幕和键盘配置树莓派WiFi和SSH

    前言 树莓派3B 43 安装系统Raspbian xff0c 默认的SSH是关闭的 xff0c 如何在无屏幕和键盘的情况下 xff0c 让笔记本通过WIFI访问树莓派 树莓派3B 43 发布后不久 xff0c 树莓派官方 Raspbian
  • ubuntu分区设置

    ubuntu分区设置 swap区 xff1a 逻辑分区 xff0c 虚拟内存类似 xff0c 大小和电脑内存一样大 xff1b boot区 xff1a 主分区 xff0c 引导系统的 xff0c 分配200M 500M xff0c 条件好些
  • 图像系统概述和名词解析

    图像系统组成 光源 xff08 包含人造光 自然光 闪光灯 xff09 照到物体上 xff0c 光线反射进入成像系统 xff0c 经过镜头 xff08 对于变焦镜头有驱动马达调整镜片位置 xff0c 实现变焦 xff09 光圈 滤光片 快门
  • 海思IQ图像清晰度调试策略

    总策略 影响清晰度的关键指标 xff1a 锐度 噪点和gamma Gamma调试步骤 YUVsharpen锐度调试 LDCI局部对比度调节 Dehaze调节 去雾算法主要用在有场景中做处理 xff0c 调整图像的对比度使更加清 去雾算法主要
  • 海思ISP曝光调整策略

    AE曝光调整 Exposure Attr 影响参数 xff1a ExpTimeRange Min Max 曝光时间Gain 各种增益控制Speed 曝光速度 xff08 影响到曝光收敛 xff0c AE闪烁 xff09 Compensati
  • ADS(ARM Developer Suite)安装与卸载中的问题(转)

    ADS用来对ARM的裸机代码进行编辑和调试 我在安装ADS1 2的过程中 xff0c 遇到了一个小问题 xff0c 写下来和大家分享一下解决方法 1 在安装程序 xff0c 进度条到100 时 xff0c 会一直停在那 xff0c 十几分钟
  • ucosIII 学习资料汇总

    网站 书籍 1 嵌入式实时操作系统uc OS III 邵贝贝译 这本书其实就是一本工具书 xff0c 我参考了官方的说明文档 xff0c 发现雷同很高 感觉就是官方说明文档翻译的 xff0c 用来应用查查接口还有点用 xff0c 不是十分推
  • USB协议传输结构

    USB作为数据通信标准 xff0c 固件可分为枚举配置和类协议部分 xff0c 枚举配置实现USB主机对设备的枚举和配置 xff0c 类协议实现设备各自的数据传输 usb2 0协议chapter8 protocol layer 1 USB协
  • 蓝牙HCI协议

    HCI 层位于蓝牙高层协议和低层协议之间 xff0c 提供了对基带控制器和链路管理器的命令以及访问蓝牙硬件的统一接口 它是我们实现自己的蓝牙设备要接触的第一个蓝牙协议 起着承上启下的作用 HCI通过包的方式来传送数据 命令和事件的 xff0

随机推荐

  • 标准USB设备请求命令

    一 标准的usb设备请求命令 控制传输是最重要和结构最复杂的一种传输类型 控制传输的 初始设置步骤 中包含了1 个8 字节的DATA0 数据包 参见图6 6 这8 字节的数据包是主机用来发送控制阶段中的请求命令的 而这些请求命令是主机配置U
  • 卡尔曼滤波基本公式推导(高斯乘积法)

    前言 卡尔曼滤波的推导这里给出两种推导方法 xff1a 一种是利用高斯乘积定理和贝叶斯公式推导出来 的 xff0c 另一种借用的是最小误差的思想 xff08 IMSE xff09 关于卡尔曼滤波的应用场景以及通俗的解释 xff0c 我相信各
  • 计算机组成原理(唐朔飞)

    计算机组成原理 唐朔飞 存储器 存储器分类 存储介质分类 半导体存储器磁表面存储器磁芯存储器 淘汰 存储方式 存储结构 存储器容量 地址总线 xff1a CPU能访问的地址宽度 xff0c 32地址线表示能访问2的32次方个存储单元地址 数
  • ubuntu配置静态IP、DNS地址

    虚拟机需要使用桥接上网 1 ifconfig 查看网卡信息 2 vi etc network interfaces 打开并编辑配置文件 配置说明 xff1a auto lo iface lo inet loopback auto ens33
  • c调用libcurl库发送GET 和 POST请求

    libcrul请求的基本套路流程 1 调用curl global init 初始化libcurl2 调用curl easy init 函数得到 easy interface型指针3 调用curl easy setopt 设置传输选项4 根据
  • LINUX 操作GPIO口

    两种方法 1 写驱动的方式 缺 2 通过linux提供的用户空间 终端控制 通过在用户空间上来操作GPIO xff0c 控制入口在 xff1a sys class gpio 首先确认内核里是否已选择上gpiolib的sysfs接口功能 默认
  • V4L2简介

    http work blog readthedocs org en latest v4l2 20intro html 第一章 V4L2简介 1 1 什么是v4l2 V4L2 xff08 Video4Linux的缩写 xff09 是Linux
  • 电子设计项目

    全套完整毕业设计智能家居控制系统设计 16X16点阵滚动显示 单片机595 43 138LED点阵 基于WIFI传输的单片机传感器设计 xff08 毕业论文 xff09 基于单片机设计的多点测温系统 数码管显示温度 基于单片机设计的公交报站
  • 视觉惯导里程计VIO综述

    最近阅读了VIO中的一些论文 xff0c 在这里做个汇总方便以后查阅 xff0c 如有问题欢迎指正 一 背景 VIO xff08 Visual Inertial Odometry xff09 视觉惯导里程计 xff0c VINS xff08
  • 【Cocos2d-X-2.1.4游戏引擎】发布第一个游戏

    有一段时间没更新博客了 xff0c 最近一直在写一个小游戏 xff0c 游戏在今天终于搞好了 xff0c 又可以开始写写博客 xff0c 打打dota的悠闲的日子了哈 看了十几天cocos2d x后 xff0c 也依照官网的例子写了个打飞机
  • 游戏升级之路

    七十一雾央原创 转载请注明 http blog csdn net hust xy 楼主学习编程有两年了 xff0c 决定向游戏发展大概就是半年前了 xff0c 在这里总结一下游戏方面的学习经历过 xff0c 给初学的朋友们参考下 xff0c
  • Nmap安装和使用详解

    文章目录 Nmap概述功能概述运行方式 Nmap安装Nmap参数详解目标说明主机发现端口扫描端口说明和扫描顺序服务与版本探测脚本扫描操作系统探测时间和性能防火墙 IDS规避和欺骗输出选项使用示例 常用扫描命令扫描ip地址或域名扫描整个网段扫
  • MSCKF_VIO:MSCKF的双目版本

    论文 xff1a MSCKF的双目版本 Robust Stereo Visual Inertial Odometry for Fast Autonomous Flight 下载地址 xff1a 点击 源码地址 xff1a https git
  • 功能测试,系统测试,兼容性测试,手工测试

    功能测试 功能测试一般需要根据编写的 测试用例 xff0c 执行测试用例 xff0c 执行的过程中提交缺陷 xff1b 功能测试一般至少会有两轮 xff0c 遇到比较麻烦的项目甚至会有三到四轮 xff0c 而每一轮测试都有其侧重点 xff0
  • C++ sdk 获取执行文件所在路径

    TCHAR szFilePath MAX PATH 43 1 61 0 GetModuleFileName NULL szFilePath MAX PATH tcsrchr szFilePath T 39 39 1 61 0 szFileP
  • UART串口

    一 串口的历史 首先 xff0c 串口对每一个做硬件和嵌入式软件的人来说 xff0c 就是一个必备的工具 xff0c 调试一个带MCU或者CPU的系统 我们在调试的过程中 xff0c 一般第一件事情 xff1a GPIO点灯 xff0c 第
  • C++软件工程师的发展前景如何?

    目前国内的嵌入式开发非常火 xff0c 而C 43 43 主要用于底层的嵌入式开发 驱动开发等 xff0c 也用于WINCE等嵌入式系统的应用软件开发 可以说C 43 43 软件工程师发展前景还是不错的 xff0c 下面就给大家具体介绍一下
  • 成为一名C++开发工程师,需要具备哪些条件?

    C 43 43 是C语言的继承 xff0c 它既可以进行C语言的过程化程序设计 xff0c 又可以进行以抽象数据类型为特点的基于对象的程序设计 xff0c 还可以进行以继承和多态为特点的面向对象的程序设计 C 43 43 擅长面向对象程序设
  • 一年精通,三年熟悉,五年了解,十年用过!C++真的这么难吗?

    C 43 43 有句俗话说 xff1a 一年精通 三年熟悉 五年了解 十年用过 如果可以把C 43 43 程序员分层的话 xff0c 看看你在第几层 xff1f 第0层 掌握基本的C 43 43 语法 xff0c 会写一些基本的if els
  • 【C语言实现贝塞尔曲线】无聊人士专用程序,PS钢笔工具最初原形~

    简介 动态演示贝塞尔曲线的绘制过程 支持任意点数 任意阶次 点击鼠标右键 xff0c 在鼠标位置将创建新的点 按住鼠标左键拖动控制点 空格键屏幕将清空 一起来玩一玩吧 xff01 运行效果 源码 程序名称 xff1a 贝塞尔曲线 inclu