这是第一篇博客,顺便深入学习一下markdown语法。
之后的图形学文章都使用C++实现。
目录
数值微分法
数值微分法通过计算直线的斜率,计算每个x对应的y坐标,并取像素x,round(y)。本方法直观可行,但执行效率低。由于每步都需要进行浮点乘法运算与舍入运算,故需要增量的方法。
算法理论
首先计算直线的斜率:
算法实现
利用openCV+Cpp进行实现。考虑了 |k|∈[0,1]与|k|∉[0,1] | k | ∈ [ 0 , 1 ] 与 | k | ∉ [ 0 , 1 ] 两种情形
#include<iostream>
#include<cmath>
#include<opencv2/core/core.hpp>
#include<opencv2/highgui/highgui.hpp>
using namespace cv;
void DDAline(Mat& m,const int x0, const int y0, const int x1, const int y1,const cv::Vec3b& v);
int main(){
Mat imageROI = Mat(500, 1000, CV_8UC3, Scalar(255, 255, 255));
DDAline(imageROI, 0, 0,400, 200, Vec3b(0, 0, 0));
namedWindow("显示结果");
imshow("显示结果", imageROI);
waitKey();
}
void DDAline(Mat& m, const int x0, const int y0, const int x1, const int y1, const cv::Vec3b& v){
double k = double(y1 - y0) / (x1 - x0);
if (k >= -1 && k <= 1){
double y = y0;
int x = x0;
for (x = x0; x <= x1; x++){
m.at<Vec3b>(int(y + 0.5),x ) = v;
y += k;
}
}
else{
double x = x0;
int y = y0;
k = 1 / k;
for (y = y0; y <= y1; y++){
m.at<Vec3b>(y,int(x+0.5)) = v;
x += k;
}
}
}
这里注意opencv中at(i0,i1)函数是操作第i0行第i1列,所以需要把xy反过来。
总体还是比较简单。cv配置、函数搞的比较麻烦。opencv还需多多熟练。
中点画线法
算法理论
首先假定
k∈[0,1]
k
∈
[
0
,
1
]
之间。
根据
(x0,y0)(x1,y1)
(
x
0
,
y
0
)
(
x
1
,
y
1
)
两点坐标可以得到直线方程:
当 F(x,y)>0 F ( x , y ) > 0 时,点在直线上方。当确定P点位置后,下一个像素点处的中点M的判别式为:
算法实现
void MidpointLine(Mat& m, const int x0, const int y0, const int x1, const int y1, const cv::Vec3b& v){
int a = y0 - y1;
int b = x1 - x0;
int d0 = 2*a + b;
int delta1 = 2*a;
int delta2 = 2*(a + b);
int x, y, d;
for (x = x0, y = y0, d = d0; x <= x1; x++){
if (d < 0){
y++;
d += delta2;
}
else{
d += delta1;
}
m.at<Vec3b>(y, x) = v;
}
}
由于把d的判别全部乘2了,可以避免小数的运算。斜率在其他范围内只要换换前后两点的顺序、换换x,y,就可以解决。
Bresenham画线算法
算法理论
还是首先假定
k∈[0,1]
k
∈
[
0
,
1
]
。
假设x列的像素已确定,那么下一个像素列坐标为x+1,行下标为y或y+1,具体是哪个取决于误差项d大于0.5还是小于0.5。每次x增加1,则误差随之增加k。程序中设e=d-0.5,则可判断e的正负值。当
d>1
d
>
1
时,则只需执行
d=d−1
d
=
d
−
1
。
算法实现
void BresenhamLine(Mat& m, const int x0, const int y0, const int x1, const int y1, const Vec3b& v){
int x, y, dx, dy;
float k, e;
dx = x1 - x0;
dy = y1 - y0;
k = double(dy) / dx;
e = -0.5;
for (x = x0, y = y0; x <= x1; x++){
m.at<Vec3b>(y, x) = v;
e += k;
if (e >= 0){
y++;
e--;
}
}
}
以上。