计算机图形学基础

1 MFC基本绘图函数

  • 在 Windows平台上,应用程序的图形设备接口(graphics device interface,GDI)被抽象为设备上下文CDC类(device context,DC)。
  • 在微软基类库MFC中,CDC类是定义设备上下文对象的基类,封装了绘图所需的成员函数。
  • 当输出文字或图形时,就需要调用CDC类的成员函数,这些成员函数具备绘制和打印图形的功能。

1.1 CDC类结构与GDI对象

1.1.1 CDC类

  • CDC类派生了CClientDC类、CMetaFileDC类、CPaintDC类和CWindowDC类。
  1. CClientDC类:显示器客户区设备上下文类。只能在窗口的客户区进行绘图,点(0,0)是客户区的左上角。
  2. CMetaFileDC类:Windows图元文件设备上下文类。封装了在Windows中绘制图元文件(*.wmf)的方法。wmf格式文件通常用于存储一系列由绘图命令所描述的图形。
  3. CpaintDC类:该类对象只在响应WM_PAINT消息时使用。MFC程序中使用CPaintDC类在视图窗口中绘图时,需要先添加WM_PAINT消息的映射函数OnPaint(),然后在OnPaint()函数中编写与CPaintDC类相关的代码,而不是编写在OnDraw()中。如果使用OnPaint()函数响应了WM_PAINT消息,则OnDraw()函数将会被自动屏蔽。
  4. CWindowDC类:整个屏幕区域的显示器设备上下文类。允许在整个屏幕区域内进行绘图,点(0,0)是屏幕的左上角。

1.1.2 简单数据类型

在绘图中常用到MFC的CPoint、CRect、CSize等简单数据类型。
由于CPoint、CSize 和CRect 是对 Windows 的POINT、RECT 和SIZE结构体的封装,因此可以直接使用其成员变量。
	
CPoint类:存放点
CPoint (int initx, int initY)// 点坐标(initX, initY)
CPoint (POINT initPt) 		// initPt:一个POINT结构
	
CSize类:存放矩形宽度和高度
CSize(int initCX, int initCY)// initCX,initCY:矩形的x,y方向的长度
CSize(SIZE initSize)  		 // initSize:一个SIZE结构
	
CRect类:存放矩形
CRect (int l, int t,int r, int b)// 矩形左上角点坐标(l,t),右下角(r,b)
CRect (const RECT& srcRect)// srcRect:一个RECT结构
CRect (LPCRECT lpSrcRect)// lpSrcRect:RECT结构的指针
CRect (POINT point, SIZE size)// 矩形左上角点point,size矩形x,y方向的长度
CRect (POINT topLeft, POINT bottomRight) // 左上角点和右下角点
常用函数:
计算宽度函数Crect :: Width
计算高度函数CRect :: Height
获取左上角点函数CRect :: TopLeft
获取右下角点函数CRect :: BottomRight
获取中心点函数CRect :: CenterPoint
扩大矩形函数CRect :: InflateRect
缩小矩形函数CRect :: DeflateRect
移动矩形函数CRect : : OffsetRect

1.2.3 绘图工具类

  • CGdiObject类:GDI绘图工具的基类,一般不能直接使用。
  • CBitmap类:封装了GDI位图,提供位图操作的接口。
  • CBrush类:封装了GDI画刷,可以选作设备上下文的当前画刷,画刷用于填充图形内部。
  • CFont类:封装了GDI字体,可以选作设备上下文中的当前字体。
  • CPallette类:封装了GDI调色板,提供应用程序和显示器之间的颜色接口。
  • CPen类:封装了GDI画笔,可以选作设备上下文的当前画笔,画笔用于绘制图形边界线。

1.2 映射模式

  • “窗口”可以理解为一种逻辑坐标系下的矩形区域
  • “视区”是设备坐标系下的矩形区域。

1.2.1 设置映射模式函数

