⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 line.cpp

📁 为联众台球游戏开发
💻 CPP
字号:
// Line.cpp : Defines the class behaviors for CDashLine
//
//	The Bresenham function in this file is derived from code from 
//			Jean-Claude Lanz mailto:Jclanz@bluewin.ch
//		and he presumably shares copyright to it
//	Otherwise the copyright belongs to Llew S. Goodstadt 
//		http://www.lg.ndirect.co.uk    mailto:lg@ndirect.co.uk
//		who hereby grants you fair use and distribution rights of the code 
//		in both commercial and non-commercial applications.

#include "stdafx.h"
#include "Line.h"
//#include "bezier.h"

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




// define _TIMING to null out the GDI calls.
//	i.e. you can find out what is the cost of the calculations
//#define _TIMING 1

/////////////////////////////////////////////////////////////////////////////
// helper

/////////////////////////////////////////////////////////////////////////////
// CDashLine

CDashLine::CDashLine(CDC * pDC, unsigned* pattern, unsigned count)
	:m_pDC(pDC), m_Pattern(0)
{
	SetPattern(pattern, count);
}

CDashLine::~CDashLine()
{
	// destroy GDI objects
	delete[] m_Pattern;
}

void CDashLine::SetPattern(unsigned* pattern, unsigned count)
{
	// Must be an even number of dash and gaps
	ASSERT(m_Count >=0);
	ASSERT(!(m_Count % 2));

	m_Count = count;
	delete[] m_Pattern;
	if (m_Count)
	{
		m_Pattern = new UINT[count];
		memcpy(m_Pattern, pattern, count * sizeof(UINT));
	}	
	else
		m_Pattern = 0;
	Reset();
}

void CDashLine::Reset()
{
	m_CurPat = 0;
	if (m_Count)
		m_CurStretch = m_Pattern[0];
}

// use linear interpolation to compute next position
void CDashLine::Bresenham(LONG x, LONG y)
{

	// Setup Bresenham
	LONG dx = x - m_CurPos.x;
	LONG dy = y - m_CurPos.y;

	LONG *p1, *p2, *pd1, *pd2;
	if (abs(dx) >= abs(dy))
	{
		p1 = &m_CurPos.x; 
		p2 = &m_CurPos.y; 
		pd1 = &dx; 
		pd2 = &dy; 
	}
	else
	{
		p1 = &m_CurPos.y; 
		p2 = &m_CurPos.x; 
		pd1 = &dy; 
		pd2 = &dx;
	}

	int max = abs(*pd1);
	int dec = abs(*pd2);
	int s1 = (*pd1 >= 0) ? 1: -1;
	int s2 = (*pd2 >= 0) ? 1: -1;
	int val = max;

	// count past correct number of pixels in current segment
	// 		or until end of this line
	for (int i = 0; i < max; i++)
	{
		val -= dec;
		if (val <= 0) 
		{	
			*p2 += s2; 
			val += max; 
		}
		*p1 += s1;

		--m_CurStretch;
		if (!m_CurStretch)
		{
			// use next pattern for next segment
			m_CurPat = (m_CurPat + 1) % m_Count;
			m_CurStretch = m_Pattern[m_CurPat];

			// draw segment or skip gap
#ifndef _TIMING
			if (m_CurPat % 2)
				m_pDC->LineTo(m_CurPos);
			else
				m_pDC->MoveTo(m_CurPos);
#endif _TIMING

		
			// if last point, return
			if (i == max - 1) 
				return;
		}
	}

	// draw to last point if necessary
#ifndef _TIMING
	if (!(m_CurPat % 2))
		m_pDC->LineTo(m_CurPos);
#endif _TIMING
}

void CDashLine::MoveTo(int x, int y)
{
	// with MoveTo, reset parameters
	Reset();

	// save current position
	m_CurPos.x = x; 
	m_CurPos.y = y;

	// move to position
	m_pDC->MoveTo(m_CurPos);
}


void CDashLine::LineTo(int x, int y)
{
	// line type and color
	if (!m_Count)
	{
		m_pDC->LineTo(x, y);
		m_CurPos.x = x; m_CurPos.y = y;
		return;
	}
#ifdef _TIMING
	m_pDC->LineTo(x, y);
#endif _TIMING

	// calculate and draw next points
	Bresenham(x, y);
}


// use linear interpolation to compute next position
/*void CDashLine::BezierTo(POINT* dest)
{
#ifdef _TIMING
	m_DC.PolyBezierTo(dest, 3);
#endif _TIMING
	if (!m_Count)
	{
		m_DC.PolyBezierTo(dest, 3);
		m_CurPos = dest[2];
		return;
	}	


	// Setup Bezier representing curve
	LBezier currentBez;
	currentBez.p[0] = m_CurPos;
	for (int i = 0; i < 3; ++i)
		currentBez.p[i+1] = dest[i];

	LBezier drawBezier;
	CPoint Output[4];

	//for (int ii = 0; ii < 100; ++ii)
	while(1)
	{
		// split off segment corresponding to current stretch, ie drawBezier
		currentBez.TSplit(drawBezier, currentBez.TAtLength(m_CurStretch));
		drawBezier.GetCPoint(Output);

		m_CurPos = Output[3];

#ifndef _TIMING
		if (m_CurPat % 2)
			m_DC.MoveTo(m_CurPos);
		else
			m_DC.PolyBezierTo(Output+1, 3);
#endif _TIMING

		// break if some part of segment did not fit on bezier
		if (!m_CurStretch)
		{
			// use next pattern for next segment
			m_CurPat = (m_CurPat + 1) % m_Count;
			m_CurStretch = m_Pattern[m_CurPat];
		}	
		else
			break;		
	}		
}*/


// Returns count of elements (dash/dot and gaps)
// You must be careful to pass in enough memory for pattern
// It is probably safest to always have an array of [8]
unsigned CDashLine::GetPattern(unsigned* pattern, bool round, unsigned penSize, unsigned style)
{
	ASSERT(style <= DL_DASHDOTDOTDOT_GAP);
	int gapLen	= round	?	penSize * 2 : penSize;
	int dotLen	= round	?	1			: penSize;
	int dashLen	= round	?	penSize * 2 : penSize * 3;
	if (style >= DL_DASH_GAP)
		gapLen *= 2;
	if (style == DL_SOLID)
		return(0);
	
	switch (style)
	{
		case DL_DASH:
		case DL_DASH_GAP:
				pattern[0] = dashLen;
				pattern[1] = gapLen;
				return 2;
		case DL_DOT:
		case DL_DOT_GAP:
				pattern[0] = dotLen;
				pattern[1] = gapLen;
				return 2;
		case DL_DASHDOT:
		case DL_DASHDOT_GAP:
				pattern[0] = dashLen;
				pattern[2] = dotLen;
				pattern[1] = 
				pattern[3] = gapLen;
				return 4;
		case DL_DASHDOTDOT:
		case DL_DASHDOTDOT_GAP:
				pattern[0] = dashLen;
				pattern[2] =
				pattern[4] = dotLen;
				pattern[1] =
				pattern[3] =
				pattern[5] = gapLen;
				return 6;
		case DL_DASHDOTDOTDOT:
		case DL_DASHDOTDOTDOT_GAP:
		default:
				pattern[0] = dashLen;
				pattern[2] =
				pattern[4] = 
				pattern[6] = dotLen;
				pattern[1] =
				pattern[3] =
				pattern[5] = 
				pattern[7] = gapLen;
				return 8;
		
	}	
		
}	

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -