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

📄 gradient.cpp

📁 一个工业控制管道流动控件,能够反映管道内流动情况.不是我写的,但觉得不错,因此转载上来
💻 CPP
📖 第 1 页 / 共 2 页
字号:
		*s /= (*l <= 0.5f) ? (v + m ) :
			(2.0f - v - m) ;
    } 
	else
		return;


    r2 = (v - r) / vm;
    g2 = (v - g) / vm;
    b2 = (v - b) / vm;

    if (r == v)
		*h = (g == m ? 5.0f + b2 : 1.0f - g2);
    else if (g == v)
		*h = (b == m ? 1.0f + r2 : 3.0f - b2);
    else
		*h = (r == m ? 3.0f + g2 : 5.0f - r2);

    	*h /= 6.0f;
}

void HSL_to_RGB(float h, float sl, float l, float *r, float *g, float *b)
{
    float v;

    v = (l <= 0.5f) ? (l * (1.0f + sl)) : (l + sl - l * sl);
    if (v <= 0) {
		*r = *g = *b = 0.0f;
    } 
	else 
	{
		float m;
		float sv;
		int sextant;
		float fract, vsf, mid1, mid2;

		m = l + l - v;
		sv = (v - m ) / v;
		h *= 6.0f;
		sextant = (int)h;	
		fract = h - sextant;
		vsf = v * sv * fract;
		mid1 = m + vsf;
		mid2 = v - vsf;
		switch (sextant) 
		{
			case 0: *r = v; *g = mid1; *b = m; break;
			case 1: *r = mid2; *g = v; *b = m; break;
			case 2: *r = m; *g = v; *b = mid1; break;
			case 3: *r = m; *g = mid2; *b = v; break;
			case 4: *r = mid1; *g = m; *b = v; break;
			case 5: *r = v; *g = m; *b = mid2; break;
		}
    }
}

COLORREF CGradient::InterpolateHSLClockwise(COLORREF first, COLORREF second, float position, float start, float end)
{
	float sh = 0, ss = 0, sl = 0, eh = 0, es = 0, el = 0, h = 0, s = 0, l = 0, r = 0, g = 0, b = 0;
	RGB_to_HSL((float)GetRValue(first)/255.0f, (float)GetGValue(first)/255.0f,
		(float)GetBValue(first)/255.0f, &sh, &ss, &sl);
	RGB_to_HSL((float)GetRValue(second)/255.0f, (float)GetGValue(second)/255.0f,
		(float)GetBValue(second)/255.0f, &eh, &es, &el);

	sh = sh - floorf(sh);
	eh = eh - floorf(eh);

	//Interpolate H clockwise
	if(eh >= sh) h = (eh*(position - start) + sh*(end-position))/(end-start);
	else h = ((eh + 1.0f)*(position - start) + sh*(end-position))/(end-start);
	h = (h>=1.0f)?h-1.0f:h;

	s = ((es*(position - start) + ss*(end-position))/(end-start));
	l = ((el*(position - start) + sl*(end-position))/(end-start));

	HSL_to_RGB(h, s, l, &r, &g, &b);
	return RGB((BYTE)(r*255.0f), (BYTE)(g*255.0f), (BYTE)(b*255.0f));
}

COLORREF CGradient::InterpolateHSLAntiClockwise(COLORREF first, COLORREF second, float position, float start, float end)
{
	float sh = 0, ss = 0, sl = 0, eh = 0, es = 0, el = 0, h = 0, s = 0, l = 0, r = 0, g = 0, b = 0;
	RGB_to_HSL((float)GetRValue(first)/255.0f, (float)GetGValue(first)/255.0f,
		(float)GetBValue(first)/255.0f, &sh, &ss, &sl);
	RGB_to_HSL((float)GetRValue(second)/255.0f, (float)GetGValue(second)/255.0f,
		(float)GetBValue(second)/255.0f, &eh, &es, &el);

	sh = sh - floorf(sh);
	eh = eh - floorf(eh);

	//Interpolate H anticlockwise
	if(eh <= sh) h = (eh*(position - start) + sh*(end-position))/(end-start);
	else h = ((eh + 1.0f)*(position - start) + sh*(end-position))/(end-start);
	h = (h>=1.0f)?h-1.0f:h;

	s = ((es*(position - start) + ss*(end-position))/(end-start));
	l = ((el*(position - start) + sl*(end-position))/(end-start));

	HSL_to_RGB(h, s, l, &r, &g, &b);
	return RGB((BYTE)(r*255.0f), (BYTE)(g*255.0f), (BYTE)(b*255.0f));
}

