首页 > 代码库 > 计算机图形学 彩色直线段的反走样(5)

计算机图形学 彩色直线段的反走样(5)

作者:卿笃军

原文地址:http://blog.csdn.net/qingdujun/article/details/40083207


本文通过一个完整的例子来演示彩色直线段的反走样。

1)创建CP2类

头文件:P2.h

// P2.h: interface for the CP2 class.
//
//////////////////////////////////////////////////////////////////////

#if !defined(AFX_P2_H__DD23884F_7F62_48E8_A906_65C4558DE4EB__INCLUDED_)
#define AFX_P2_H__DD23884F_7F62_48E8_A906_65C4558DE4EB__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#include "RGB.h"

//二维点类  
class CP2    
{  
public:  
    CP2();  
    CP2(double x,double y, CRGB c); 
    virtual ~CP2();  
public:         //方便访问,直接定义为共有  
    double x;  
    double y;  
	CRGB c;
};  
  
#endif // !defined(AFX_P2_H__DD23884F_7F62_48E8_A906_65C4558DE4EB__INCLUDED_)
实现文件:P2.cpp

// P2.cpp: implementation of the CP2 class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "WuLine.h"
#include "P2.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CP2::CP2()
{

}

CP2::CP2(double x,double y, CRGB c)
{
	this->x = x;
	this->y = y;
	this->c = c;
}

CP2::~CP2()
{

}
2)创建CRGB类

头文件:RGB.h

// RGB.h: interface for the CRGB class.
//
//////////////////////////////////////////////////////////////////////

#if !defined(AFX_RGB_H__F163CE21_A4E9_4B66_9011_3B63D6E588D2__INCLUDED_)
#define AFX_RGB_H__F163CE21_A4E9_4B66_9011_3B63D6E588D2__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

class CRGB  
{
public:
	CRGB();
	CRGB(double r,double g,double b);		
	virtual ~CRGB();
	friend CRGB operator+(const CRGB &,const CRGB &);//运算符重载
	friend CRGB operator-(const CRGB &,const CRGB &);
	friend CRGB operator*(const CRGB &,const CRGB &);
	friend CRGB operator*(const CRGB &,double);
	friend CRGB operator*(double,const CRGB &);
	friend CRGB operator/(const CRGB &,double);public:	
public:	
	double red;   //红色分量
	double green; //绿色分量
	double blue;  //蓝色分量
};

#endif // !defined(AFX_RGB_H__F163CE21_A4E9_4B66_9011_3B63D6E588D2__INCLUDED_)
实现文件:RGB.cpp

// RGB.cpp: implementation of the CRGB class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "WuLine.h"
#include "RGB.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CRGB::CRGB()
{
	red=1.0;
	green=1.0;
	blue=1.0;
}

CRGB::~CRGB()
{

}
CRGB::CRGB(double r,double g,double b)//重载构造函数
{
	red=r;
	green=g;
	blue=b;
}

CRGB operator +(const CRGB &c1,const CRGB &c2)//+运算符重载
{
	CRGB c;
	c.red=c1.red+c2.red;
	c.green=c1.green+c2.green;
	c.blue=c1.blue+c2.blue;
	return c;
}

CRGB operator -(const CRGB &c1,const CRGB &c2)//-运算符重载
{
	CRGB c;
	c.red=c1.red-c2.red;
	c.green=c1.green-c2.green;
	c.blue=c1.blue-c2.blue;
	return c;
}

CRGB operator *(const CRGB &c1,const CRGB &c2)//*运算符重载
{
	CRGB c;
	c.red=c1.red*c2.red;
	c.green=c1.green*c2.green;
	c.blue=c1.blue*c2.blue;
	return c;
}

CRGB operator *(const CRGB &c1,double k)//*运算符重载
{
   CRGB c;
   c.red=k*c1.red;
   c.green=k*c1.green;
   c.blue=k*c1.blue;
   return c;
}

CRGB operator *(double k,const CRGB &c1)//*运算符重载
{
   CRGB c;
   c.red=k*c1.red;
   c.green=k*c1.green;
   c.blue=k*c1.blue;
   return c;
}

CRGB operator /(const CRGB &c1,double k)// /运算符重载
{
   CRGB c;
   c.red=c1.red/k;
   c.green=c1.green/k;
   c.blue=c1.blue/k;
   return c;
}

CRGB operator +=(CRGB &c1,CRGB &c2)//+=运算符重载
{
	c1.red=c1.red+c2.red;
	c1.green=c1.green+c2.green;
	c1.blue=c1.blue+c2.blue;
	return c1;
}

CRGB operator -=(CRGB &c1,CRGB &c2)//-=运算符重载
{
	c1.red=c1.red-c2.red;
	c1.green=c1.green-c2.green;
	c1.blue=c1.blue-c2.blue;
	return c1;
}