CDC :: SetMapMode
原型:
virtual int SetMapMode (int nMapMode)  // nMapMode:模式代码
返回值:原映射模式,用整数值表示
说明:函数定义了将逻辑坐标转换为设备坐标的度量单位,并定义了设备坐标系的工轴和y轴方向。

1.2.2 设置窗口范围函数

CDC :: Set WindowExt
原型:
virtual CSize SetwindowExt (int cx, int cy)// cx,xy:窗口x,y范围的逻辑坐标
virtual CSize SetwindowExt (SIZE size);  	 // size:窗口的SIZE结构或CSize对象
返回值:原窗口范围的CSize对象

1.2.3 设置视区范围函数

CDC :: Set ViewportExt
原型:
virtual CSize SetViewportExt (int cx, int cy); // cx,xy:视区x,y范围的逻辑坐标
virtual CSize SetviewportExt(SIZE size) ;  	 // size:视区的SIZE结构或CSize对象
返回值:原视区范围的CSize对象。

1.2.4 设置窗口原点函数

CDC :: Set ViewportOrg
原型:
CPoint Setwindoworg(int x, int y)// x,y:窗口新原点坐标
CPoint Setwindoworg(POINT point)  // point:窗口新原点的POINT结构或CPoin对象
返回值:原窗口原点的CPoint 对象。

1.2.5 设置视区原点函数

CDC :: Set ViewportOrg
原型:
virtual CPoint Setviewportorg(int x, int y)// x,y:视区新原点坐标
virtual CPoint Setviewportorg (POINT point)
返回值:原视区原点的CPoint对象。
参数:point是视区原点的POINT结构或CPoint对象。视区坐标系原点必须位于设备坐标系的范围之内

1.3 使用GDI对象

1.3.1 创建画笔函数

  • MFC中画笔用来绘制直线、曲线或区域的边界线,具有线型、宽度和颜色三种属性。
  • 画笔的线型通常有实线、虚线、点线、点划线、双点划线、不可见线和内框架线7种样式,画笔样式都是以“PS_”为前缀的预定义标识符,代表PenStyle。
  • 画笔的宽度是用像素表示的线条宽度。
  • 画笔的颜色是用RGB宏表示的线条颜色。
  • 默认的画笔绘制一个像素宽度的黑色实线。若要更换新画笔,可以在创建新画笔对象后,将其选入设备上下文,就可以使用新画笔进行绘图,使用完新画笔后要将设备上下文恢复原状。
Cpen :: CreatePen
原型:
BOOL CreatePen (int nPenStyle, int nwidth, COLORREF crColor)
// nPenStyle:画笔样式
// nWidth:画笔的宽度
// crColor:画笔的颜色
说明:
画笔也可使用构造函数直接定义。原型为:
CPen (int nPenstyle, int nwidth, COLORREF crcolor);
COLORREF是32位颜色数据类型,用双字表示。原型为:
typedef DWORD COLORREF;

1.3.2 创建画刷函数

  • 画刷用于对封闭图形内部进行填充,默认的画刷是白色实体画刷。
  • 若要更换新画刷,可以在创建新画刷对象后,将其选入设备上下文,就可以使用新画刷填充图形内部,使用完新画刷后要将设备上下文恢复原状。
  • 画刷仅对使用Chord()、Ellipse()、FillRect()、FrameRect()、InvertRect()、Pie()、Polygon()、PolyPolygon()、RoundRect()等函数所绘制的闭合图形有效。
(1)创建实体画刷函数
Cbrush :: CreateSolidBrush
原型:
BOOL CreatesolidBrush (COLORREF crColor); // crColor是画刷的颜色
说明:
实体画刷是用指定的颜色填充图形内部。
实体画刷也可以使用构造函数直接定义。原型为:
CBrush (COLORREF crColor) ;
(2)创建阴影画刷函数
Cbrush :: CreateHatchBrush
原型:
BOOL CreateHatchBrush(int nIndex, COLORREF crColor);
参数:nIndex是阴影样式;crColor是阴影线的颜色。
说明:
阴影画刷使用指定的阴影样式和颜色填充图形内部。
阴影画刷也可以使用构造函数直接定义。原型为:
CBrush(int nIndex, COLORREF crColor);
(3)创建位图画刷函数
Cbrush :: CreatePatternBrush
原型:
BOOL CreatePatternBrush (CBitmap *pBitmap); // pBitmap是位图标识符
说明:
位图画刷使用位图创建一个逻辑画刷,位图可以是从资源中导入的DDB位图。
使用位图画刷时,如果要确保位图在画刷中的相对位置不变,需使用SetBrushOrg()函数设置画刷起点。
位图画刷也可以使用构造函数直接定义。原型为:
CBrush (CBitmap *pBitmap);

1.3.3 选入GDI对象

//GDI对象创建完毕后,只有选入当前设备上下文中才能使用。
CDC :: SelectObject
原型:
CPen * selectobject (CPen * pPen); // pPen是将要选择的画笔对象指针
Cbrush * selectobject (CBrush * pBrush); // pBrush是将要选择的画刷对象指针
CBitmap * Selectobject (CBitmap * pBitmap); // pBitmap将要选择的位图对象指针
返回值:如果成功,返回被替换对象的指针;否则,返回NULL。
说明:函数将设备上下文中的原GDI对象换为新对象,时返回指向原对象的指针。

1.3.4 删除GDI对象

CGdiObject :: DeleteObject
原型:
BOOL Deleteobject();
说明:
GDI对象使用完毕后,如果程序结束,会自动删除GDI对象。如果程序未结束,并重复创建同名GDI对象,则需要先把已成自由状态的原GDI对象从系统内存中清除。
这里请注意不能使用DeleteObject()函数删除正在被选入设备上下文中的CGdiObject对象。

1.3.5 选入库对象

//除了自定义的GDI对象外,Windows系统中还准备了一些使用频率较高的画笔和画刷,不需要创建,就可以直接选用。
//同样,使用完库画笔和画刷后也不需要调用DeleteObject()函数从内存中删除。
CDC :: SelectStockObject
原型:
virtual CGdiobject * SelectstockObject(int nIndex);
返回值:如果调用成功,返回被替代的CGdiObject类对象的指针;否则返回NULL。
参数:参数nIndex可以是表所示的库画笔代码或表所示的库画刷代码

1.4 CDC类绘图成员函数

除了绘制像素点外,绘制图形时通常是先创建画笔和画刷,然后再调用CDC类的绘图成员函数绘制直线、矩形、多边形、椭圆等。

1.4.1 绘制像素点函数

CDC :: SetPixel 和CDC ::SetPixelV
原型:
COLORREF SetPixel (int x, int y, COLORREF crColor);
COLORREF SetPixel (POINT point, COLORREF crColor);
BOOL SetPixelV (int x, int y, COLORREF crColor);
BOOL SetPixelV (POINT point, COLORREF crColor)
返回值:
SetPixel()函数如果调用成功,返回所绘制像素点的RGB值;否则(如果点不在裁剪区域内),返回一1SetPixelV()函数如果调用成功,返回“非0”;否则,返回“0”,所以执行速度更快。
参数:
x,y是像素点位置的x,y的逻辑坐标;crColor是像素点颜色;point是POINT结构或CPoint对象

1.4.2 获取像素点颜色函数

CDC :: GetPixel
原型:
COLORREF GetPixel (int x,int y) const// x,y:像素点的逻辑坐标
COLORREF GetPixel (POINT point) const  // point:包含逻辑坐标的像素点
返回值:
如果调用成功,返回指定像素的RGB值;否则(如果点不在裁剪区域内);返回一1。
说明:
获得指定像素点的RGB颜色值,本函数是常成员函数。

1.4.3 绘制直线段函数

  • 配合使用MoveTo()和LineTo()函数可以绘制直线段或折线。
  • 直线段的绘制过程中有一个称为“当前位置”的特殊位置。每次绘制直线段都是以当前位置为起点,线段绘制结束后,直线段的终点又成为当前位置。
  • 由于当前位置在不断更新,只使用LineTo()函数可以绘制连续直线。
(1)设置当前位置函数
CDC :: MoveTo
原型:
CPoint MoveTo (int x, int y)// x,y:新位置的点坐标
CPoint MoveTo (POINT point) // point:POINT结构或CPoint对象
返回值:先前位置的CPoint对象。
说明:本函数只将画笔的当前位置移动到坐标x和y(或point)处,不画线。
(2)绘制直线段函数
CDC :: LineTo
原型:
BOOL LineTo (int x, int y)// x,y:线段终点坐标
BOOL LineTo (POINT point) // point:POINT结构或CPoint对象
说明:
从当前位置绘制直线段,但不包括(x,y)点。
绘制直线段的函数不能指定颜色,直线段的颜色通过画笔来指定。

1.4.4 绘制矩形函数

矩形通过左上角点和右下角点唯一定义。

(1)绘制直角矩形
CDC :: Rectangle
原型:
BOOL Rectangle (int x1, int y1, int x2, int y2); // 参数:左上角,右下角点坐标
BOOL Rectangle (LPCRECT lpRect) // lpRec:CRect对象或RECT结构的指针
说明:
Rectangle()函数使用当前画刷填充直角矩形内部,并使用当前画笔绘制直角矩形边界线。
矩形不包括右边界坐标和下边界坐标,即矩形宽度为x2-xl,高度为y2-y1。
(2)绘制圆角矩形
CDC :: RoundRect
原型:
BOOL RoundRect (int x1, int y1, int x2, int y2, int x3, int y3);
BOOL RoundRect (LPCRECT lpRect, POINT point)
参数:
xl,yl:矩形左上角点坐标,x2,y2:矩形右下角点坐标,x3,y3:圆角椭圆的宽度和高度;
lpRect:CRect对象或RECT结构的指针,point是包含圆角椭圆宽度和高度的点坐标,可以是POINT结构或CPoint对象。
说明:
RoundRect()函数使用当前画刷填充圆角矩形内部,并使用当前画笔绘制圆角矩形边界线。
圆角矩形不包括右边界坐标和下边界坐标,即圆角矩形宽度为x2-xl,高度为y2-yl。
x3,y3代表绘制圆角的椭圆的宽度和高度。在每个圆角上,其值取半。
(3)设置填充模式函数
CDC ::SetPolyFillMode
原型:
int SetPolyFillMode (int nPolyFillMode) ;
返回值:
如果调用成功,返回原填充模式;否则,返回“O”。在MFC中,ALTERNATE宏定义为1,WINDING宏定义为2。
参数:
nPolyFillMode是多边形填充模式,可以选ALTERNATE或WINDING。默认的填充模式是ALTERNATE。
(4)画刷填充矩形函数
CDC:: FillRect
原型:
void FillRect (LPCRECT lpRect , CBrush * pBrush);
参数:
lpRect是指向矩形的指针,是一个Rect结构或CRect对象;pBrush指定画刷对象指针。
说明:
该函数使用当前画刷填充整个矩形,包括左边界和上边界,但不包括右边界和下边界。
当前画笔对该函数不起作用。
(5)颜色填充矩形函数
CDC:: FillSolidRect
原型:
void FillSolidRect (LPCRECT lpRect,COLORREF clr);
void FillSolidRect (int x, int y, int cx, int cy,COLORREF clr);
参数:lpRect是指向矩形的指针,是一个Rect结构或CRect对象;x,y指定矩形的左上角点坐标,cx,cy指定矩形的宽度和高度;clr指定画刷颜色。
说明:
FillSolidRect()函数与FillRect()函数类似,FillSolidRect()函数仅使用颜色填充矩形,而FillRect()函数可以使用颜色也可以使用阴影或图案填充矩形。
FillRect()函数的填充速度低于FillSolidRect()函数。
当前画笔对该函数不起作用。

1.4.5 绘制椭圆函数

