📄 pline.cpp
字号:
/////////////////////////////////////////////////////////////////////////////////
//
// PLine.cpp: implementation of the CPLine class.
//
////////////////////////////////////////////////////////////////////////////////
// 版权所有(2002)
// Copyright(2002)
// 编写者: 向世明
// Author: Xiang Shiming
#include "stdafx.h"
#include "PLine.h"
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CPLine::CPLine(){}
CPLine::~CPLine(){}
//该函数充分利用Window画笔进行绘制直线
//四个参数:
//pDC----设备描述表
//pt1----直线起点
//pt2----直线终点
//pen----直线颜色及线风格
//该函数只能绘制一条颜色相同的直线.
//注意, 对于 pt1 和 pt2 两个参数还可以接受CPoint对象
void CPLine::Draw(CDC *pDC, POINT pt1, POINT pt2, CPen& pen)
{
//选择画笔
CPen* oldPen = pDC->SelectObject(&pen);
//绘制直线
pDC->MoveTo(pt1);
pDC->LineTo(pt2);
//选择原来的设备属性
pDC->SelectObject(oldPen);
}
void CPLine::Draw(CDC *pDC, int x1, int y1, int x2, int y2, CPen& pen)
{
//选择画笔
CPen* oldPen = pDC->SelectObject(&pen);
//绘制直线
pDC->MoveTo(x1, y1);
pDC->LineTo(x2, y2);//do not include the point (x2, y2)
//选择原来的设备属性
pDC->SelectObject(oldPen);
}
//绘制一条直线, 直线的宽度为1, 直线的颜色由直线两个端点的颜色共同决定
//注意, 对于 pt1 和 pt2 两个参数还可以接受CPoint对象
//注意, 浮点颜色的有效值为[0, 1]区间内的浮点小数
//与Windows相对应, 该算法也不包含最后一个点(x2, y2)
//注意, 从(x1, y1)--(x2, y2)与(x2, y2)--(x1, y1)略有些许不同.
//评价:该函数绘制的直线(像素位置)与Windows的LineTo()函数绘制的结果是完全一致的
void CPLine::Draw(CDC *pDC, int x1, int y1, int x2, int y2, FLOATCOLORRGB clr1, FLOATCOLORRGB clr2)
{
//两端点间的水平偏移量和垂直偏移量
int nDx = x2 - x1;
int nDy = y2 - y1;
//两端点间的水平距离和垂直距离
int nIx = ABS(nDx);
int nIy = ABS(nDy);
//描点步数(增量总值)
int nInc = MAX(nIx, nIy);
//直线当前点的颜色
float fPlotR = clr1.red, fPlotG = clr1.green, fPlotB = clr1.blue;
//绘制第一个点, 即, 直线的起点
pDC->SetPixelV(x1, y1, RGB((BYTE)(fPlotR * 255.0f), (BYTE)(fPlotG * 255.0f), (BYTE)(fPlotB * 255.0f)));
if(nInc < 2) return;
//用于判断是否在nJudgeX, nJudgeY方向上向前进
int nJudgeX = -nIy, nJudgeY = -nIx;
//通过增量计算得到的当前点
int x = x1, y = y1;
//开始进行增量计算
//采用Bresenham算法.在这里, 我们将算法进行改进,
//使其对于任意斜率的直线都能绘制, 而且绘制方向始终为从起点绘制到终点
//与Windows相对应, 该算法也不包含最后一个点(x2, y2)
nInc--;
//注意, 整数乘2在计算机中采用移位实现
//Bresenham算法
int nTwoIx = 2 * nIx, nTwoIy = 2 * nIy;
//颜色增量
float fIncR = (clr2.red - fPlotR) / nInc;
float fIncG = (clr2.green - fPlotG) / nInc;
float fIncB = (clr2.blue - fPlotB) / nInc;
//开始增量计算
for(int i = 0;i < nInc; i++)
{
nJudgeX += nTwoIx;
nJudgeY += nTwoIy;
//通过增量法计算的当前点是否属于直线上的点
BOOL bPlot = FALSE;
//检测 nJudgeX 方向
if(nJudgeX >= 0)
{
bPlot = TRUE;
nJudgeX -= nTwoIy;
//将任意走向的直线统一起来
if(nDx > 0)x++;
else if(nDx < 0)x--;
}
//检测 nJudgeY 方向
if(nJudgeY >= 0)
{
bPlot = TRUE;
nJudgeY -= nTwoIx;
//将任意走向的直线统一起来
if(nDy > 0)y++;
else if(nDy < 0)y--;
}
//如果当前点在直线上
if(bPlot)
{
fPlotR += fIncR;
fPlotG += fIncG;
fPlotB += fIncB;
//绘制当前点
pDC->SetPixelV(x, y,
RGB((BYTE)(fPlotR * 255.0f), (BYTE)(fPlotG * 255.0f), (BYTE)(fPlotB * 255.0f)));
}//end if
}//end for
}
//采用Bresenham算法绘制一条颜色渐变的直线
void CPLine::Draw(CDC *pDC, POINT pt1, POINT pt2, FLOATCOLORRGB clr1, FLOATCOLORRGB clr2)
{
//两端点坐标
int x1 = pt1.x, y1 = pt1.y;
int x2 = pt2.x, y2 = pt2.y;
Draw(pDC, x1, y1, x2, y2, clr1, clr2);
}
//采用Bresenham算法绘制一条颜色相同的直线
//将Bresenham算法写成统一的形式
//x1, y1, x2, y2直线的起点和端点
void CPLine::Draw(CDC *pDC, int x1, int y1, int x2, int y2, COLORREF clr)
{
//两端点间的水平偏移量和垂直偏移量
int nDx = x2 - x1;
int nDy = y2 - y1;
//两端点间的水平距离和垂直距离
int nIx = ABS(nDx);
int nIy = ABS(nDy);
//描点步数(增量总值)
int nInc = MAX(nIx, nIy);
//绘制第一个点, 即, 直线的起点
pDC->SetPixelV(x1, y1, clr);
//不包含终点
if(nInc < 2)return;
//用于判断是否在nJudgeX, nJudgeY方向上向前进
int nJudgeX = -nIy, nJudgeY = -nIx;
//通过增量计算得到的当前点
int x = x1, y = y1;
//开始进行增量计算
//采用Bresenham算法.在这里, 我们将算法进行改进,
//使其对于任意斜率的直线都能绘制, 而且绘制方向始终为从起点绘制到终点
//注意, 整数乘2在计算机中采用移位实现
//Bresenham算法
int nTwoIx = 2 * nIx, nTwoIy = 2 * nIy;
//与Windows相对应, 该算法也不包含最后一个点(x2, y2)
nInc--;
//开始增量计算
for(int i = 0;i < nInc; i++)
{
nJudgeX += nTwoIx;
nJudgeY += nTwoIy;
//通过增量法计算的当前点是否属于直线上的点
BOOL bPlot = FALSE;
//检测 X 方向
if(nJudgeX >= 0)
{
bPlot = TRUE;
nJudgeX -= nTwoIy;
//将任意走向的直线统一起来
if(nDx > 0)x++;
else if(nDx < 0)x--;
}
//检测 Y 方向
if(nJudgeY >= 0)
{
bPlot = TRUE;
nJudgeY -= nTwoIx;
//将任意走向的直线统一起来
if(nDy > 0)y++;
else if(nDy < 0)y--;
}
//如果当前点在直线上, 则绘制当前点
if(bPlot) pDC->SetPixelV(x, y, clr);
}//end for
}
//采用Bresenham算法(统一表示)
void CPLine::Draw(CDC *pDC, POINT pt1, POINT pt2, COLORREF clr)
{
int x1 = pt1.x, y1= pt1.y, x2 = pt2.x, y2 = pt2.y;
Draw(pDC, x1, y1, x2, y2, clr);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -