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

📄 gradient.cpp

📁 一个工业控制管道流动控件,能够反映管道内流动情况.不是我写的,但觉得不错,因此转载上来
💻 CPP
📖 第 1 页 / 共 2 页
字号:
#include "stdafx.h"
#include "Gradient.h"

#include <math.h>

IMPLEMENT_SERIAL(CGradient, CObject, 0)
IMPLEMENT_SERIAL(CPeg, CObject, 0)

UINT CPeg::uniqueID = 0;

//------------------------------------------------------------
CPeg::CPeg()
{
	id = uniqueID;
	uniqueID++;
	colour = 0x00000000;
	position = 0.0f;
}

CPeg::CPeg(const CPeg &src)
{
	colour = src.colour;
	position = src.position;
	id = src.id;
}

CPeg & CPeg::operator = (const CPeg &src)
{
	colour = src.colour;
	position = src.position;
	id = src.id; 

	return *this;
}

void CPeg::Serialize(CArchive &ar)
{
	if(ar.IsLoading())
	{
		ar >> colour;
		ar >> position;
		id = uniqueID;
		uniqueID++;
	}
	else
	{
		ar << colour;
		ar << position;
	}
}

//-------------------------------------------------------------
CGradient::CGradient()
{
	m_StartPeg.colour = 0x00000000;
	m_StartPeg.position = 0.0f;
	m_EndPeg.colour = 0x00FFFFFF;
	m_EndPeg.position = 1.0f;
	m_Background.colour = 0x00000000; //A default pal
	m_Background.position = 0.0f;
	m_InterpolationMethod = Cosine;
	m_UseBackground = false;
	m_Quantization = -1;
}

CGradient::CGradient(CGradient &src)
{
	m_StartPeg.colour = m_StartPeg.colour;
	m_EndPeg.colour = m_EndPeg.colour;
	m_Background.colour = m_Background.colour;
	m_InterpolationMethod = src.m_InterpolationMethod;
	m_UseBackground = src.m_UseBackground;
	m_Quantization = src.m_Quantization;

	pegs.RemoveAll();
	for(int i = 0; i < src.pegs.GetSize(); i++)
	{
		pegs.Add(src.pegs[i]);
	}
}

CGradient::~CGradient()
{
	pegs.RemoveAll();	
}

CGradient& CGradient::operator =(CGradient &src)
{
	pegs.RemoveAll();	
	for(int i = 0; i < src.pegs.GetSize(); i++)
	{
		pegs.Add(src.pegs[i]);
	}

	m_StartPeg.colour = m_StartPeg.colour;
	m_EndPeg.colour = m_EndPeg.colour;
	m_Background.colour = m_Background.colour;
	m_InterpolationMethod = src.m_InterpolationMethod;
	m_UseBackground = src.m_UseBackground;
	m_Quantization = src.m_Quantization;

	return *this;
}

int CGradient::AddPeg(COLORREF crColour, float fPosition)
{	
	CPeg peg;

	if(fPosition < 0) 
		fPosition = 0;
	else if(fPosition > 1)
		fPosition = 1;

	peg.colour = crColour;
	peg.position = fPosition;
	pegs.Add(peg);
	SortPegs();

	return IndexFromId(peg.GetID());
}

int CGradient::AddPeg(CPeg peg)
{
	return AddPeg(peg.colour, peg.position);
}

//----- Assorted short functions -----//
void CGradient::RemovePeg(int iIndex) {pegs.RemoveAt(iIndex);}
void CGradient::SortPegs() {QuickSort(0, pegs.GetUpperBound());}
int CGradient::GetPegCount() const {return pegs.GetSize();}

const CPeg CGradient::GetPeg(int iIndex) const
{
	ASSERT(iIndex > -4 && iIndex != -1 && iIndex < GetPegCount());
		//You must pass a valid peg index or STARTPEG, ENDPEG, or BACKGROUND!
	
	if(iIndex >= 0)
	{
		const CPeg peg(pegs[iIndex]);
		return peg;
	}
	else if(iIndex == STARTPEG)
		return m_StartPeg;
	else if(iIndex == ENDPEG)
		return m_EndPeg;
	else return m_Background;
}