CDC :: Ellipse
原型:
BOOLEllipse (int x1, int yl, int x2, int y2); // 参数:外接矩形左上右下点坐标
BOOLEllipse (LPCRECT lpRect)
说明:Ellipse()函数使用当前画刷填充椭圆内部,并使用当前画笔绘制椭圆边界线。

1.4.6 绘制椭圆弧函数

在这里插入代码片CDC ::Arc
原型:
BOOL Arc(int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4);
BOOL Arc (LPCRECT lpRect, POINT ptStart, POINT ptEnd);
参数:
(x1,y1),(x2,y2)是外接矩形左上右下角点坐标;
(x3,y3)(x4,y4)为椭圆弧起点和终点,该参数不一定严格位于椭圆弧上;
lpRect指定外接矩形的位置和大小,可以是CRect对象或RECT结构;ptStart,ptEnd是椭圆弧的起点坐标和终点坐标,可以是CPoint对象或POINT结构。
说明:
椭圆弧的真实起点是外接矩形中心点与(x3,y3)(或ptStart)点所构成的射线与椭圆的交点,真实终点是外接矩形中心点与(x4,y4)(或ptEnd)点所构成的射线与椭圆的交点。
Arc()函数使用当前画笔绘制椭圆弧边界线。由于椭圆弧可能不封闭,因此不对椭圆弧内部进行填充。

默认的椭圆弧绘制方向是逆时针,可以通过调用SetArcDirection()函数将绘制方向设为顺时针。

SetArcDirection()函数的原型为:
int SetArcDirection(int nArcDirection);
参数nArcDirection:
AD_COUNTERCLOCKWISE(逆时针)
AD_CLOCKWISE(顺时针)

1.4.7 绘制扇形函数

CDC ::Pie
原型:
BOOL Pie(int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4);
BOOL Pie(LPCRECT lpRect,POINT ptStart, POINT ptEnd);
参数:所有参数和圆弧相同
说明:
扇形中心位置坐标是外接矩形的中心。扇形从起点到终点逆时针方向绘制。扇形使用直线段连接扇形中心与扇形的起点和终点。
Pie()函数使用当前画刷填充扇形内部,并用当前画笔绘制扇形边界线。
扇形不包括右边界坐标和下边界坐标,即扇形宽度为x2-xl,高度为y2-y1。

1.4.8 绘制多边形函数

CDC :: Polygon
原型:
BOOL Polygon (LPPOINT lpPoints, int nCount);
参数:
lpPoints指定多边形顶点数组指针,数组中的每一个顶点对,是一个POINT结构或CPoint对象;nCount指定多边形顶点数组中的顶点个数。
说明:多边形自动闭合。使用当前画刷填充内部,当前画笔绘制边界线。

1.4.9 路径层函数

(1)打开路径层
CDC :: BeginPath
原型:
BOOL BeginPath();
(2)关闭路径层
CDC :: EndPath
原型:
BOOL EndPath();
说明:关闭路径层,并将路径层选入设备上下文。
(3)填充路径层
CDC :: FillPath
原型:
BOOL FillPath();
说明:
使用当前画刷和填充模式填充路径层内部,同时关闭已经打开的路径层。
路径层填充完毕后,将被设备上下文废弃。
(4)绘制并填充路径层
CDC :: StrokeAndFillPath
原型:
BOOL StrokeAndFillPath();
说明:使用当前画笔绘制路径层的轮廓,并使用当前画刷填充路径层内部,同时关闭已经打开的路径层。
相比于FillPath函数,该函数会绘制边界。

1.4.10 绘制Bezier样条函数

CDC :: PolyBezier
原型:
BOOL PolyBezier (const POINT * lpPoints, int nCount);
参数:
lpPoints是样条的终点是和控制点组成的POINT结构数组指针;
nCount表示lpPoints数组中的数组元素个数。
说明:
每段 Bezier样条要求有两个中间控制点和一个终止控制点。第一段 Bezier样条还要求一个起始控制点。
PolyBezier()函数可以绘制一段或多段 Bezier样条。绘制多段 Bezier 样条时,除第一段样条使用4个控制点外,其余各段样条仅使用3个控制点,因为后面一段样条总把前一段样条的终止控制点作为自己的起始控制点。只绘制一段 Bezier样条时,参数 lpPoints应为4。绘制n段 Bezier样条时,参数lpPoints应为n×31PolyBezier()函数使用当前画笔绘制样条,并且一般不闭合,因此不填充内部。
PolyBezier()函数不更新当前点位置。

1.4.11 文本函数

(1)设置文本颜色函数
CDC :: SetTextColor
原型:
virtual COLORREF SetTextColor (COLORREF crColor); // 参数:新文本颜色
返回值:原文本颜色的RGB值。
(2)设置文本背景模式函数
CDC :: SetBkMode
原型:
int SetBkMode (int nBkMode);
返回值:原文本背景模式。
参数:nBkMode可以取OPAQUE或TRANSPARENT。
说明:
OPAQUE文本背景用当前背景颜色填充,这是默认的文本背景模式;
TRANSPARENT文本背景透明。
(3)设置文本背景颜色函数
CDC :: SetBkColor
原型:
virtual COLORREF SetBkColor (COLORREF crColor); // 参数:新文本背景颜色
返回值:原文本背景色的RGB值。
(4)输出文本函数
CDC :: TextOut
原型:
virtual BOOL Textout(int x, int y, LPCTSTR lpszString, int nCount);
BOOL TextOut(int x, int y, const cstring& str) ;
参数:
x,y是文本的起点逻辑坐标;lpszString是字符串指针;nCount是文本的字节长度。
str是CString对象。
(5)设置文本格式函数
CString :: Format
原型:
void Format (LPCTSTR lpszFormat,);
void Format (UINT nFormatID,);
参数:
lpszFormat是格式控制字符串,如%d、%f、%c等;
nFormatID是包含格式控制字符串的资源标识符。
说明:CString类的Format()成员函数可将任意数据类型转换为CString字符串,常用于输出数值型数据。

2 基本图形扫描转换

2.1 直线的扫描转换

宏定义:
#define ROUND(d) int(d + 0.5)

2.1.1 数值微分算法DDA

// 使用局限性:
// 该算法适用于直线斜率为0~1之间,当斜率大于1时绘制的点稀疏。

// 算法描述:
void DDALine(CDC *pDC, CPoint p1, CPoint p2)
{
	int dx = p2.x – p1.x;
	int dy = p2.y – p1.y;
	double k = double(dy) / dx;
	int x;
	double y = p1.y;
	for(x = p1.x; x < p2.x; x++)
	{
		pDC->SetPixelV(x,ROUND(y),RGB(0,0,0));
		y += k;
	}
}

2.1.2 中点画线算法

void MCLine(CDC *pDC, CPoint p1, CPoint p2)
{
	int dy = p2.y - p1.y;
	int dx = p2.x - p1.x;
	int x;
	double y = p1.y;
	double k = double(dy) / dx;
	double d = 0.5 - k;
	for (x = p1.x; x < p2.x; x++)
	{
		if(d < 0)
		{
			d += 1 - k;
			y += 1;
		}
		else
			d += -k;
		pDC->SetPixelV(x,y,RGB(0,0,0));
	}
}

2.1.3 中点BresenhamLine算法

void BresenhamLine(CDC *pDC, CPoint p1, CPoint p2)
{
	int dx = p2.x - p1.x;
	int dy = p2.y - p1.y;
	double e = -dx;
	int x = p1.x;
	double y = p1.y;
	for(x = p1.x; x < p2.x; x++)
	{
		pDC->SetPixelV(x,y,RGB(0,0,0));
		e += (2 * dy);
		if(e >= 0)
		{
			e -= (2 * dx);
			y += 1;
		}
	}
}

参考资料:《计算机图形学基础教程 VisualC++版 第2版》清华大学出版社
  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值