进行直线绘制时,考虑两个问题:
1. 如何绘制直线?
2. 如何使直线看起来更自然?
针对这两个问题,分别使用DDA算法和反走样直线算法进行解决。
直线类的设计如下:
class CLine
{
public:
CLine();
virtual ~CLine();
void MoveTo(CDC *, CP2);//移动到指定位置
void MoveTo(CDC *, double, double);
void LineTo(CDC *, CP2);//绘制直线,不含终点
void LineTo(CDC *, double, double);
void GetColor(COLORREF c0, COLORREF c1);//直线颜色
void GetBKColor(COLORREF BKColor);//背景颜色
void IfAnti(BOOL flag);
public:
BOOL IsAnti;//是否反走样
CP2 P0;//起点
CP2 P1;//终点
CRGB color0;//起始颜色
CRGB color1;//结束颜色
CRGB BKcolor;//背景颜色
};
实现如下:
CLine::CLine()
{
IsAnti = TRUE;
BKcolor = CRGB(1, 1, 1);
color0 = CRGB(0, 0, 0);
color1 = CRGB(0, 0, 0);
}
CLine::~CLine()
{
}
void CLine::IfAnti(BOOL flag) {
IsAnti = flag;
}
void CLine::GetColor(COLORREF c0, COLORREF c1) {
color0 = CRGB(GetRValue(c0) / 255.0, GetGValue(c0) / 255.0, GetBValue(c0) / 255.0);
color1 = CRGB(GetRValue(c1) / 255.0, GetGValue(c1) / 255.0, GetBValue(c1) / 255.0);
}
void CLine::GetBKColor(COLORREF BKColor) {
this->BKcolor.red = GetRValue(BKColor) / 255.0;
this->BKcolor.green = GetGValue(BKColor) / 255.0;
this->BKcolor.blue = GetBValue(BKColor) / 255.0;
}
void CLine::MoveTo(CDC* pDC, CP2 p0)//绘制直线起点函数
{
P0 = p0;
}
void CLine::MoveTo(CDC* pDC, double x0, double y0)//重载函数
{
P0 = CP2(x0, y0);
}
void CLine::LineTo(CDC* pDC, CP2 p1)
{
P1 = p1;
double dx = abs(P1.x - P0.x);
double dy = abs(P1.y - P0.y);
BOOL bInterChange = FALSE;
double e, signX, signY, temp;
signX = (P1.x > P0.x) ? 1 : ((P1.x < P0.x) ? -1 : 0);
signY = (P1.y > P0.y) ? 1 : ((P1.y < P0.y) ? -1 : 0);
if (dy > dx)
{
temp = dx;
dx = dy;
dy = temp;
bInterChange = TRUE;
}
e = 0;
double incrR = (color1.red - color0.red) / dx;
double incrG = (color1.green - color0.green) / dx;
double incrB = (color1.blue - color0.blue) / dx;
double foreR = color0.red;double foreB = color0.blue;double foreG = color0.green;
double backR = BKcolor.red;double backG = BKcolor.green;double backB = BKcolor.blue;
CP2 p = P0;//从起点开始绘制直线
for (int i = 1; i <= dx; i++)
{
CRGB c0((backR - foreR) * e + foreR, (backG - foreG) * e + foreG, (backB - foreB) * e + foreB);
CRGB c1((backR - foreR) * (1 - e) + foreR, (backG - foreG) * (1 - e) + foreG, (backB - foreB) * (1 - e) + foreB);
if (bInterChange)//y为主位移方向
{
if (IsAnti)
pDC->SetPixelV(p.x + signX, p.y, COLOR(c1));
pDC->SetPixelV(p.x, p.y, COLOR(c0));
}
else//x为主位移方向
{
if (IsAnti)
pDC->SetPixelV(p.x, p.y + signY, COLOR(c1));
pDC->SetPixelV(p.x, p.y, COLOR(c0));
}
foreR += incrR;foreG += incrG;foreB += incrB;
if (bInterChange)
p.y += signY;
else
p.x += signX;
e += (dy / dx);
if (e >= 1.0)
{
if (bInterChange)
p.x += signX;
else
p.y += signY;
e--;
}
}
P0 = p1;
}
void CLine::LineTo(CDC* pDC, double x1, double y1)//重载函数
{
LineTo(pDC, CP2(x1, y1));
}