画贝塞尔曲线的函数
2022-2-17 ~ 2022-8-28
(1)
程序截图
简单说明
这个函数就是
void drawBezierCurve(COLORREF color, const unsigned int len, ...)
color 是贝塞尔曲线的颜色,len 是画出贝塞尔曲线所需要的点的个数,最少 1 个,不要乱传。之后的参数传的就是画出贝塞尔曲线要的点,数据类型为 Vec2。
这个函数实现的基础是参数方程,用参数方程将一条直线转化为一个参数的方程,如:
A * x + B * y + C=0 可以转化为 x = x0 - B * t;y = y0 + A * t,x0、y0 为直线上任意一个点的横纵坐标值,t 为未知参数。
对于一条线段,可以根据线段上两个端点转化为参数方程:
x = x0 + (x1 - x0) * t
y = y0 + (y1 - y0) * t
t ∈ [0, 1]
将这条线段分为 CURVEPIECE 份,t 从 0 到 1 一份一份地加,就能得到这条线段上均匀分布的 CURVEPIECE 个点。
贝塞尔曲线就是对 n 个点连线组成的 n 条(线段上对应份的点)的连线的 (n - 1) 条(线段的对应份点)的连线的……直到最后 1 条线段上(对应份点的连线)。
这个曲线的算法如果用递归的话可能会占用很大内存,毕竟每一轮的点的值都保存下来了,我这里用循环做,空间占用只有两轮内点的值。
代码实现
////////////////////////////////////////////
// 程序:画贝塞尔曲线的函数
// 作者:我想做三国志
// 编译环境:Visual Studio 2019,EasyX_20211109
// 编写日期:2022-2-17
#include <graphics.h>
#include <conio.h>
using namespace std;
// 画贝塞尔曲线的函数,包括这个 Vec2 结构体
struct Vec2
{
double x, y;
};
void drawBezierCurve(COLORREF color, const unsigned int len, ...)
{
if (len <= 0) return;
va_list list;
va_start(list, len);
Vec2* temp = new Vec2[len];
for (int i = 0; i < len; i++)
temp[i] = va_arg(list, Vec2);
va_end(list);
if (len == 1)
{
putpixel(temp->x, temp->y, color);
return;
}
Vec2* parent = nullptr, * child = nullptr;
Vec2 lastPoint = temp[0];
setlinecolor(color);
for (double LineNum = 0; LineNum < 1 + 1.0 / 100; LineNum += 1.0 / 100)
{
int size = len;
parent = temp;
while (size > 1)
{
child = new Vec2[size - 1];
for (int i = 0; i < size - 1; i++)
{
child[i].x = parent[i].x + (parent[i + 1].x - parent[i].x) * LineNum;
child[i].y = parent[i].y + (parent[i + 1].y - parent[i].y) * LineNum;
}
if (parent != temp)delete[] parent;
parent = child;
size--;
}
line(lastPoint.x, lastPoint.y, parent->x, parent->y);
lastPoint.x = parent->x;
lastPoint.y = parent->y;
delete[] parent;
parent = nullptr;
child = nullptr;
}
delete[] temp;
}
int main()
{
initgraph(640, 480);
Vec2 a = { 100, 80 };
Vec2 b = { 540, 80 };
Vec2 c = { 540, 400 };
Vec2 d = { 100, 400 };
setlinecolor(BLUE);
line(a.x, a.y, b.x, b.y);
line(b.x, b.y, c.x, c.y);
line(c.x, c.y, d.x, d.y);
drawBezierCurve(RED, 4, a, b, c, d);
_getch();
closegraph();
return 0;
}