作者:卿笃军
原文地址: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
时间: 2024-09-30 18:05:07