CRGB operator *=(CRGB &c1,CRGB &c2)//*=运算符重载
{
	c1.red=c1.red*c2.red;
	c1.green=c1.green*c2.green;
	c1.blue=c1.blue*c2.blue;
	return c1;
}

CRGB operator /=(CRGB &c1,double k)///=运算符重载
{
	c1.red=c1.red/k;
	c1.green=c1.green/k;
	c1.blue=c1.blue/k;
	return c1;
}
3)创建CWuAnti类
头文件:WuAnti.h

// WuAnti.h: interface for the CWuAnti class.
//
//////////////////////////////////////////////////////////////////////

#if !defined(AFX_WUANTI1_H__2C2D354F_C8AA_4F64_81CC_56195DEE5704__INCLUDED_)
#define AFX_WUANTI1_H__2C2D354F_C8AA_4F64_81CC_56195DEE5704__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
#include "P2.h"
class CWuAnti  
{
public:
	CWuAnti();
	virtual ~CWuAnti();  
	void MoveTo(double x, double y, CRGB c); //移动到指定位置,指定起点颜色  
	void MoveTo(CP2 p0);
	void LineTo(CDC *pDC, double x, double y, CRGB c); //绘制Wu反走样直线,不含终点,指定终点颜色
	void LineTo(CDC *pDC, CP2 p1);
private:  
    CP2 P0;      //起点  
    CP2 P1;      //终点
};

#endif // !defined(AFX_WUANTI1_H__2C2D354F_C8AA_4F64_81CC_56195DEE5704__INCLUDED_)
实现文件:WuAnti.cpp

// WuAnti.cpp: implementation of the CWuAnti class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "WuLine.h"
#include "WuAnti.h"

#include "RGB.h"
#include <math.h>  
#define Round(d) int(floor(d+0.5))//四舍五入宏定义

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CWuAnti::CWuAnti()
{

}

CWuAnti::~CWuAnti()
{

}

void CWuAnti::MoveTo(double x, double y, CRGB c)  //绘制彩色线条,指定起点颜色
{  
    P0.x=x;
	P0.y=y;
	P0.c=c;
}  

void CWuAnti::MoveTo(CP2 p0)      //绘制彩色线条
{  
	P0=p0;
}  

void CWuAnti::LineTo(CDC *pDC, double x, double y, CRGB c) //绘制,指定终点颜色  
{  
	LineTo(pDC, CP2(x, y, c));   
}  

