Bezier Curve

Formula

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
void naive_bezier(const std::vector<cv::Point2f>& points, cv::Mat& window)
{
auto& p_0 = points[0];
auto& p_1 = points[1];
auto& p_2 = points[2];
auto& p_3 = points[3];

for (double t = 0.0; t <= 1.0; t += 0.001)
{
auto point = std::pow(1 - t, 3) * p_0 + 3 * t * std::pow(1 - t, 2) * p_1 +
3 * std::pow(t, 2) * (1 - t) * p_2 + std::pow(t, 3) * p_3;

window.at<cv::Vec3b>(point.y, point.x)[2] = 255;
}
}

de Casteljau

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
cv::Point2f recursive_bezier(const std::vector<cv::Point2f>& control_points, float t)
{
int nums = control_points.size();
std::vector<cv::Point2f> points = control_points;
for (int i = nums; i >= 2; i--)
{
for (int j = 0; j < i-1; j++)
{
points[j] = (1 - t) * points[j] + t * points[j + 1];
}
}
return points[0];
}

void bezier(const std::vector<cv::Point2f>& control_points, cv::Mat& window)
{
for (double t = 0.0; t <= 1.0; t += 0.001)
{
auto point = recursive_bezier(control_points, t);
window.at<cv::Vec3b>(point.y, point.x)[1] = 255;
}
}

Bilinear

point的x,y是float形式,转成int形式才能绘制在屏幕上的某个像素点,由此损失精度

p点处在4个像素点之间,对4个像素点进行绘制可以平滑曲线

离p远的像素点颜色更淡

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
void bezier_linear(const std::vector<cv::Point2f>& control_points, cv::Mat& window)
{
for (double t = 0.0; t <= 1.0; t += 0.001)
{
cv::Point2f p = recursive_bezier(control_points, t);

// 点 p 最相邻的四个点
cv::Point2i p0(p.x - std::floor(p.x) < 0.5 ? std::floor(p.x) : std::ceil(p.x),
p.y - std::floor(p.y) < 0.5 ? std::floor(p.y) : std::ceil(p.y));
std::vector<cv::Point2i> ps = { p0, cv::Point2i(p0.x - 1, p0.y),
cv::Point2i(p0.x, p0.y - 1), cv::Point2i(p0.x - 1, p0.y - 1),
};

// 点 p 到相邻四个点的中心点的距离
float sum_d = 0.f;
std::vector<float> ds = {};
for (int i = 0; i < 4; i++) {
cv::Point2f cp(ps[i].x + 0.5f, ps[i].y + 0.5f);
float d = std::sqrt(std::pow(p.x - cp.x, 2) + std::pow(p.y - cp.y, 2));
ds.push_back(d);
sum_d += d;
};

// assign colors
for (int i = 0; i < 4; i++) {
float k = ds[i] / sum_d;
window.at<cv::Vec3b>(ps[i].y, ps[i].x)[1] = std::min(255.f, window.at<cv::Vec3b>(ps[i].y, ps[i].x)[1] + 255.f * k);
};
}
}

结果

Bresenham Line

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
void rst::rasterizer::draw_line(Eigen::Vector3f begin, Eigen::Vector3f end)
{
auto x1 = begin.x();
auto y1 = begin.y();
auto x2 = end.x();
auto y2 = end.y();

Eigen::Vector3f line_color = {255, 255, 255};

int x,y,dx,dy,dx1,dy1,px,py,xe,ye,i;

dx=x2-x1;
dy=y2-y1;
dx1=fabs(dx);
dy1=fabs(dy);
px=2*dy1-dx1;
py=2*dx1-dy1;

if(dy1<=dx1)
{
if(dx>=0)
{
x=x1;
y=y1;
xe=x2;
}
else
{
x=x2;
y=y2;
xe=x1;
}
Eigen::Vector3f point = Eigen::Vector3f(x, y, 1.0f);
set_pixel(point,line_color);
for(i=0;x<xe;i++)
{
x=x+1;
if(px<0)
{
px=px+2*dy1;
}
else
{
if((dx<0 && dy<0) || (dx>0 && dy>0))
{
y=y+1;
}
else
{
y=y-1;
}
px=px+2*(dy1-dx1);
}
Eigen::Vector3f point = Eigen::Vector3f(x, y, 1.0f);
set_pixel(point,line_color);
}
}
else
{
if(dy>=0)
{
x=x1;
y=y1;
ye=y2;
}
else
{
x=x2;
y=y2;
ye=y1;
}
Eigen::Vector3f point = Eigen::Vector3f(x, y, 1.0f);
set_pixel(point,line_color);
for(i=0;y<ye;i++)
{
y=y+1;
if(py<=0)
{
py=py+2*dx1;
}
else
{
if((dx<0 && dy<0) || (dx>0 && dy>0))
{
x=x+1;
}
else
{
x=x-1;
}
py=py+2*(dx1-dy1);
}
Eigen::Vector3f point = Eigen::Vector3f(x, y, 1.0f);
set_pixel(point,line_color);
}
}
}

结果