一、功能要求
实现一个图形函数库,具有绘制直线段、任意圆弧、椭圆弧、多边形区域的阴影填充和颜色填充等功能,仅调用画点函数 Windows API: setpixel(hdc,x,y,color)
二、实现效果
![](https://i-blog.csdnimg.cn/blog_migrate/751434330a2296965c416f385649e5d7.png)
三、算法实现
1. 绘制直线
绘制直线使用的是DDA算法(数字微分分析法),该算法的核心思想是依据直线的微分方程依次确定描述直线的各个像素点。
例如,已知直线的两个端点为(x1,y1)与(x2,y2),则两个方向的变化量为dx=x2-x1,dy=y2-y1,两个方向最大变化量的绝对值为step=max(|dx|,|dy|),这时就可以计算两个方向的增量xin=dx/steps,yin=dy/steps。得出增量后利用循环的方式依次绘制x=x+xin与y=y+yin。
具体实现代码如下:
//绘制线段_DDA算法
public void DrawLineDDA(int xStart, int yStart, int xEnd, int yEnd, int lineWidth,int color)
{
int dx = xEnd - xStart, dy = yEnd - yStart;
int steps = Math.Abs(dx) > Math.Abs(dy) ? Math.Abs(dx) : Math.Abs(dy);
float xIncrement = dx / (float)steps;
float yIncrement = dy / (float)steps;
float x = xStart, y = yStart;
DrawLinePixel((int)Math.Round(x), (int)Math.Round(y), lineWidth,color);
for (int i = 0; i < steps; i++)
{
x += xIncrement;
y += yIncrement;
DrawLinePixel((int)Math.Round(x), (int)Math.Round(y), lineWidth,color);
}
}
2. 绘制圆弧
根据圆心和半径可直接计算每个顶点的坐标,设内接正多边形的一个顶点为Pi(xi,yi),角度为θi,则可得出:
![](https://i-blog.csdnimg.cn/blog_migrate/3d894ea5c4bdf52c45e2fed5f7756a3e.png)
具体实现代码如下:
//绘制圆弧
public void DrawArc(int centerX, int centerY, int startAngle, int sweepAngle, int r)
{
double startA = startAngle * Math.PI / 180;
double sweepA = sweepAngle * Math.PI / 180;
double span = 0.3 * Math.PI / 180;
for(double i = startA; i <= startA + sweepA; i += span)
{
int x = (int)(centerX + r * Math.Cos(i - Math.PI / 2));
int y = (int)(centerY + r * Math.Sin(i - Math.PI / 2));
setPixel(x, y,0);
}
}
3. 绘制椭圆弧
绘制椭圆弧的思想与圆弧类似,利用了椭圆的参数方程:
![](https://i-blog.csdnimg.cn/blog_migrate/bd2c190922b68a769286ed54eb7b86f4.png)
具体实现代码如下:
//绘制椭圆弧
public void DrawEllipseArc(int centerX, int centerY, int a, int b, int startAngle, int sweepAngle)
{
double startA = startAngle * Math.PI / 180;
double sweepA = sweepAngle * Math.PI / 180;
double span = 0.3 * Math.PI / 180;
for (double i = startA; i <= startA + sweepA; i += span)
{
int x = (int)(centerX + a * Math.Cos(i - Math.PI / 2));
int y = (int)(centerY + b * Math.Sin(i - Math.PI / 2));
setPixel(x, y,0);
}
}
4. 绘制文字
文字的绘制是通过扫描矢量字符实现的,加载任一字库(这里加载了 hzk16h 字库),根据文字计算出对应字模在字库中的位置,之后就可以将此字符掩膜中每个像素对应位置平移后的值写入显示缓存,从而在屏幕上显示此字符。
具体实现代码如下:
//绘制文字
public void DrawString(String massage,int x, int y){
FileStream fsHzk16 = new FileStream("hzk16h", FileMode