计算机图形学 彩色直线段的反走样(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

时间: 2024-09-30 18:05:07

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

计算机图形学 Cohen-Sutherland直线段裁剪算法

作者 : 卿笃军 原文地址:http://blog.csdn.net/qingdujun/article/details/40822977 本文通过一个完整的实例演示Cohen-Sutherland直线段裁剪算法. 1)创建类CP2 头文件:P2.h // P2.h: interface for the CP2 class. // ////////////////////////////////////////////////////////////////////// #if !defined

计算机图形学(三)_图元的属性_3_OpenGL颜色函数(上)

OpenGL颜色函数(上) 设定颜色显示模型(color display mode)为RGB: glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB); 变量表中的第一个参数指示正在使用单个帧缓存,第二个参数设定RGB模式,即默认模式.我们可以用GLUT_RGB或GLUT_RGBA之一来选择颜色模型.如果要用指向颜色表的索引来指定颜色,则用OpenGL常量GLUT_INDEX取代GLUT_RGB.  OpenGL的RGB和RGBA颜色模型 多数OpenGL图元使

计算机图形学 直线反走样Wu算法(4)

作者:卿笃军 原文地址:http://blog.csdn.net/qingdujun/article/details/40048285 本文通过一个完整的实例来演示,直线反走样Wu算法. 1)创建CP2类 头文件:P2.h // P2.h: interface for the CP2 class. // ////////////////////////////////////////////////////////////////////// #if !defined(AFX_P2_H__DD2

计算机图形学之光栅图形学——反走样算法简介

本文是对 赵明老师 <计算机图形学>MOOC课程 部分章节的小总结. 走样是数字化不可避免的. 简化:

图形学复习4——光栅化(画线画圆扫描线反走样算法)

图形学复习 CH7 光栅化 前几章介绍了几何处理和裁剪变换,接下来的步骤就是光栅化 光栅化是将形式表示的几何图元转换为阵列表示的数据片元的过程,片元中每一个像素对应帧缓冲区中的每一个像素 7.1 线段生成算法 (1)DDA画线算法 设直线表达式为y=mx+b,输入直线两端点坐标(x0,y0)和(xend,yend),可以计算出m=yend?y0xend?x0和b=y0?m?x0 DAA是基于微分运算的线段生成算法,其主要计算式便是δy=mδx: 若|m|≤1则x方向的变化大于y方向的变化,以x方

图形学中的贴图采样、走样与反走样等

计算机图形学中不可避免的会涉及到图像分析与处理的相关知识,前些时间也重温了下常用到的采样.重建以及纹理贴图等内容,并对其中的走样与反走样有了更多的认识,这里小结一下. 1. 基本问题 信号的采样与重建过程中首先面临着两个基本的问题: 给定一个连续的信号g(x)以及它的离散采样信号gs(x),能否通过gs(x)来完整的描述g(x) 的信息: 如果可以,如何通过gs(x)来重建出原始信号g(x). 这些通过对信息进行频域的分析即可得到相应的结论. 2. 采样 将一处于空间域(或时域)内的信号向频域进

[计算机图形学] 基于C#窗口的Bresenham直线扫描算法、种子填充法、扫描线填充法模拟软件设计(一)

一.首先说明: 这是啥? —— 这是利用C#FORM写的一个用来演示计算机图形学中 ①Bresenham直线扫描算法(即:连点成线):②种子填充法(即:填充多边形):③扫描线填充法 有啥用? ——  无论是连点成线还是区域填充在高级编程中基本上都提供很高效的库函数来调用.这里拿出这些算法一方面有利于大家理解那些封装的函数底层是实现:另一方面是方便嵌入式TFT屏幕底层驱动开发时借鉴的. 是啥样? ——  如下面的操作,不言而喻. 二.进入正题: 2-1.直线的扫描转换 图形的扫描转换实质就是在光栅

计算机图形学 绘制任意斜率的直线(1)

作者:卿笃军 原文地址:http://blog.csdn.net/qingdujun/article/details/40025917 本文演示,通过自己编写绘制直线函数(像素点填充),绘制任意斜率的直线. 1)创建CP2类 头文件:p2.h // P2.h: interface for the CP2 class. // ////////////////////////////////////////////////////////////////////// #if !defined(AFX

计算机图形学——光栅图形学直线算法简介

本文是对 赵明老师 <计算机图形学>MOOC课程 部分章节的小总结. 直线是组成图形的基础,其算法往往被多次调用,其好坏直接影响图形的显示效果和速度.以下是一些画直线的常用算法. 1.DDA算法: 此算法基于增量思想. 对于直线的斜截式:y=kx+b,考虑每次 x 递增 1, 都有 y[i+1] = y[i] + k,这样就将 kx 部分的乘法转换成递推的加法. 由于像素点都是整数坐标,所以每次求得的 y 都要取整操作,采用加 0.5 取整数部分的方法:(int)(y[i]+0.5). 但是,