int CGradient::SetPeg(int iIndex, COLORREF crColour, float fPosition)
{
	UINT tempid;

	ASSERT(iIndex > -4 && iIndex != -1 && iIndex < GetPegCount());
		//You must pass a valid peg index or STARTPEG, ENDPEG, or BACKGROUND!
	
	if(fPosition < 0) fPosition = 0;
	else if(fPosition > 1) fPosition = 1;
	
	if(iIndex == STARTPEG)
		m_StartPeg.colour = crColour;
	else if(iIndex == ENDPEG)
		m_EndPeg.colour = crColour;
	else if(iIndex == BACKGROUND)
		m_Background.colour = crColour;
	else
	{
		pegs[iIndex].colour = crColour;
		pegs[iIndex].position = fPosition;
		tempid = pegs[iIndex].GetID();
		SortPegs();
		return IndexFromId(tempid);
	}
	return -1;
}

int CGradient::SetPeg(int iIndex, CPeg peg)
{
	UINT tempid;

	ASSERT(iIndex > -4 && iIndex != -1 && iIndex < GetPegCount());
		//You must pass a valid peg index or STARTPEG, ENDPEG, or BACKGROUND!
	
	if(peg.position < 0.0f) peg.position = 0.0f;
	else if(peg.position > 1.0f) peg.position = 1.0f;
	
	if(iIndex == STARTPEG)
		m_StartPeg.colour = peg.colour;
	else if(iIndex == ENDPEG)
		m_EndPeg.colour = peg.colour;
	else if(iIndex == BACKGROUND)
		m_Background.colour = peg.colour;
	else
	{
		pegs[iIndex].colour = peg.colour;
		pegs[iIndex].position = peg.position;
		tempid = pegs[iIndex].GetID();
		SortPegs();
		return IndexFromId(tempid);
	}
	return -1;
}

void CGradient::Make8BitPalette(RGBTRIPLE *lpPal)
{
	MakeEntries(lpPal, 256);
}

void CGradient::MakePalette(CPalette *lpPal)
{
	RGBTRIPLE *entries = new RGBTRIPLE[256];
	LOGPALETTE *logpal;
	logpal = (LOGPALETTE*)malloc(2*sizeof(WORD) + 256*sizeof(PALETTEENTRY));

	lpPal->DeleteObject();

	Make8BitPalette(entries);

	logpal->palVersion = 0x300;
	logpal->palNumEntries = 256;

	for(int i = 0; i < 256; i++)
	{
		logpal->palPalEntry[i].peRed = entries[i].rgbtRed;
		logpal->palPalEntry[i].peGreen = entries[i].rgbtGreen;
		logpal->palPalEntry[i].peBlue = entries[i].rgbtBlue;
		logpal->palPalEntry[i].peFlags = PC_RESERVED;
	}

	delete[] entries;

	lpPal->CreatePalette(logpal);
	free(logpal);
}

void CGradient::MakeEntries(RGBTRIPLE *lpPal, int iEntryCount)
{
	float pos;
	COLORREF colour;

	ASSERT(iEntryCount > 1);
	ASSERT(iEntryCount < 65535);

	InterpolateFn Interpolate = GetInterpolationProc();
	ASSERT(Interpolate != NULL);

	if(pegs.GetSize() > 0)
	{
		//Some things are already constant and so can be found early
		float firstpegpos = pegs[0].position;
		float lastpegpos = pegs[pegs.GetUpperBound()].position;
		COLORREF lastpegcolour = pegs[pegs.GetUpperBound()].colour;
		int curpeg;

		for(int i = 0; i < iEntryCount; i++)
		{
			if(m_Quantization == -1)
				pos = (float)i/iEntryCount;	
			else
				pos = ((float)(int)(((float)i/iEntryCount)*m_Quantization))/m_Quantization + 0.5f / m_Quantization;
			
			if(pos <= firstpegpos)
			{
				colour = Interpolate(m_StartPeg.colour, pegs[0].colour, pos, 0, firstpegpos);
				lpPal[i].rgbtRed = GetRValue(colour);
				lpPal[i].rgbtGreen = GetGValue(colour);
				lpPal[i].rgbtBlue = GetBValue(colour);
			}
			else if(pos > lastpegpos)
			{
				colour = Interpolate(lastpegcolour, m_EndPeg.colour, pos, lastpegpos, 1);
				lpPal[i].rgbtRed = GetRValue(colour);
				lpPal[i].rgbtGreen = GetGValue(colour);
				lpPal[i].rgbtBlue = GetBValue(colour);
			}
			else
			{
				curpeg = IndexFromPos(pos);
				colour = Interpolate(pegs[curpeg].colour, pegs[curpeg+1].colour, pos, pegs[curpeg].position, pegs[curpeg+1].position);
				lpPal[i].rgbtRed = GetRValue(colour);
				lpPal[i].rgbtGreen = GetGValue(colour);
				lpPal[i].rgbtBlue = GetBValue(colour);
			}
		}
	}
	else
	{
		//When there are no extra peg we can just interpolate the start and end
		for(int i = 0; i < iEntryCount; i++)
		{
			if(m_Quantization == -1)
				pos = (float)i/iEntryCount;	
			else
				pos = ((float)(int)(((float)i/iEntryCount)*m_Quantization))/m_Quantization + 0.5f / m_Quantization;
			
			colour = Interpolate(m_StartPeg.colour, m_EndPeg.colour, pos, 0, 1);
			lpPal[i].rgbtRed = GetRValue(colour);
			lpPal[i].rgbtGreen = GetGValue(colour);
			lpPal[i].rgbtBlue = GetBValue(colour);
		}
	}

	if(m_UseBackground)
	{
		lpPal[0].rgbtRed = GetRValue(m_Background.colour);
		lpPal[0].rgbtGreen = GetGValue(m_Background.colour);
		lpPal[0].rgbtBlue = GetBValue(m_Background.colour);
	}
}

