图元算法
画线
- DDA算法
简单的求点算法,下面直接给出实现
void DDALine(const screenPt& start,const screenPt& end)
{
int dx = end.x - start.x;
int dy = end.y - start.y;
int steps; //步长
float xIncrement, yIncrement; //x,y增长值
float x = start.x, y = start.y;
if (abs(dx)>abs(dy))
steps = abs(dx);
else
steps = abs(dy);
xIncrement = float(dx) / float(steps);
yIncrement = float(dy) / float(steps);
DrawPoint(x, y);
for(int k = 0; k < steps; ++k)
{
x += xIncrement;
y += yIncrement;
DrawPoint(Round(x), Round(y));
}
}
Bresenham算法
光栅化画线算法
void BreseLine(screenPt&& start,screenPt&& end,const colorPt& pt)
{
glColor3f(pt.r,pt.g,pt.b);
int x, y;
if (start.x>end.x)
{
std::swap(start.x, end.x);
std::swap(start.y, end.y);
}
if (start.x == end.x) //竖直线
{
if (start.y > end.y)
{
std::swap(start.y, end.y);
}
x = start.x;
y = start.y;
while (y<end.y)
{
DrawPoint(x, y);
y++;
}
return;
}
if (start.y == end.y) //水平线
{
x = start.x;
y = start.y;
while (x<end.x)
{
DrawPoint(x, y);
x++;
}
return;
}
int dx = end.x - start.x;
int dy = end.y - start.y;
float m = float(dy) / float(dx);
int p;
int twoDy = 2 * dy, twoMinusDx = 2 * (dy - dx), twoDx = 2 * dx, twoMinusDy = 2 * (dx - dy);
int twoSum = 2 * (dy + dx);
if (m>0&&m<1)
{
p = 2 * dy - dx;
x = start.x;
y = start.y;
DrawPoint(x, y);
while (x < end.x)
{
x ++;
if (p < 0)
{
p += twoDy;
}
else
{
y ++;
p += twoMinusDx;
}
DrawPoint(x, y);
}
}
if(m>1)
{
p = 2 * dx;
x = start.x;
y = start.y;
DrawPoint(x, y);
while (y < end.y)
{
y++;
if (p < 0)
{
p += twoDx;
}
else
{
x++;
p += twoMinusDy;
}
DrawPoint(x, y);
}
}
if (m>-1&&m<0)
{
p = 2 * dy + dx;
x = start.x;
y = start.y;
DrawPoint(x, y);
while (x<end.x)
{
x++;
if (p>=0)
{
p += twoDy;
}
else
{
y--;
p += twoSum;
}
DrawPoint(x, y);
}
}
if (m<=-1)
{
p = 2 * dx - dy;
x = start.x;
y = start.y;
DrawPoint(x, y);
while (y>end.y)
{
y--;
if (p>=0)
{
p -= twoDx;
}
else
{
x++;
p -= twoSum;
}
DrawPoint(x, y);
}
}
}
具体的计算步骤见笔记(这里直接计算了四种情况下的点位置,也可以用对称性只计算第一象限且m为正的直线)
中点画圆算法
void cricleMiddle(screenPt&& centerPt,int radius)
{
int p = 1 - radius;
screenPt pt(0,radius);
void circlePlotPoints(screenPt & pt, screenPt & center);
circlePlotPoints(pt, centerPt);
while (pt.x<pt.y)
{
++pt.x;
if (p<0)
{
p += (2 * pt.x + 1);
}
else
{
--pt.y;
p += (2 * pt.x + 1 - 2 * pt.y);
}
circlePlotPoints(pt, centerPt);
}
}
void circlePlotPoints(screenPt& pt,screenPt ¢er)
{
DrawPoint(center.x + pt.x, center.y + pt.y);
DrawPoint(center.x - pt.x, center.y + pt.y);
DrawPoint(center.x + pt.x, center.y - pt.y);
DrawPoint(center.x - pt.x, center.y - pt.y);
DrawPoint(center.x + pt.y, center.y + pt.x);
DrawPoint(center.x - pt.y, center.y + pt.x);
DrawPoint(center.x + pt.y, center.y - pt.x);
DrawPoint(center.x - pt.y, center.y - pt.x);
}
中点画椭圆算法
void ellipseMiddle(screenPt&& centerPt,int Rx,int Ry)
{
glColor3f(0.3, 0.2, 0.3);
int Rx2 = Rx * Rx;
int Ry2 = Ry * Ry;
int twoRx2 = 2 * Rx2;
int twoRy2 = 2 * Ry2;
int p;
screenPt pt(0, Ry);
int px = 0;
int py = twoRx2 * pt.y;
void ellipsePlotPoints(screenPt & pt, screenPt & center);
ellipsePlotPoints(pt, centerPt);
//第一部
p = Round(Ry2 - Rx2 * Ry + 0.25 * Rx2);
while (px<py)
{
++pt.x;
px += twoRy2;
if (p < 0)
p += (Ry2 + px);
else
{
--pt.y;
py -= twoRx2;
p += (Ry2 + px - py);
}
ellipsePlotPoints(pt, centerPt);
}
//第二部分
p = Round(Ry2 * (pt.x + 0.5) * (pt.x + 0.5) + Rx2 * (pt.y - 1) * (pt.y - 1) - Rx2 * Ry2);
while (pt.y>0)
{
--pt.y;
py -= twoRx2;
if (p>0)
{
p += (Rx2 - py);
}
else
{
++pt.x;
px += twoRy2;
p += (Rx2 - py + px);
}
ellipsePlotPoints(pt, centerPt);
}
}
void ellipsePlotPoints(screenPt& pt,screenPt& center)
{
DrawPoint(center.x + pt.x, center.y + pt.y);
DrawPoint(center.x - pt.x, center.y + pt.y);
DrawPoint(center.x + pt.x, center.y - pt.y);
DrawPoint(center.x - pt.x, center.y - pt.y);
}
中点画抛物线算法
void parabolicCurveMiddle(screenPt&& center,float m)
{
glColor3f(0.3, 0.6, 0.2);
float a = abs(m);
int p = a - 1 / 2;
screenPt pt(0,0);
void parabolicCurvePlotPoints(screenPt & pt, screenPt & center, float m);
parabolicCurvePlotPoints(pt,center,m);
//第一区域
while ((2*a*pt.x)<1)
{
p += (2 * a * pt.x + 3 * a);
if (p>=0)
{
p += (-1);
++pt.y;
}
pt.x++;
parabolicCurvePlotPoints(pt, center, m);
}
p = (a*a*(pt.x+1/2)*(pt.x+1/2) - (pt.y+1));
while ((center.y+pt.y)<=Height)
{
if (p<0)
{
p += (2 * pt.x * a + 2 * a - 1);
++pt.x;
}
else
{
p += (-1);
}
++pt.y;
parabolicCurvePlotPoints(pt, center, m);
}
}
void parabolicCurvePlotPoints(screenPt& pt, screenPt& center, float a)
{
if (a>0)
{
DrawPoint(center.x + pt.x, center.y + pt.y);
DrawPoint(center.x - pt.x, center.y + pt.y);
}
else if(a<0)
{
DrawPoint(center.x + pt.x, center.y - pt.y);
DrawPoint(center.x - pt.x, center.y - pt.y);
}
}