Code_TYMPAN  4.4.0
Industrial site acoustic simulation
color.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (C) <2012-2014> <EDF-R&D> <FRANCE>
3  * This program is free software; you can redistribute it and/or modify
4  * it under the terms of the GNU General Public License as published by
5  * the Free Software Foundation; either version 2 of the License, or
6  * (at your option) any later version.
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
10  * See the GNU General Public License for more details.
11  * You should have received a copy of the GNU General Public License along
12  * with this program; if not, write to the Free Software Foundation, Inc.,
13  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
14  */
15 
16 #include <limits>
17 #include <cmath>
18 
19 #include "color.h"
20 
21 #include <math.h>
22 
23 #ifndef M_PI
25  #define M_PI 3.1415926535897932384626433832795
26 #endif
27 
28 const OColor OColor::BLACK = OColor(0.0f, 0.0f, 0.0f);
29 const OColor OColor::BLUE = OColor(0.0f, 0.0f, 1.0f);
30 const OColor OColor::GREEN = OColor(0.0f, 1.0f, 0.0f);
31 const OColor OColor::CYAN = OColor(0.0f, 1.0f, 1.0f);
32 const OColor OColor::RED = OColor(1.0f, 0.0f, 0.0f);
33 const OColor OColor::MAGENTA = OColor(1.0f, 0.0f, 1.0f);
34 const OColor OColor::YELLOW = OColor(1.0f, 1.0f, 0.0f);
35 const OColor OColor::WHITE = OColor(1.0f, 1.0f, 1.0f);
36 
37 const float OColor::equality_threshold = 1e3f * std::numeric_limits<float>::epsilon();
38 
39 bool OColor::operator==(const OColor& c) const
40 {
41  return (float_eq(r, c.r) && float_eq(g, c.g) && float_eq(b, c.b) && float_eq(a, c.a));
42 }
43 
44 unsigned int OColor::getAsRGBA() const
45 {
46  // Conversion au format 32 bits
47  // (RGBA = 8888)
48 
49  unsigned char val8 = 0;
50  unsigned int val32 = 0;
51 
52  // Red
53  val8 = static_cast<unsigned char>(r * 255);
54  val32 = val8 << 24;
55 
56  // Green
57  val8 = static_cast<unsigned char>(g * 255);
58  val32 += val8 << 16;
59 
60  // Blue
61  val8 = static_cast<unsigned char>(b * 255);
62  val32 += val8 << 8;
63 
64  // Alpha
65  val8 = static_cast<unsigned char>(a * 255);
66  val32 += val8;
67 
68  return val32;
69 }
70 
71 void OColor::setAsRGBA(const unsigned int val)
72 {
73  // Conversion au format 32 bits
74  // (RGBA = 8888)
75 
76  unsigned int val32 = val;
77 
78  // Red
79  r = ((val32 >> 24) & 0xFF) / 255.0f;
80 
81  // Green
82  g = ((val32 >> 16) & 0xFF) / 255.0f;
83 
84  // Blue
85  b = ((val32 >> 8) & 0xFF) / 255.0f;
86 
87  // Alpha
88  a = (val32 & 0xFF) / 255.0f;
89 }
90 
91 void OColor::getAsHSB(float& hue, float& saturation, float& brightness) const
92 {
93  // Clamp RGB color
94  OColor c = clampCopy();
95 
96  // Get min and max rgb value
97  float min = std::min<float>(std::min<float>(c.r, c.g), c.b);
98  float max = std::max<float>(std::max<float>(c.r, c.g), c.b);
99 
100  // Get delta between min and max value
101  float delta = max - min;
102 
103  // Brightness is the max value
104  brightness = max;
105 
106  if (delta == 0.0f)
107  {
108  // This is a gray, no chroma
109  hue = 0.0f;
110  saturation = 0.0f;
111  return;
112  }
113 
114  // Chromatic
115  saturation = delta / max;
116 
117  if (c.r == max)
118  {
119  hue = ((c.g - c.b) / delta) / 6.0f;
120  }
121  else if (c.g == max)
122  {
123  hue = (2.0f + (c.b - c.r) / delta) / 6.0f;
124  }
125  else if (c.b == max)
126  {
127  hue = (4.0f + (c.r - c.g) / delta) / 6.0f;
128  }
129 
130  // Wrap hue
131  if (hue > 1.0f)
132  {
133  hue -= (int)hue;
134  }
135  else if (hue < 0.0f)
136  {
137  hue += (int)hue + 1;
138  }
139 }
140 
141 void OColor::setAsHSB(const float hue, const float saturation, const float brightness)
142 {
143  float h = hue;
144  float s = saturation;
145  float br = brightness;
146 
147  // Wrap hue
148  if (h > 1.0f)
149  {
150  h -= (int)h;
151  }
152  else if (h < 0.0f)
153  {
154  h += (int)h + 1;
155  }
156 
157  // Set alpha = 100%;
158  a = 1.0;
159 
160  // Clamp saturation / brightness
161  s = std::min<float>(s, 1.0f);
162  s = std::max<float>(s, 0.0f);
163  br = std::min<float>(br, 1.0f);
164  br = std::max<float>(br, 0.0f);
165 
166  if (br == 0.0f)
167  {
168  // Early exit, this has to be black
169  r = g = b = 0.0f;
170  return;
171  }
172 
173  if (s == 0.0f)
174  {
175  // Early exit, this has to be grey
176 
177  r = g = b = br;
178  return;
179  }
180 
181  float hueDomain = h * 6.0f;
182  if (hueDomain >= 6.0f)
183  {
184  // Wrap around, and allow mathematical errors
185  hueDomain = 0.0f;
186  }
187  unsigned short domain = (unsigned short)hueDomain;
188  float f1 = br * (1 - s);
189  float f2 = br * (1 - s * (hueDomain - domain));
190  float f3 = br * (1 - s * (1 - (hueDomain - domain)));
191 
192  switch (domain)
193  {
194  case 0:
195  // Red domain; green ascends
196  r = br;
197  g = f3;
198  b = f1;
199  break;
200  case 1:
201  // Yellow domain; red descends
202  r = f2;
203  g = br;
204  b = f1;
205  break;
206  case 2:
207  // Green domain; blue ascends
208  r = f1;
209  g = br;
210  b = f3;
211  break;
212  case 3:
213  // Cyan domain; green descends
214  r = f1;
215  g = f2;
216  b = br;
217  break;
218  case 4:
219  // Blue domain; red ascends
220  r = f3;
221  g = f1;
222  b = br;
223  break;
224  case 5:
225  // Magenta domain; blue descends
226  r = br;
227  g = f1;
228  b = f2;
229  break;
230  }
231 }
232 
234 {
235  // Red
236  if (r < 0.0f)
237  {
238  r = 0.0f;
239  }
240  else if (r > 1.0f)
241  {
242  r = 1.0f;
243  }
244 
245  // Green
246  if (g < 0.0f)
247  {
248  g = 0.0f;
249  }
250  else if (g > 1.0f)
251  {
252  g = 1.0f;
253  }
254 
255  // Blue
256  if (b < 0.0f)
257  {
258  b = 0.0f;
259  }
260  else if (b > 1.0f)
261  {
262  b = 1.0f;
263  }
264 
265  // Alpha
266  if (a < 0.0f)
267  {
268  a = 0.0f;
269  }
270  else if (a > 1.0f)
271  {
272  a = 1.0f;
273  }
274 }
275 
277 {
278  OColor color = *this;
279  color.clamp();
280  return color;
281 }
282 
283 void TYColorManager::getSCurveColorTable(const unsigned int& nbColors, const float* hueRange,
284  const float* saturationRange, const float* valueRange,
285  OLookupTable& outColors)
286 {
287  outColors.resize(nbColors);
288 
289  float hueStep = (hueRange[1] - hueRange[0]) / (nbColors - 1);
290  float saturationStep = (saturationRange[1] - saturationRange[0]) / (nbColors - 1);
291  float valueStep = (valueRange[1] - valueRange[0]) / (nbColors - 1);
292 
293  float h = NAN, s = NAN, v = NAN;
294  OColor rgb;
295  for (unsigned int i = 0; i < nbColors; ++i)
296  {
297  h = hueRange[0] + i * hueStep;
298  s = saturationRange[0] + i * saturationStep;
299  v = valueRange[0] + i * valueStep;
300  rgb.setAsHSB(h, s, v);
301 
302  outColors[i].r = (1.0f - cos(rgb.r * static_cast<float>(M_PI))) * 0.5f;
303  outColors[i].g = (1.0f - cos(rgb.g * static_cast<float>(M_PI))) * 0.5f;
304  outColors[i].b = (1.0f - cos(rgb.b * static_cast<float>(M_PI))) * 0.5f;
305  }
306 }
307 
308 void TYColorManager::getLinearColorTable(const unsigned int& nbColors, const float* hueRange,
309  const float* saturationRange, const float* valueRange,
310  OLookupTable& outColors)
311 {
312  outColors.resize(nbColors);
313 
314  float hueStep = (hueRange[1] - hueRange[0]) / (nbColors - 1);
315  float saturationStep = (saturationRange[1] - saturationRange[0]) / (nbColors - 1);
316  float valueStep = (valueRange[1] - valueRange[0]) / (nbColors - 1);
317 
318  float h = NAN, s = NAN, v = NAN;
319  OColor rgb;
320  for (unsigned int i = 0; i < nbColors; ++i)
321  {
322  h = hueRange[0] + i * hueStep;
323  s = saturationRange[0] + i * saturationStep;
324  v = valueRange[0] + i * valueStep;
325  rgb.setAsHSB(h, s, v);
326 
327  // XXX What is the meaning of this offset?
328  outColors[i].r = rgb.r + 0.5f / 255.0f;
329  outColors[i].g = rgb.g + 0.5f / 255.0f;
330  outColors[i].b = rgb.b + 0.5f / 255.0f;
331  }
332 }
333 
334 void TYColorManager::getSqrtColorTable(const unsigned int& nbColors, const float* hueRange,
335  const float* saturationRange, const float* valueRange,
336  OLookupTable& outColors)
337 {
338  outColors.resize(nbColors);
339 
340  float hueStep = (hueRange[1] - hueRange[0]) / (nbColors - 1);
341  float saturationStep = (saturationRange[1] - saturationRange[0]) / (nbColors - 1);
342  float valueStep = (valueRange[1] - valueRange[0]) / (nbColors - 1);
343 
344  float h = NAN, s = NAN, v = NAN;
345  OColor rgb;
346  for (unsigned int i = 0; i < nbColors; ++i)
347  {
348  h = hueRange[0] + i * hueStep;
349  s = saturationRange[0] + i * saturationStep;
350  v = valueRange[0] + i * valueStep;
351  rgb.setAsHSB(h, s, v);
352 
353  outColors[i].r = std::sqrt(rgb.r) + 0.5f / 255.0f;
354  outColors[i].g = std::sqrt(rgb.g) + 0.5f / 255.0f;
355  outColors[i].b = std::sqrt(rgb.b) + 0.5f / 255.0f;
356  }
357 }
358 
359 void TYColorManager::getGaussColorTable(const unsigned int& nbColors, const float& alpha1,
360  const float& alpha2, OLookupTable& outColors)
361 {
362  outColors.resize(nbColors);
363 
364  float colors = static_cast<float>(nbColors);
365  for (unsigned int i = 0; i < nbColors; ++i)
366  {
367  OColor& color = outColors[i];
368  color.r = exp(-(colors - i) * (colors - i) * alpha2 * alpha2 / (colors * colors));
369  color.g = exp(-(i - colors / 2) * (i - colors / 2) * alpha1 * alpha1 / (colors * colors));
370  color.b = exp(-(i * i * alpha2 * alpha2 / (colors * colors)));
371  }
372 }
NxReal s
Definition: NxVec3.cpp:317
NxReal c
Definition: NxVec3.cpp:317
#define min(a, b)
Definition: color.h:31
static const OColor GREEN
Definition: color.h:88
unsigned int getAsRGBA() const
Definition: color.cpp:44
static const OColor BLUE
Definition: color.h:87
float b
Definition: color.h:33
OColor clampCopy() const
Definition: color.cpp:276
static const OColor RED
Definition: color.h:90
static const OColor BLACK
Definition: color.h:86
float a
Definition: color.h:33
static const OColor WHITE
Definition: color.h:93
void getAsHSB(float &hue, float &saturation, float &brightness) const
Definition: color.cpp:91
float r
Definition: color.h:33
void clamp()
Definition: color.cpp:233
static const float equality_threshold
Definition: color.h:96
static const OColor YELLOW
Definition: color.h:92
float g
Definition: color.h:33
void setAsHSB(const float hue, const float saturation, const float brightness)
Definition: color.cpp:141
static bool float_eq(float a, float b, float epsilon=equality_threshold)
Definition: color.h:98
void setAsRGBA(const unsigned int val)
Definition: color.cpp:71
static const OColor MAGENTA
Definition: color.h:91
bool operator==(const OColor &other) const
Definition: color.cpp:39
static const OColor CYAN
Definition: color.h:89
static void getLinearColorTable(const unsigned int &nbColors, const float *hueRange, const float *saturationRange, const float *valueRange, OLookupTable &outColors)
Generation de la table de couleurs basee sur une rampe lineaire ( y = x+0.5/255 )
Definition: color.cpp:308
static void getGaussColorTable(const unsigned int &nbColors, const float &alpha1, const float &alpha2, OLookupTable &outColors)
Generation de la table de couleurs a partir d'une repartition gaussienne en R, G, B.
Definition: color.cpp:359
static void getSqrtColorTable(const unsigned int &nbColors, const float *hueRange, const float *saturationRange, const float *valueRange, OLookupTable &outColors)
Generation de la table de couleurs basee sur une rampe sqrt ( y = sqrt(x)+0.5/255 )
Definition: color.cpp:334
static void getSCurveColorTable(const unsigned int &nbColors, const float *hueRange, const float *saturationRange, const float *valueRange, OLookupTable &outColors)
Generation de la table de couleurs basee sur une rampe S-Curve ( y = (1-cos(pi*x))/2 )
Definition: color.cpp:283
#define M_PI
Pi.
Definition: color.cpp:25
std::vector< OColor > OLookupTable
Collection de OColor.
Definition: color.h:105