// RGB HSV Conversion
// March 6th 2010
// Created By Nic Raboy

#include <iostream>

using namespace std;

// A nice container for the variables of HSV color
struct HSV
{
	double h;
	double s;
	double v;
};

// A nice container for the variables of RGB color
struct RGB
{
	double r;	// Red
	double g;	// Green
	double b;	// Blue
};

// Finds the highest of the three doubles inputed
double max(double x, double y, double z)
{
	double m = -1;
	if(m <= x) { m = x; }
	if(m <= y) { m = y; }
	if(m <= z) { m = z; }
	return m;
}

// Finds the lowest of the three doubles inputed
double min(double x, double y, double z)
{
	double m = 99999;
	if(m >= x) { m = x; }
	if(m >= y) { m = y; }
	if(m >= z) { m = z; }
	return m;
}

// Convert RGB color into HSV
HSV rgbToHsv(double r, double g, double b)
{
	double minimum, maximum, delta;
	HSV hsv;
	minimum = min(r, g, b);
	maximum = max(r, g, b);
	hsv.v = maximum;
	delta = maximum - minimum;
	// If the maximum is zero then there is no correct HSV and it failed
	if(maximum != 0)
	{
		hsv.s = delta / maximum * 100;
	}
	else
	{
		hsv.s = 0;
		hsv.h = -1;
		return hsv;
	}
	if(r == maximum)
	{
		hsv.h = (g - b) / delta;
	}
	else if(g == maximum)
	{
		hsv.h = 2 + (b - r) / delta;
	}
	else
	{
		hsv.h = 4 + (r - g) / delta;
	}
	hsv.h *= 60;	// Convert to degrees
	// We don't want negative degrees so we must end up on the other side of the circle
	if(hsv.h < 0)
	{
		hsv.h += 360;
	}
	return hsv;
}

// Convert HSV color into RGB
RGB hsvToRgb(double h, double s, double v)
{
	RGB rgb;
	int i = (int)(h / 60);	// We converted our number into degrees so we need to convert back and floor it
	double p, t, q, f;
	f = h / 60 - i;
	p = v * (1 - s / 100);
	q = v * (1 - (s / 100) * f);
	t = v * (1 - (s / 100) * (1 - f));
	// The different combinations for RGB given whatever our floored h value is
	switch(i)
	{
		case 0: rgb.r = v; rgb.g = t; rgb.b = p; break;
		case 1: rgb.r = q; rgb.g = v; rgb.b = p; break;
		case 2: rgb.r = p; rgb.g = v; rgb.b = t; break;
		case 3: rgb.r = p; rgb.g = q; rgb.b = v; break;
		case 4: rgb.r = t; rgb.g = p; rgb.b = v; break;
		case 5: rgb.r = v; rgb.g = p; rgb.b = q; break;
	}
	return rgb;
}

int main()
{
	HSV hsv = rgbToHsv(5, 10, 15);
	RGB rgb = hsvToRgb(hsv.h, hsv.s, hsv.v);
	cout << "HSV: " << hsv.h << ", " << hsv.s << ", " << hsv.v << endl;
	cout << "RGB: " << rgb.r << ", " << rgb.g << ", " << rgb.b << endl;
	return 0;
}