COLORREF CGradient::InterpolateHSLLongest(COLORREF first, COLORREF second, float position, float start, float end)
{
	float sh = 0, ss = 0, sl = 0, eh = 0, es = 0, el = 0, h = 0, s = 0, l = 0, r = 0, g = 0, b = 0;
	RGB_to_HSL((float)GetRValue(first)/255.0f, (float)GetGValue(first)/255.0f,
		(float)GetBValue(first)/255.0f, &sh, &ss, &sl);
	RGB_to_HSL((float)GetRValue(second)/255.0f, (float)GetGValue(second)/255.0f,
		(float)GetBValue(second)/255.0f, &eh, &es, &el);

	sh = sh - (float)floor(sh);
	eh = eh - (float)floor(eh);

	//Interpolate H short route
	if(((eh-sh)-floor(eh-sh) < 0.5f)?(eh < sh):(eh >= sh)) h = (eh*(position - start) + sh*(end-position))/(end-start);
	else h = ((eh+(sh>eh?1.0f:-1.0f))*(position - start) + sh*(end-position))/(end-start);
	//TRACE3("sh: %f eh: %f h: %f\n", sh, eh, h);
	
	h = h - floorf(h);

	s = ((es*(position - start) + ss*(end-position))/(end-start));
	l = ((el*(position - start) + sl*(end-position))/(end-start));

	HSL_to_RGB(h, s, l, &r, &g, &b);
	return RGB((BYTE)(r*255.0f), (BYTE)(g*255.0f), (BYTE)(b*255.0f));
}
 
COLORREF CGradient::InterpolateHSLShortest(COLORREF first, COLORREF second, float position, float start, float end)
{
	float sh = 0, ss = 0, sl = 0, eh = 0, es = 0, el = 0, h = 0, s = 0, l = 0, r = 0, g = 0, b = 0;
	RGB_to_HSL((float)GetRValue(first)/255.0f, (float)GetGValue(first)/255.0f,
		(float)GetBValue(first)/255.0f, &sh, &ss, &sl);
	RGB_to_HSL((float)GetRValue(second)/255.0f, (float)GetGValue(second)/255.0f,
		(float)GetBValue(second)/255.0f, &eh, &es, &el);

	sh = sh - (float)floor(sh);
	eh = eh - (float)floor(eh);

	//Interpolate H short route
	if(((eh-sh)-floor(eh-sh) > 0.5f)?(eh < sh):(eh >= sh)) h = (eh*(position - start) + sh*(end-position))/(end-start);
	else h = ((eh+(sh>eh?1.0f:-1.0f))*(position - start) + sh*(end-position))/(end-start);
	//TRACE3("sh: %f eh: %f h: %f\n", sh, eh, h);
	
	h = h - floorf(h);

	s = ((es*(position - start) + ss*(end-position))/(end-start));
	l = ((el*(position - start) + sl*(end-position))/(end-start));

	HSL_to_RGB(h, s, l, &r, &g, &b);
	return RGB((BYTE)(r*255.0f), (BYTE)(g*255.0f), (BYTE)(b*255.0f));
}

int CGradient::IndexFromPos(float pos)
{
	ASSERT(pos >= 0.0f && pos <= 1.0f);
		// positions betwen 0 and 1!

	if(pos < pegs[0].position)
		return STARTPEG;

	for(int i = 0; i < pegs.GetSize()-1; i++)
		if(pos >= pegs[i].position && pos <= pegs[i+1].position)
			return i;

	return -1; // Eh? somethings wrong here
}

int CGradient::IndexFromId(UINT id)
{
	for(int i = 0; i < pegs.GetSize(); i++)
		if(id == pegs[i].GetID())
			return i;
	return -1;
}


//----- Fast sorting alogarithm functions -----//
int CGradient::Partition(int lb, int ub)
{
    CPeg temppeg, pivot;
    int i, j, p;

	/* select pivot and exchange with 1st element */
	p = lb + ((ub - lb)>>1);
    pivot = pegs[p];
    pegs[p] = pegs[lb];

    /* sort lb+1..ub based on pivot */
    i = lb+1;
    j = ub;
    while(1)
	{
        while(i < j && pivot.position >= pegs[i].position) i++;
        while(j >= i && pegs[j].position >= pivot.position) j--;
        if(i >= j) break;
        temppeg.colour = pegs[i].colour;
		temppeg.position = pegs[i].position;
        pegs[i].colour = pegs[j].colour;
        pegs[i].position = pegs[j].position;
        pegs[j].colour = temppeg.colour;
        pegs[j].position = temppeg.position;
        j--; i++;
    }

    /* pivot belongs in a[j] */
    pegs[lb] = pegs[j];
    pegs[j] = pivot;

    return j;
}