COLORREF CGradient::InterpolateLinear(COLORREF first, COLORREF second, float position, float start, float end)
{
	if(start == end) return first;
	if(end - start == 0) return second;
	if(position == start) return first;
	if(position == end) return second;
	return RGB((BYTE)((GetRValue(second)*(position - start) + GetRValue(first)*(end-position))/(end-start)),
		(BYTE)((GetGValue(second)*(position - start) + GetGValue(first)*(end-position))/(end-start)),
		(BYTE)((GetBValue(second)*(position - start) + GetBValue(first)*(end-position))/(end-start)));
}

COLORREF CGradient::InterpolateReverse(COLORREF first, COLORREF second, float position, float start, float end)
{
	if(start == end) return first;
	if(end - start == 0) return second;
	if(position == start) return second;
	if(position == end) return first;
	return RGB((BYTE)((GetRValue(first)*(position - start) + GetRValue(second)*(end-position))/(end-start)),
		(BYTE)((GetGValue(first)*(position - start) + GetGValue(second)*(end-position))/(end-start)),
		(BYTE)((GetBValue(first)*(position - start) + GetBValue(second)*(end-position))/(end-start)));
}

COLORREF CGradient::InterpolateFlatStart(COLORREF first, COLORREF, float, float, float)
{
	return first;
}

COLORREF CGradient::InterpolateFlatMid(COLORREF first, COLORREF second,	float, float, float)
{
	unsigned short sr, sg, sb, er, eg, eb;
	sr = GetRValue(first);
	sg = GetGValue(first);
	sb = GetBValue(first);
	er = GetRValue(second);
	eg = GetGValue(second);
	eb = GetBValue(second);

	return RGB((sr+er)/2, (sg+eg)/2, (sb+eb)/2);
}

COLORREF CGradient::InterpolateFlatEnd(COLORREF, COLORREF second, float, float, float)
{return second;}

COLORREF CGradient::InterpolateCosine(COLORREF first, COLORREF second, float position, float start, float end)
{
	float theta = (position-start)/(end-start) * 3.1415927f;
	float f = (1 - cosf(theta)) * .5f;
	
	return RGB((BYTE)(((float)GetRValue(first))*(1-f) + ((float)GetRValue(second))*f),
		(BYTE)(((float)GetGValue(first))*(1-f) + ((float)GetGValue(second))*f),
		(BYTE)(((float)GetBValue(first))*(1-f) + ((float)GetBValue(second))*f));
}

void RGB_to_HSL	(float r, float g, float b, float *h, float *s, float *l)
{
    float v;
    float m;
    float vm;
    float r2, g2, b2;

    v = max(r,g);
    v = max(v,b);
    m = min(r,g);
    m = min(m,b);

    if ((*l = (m + v) / 2.0f) <= 0.0f) return;
    if ((*s = vm = v - m) > 0.0f) {

⌨️ 快捷键说明

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