void CWuAnti::LineTo(CDC *pDC, CP2 p1)
{
	P1=p1;
	CP2 p,t;
	CRGB c0,c1;
	//COLORREF Cf,Cb = pDC->GetBkColor(); 
	if(fabs(P0.x-P1.x)==0)//绘制垂线
	{
		if(P0.y>P1.y)//交换顶点,使得起始点低于终点顶点
		{
			t=P0;P0=P1;P1=t;
		}
		for(p=P0;p.y<P1.y;p.y++)
		{
			//线性插值:c=(1-t)c0+tc1, t=(x-x0)/(x1-x0)或t=(y-y0)/(y1-y0)
			//  ------>c=c0+t(c1-c0)
			p.c=P0.c+(P1.c-P0.c)*(p.y-P0.y)/(p1.y-P0.y); //重载RGB,‘+’‘-’‘*’‘/’运算符
			pDC->SetPixelV(Round(p.x),Round(p.y),RGB(p.c.red,p.c.green,p.c.blue));
		}
	}	
	else
	{
		double k,e=0;
		k=(P1.y-P0.y)/(P1.x-P0.x);
		if(k>1.0)//绘制k>1 (y为主方向)
		{
			if(P0.y>P1.y)
			{
				t=P0;P0=P1;P1=t;
			}	  		
			for(p=P0;p.y<P1.y;p.y++)
			{
				//像素亮度级别
				c0=CRGB(e,e,e);
				c1=CRGB(1.0-e,1.0-e,1.0-e);
				//线性插值:c=(1-t)c0+tc1, t=(x-x0)/(x1-x0)或t=(y-y0)/(y1-y0)
				p.c=P0.c+(P1.c-P0.c)*(p.y-P0.y)/(p1.y-P0.y);
				pDC->SetPixelV(Round(p.x),Round(p.y),RGB(c0.red*p.c.red,c0.green*p.c.green,c0.blue*p.c.blue));
				pDC->SetPixelV(Round(p.x+1),Round(p.y),RGB(c1.red*p.c.red,c1.green*p.c.green,c1.blue*p.c.blue));
				e+=(1.0/k);
                if(e>=1.0)
				{
					p.x++;
					e--;
				}
			}
		}
		if(0.0<=k && k<=1.0)//绘制0=<k=<1 (x为主方向)
		{
			if(P0.x>P1.x)
			{
				t=P0;P0=P1;P1=t;
			}	  
			for(p=P0;p.x<P1.x;p.x++)
			{
				c0=CRGB(e,e,e);
				c1=CRGB(1.0-e,1.0-e,1.0-e);
				p.c=P0.c+(P1.c-P0.c)*(p.x-P0.x)/(p1.x-P0.x);
				pDC->SetPixelV(Round(p.x),Round(p.y),RGB(c0.red*p.c.red,c0.green*p.c.green,c0.blue*p.c.blue));
				pDC->SetPixelV(Round(p.x),Round(p.y+1),RGB(c1.red*p.c.red,c1.green*p.c.green,c1.blue*p.c.blue));
				e=e+k;
                if(e>=1.0)
				{
					p.y++;
					e--;
				}
			}
		}		
		if(k>=-1.0 && k<0.0)//绘制-1=<k<0 (x为主方向)
		{
			if(P0.x>P1.x)
			{
				t=P0;P0=P1;P1=t;
			}	 
			for(p=P0;p.x<P1.x;p.x++)
			{
				c0=CRGB(e,e,e);
				c1=CRGB(1.0-e,1.0-e,1.0-e);
				p.c=P0.c+(P1.c-P0.c)*(p.x-P0.x)/(p1.x-P0.x);
				pDC->SetPixelV(Round(p.x),Round(p.y),RGB(c0.red*p.c.red,c0.green*p.c.green,c0.blue*p.c.blue));
				pDC->SetPixelV(Round(p.x),Round(p.y-1),RGB(c1.red*p.c.red,c1.green*p.c.green,c1.blue*p.c.blue));
				e=e-k;
                if(e>=1.0)
				{
					p.y--;
					e--;
				}
			}
		}
		if(k<-1.0)//绘制k<-1 (y为主方向)
		{
			if(P0.y<P1.y)
			{
				t=P0;P0=P1;P1=t;
			}	  
			for(p=P0;p.y>P1.y;p.y--)
			{
				c0=CRGB(e,e,e);
				c1=CRGB(1.0-e,1.0-e,1.0-e);
				p.c=P0.c+(P1.c-P0.c)*(p.y-P0.y)/(p1.y-P0.y);
				pDC->SetPixelV(Round(p.x),Round(p.y),RGB(c0.red*p.c.red,c0.green*p.c.green,c0.blue*p.c.blue));
				pDC->SetPixelV(Round(p.x+1),Round(p.y),RGB(c1.red*p.c.red,c1.green*p.c.green,c1.blue*p.c.blue));
				e=e-1/k;
                if(e>=1.0)
				{
					p.x++;
					e--;
				}
			}
		}
	}
	P0=p1;
}
4)OnDraw函数

void CWuLineView::OnDraw(CDC* pDC)
{
	CWuLineDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	// 设置绘图坐标系:原点为View视图区域中心,X轴正向水平向右,Y轴正向垂直向上
	CRect rect;
	GetClientRect(&rect);//获得客户区矩形的大小
	pDC->SetMapMode(MM_ANISOTROPIC);                    //自定义坐标系
	pDC->SetWindowExt(rect.Width(),rect.Height());      //设置窗口比例
	pDC->SetViewportExt(rect.Width(),-rect.Height());   //设置视区比例,且x轴向右,y轴向上
	pDC->SetViewportOrg(rect.Width()/2,rect.Height()/2);//设置客户区中心为坐标系原点
	rect.OffsetRect(-rect.Width()/2,-rect.Height()/2);  //矩形与客户区重合

	CWuAnti *line=new CWuAnti;//动态创建直线绘制类对象
	line->MoveTo(100,-200,CRGB(255,0,0));  
    line->LineTo(pDC,100,200,CRGB(0,255,0)); 
	
	//0<=k<=1
    line->MoveTo(-206,-137,CRGB(255,0,0));  
    line->LineTo(pDC,214,175,CRGB(0,255,0));  

	//k>1
	line->MoveTo(-201,-253,CRGB(255,0,0));  
    line->LineTo(pDC,201,266,CRGB(0,255,0));
	
	//k<-1
	line->MoveTo(-186,293,CRGB(255,0,0));  
    line->LineTo(pDC,201,-236,CRGB(0,255,0)); 

	//-1<k<0
	line->MoveTo(-286,193,CRGB(255,0,0));  
    line->LineTo(pDC,221,-246,CRGB(0,255,0)); 
 }
5)运行效果(放大25倍)







原文地址:http://blog.csdn.net/qingdujun/article/details/40083207

参考文献:计算机图形学基础教程(Visual C++版)(第2版) 孔令德 编著

百度文库,人生憶夢贡献,Wu反走样直线算法:http://wenku.baidu.com/link?url=6Nqvs2eaZTf9XrEXL7siH0bZOkfEk3W2OYM33Lo4ItYbA68Q1bquvCqt5O-BsJVxts8AKvBXgnx_qi_X1Ys7kG9wlcO8zGgq7JBXE8tdr6a


计算机图形学 彩色直线段的反走样(5)