Color.cpp
Go to the documentation of this file.
1 // (C) Copyright Renaud Detry 2007-2015.
2 // Distributed under the GNU General Public License and under the
3 // BSD 3-Clause License (See accompanying file LICENSE.txt).
4 
5 /** @file */
6 
7 #include <nuklei/Descriptor.h>
8 
9 namespace nuklei
10 {
11 
12  const std::string Color::TypeNames[] = { "rgb", "hsv", "hsvcone", "unknown" };
13 
14  //const appear_t RGBColor::MAX_DIST = 1.73205080756888 + 1e-6; //sqrt(3)
15  const appear_t RGBColor::MAX_DIST = 1.73205180756888; // GCC 4.2 -frounding-math bug
16 
17  RGBColor::RGBColor(const Color&c)
18  {
19  const RGBColor* rgbc;
20  const HSVColor* hsvc;
21  const HSVConeColor* hsvcc;
22  if ( (rgbc = dynamic_cast<const RGBColor*>(&c)) != NULL) c_ = rgbc->c_;
23  else if ( (hsvc = dynamic_cast<const HSVColor*>(&c)) != NULL)
24  {
25  appear_t h = hsvc->H() * 180 / M_PI, s = hsvc->S(), v = hsvc->V();
26  NUKLEI_RANGE_CHECK(h, 0, 360);
27 
28  int i;
29  appear_t f, p, q, t, hTemp;
30 
31  if(s == 0.0)
32  {
33  R() = G() = B() = v;
34  return;
35  }
36 
37  hTemp = h/60.0f;
38  i = (int)std::floor( hTemp );
39  f = hTemp - i;
40  p = v * ( 1 - s );
41  q = v * ( 1 - s * f );
42  t = v * ( 1 - s * ( 1 - f ) );
43 
44  switch( i )
45  {
46  case 0:{R() = v;G() = t;B() = p;break;}
47  case 1:{R() = q;G() = v;B() = p;break;}
48  case 2:{R() = p;G() = v;B() = t;break;}
49  case 3:{R() = p;G() = q;B() = v;break;}
50  case 4:{R() = t;G() = p;B() = v;break;}
51  default:{R() = v;G() = p;B() = q;break;}
52  }
53  }
54  else if ( (hsvcc = dynamic_cast<const HSVConeColor*>(&c)) != NULL)
55  {
56  HSVColor tmp(*hsvcc);
57  RGBColor tmp2(tmp);
58  c_ = tmp2.getRGB();
59  }
60  else NUKLEI_THROW("Unknown color type");
61  assertConsistency();
62  }
63 
64  void RGBColor::makeRandom()
65  {
66  for (int i = 0; i < 3; ++i)
67  c_[i] = Random::uniform();
68  }
69 
70  // This is wrong:
71  //const appear_t HSVColor::MAX_DIST = 2 + 1e-6;
72  const appear_t HSVColor::MAX_DIST = 2.000001; // GCC 4.2 -frounding-math bug
73 
74  HSVColor::HSVColor(const Color& c)
75  {
76  const RGBColor* rgbc = NULL;
77  const HSVColor* hsvc = NULL;
78  const HSVConeColor* hsvcc = NULL;
79  if ( (rgbc = dynamic_cast<const RGBColor*>(&c)) != NULL)
80  {
81  appear_t rgbMin, rgbMax, delta;
82  appear_t r = rgbc->R(), g = rgbc->G(), b = rgbc->B();
83 
84  rgbMin = std::min(r,std::min(g,b));
85  rgbMax = std::max(r,std::max(g,b));
86  delta = rgbMax - rgbMin;
87  V() = rgbMax;
88 
89  S() = 0;
90  if (rgbMax > 0)
91  S() = delta / rgbMax;
92  // fixme: handle floating point check here.
93  NUKLEI_ASSERT( 0 <= S() && S() <= 1 );
94 
95  H() = 0;
96 
97  if (delta > 0)
98  {
99  if (rgbMax == r && rgbMax != g)
100  H() += (g - b) / delta;
101  if (rgbMax == g && rgbMax != b)
102  H() += (2 + (b - r) / delta);
103  if (rgbMax == b && rgbMax != r)
104  H() += (4 + (r - g) / delta);
105  H() *= 60;
106  if (H() < 0)
107  H() += 360;
108  }
109 
110  H() *= M_PI / 180;
111  }
112  else if ( (hsvc = dynamic_cast<const HSVColor*>(&c)) != NULL) c_ = hsvc->c_;
113  else if ( (hsvcc = dynamic_cast<const HSVConeColor*>(&c)) != NULL)
114  {
115  NUKLEI_ASSERT(hsvcc->W() > 0);
116  V() = hsvcc->WV() / hsvcc->W();
117  if (V() > 0)
118  {
119  S() = std::sqrt( std::pow(hsvcc->SCosH(), 2) + std::pow(hsvcc->SSinH(), 2) ) / V();
120  if (hsvcc->SSinH() >= 0) H() = ACos(hsvcc->SCosH() / (V()*S()));
121  else H() = 2*M_PI-ACos(hsvcc->SCosH() / (V()*S()));
122  }
123  else if (V() == 0)
124  {
125  S() = 1;
126  H() = 0;
127  }
128  else NUKLEI_ASSERT(false);
129  }
130  else NUKLEI_THROW("Unknown color type");
131  assertConsistency();
132  }
133 
134 
135  void HSVColor::makeRandom()
136  {
137  while (true)
138  {
139  Vector3 v(Random::uniform()*2-1, Random::uniform()*2-1, 0);
140  if (dist<groupS::r3>::d(v, Vector3::ZERO) > 1.0 || dist<groupS::r3>::d(v, Vector3::ZERO) < .1)
141  continue;
142 
143  HSVColor hsv;
144  if (v.Y() >= 0) c_ = Vector3(ACos(la::normalized(v).Dot(Vector3::UNIT_X)),
145  v.Length(),
146  1);
147  else c_ = Vector3(2*M_PI-ACos(la::normalized(v).Dot(Vector3::UNIT_X)),
148  v.Length(),
149  1);
150  break;
151  }
152  }
153 
154  appear_t HSVColor::distanceTo(const Color& c) const
155  {
156  NUKLEI_ASSERT("Recently changed. Please don't use.");
157  return distanceTo(dynamic_cast<const HSVColor&>(c));
158  }
159 
160  appear_t HSVColor::distanceTo(const HSVColor& hsv) const
161  {
162  NUKLEI_ASSERT("Recently changed. Please don't use.");
163  return (c_-hsv.c_).Length();
164  }
165 
166 
167  //const appear_t HSVConeColor::MAX_DIST = 2 + 1e-6;
168  const appear_t HSVConeColor::MAX_DIST = 2.000001; // GCC 4.2 -frounding-math bug
169 
170  HSVConeColor::HSVConeColor(const Color& c)
171  {
172  const RGBColor* rgbc = NULL;
173  const HSVColor* hsvc = NULL;
174  const HSVConeColor* hsvcc = NULL;
175  if ( (rgbc = dynamic_cast<const RGBColor*>(&c)) != NULL)
176  {
177  HSVColor hsv(c);
178  HSVConeColor hsvCone(hsv);
179  c_ = hsvCone.c_;
180  valueWeight_ = hsvCone.valueWeight_;
181  }
182  else if ( (hsvc = dynamic_cast<const HSVColor*>(&c)) != NULL)
183  {
184  Vector3 ec;
185  ec.X() = std::cos(hsvc->H()) * hsvc->S() * hsvc->V();
186  ec.Y() = std::sin(hsvc->H()) * hsvc->S() * hsvc->V();
187  NUKLEI_RANGE_CHECK(HSV_METRIC_VALUE_WEIGHT, 0, 1);
188  ec.Z() = hsvc->V()*HSV_METRIC_VALUE_WEIGHT;
189  c_ = ec;
190  valueWeight_ = HSV_METRIC_VALUE_WEIGHT;
191  }
192  else if ( (hsvcc = dynamic_cast<const HSVConeColor*>(&c)) != NULL)
193  {
194  c_ = hsvcc->c_;
195  valueWeight_ = hsvcc->valueWeight_;
196  }
197  else NUKLEI_THROW("Unknown color type");
198  assertConsistency();
199  }
200 
201 
202  void HSVConeColor::makeRandom()
203  {
204  while (true)
205  {
206  Vector3 v(Random::uniform()*2-1, Random::uniform()*2-1, 0);
207  appear_t value = Random::uniform()*HSV_METRIC_VALUE_WEIGHT;
208 
209  if (dist<groupS::r3>::d(v, Vector3::ZERO) > value/HSV_METRIC_VALUE_WEIGHT)
210  continue;
211 
212  v.Z() = value;
213  c_ = v;
214  valueWeight_ = HSV_METRIC_VALUE_WEIGHT;
215  break;
216  }
217  }
218 
219  appear_t HSVConeColor::distanceTo(const Color& c) const
220  {
221  return distanceTo(dynamic_cast<const HSVConeColor&>(c));
222  }
223 
224  appear_t HSVConeColor::distanceTo(const HSVConeColor& hsvc) const
225  {
226  return (c_-hsvc.c_).Length();
227  }
228 
229 }
Definition: Color.h:56
Public namespace.
Definition: Color.cpp:9
Definition: Color.h:127
#define NUKLEI_ASSERT(expression)
Throws an Error if expression is not true.
Definition: Common.h:113
double appear_t
Type for appearance-related values (e.g., color)
Definition: Definitions.h:29
Definition: GenericKernel.h:73
static double uniform()
This function returns a double precision floating point number uniformly distributed in the range .
Definition: Random.cpp:159
Definition: Color.h:190
Definition: Color.h:18
#define NUKLEI_THROW(x)
Throws an Error.
Definition: Common.h:94
© Copyright 2007-2013 Renaud Detry.
Distributed under the terms of the GNU General Public License (GPL).
(See accompanying file LICENSE.txt or copy at http://www.gnu.org/copyleft/gpl.html.)
Revised Sun Sep 13 2020 19:10:06.