SUMO - Simulation of Urban MObility
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
RGBColor.cpp
Go to the documentation of this file.
1 /****************************************************************************/
10 // A RGB-color definition
11 /****************************************************************************/
12 // SUMO, Simulation of Urban MObility; see http://sumo-sim.org/
13 // Copyright (C) 2001-2014 DLR (http://www.dlr.de/) and contributors
14 /****************************************************************************/
15 //
16 // This file is part of SUMO.
17 // SUMO is free software: you can redistribute it and/or modify
18 // it under the terms of the GNU General Public License as published by
19 // the Free Software Foundation, either version 3 of the License, or
20 // (at your option) any later version.
21 //
22 /****************************************************************************/
23 
24 
25 // ===========================================================================
26 // included modules
27 // ===========================================================================
28 #ifdef _MSC_VER
29 #include <windows_config.h>
30 #else
31 #include <config.h>
32 #endif
33 
34 #include <cmath>
35 #include <cassert>
36 #include <string>
37 #include <sstream>
39 #include <utils/common/ToString.h>
42 #include <utils/common/StdDefs.h>
43 #include "RGBColor.h"
44 
45 #ifdef CHECK_MEMORY_LEAKS
46 #include <foreign/nvwa/debug_new.h>
47 #endif // CHECK_MEMORY_LEAKS
48 
49 
50 // ===========================================================================
51 // static member definitions
52 // ===========================================================================
53 const RGBColor RGBColor::RED = RGBColor(255, 0, 0, 255);
54 const RGBColor RGBColor::GREEN = RGBColor(0, 255, 0, 255);
55 const RGBColor RGBColor::BLUE = RGBColor(0, 0, 255, 255);
56 const RGBColor RGBColor::YELLOW = RGBColor(255, 255, 0, 255);
57 const RGBColor RGBColor::CYAN = RGBColor(0, 255, 255, 255);
58 const RGBColor RGBColor::MAGENTA = RGBColor(255, 0, 255, 255);
59 const RGBColor RGBColor::WHITE = RGBColor(255, 255, 255, 255);
60 const RGBColor RGBColor::BLACK = RGBColor(0, 0, 0, 255);
61 const RGBColor RGBColor::GREY = RGBColor(128, 128, 128, 255);
62 
64 const std::string RGBColor::DEFAULT_COLOR_STRING = toString(RGBColor::DEFAULT_COLOR);
65 
66 
67 // ===========================================================================
68 // method definitions
69 // ===========================================================================
71  : myRed(0), myGreen(0), myBlue(0), myAlpha(0) {}
72 
73 
74 RGBColor::RGBColor(unsigned char red, unsigned char green, unsigned char blue, unsigned char alpha)
75  : myRed(red), myGreen(green), myBlue(blue), myAlpha(alpha) {}
76 
77 
79  : myRed(col.myRed), myGreen(col.myGreen), myBlue(col.myBlue), myAlpha(col.myAlpha) {}
80 
81 
83 
84 
85 void
86 RGBColor::set(unsigned char r, unsigned char g, unsigned char b, unsigned char a) {
87  myRed = r;
88  myGreen = g;
89  myBlue = b;
90  myAlpha = a;
91 }
92 
93 
94 std::ostream&
95 operator<<(std::ostream& os, const RGBColor& col) {
96  if (col == RGBColor::RED) {
97  return os << "red";
98  }
99  if (col == RGBColor::GREEN) {
100  return os << "green";
101  }
102  if (col == RGBColor::BLUE) {
103  return os << "blue";
104  }
105  if (col == RGBColor::YELLOW) {
106  return os << "yellow";
107  }
108  if (col == RGBColor::CYAN) {
109  return os << "cyan";
110  }
111  if (col == RGBColor::MAGENTA) {
112  return os << "magenta";
113  }
114  if (col == RGBColor::WHITE) {
115  return os << "white";
116  }
117  if (col == RGBColor::BLACK) {
118  return os << "black";
119  }
120  if (col == RGBColor::GREY) {
121  return os << "grey";
122  }
123  os << static_cast<int>(col.myRed) << ","
124  << static_cast<int>(col.myGreen) << ","
125  << static_cast<int>(col.myBlue);
126  if (col.myAlpha < 255) {
127  os << "," << static_cast<int>(col.myAlpha);
128  }
129  return os;
130 }
131 
132 
133 bool
135  return myRed == c.myRed && myGreen == c.myGreen && myBlue == c.myBlue && myAlpha == c.myAlpha;
136 }
137 
138 
139 bool
141  return myRed != c.myRed || myGreen != c.myGreen || myBlue != c.myBlue || myAlpha != c.myAlpha;
142 }
143 
144 
145 RGBColor
146 RGBColor::changedBrightness(int change, int toChange) const {
147  const unsigned char red = (unsigned char)(MIN2(MAX2(myRed + change, 0), 255));
148  const unsigned char blue = (unsigned char)(MIN2(MAX2(myBlue + change, 0), 255));
149  const unsigned char green = (unsigned char)(MIN2(MAX2(myGreen + change, 0), 255));
150  int changed = ((int)red - (int)myRed) + ((int)blue - (int)myBlue) + ((int)green - (int)myGreen);
151  const RGBColor result(red, green, blue, myAlpha);
152  if (changed == toChange * change) {
153  return result;
154  } else if (changed == 0) {
155  return result;
156  } else {
157  const int maxedColors = (red != myRed + change ? 1 : 0) + (blue != myBlue + change ? 1 : 0) + (green != myGreen + change ? 1 : 0);
158  if (maxedColors == 3) {
159  return result;
160  } else {
161  const int toChangeNext = 3 - maxedColors;
162  return result.changedBrightness((int)((toChange * change - changed) / toChangeNext), toChangeNext);
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 == "white") {
189  return WHITE;
190  }
191  if (coldef == "black") {
192  return BLACK;
193  }
194  if (coldef == "grey" || coldef == "gray") {
195  return GREY;
196  }
197  unsigned char r = 0;
198  unsigned char g = 0;
199  unsigned char b = 0;
200  unsigned char a = 255;
201  if (coldef[0] == '#') {
202  const int coldesc = TplConvert::_hex2int(coldef.c_str());
203  if (coldef.length() == 7) {
204  r = static_cast<unsigned char>((coldesc & 0xFF0000) >> 16);
205  g = static_cast<unsigned char>((coldesc & 0x00FF00) >> 8);
206  b = coldesc & 0xFF;
207  } else if (coldef.length() == 9) {
208  r = static_cast<unsigned char>((coldesc & 0xFF000000) >> 24);
209  g = static_cast<unsigned char>((coldesc & 0x00FF0000) >> 16);
210  b = static_cast<unsigned char>((coldesc & 0x0000FF00) >> 8);
211  a = coldesc & 0xFF;
212  } else {
213  throw EmptyData();
214  }
215  } else {
216  std::vector<std::string> st = StringTokenizer(coldef, ",").getVector();
217  if (st.size() == 3 || st.size() == 4) {
218  try {
219  r = static_cast<unsigned char>(TplConvert::_2int(st[0].c_str()));
220  g = static_cast<unsigned char>(TplConvert::_2int(st[1].c_str()));
221  b = static_cast<unsigned char>(TplConvert::_2int(st[2].c_str()));
222  if (st.size() == 4) {
223  a = static_cast<unsigned char>(TplConvert::_2int(st[3].c_str()));
224  }
225  if (r <= 1 && g <= 1 && b <= 1 && (st.size() == 3 || a <= 1)) {
226  throw NumberFormatException();
227  }
228  } catch (NumberFormatException&) {
229  r = static_cast<unsigned char>(TplConvert::_2SUMOReal(st[0].c_str()) * 255. + 0.5);
230  g = static_cast<unsigned char>(TplConvert::_2SUMOReal(st[1].c_str()) * 255. + 0.5);
231  b = static_cast<unsigned char>(TplConvert::_2SUMOReal(st[2].c_str()) * 255. + 0.5);
232  if (st.size() == 4) {
233  a = static_cast<unsigned char>(TplConvert::_2SUMOReal(st[3].c_str()) * 255. + 0.5);
234  }
235  }
236  } else {
237  throw EmptyData();
238  }
239  }
240  return RGBColor(r, g, b, a);
241 }
242 
243 
244 RGBColor
246  const std::string& coldef, const std::string& objecttype,
247  const char* objectid, bool report, bool& ok) {
248  UNUSED_PARAMETER(report);
249  try {
250  return parseColor(coldef);
251  } catch (NumberFormatException&) {
252  } catch (EmptyData&) {
253  }
254  ok = false;
255  std::ostringstream oss;
256  oss << "Attribute 'color' in definition of ";
257  if (objectid == 0) {
258  oss << "a ";
259  }
260  oss << objecttype;
261  if (objectid != 0) {
262  oss << " '" << objectid << "'";
263  }
264  oss << " is not a valid color.";
265  WRITE_ERROR(oss.str());
266  return RGBColor();
267 }
268 
269 
270 RGBColor
271 RGBColor::interpolate(const RGBColor& minColor, const RGBColor& maxColor, SUMOReal weight) {
272  if (weight < 0) {
273  weight = 0;
274  }
275  if (weight > 1) {
276  weight = 1;
277  }
278  const unsigned char r = minColor.myRed + static_cast<char>((maxColor.myRed - minColor.myRed) * weight);
279  const unsigned char g = minColor.myGreen + static_cast<char>((maxColor.myGreen - minColor.myGreen) * weight);
280  const unsigned char b = minColor.myBlue + static_cast<char>((maxColor.myBlue - minColor.myBlue) * weight);
281  const unsigned char a = minColor.myAlpha + static_cast<char>((maxColor.myAlpha - minColor.myAlpha) * weight);
282  return RGBColor(r, g, b, a);
283 }
284 
285 
286 RGBColor
288  // H is given on [0, 6] or UNDEFINED. S and V are given on [0, 1].
289  // RGB are each returned on [0, 255].
290  //float h = HSV.H, s = HSV.S, v = HSV.V,
291  SUMOReal f;
292  h /= 60.;
293  int i;
294  //if (h == UNDEFINED) RETURN_RGB(v, v, v);
295  i = int(floor(h));
296  f = float(h - i);
297  if (!(i & 1)) {
298  f = 1 - f; // if i is even
299  }
300  const unsigned char m = static_cast<unsigned char>(v * (1 - s) * 255. + 0.5);
301  const unsigned char n = static_cast<unsigned char>(v * (1 - s * f) * 255. + 0.5);
302  const unsigned char vv = static_cast<unsigned char>(v * 255. + 0.5);
303  switch (i) {
304  case 6:
305  case 0:
306  return RGBColor(vv, n, m, 255);
307  case 1:
308  return RGBColor(n, vv, m, 255);
309  case 2:
310  return RGBColor(m, vv, n, 255);
311  case 3:
312  return RGBColor(m, n, vv, 255);
313  case 4:
314  return RGBColor(n, m, vv, 255);
315  case 5:
316  return RGBColor(vv, m, n, 255);
317  }
318  return RGBColor(255, 255, 255, 255);
319 }
320 
321 
322 /****************************************************************************/
323