void CGradient::QuickSort(int lb, int ub)
{
    int m;

   /**************************
    *  sort array pegs[lb..ub]  *
    **************************/

    while (lb < ub)
	{
        /* quickly sort short lists */
        if (ub - lb <= 12)
		{
            InsertSort(lb, ub);
            return;
        }

        m = Partition(lb, ub);

        if (m - lb <= ub - m)
		{
            QuickSort(lb, m - 1);
            lb = m + 1;
        }
		else
		{
            QuickSort(m + 1, ub);
            ub = m - 1;
        }
    }
}

void CGradient::InsertSort(int lb, int ub)
{
    CPeg temppeg;
    
    for (int i = lb + 1; i <= ub; i++)
	{
        temppeg = pegs[i];
        for(int j = i-1; j >= lb && pegs[j].position > temppeg.position; j--)
			pegs[j+1] = pegs[j];
		pegs[j+1] = temppeg;
    }
}

COLORREF CGradient::ColourFromPosition(float pos)
{
	if(pos < 0 || pos > 1)
	{
		ASSERT(0); // Position out of bounds!!
		return 0;
	}

	if(pos == 0 && m_UseBackground)
		return m_Background.colour;
	
	InterpolateFn Interpolate = GetInterpolationProc();
	ASSERT(Interpolate != NULL);
	
	if(m_Quantization != -1)
		pos = ((float)(int)(pos*m_Quantization))/m_Quantization + 0.5f / m_Quantization;

	if(pegs.GetSize() > 0)
	{
		//Some thing are aready constant and so can be found early
		float firstpegpos = pegs[0].position;
		float lastpegpos = pegs[pegs.GetUpperBound()].position;

		if(pos <= firstpegpos)
			return Interpolate(m_StartPeg.colour, pegs[0].colour, pos, 0,
				firstpegpos+1);
		else if(pos > lastpegpos)
			return Interpolate(pegs[pegs.GetUpperBound()].colour, m_EndPeg.colour,
				pos, lastpegpos, 1);
		else
		{
			int curpeg;
			curpeg = IndexFromPos(pos);
			return Interpolate(pegs[curpeg].colour, pegs[curpeg+1].colour, pos,
				pegs[curpeg].position, pegs[curpeg+1].position);
		}
	}
	else
	{
		//When there are no extra pegs we can just interpolate the start and end
		return Interpolate(m_StartPeg.colour, m_EndPeg.colour, pos, 0, 1);
	}
}

void CGradient::Serialize(CArchive &ar)
{
	if(ar.IsLoading())
	{
		int pegcount, temp;

		ar >> m_Background.colour;
		ar >> m_StartPeg.colour;
		ar >> m_EndPeg.colour;
		ar >> m_UseBackground;
		ar >> m_Quantization;
		ar >> temp;
		m_InterpolationMethod = (CGradient::InterpolationMethod)temp;

		ar >> pegcount;

		pegs.SetSize(pegcount);
		for(int i = 0; i < pegcount; i++)
			pegs[i].Serialize(ar);
	}
	else
	{
		ar << m_Background.colour;
		ar << m_StartPeg.colour;
		ar << m_EndPeg.colour;
		ar << (unsigned int)m_UseBackground;
		ar << m_Quantization;
		ar << (unsigned int)m_InterpolationMethod;
		
		ar << pegs.GetSize();

		for(int i = 0; i < pegs.GetSize(); i++)
			pegs[i].Serialize(ar);
	}
}

CGradient::InterpolationMethod CGradient::GetInterpolationMethod() const
{
	return m_InterpolationMethod;
}

void CGradient::SetInterpolationMethod(const InterpolationMethod method)
{
	m_InterpolationMethod = method;
}

int CGradient::GetQuantization() const
{
	return m_Quantization;
}

void CGradient::SetQuantization(const int entries)
{
	m_Quantization = entries;
}

InterpolateFn CGradient::GetInterpolationProc()
{
	switch(m_InterpolationMethod)
	{
	case Linear: return InterpolateLinear;
	case FlatStart: return InterpolateFlatStart;
	case FlatMid: return InterpolateFlatMid;
	case FlatEnd: return InterpolateFlatEnd;
	case Cosine: return InterpolateCosine;
	case HSLRedBlue: return InterpolateHSLClockwise;
	case HSLBlueRed: return InterpolateHSLAntiClockwise;
	case HSLShortest: return InterpolateHSLShortest;
	case HSLLongest: return InterpolateHSLLongest;
	case Reverse: return InterpolateReverse;
	default: return 0;
	}
}

⌨️ 快捷键说明

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