Eclipse SUMO - Simulation of Urban MObility
RGBColor.cpp
Go to the documentation of this file.
1 /****************************************************************************/
2 // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
3 // Copyright (C) 2001-2020 German Aerospace Center (DLR) and others.
4 // This program and the accompanying materials are made available under the
5 // terms of the Eclipse Public License 2.0 which is available at
6 // https://www.eclipse.org/legal/epl-2.0/
7 // This Source Code may also be made available under the following Secondary
8 // Licenses when the conditions for such availability set forth in the Eclipse
9 // Public License 2.0 are satisfied: GNU General Public License, version 2
10 // or later which is available at
11 // https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
12 // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
13 /****************************************************************************/
21 // A RGB-color definition
22 /****************************************************************************/
23 #include <config.h>
24 
25 #include <cmath>
26 #include <cassert>
27 #include <string>
28 #include <sstream>
31 #include <utils/common/ToString.h>
34 #include <utils/common/StdDefs.h>
35 #include "RGBColor.h"
36 
37 
38 // ===========================================================================
39 // static member definitions
40 // ===========================================================================
41 const RGBColor RGBColor::RED = RGBColor(255, 0, 0, 255);
42 const RGBColor RGBColor::GREEN = RGBColor(0, 255, 0, 255);
43 const RGBColor RGBColor::BLUE = RGBColor(0, 0, 255, 255);
44 const RGBColor RGBColor::YELLOW = RGBColor(255, 255, 0, 255);
45 const RGBColor RGBColor::CYAN = RGBColor(0, 255, 255, 255);
46 const RGBColor RGBColor::MAGENTA = RGBColor(255, 0, 255, 255);
47 const RGBColor RGBColor::ORANGE = RGBColor(255, 128, 0, 255);
48 const RGBColor RGBColor::WHITE = RGBColor(255, 255, 255, 255);
49 const RGBColor RGBColor::BLACK = RGBColor(0, 0, 0, 255);
50 const RGBColor RGBColor::GREY = RGBColor(128, 128, 128, 255);
51 const RGBColor RGBColor::INVISIBLE = RGBColor(0, 0, 0, 0);
52 
55 
56 // random colors do not affect the simulation. No initialization is necessary
57 std::mt19937 RGBColor::myRNG;
58 
59 // ===========================================================================
60 // method definitions
61 // ===========================================================================
63  : myRed(0), myGreen(0), myBlue(0), myAlpha(0) {}
64 
65 
66 RGBColor::RGBColor(unsigned char red, unsigned char green, unsigned char blue, unsigned char alpha)
67  : myRed(red), myGreen(green), myBlue(blue), myAlpha(alpha) {}
68 
69 
70 void
71 RGBColor::set(unsigned char r, unsigned char g, unsigned char b, unsigned char a) {
72  myRed = r;
73  myGreen = g;
74  myBlue = b;
75  myAlpha = a;
76 }
77 
78 
79 std::ostream&
80 operator<<(std::ostream& os, const RGBColor& col) {
81  if (col == RGBColor::RED) {
82  return os << "red";
83  }
84  if (col == RGBColor::GREEN) {
85  return os << "green";
86  }
87  if (col == RGBColor::BLUE) {
88  return os << "blue";
89  }
90  if (col == RGBColor::YELLOW) {
91  return os << "yellow";
92  }
93  if (col == RGBColor::CYAN) {
94  return os << "cyan";
95  }
96  if (col == RGBColor::MAGENTA) {
97  return os << "magenta";
98  }
99  if (col == RGBColor::ORANGE) {
100  return os << "orange";
101  }
102  if (col == RGBColor::WHITE) {
103  return os << "white";
104  }
105  if (col == RGBColor::BLACK) {
106  return os << "black";
107  }
108  if (col == RGBColor::GREY) {
109  return os << "grey";
110  }
111  os << static_cast<int>(col.myRed) << ","
112  << static_cast<int>(col.myGreen) << ","
113  << static_cast<int>(col.myBlue);
114  if (col.myAlpha < 255) {
115  os << "," << static_cast<int>(col.myAlpha);
116  }
117  return os;
118 }
119 
120 
121 bool
123  return myRed == c.myRed && myGreen == c.myGreen && myBlue == c.myBlue && myAlpha == c.myAlpha;
124 }
125 
126 
127 bool
129  return myRed != c.myRed || myGreen != c.myGreen || myBlue != c.myBlue || myAlpha != c.myAlpha;
130 }
131 
132 
133 RGBColor
135  // obtain inverse colors
136  const unsigned char r = (unsigned char)(255 - (int)myRed);
137  const unsigned char g = (unsigned char)(255 - (int)myGreen);
138  const unsigned char b = (unsigned char)(255 - (int)myBlue);
139  // return inverted RBColor
140  return RGBColor(r, g, b, myAlpha);
141 }
142 
143 
144 RGBColor
145 RGBColor::changedBrightness(int change, int toChange) const {
146  const unsigned char red = (unsigned char)(MIN2(MAX2(myRed + change, 0), 255));
147  const unsigned char blue = (unsigned char)(MIN2(MAX2(myBlue + change, 0), 255));
148  const unsigned char green = (unsigned char)(MIN2(MAX2(myGreen + change, 0), 255));
149  int changed = ((int)red - (int)myRed) + ((int)blue - (int)myBlue) + ((int)green - (int)myGreen);
150  const RGBColor result(red, green, blue, myAlpha);
151  if (changed == toChange * change) {
152  return result;
153  } else if (changed == 0) {
154  return result;
155  } else {
156  const int maxedColors = (red != myRed + change ? 1 : 0) + (blue != myBlue + change ? 1 : 0) + (green != myGreen + change ? 1 : 0);
157  if (maxedColors == 3) {
158  return result;
159  } else {
160  const int toChangeNext = 3 - maxedColors;
161  return result.changedBrightness((int)((toChange * change - changed) / toChangeNext), toChangeNext);
162  }
163  }
164 }
165 
166 
167 RGBColor
168 RGBColor::parseColor(std::string coldef) {
169  std::transform(coldef.begin(), coldef.end(), coldef.begin(), tolower);
170  if (coldef == "red") {
171  return RED;
172  }
173  if (coldef == "green") {
174  return GREEN;
175  }
176  if (coldef == "blue") {
177  return BLUE;
178  }
179  if (coldef == "yellow") {
180  return YELLOW;
181  }
182  if (coldef == "cyan") {
183  return CYAN;
184  }
185  if (coldef == "magenta") {
186  return MAGENTA;
187  }
188  if (coldef == "orange") {
189  return ORANGE;
190  }
191  if (coldef == "white") {
192  return WHITE;
193  }
194  if (coldef == "black") {
195  return BLACK;
196  }
197  if (coldef == "grey" || coldef == "gray") {
198  return GREY;
199  }
200  if (coldef == "invisible") {
201  return INVISIBLE;
202  }
203  if (coldef == "random") {
204  return fromHSV(RandHelper::rand(360, &myRNG),
205  // prefer more saturated colors
206  pow(RandHelper::rand(&myRNG), 0.3),
207  // prefer brighter colors
208  pow(RandHelper::rand(&myRNG), 0.3));
209  }
210  unsigned char r = 0;
211  unsigned char g = 0;
212  unsigned char b = 0;
213  unsigned char a = 255;
214  if (coldef[0] == '#') {
215  const int coldesc = StringUtils::hexToInt(coldef);
216  if (coldef.length() == 7) {
217  r = static_cast<unsigned char>((coldesc & 0xFF0000) >> 16);
218  g = static_cast<unsigned char>((coldesc & 0x00FF00) >> 8);
219  b = coldesc & 0xFF;
220  } else if (coldef.length() == 9) {
221  r = static_cast<unsigned char>((coldesc & 0xFF000000) >> 24);
222  g = static_cast<unsigned char>((coldesc & 0x00FF0000) >> 16);
223  b = static_cast<unsigned char>((coldesc & 0x0000FF00) >> 8);
224  a = coldesc & 0xFF;
225  } else {
226  throw EmptyData();
227  }
228  } else {
229  std::vector<std::string> st = StringTokenizer(coldef, ",").getVector();
230  if (st.size() == 3 || st.size() == 4) {
231  try {
232  r = static_cast<unsigned char>(StringUtils::toInt(st[0]));
233  g = static_cast<unsigned char>(StringUtils::toInt(st[1]));
234  b = static_cast<unsigned char>(StringUtils::toInt(st[2]));
235  if (st.size() == 4) {
236  a = static_cast<unsigned char>(StringUtils::toInt(st[3]));
237  }
238  if (r <= 1 && g <= 1 && b <= 1 && (st.size() == 3 || a <= 1)) {
239  throw NumberFormatException("(color component) " + coldef);
240  }
241  } catch (NumberFormatException&) {
242  r = static_cast<unsigned char>(StringUtils::toDouble(st[0]) * 255. + 0.5);
243  g = static_cast<unsigned char>(StringUtils::toDouble(st[1]) * 255. + 0.5);
244  b = static_cast<unsigned char>(StringUtils::toDouble(st[2]) * 255. + 0.5);
245  if (st.size() == 4) {
246  a = static_cast<unsigned char>(StringUtils::toDouble(st[3]) * 255. + 0.5);
247  }
248  }
249  } else {
250  throw EmptyData();
251  }
252  }
253  return RGBColor(r, g, b, a);
254 }
255 
256 
257 RGBColor
259  const std::string& coldef, const std::string& objecttype,
260  const char* objectid, bool report, bool& ok) {
261  UNUSED_PARAMETER(report);
262  try {
263  return parseColor(coldef);
264  } catch (NumberFormatException&) {
265  } catch (EmptyData&) {
266  }
267  ok = false;
268  std::ostringstream oss;
269  oss << "Attribute 'color' in definition of ";
270  if (objectid == nullptr) {
271  oss << "a ";
272  }
273  oss << objecttype;
274  if (objectid != nullptr) {
275  oss << " '" << objectid << "'";
276  }
277  oss << " is not a valid color.";
278  WRITE_ERROR(oss.str());
279  return RGBColor();
280 }
281 
282 
283 RGBColor
284 RGBColor::interpolate(const RGBColor& minColor, const RGBColor& maxColor, double weight) {
285  if (weight < 0) {
286  weight = 0;
287  }
288  if (weight > 1) {
289  weight = 1;
290  }
291  const unsigned char r = (unsigned char)((int)minColor.myRed + (((int)maxColor.myRed - (int)minColor.myRed) * weight));
292  const unsigned char g = (unsigned char)((int)minColor.myGreen + (((int)maxColor.myGreen - (int)minColor.myGreen) * weight));
293  const unsigned char b = (unsigned char)((int)minColor.myBlue + (((int)maxColor.myBlue - (int)minColor.myBlue) * weight));
294  const unsigned char a = (unsigned char)((int)minColor.myAlpha + (((int)maxColor.myAlpha - (int)minColor.myAlpha) * weight));
295  return RGBColor(r, g, b, a);
296 }
297 
298 
299 RGBColor
300 RGBColor::fromHSV(double h, double s, double v) {
301  h /= 60.;
302  const int i = int(floor(h));
303  double f = h - i;
304  if (i % 2 == 0) {
305  f = 1. - f;
306  }
307  const unsigned char m = static_cast<unsigned char>(v * (1 - s) * 255. + 0.5);
308  const unsigned char n = static_cast<unsigned char>(v * (1 - s * f) * 255. + 0.5);
309  const unsigned char vv = static_cast<unsigned char>(v * 255. + 0.5);
310  switch (i) {
311  case 6:
312  case 0:
313  return RGBColor(vv, n, m, 255);
314  case 1:
315  return RGBColor(n, vv, m, 255);
316  case 2:
317  return RGBColor(m, vv, n, 255);
318  case 3:
319  return RGBColor(m, n, vv, 255);
320  case 4:
321  return RGBColor(n, m, vv, 255);
322  case 5:
323  return RGBColor(vv, m, n, 255);
324  }
325  return RGBColor(255, 255, 255, 255);
326 }
327 
328 RGBColor
329 RGBColor::randomHue(double s, double v) {
330  return fromHSV(RandHelper::rand(360, &myRNG), s, v);
331 }
332 
333 
334 /****************************************************************************/
#define WRITE_ERROR(msg)
Definition: MsgHandler.h:284
std::ostream & operator<<(std::ostream &os, const RGBColor &col)
Definition: RGBColor.cpp:80
#define UNUSED_PARAMETER(x)
Definition: StdDefs.h:29
T MIN2(T a, T b)
Definition: StdDefs.h:73
T MAX2(T a, T b)
Definition: StdDefs.h:79
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition: ToString.h:44
static RGBColor interpolate(const RGBColor &minColor, const RGBColor &maxColor, double weight)
Interpolates between two colors.
Definition: RGBColor.cpp:284
unsigned char myRed
The color amounts.
Definition: RGBColor.h:201
static const RGBColor WHITE
Definition: RGBColor.h:187
unsigned char red() const
Returns the red-amount of the color.
Definition: RGBColor.h:52
static const std::string DEFAULT_COLOR_STRING
The string description of the default color.
Definition: RGBColor.h:197
static const RGBColor BLUE
Definition: RGBColor.h:182
static const RGBColor GREY
Definition: RGBColor.h:189
static const RGBColor YELLOW
Definition: RGBColor.h:183
static const RGBColor INVISIBLE
Definition: RGBColor.h:190
static RGBColor parseColor(std::string coldef)
Parses a color information.
Definition: RGBColor.cpp:168
static RGBColor parseColorReporting(const std::string &coldef, const std::string &objecttype, const char *objectid, bool report, bool &ok)
Parses a color information.
Definition: RGBColor.cpp:258
RGBColor()
Constructor.
Definition: RGBColor.cpp:62
unsigned char green() const
Returns the green-amount of the color.
Definition: RGBColor.h:59
static const RGBColor ORANGE
Definition: RGBColor.h:186
static const RGBColor CYAN
Definition: RGBColor.h:184
RGBColor invertedColor() const
obtain inverted of current RGBColor
Definition: RGBColor.cpp:134
static const RGBColor GREEN
Definition: RGBColor.h:181
static RGBColor fromHSV(double h, double s, double v)
Converts the given hsv-triplet to rgb, inspired by http://alvyray.com/Papers/CG/hsv2rgb....
Definition: RGBColor.cpp:300
unsigned char myBlue
Definition: RGBColor.h:201
unsigned char blue() const
Returns the blue-amount of the color.
Definition: RGBColor.h:66
static const RGBColor BLACK
Definition: RGBColor.h:188
RGBColor changedBrightness(int change, int toChange=3) const
Returns a new color with altered brightness.
Definition: RGBColor.cpp:145
bool operator!=(const RGBColor &c) const
Definition: RGBColor.cpp:128
void set(unsigned char r, unsigned char g, unsigned char b, unsigned char a)
assigns new values
Definition: RGBColor.cpp:71
unsigned char myGreen
Definition: RGBColor.h:201
static const RGBColor MAGENTA
Definition: RGBColor.h:185
bool operator==(const RGBColor &c) const
Definition: RGBColor.cpp:122
unsigned char myAlpha
Definition: RGBColor.h:201
static std::mt19937 myRNG
A random number generator to generate random colors independent of other randomness.
Definition: RGBColor.h:204
static const RGBColor DEFAULT_COLOR
The default color (for vehicle types and vehicles)
Definition: RGBColor.h:194
static const RGBColor RED
named colors
Definition: RGBColor.h:180
static RGBColor randomHue(double s=1, double v=1)
Return color with random hue.
Definition: RGBColor.cpp:329
static double rand(std::mt19937 *rng=nullptr)
Returns a random real number in [0, 1)
Definition: RandHelper.h:51
std::vector< std::string > getVector()
return vector of strings
static int hexToInt(const std::string &sData)
converts a string with a hex value into the integer value described by it by calling the char-type co...
static double toDouble(const std::string &sData)
converts a string into the double value described by it by calling the char-type converter
static int toInt(const std::string &sData)
converts a string into the integer value described by it by calling the char-type converter,...