title: 图形学-直线的扫描转换
date: 2018-10-22 20:31:06
updated: 2018-10-22 20:31:06
description: Bresenham算法画直线
categories: 必修
photo:
tags:
完成中点Bresenham画线,要求如下
VisualStudio2017
MFC应用程序
设当前屏幕上最逼近直线的像素点为Pi(xi,yi),下一个像素点Pi+1(xi+1,yi+1)相较于前一个像素点的坐标每次在主位移方向上+or-1,另一个方向上是否+or-1取决于中点偏差判别式的值。
若直线斜率绝对值<=1,直线在x方向上变化快,以x为主位移方向。否则,以y为主位移方向。
从Pi(xi,yi)点出发选择下一像素时,需将Pu和Pd的中点M(xi+1,yi+0.5)代入隐函数方程,构造中点误差项di。
di = F(xi+1,yi+0.5) = yi+0.5-k(xi+1)-b
当di < 0时,中点M在直线的下方,Pu点离直线距离更近,下一像素点应选取Pu,即y向上走一步;di = 0时,选取两点均可。否则,选取Pd点,y方向上不移动。
因此
void CMy1401160120View::MoveLine()
{
// TODO: 在此添加命令处理程序代码
CDC *pDC = GetDC();
COLORREF clr = RGB(255, 0, 0);
double dx = x1 - x0, dy = y1 - y0;
int x = Round(x0), y = Round(y0);
//绘制垂线
if (fabs(x - x1)<1e-6) {
if (y0>y1) {
swap(y0, y1);
swap(x0, x1);
}
for (y = Round(y0); y < Round(y1); y++) {
pDC->SetPixelV(Round(x), Round(y), clr);
}
}
else {
double k, d;//k为斜率,d为中点误差项
k = dy / dx;
//0= 0.0 && k <= 1.0) {
if (x0 > x1) {
swap(x0, x1);
swap(y0, y1);
}
d = 0.5 - k;
for (x = Round(x0); x < Round(x1); x++) {
pDC->SetPixelV(Round(x), Round(y), clr);
if (d < 0) {
y++;
d += 1 - k;
}
else {
d -= k;
}
}
}
if (k > 1) {
COLORREF clr = RGB(255, 0, 0);
if (y0 > y1) {
swap(x0, x1);
swap(y0, y1);
}
d = 1 - 0.5*k;
for (y = Round(y0); y < Round(y1); y++) {
pDC->SetPixelV(Round(x), Round(y), clr);
if (d >= 0) {
x++;
d += 1 - k;
}
else {
d += 1;
}
}
}
if (k >= -1.0 && k <= 0.0) {
if (x0 > x1) {
swap(x0, x1);
swap(y0, y1);
}
d = -0.5 - k;
for (x = Round(x0); x < Round(x1); x++) {
pDC->SetPixelV(Round(x), Round(y), clr);
if (d > 0) {
y--;
d -= 1 + k;
}
else {
d -= k;
}
}
}
if (k < -1.0) {
if (y0 < y1) {
swap(x0, x1);
swap(y0, y1);
}
d = -1 - 0.5*k;
for (y = Round(y0); y > Round(y1); y--) {
pDC->SetPixelV(Round(x), Round(y), clr);
if (d < 0) {
x++;
d -= 1 + k;
}
else {
d -= 1;
}
}
}
}
}
void CMy1401160120View::OnLButtonDown(UINT nFlags, CPoint point)
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
CView::OnLButtonDown(nFlags, point);
x0 = point.x;
y0 = point.y;
}
void CMy1401160120View::OnLButtonUp(UINT nFlags, CPoint point)
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
CView::OnLButtonUp(nFlags, point);
x1 = point.x;
y1 = point.y;
MoveLine();
}
点击画图——直线
然后按下鼠标左键画直线
结果如下所示:
代码逻辑还是挺简单的,但是对vs不熟悉,对于事件响应反而搞了挺半天的,觉得顺手就写下博客记录一下。需要完整代码的自行联系帅气的作者。