SUMO - Simulation of Urban MObility
GLHelper.cpp
Go to the documentation of this file.
1 /****************************************************************************/
9 // Some methods which help to draw certain geometrical objects in openGL
10 /****************************************************************************/
11 // SUMO, Simulation of Urban MObility; see http://sumo.dlr.de/
12 // Copyright (C) 2001-2016 DLR (http://www.dlr.de/) and contributors
13 /****************************************************************************/
14 //
15 // This file is part of SUMO.
16 // SUMO is free software: you can redistribute it and/or modify
17 // it under the terms of the GNU General Public License as published by
18 // the Free Software Foundation, either version 3 of the License, or
19 // (at your option) any later version.
20 //
21 /****************************************************************************/
22 
23 
24 // ===========================================================================
25 // included modules
26 // ===========================================================================
27 #ifdef _MSC_VER
28 #include <windows_config.h>
29 #else
30 #include <config.h>
31 #endif
32 
33 #include <cassert>
34 #include <utils/geom/GeomHelper.h>
35 #include <utils/common/StdDefs.h>
37 #include <utils/common/ToString.h>
40 #include "GLHelper.h"
41 
42 #ifdef CHECK_MEMORY_LEAKS
43 #include <foreign/nvwa/debug_new.h>
44 #endif // CHECK_MEMORY_LEAKS
45 
46 
47 #define CIRCLE_RESOLUTION (SUMOReal)10 // inverse in degrees
48 
49 // ===========================================================================
50 // static member definitions
51 // ===========================================================================
52 std::vector<std::pair<SUMOReal, SUMOReal> > GLHelper::myCircleCoords;
53 
54 
55 void APIENTRY combCallback(GLdouble coords[3],
56  GLdouble* vertex_data[4],
57  GLfloat weight[4], GLdouble** dataOut) {
58  UNUSED_PARAMETER(weight);
59  UNUSED_PARAMETER(*vertex_data);
60  GLdouble* vertex;
61 
62  vertex = (GLdouble*)malloc(7 * sizeof(GLdouble));
63 
64  vertex[0] = coords[0];
65  vertex[1] = coords[1];
66  vertex[2] = coords[2];
67  *dataOut = vertex;
68 }
69 
70 // ===========================================================================
71 // method definitions
72 // ===========================================================================
73 
74 
75 void
77  if (v.size() == 0) {
78  return;
79  }
80  glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
81  glBegin(GL_POLYGON);
82  for (PositionVector::const_iterator i = v.begin(); i != v.end(); i++) {
83  const Position& p = *i;
84  glVertex2d(p.x(), p.y());
85  }
86  if (close) {
87  const Position& p = *(v.begin());
88  glVertex2d(p.x(), p.y());
89  }
90  glEnd();
91 }
92 
93 
94 void
96  if (v.size() == 0) {
97  return;
98  }
99  GLUtesselator* tobj = gluNewTess();
100  gluTessCallback(tobj, GLU_TESS_VERTEX, (GLvoid(APIENTRY*)()) &glVertex3dv);
101  gluTessCallback(tobj, GLU_TESS_BEGIN, (GLvoid(APIENTRY*)()) &glBegin);
102  gluTessCallback(tobj, GLU_TESS_END, (GLvoid(APIENTRY*)()) &glEnd);
103  gluTessCallback(tobj, GLU_TESS_COMBINE, (GLvoid(APIENTRY*)()) &combCallback);
104  gluTessProperty(tobj, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_ODD);
105  gluTessBeginPolygon(tobj, NULL);
106  gluTessBeginContour(tobj);
107  double* points = new double[(v.size() + int(close)) * 3];
108 
109  for (int i = 0; i != (int)v.size(); ++i) {
110  points[3 * i] = v[i].x();
111  points[3 * i + 1] = v[i].y();
112  points[3 * i + 2] = 0;
113  gluTessVertex(tobj, points + 3 * i, points + 3 * i);
114  }
115  if (close) {
116  const int i = (int)v.size();
117  points[3 * i] = v[0].x();
118  points[3 * i + 1] = v[0].y();
119  points[3 * i + 2] = 0;
120  gluTessVertex(tobj, points + 3 * i, points + 3 * i);
121  }
122  gluTessEndContour(tobj);
123  gluTessEndPolygon(tobj);
124  gluDeleteTess(tobj);
125  delete[] points;
126 }
127 
128 
129 void
130 GLHelper::drawBoxLine(const Position& beg, SUMOReal rot, SUMOReal visLength,
131  SUMOReal width, SUMOReal offset) {
132  glPushMatrix();
133  glTranslated(beg.x(), beg.y(), 0);
134  glRotated(rot, 0, 0, 1);
135  glBegin(GL_QUADS);
136  glVertex2d(-width - offset, 0);
137  glVertex2d(-width - offset, -visLength);
138  glVertex2d(width - offset, -visLength);
139  glVertex2d(width - offset, 0);
140  glEnd();
141  glPopMatrix();
142 }
143 
144 
145 void
146 GLHelper::drawBoxLine(const Position& beg1, const Position& beg2,
147  SUMOReal rot, SUMOReal visLength,
148  SUMOReal width) {
149  glPushMatrix();
150  glTranslated((beg2.x() + beg1.x())*.5, (beg2.y() + beg1.y())*.5, 0);
151  glRotated(rot, 0, 0, 1);
152  glBegin(GL_QUADS);
153  glVertex2d(-width, 0);
154  glVertex2d(-width, -visLength);
155  glVertex2d(width, -visLength);
156  glVertex2d(width, 0);
157  glEnd();
158  glPopMatrix();
159 }
160 
161 
162 bool
164  SUMOReal delta = angle2 - angle1;
165  while (delta > 180) {
166  delta -= 360;
167  }
168  while (delta < -180) {
169  delta += 360;
170  }
171  return delta <= 0;
172 }
173 
174 
175 void
177  const std::vector<SUMOReal>& rots,
178  const std::vector<SUMOReal>& lengths,
179  SUMOReal width, int cornerDetail, SUMOReal offset) {
180  // draw the lane
181  int e = (int) geom.size() - 1;
182  for (int i = 0; i < e; i++) {
183  drawBoxLine(geom[i], rots[i], lengths[i], width, offset);
184  }
185  // draw the corner details
186  if (cornerDetail > 0) {
187  for (int i = 1; i < e; i++) {
188  glPushMatrix();
189  glTranslated(geom[i].x(), geom[i].y(), 0.1);
190  if (rightTurn(rots[i - 1], rots[i])) {
191  // inside corner
192  drawFilledCircle(MIN2(lengths[i], width - offset), cornerDetail);
193  } else {
194  // outside corner, make sure to only draw a segment of the circle
195  SUMOReal angleBeg = -rots[i - 1];
196  SUMOReal angleEnd = 180 - rots[i];
197  // avoid drawing more than 360 degrees
198  if (angleEnd - angleBeg > 360) {
199  angleBeg += 360;
200  }
201  if (angleEnd - angleBeg < -360) {
202  angleEnd += 360;
203  }
204  // for a left tur, draw the right way around
205  if (angleEnd > angleBeg) {
206  angleEnd -= 360;
207  }
208  drawFilledCircle(MIN2(lengths[i], width + offset), cornerDetail, angleBeg, angleEnd);
209  }
210  glEnd();
211  glPopMatrix();
212  }
213  }
214 }
215 
216 
217 void
219  const std::vector<SUMOReal>& rots,
220  const std::vector<SUMOReal>& lengths,
221  const std::vector<RGBColor>& cols,
222  SUMOReal width, int cornerDetail, SUMOReal offset) {
223  int e = (int) geom.size() - 1;
224  for (int i = 0; i < e; i++) {
225  setColor(cols[i]);
226  drawBoxLine(geom[i], rots[i], lengths[i], width, offset);
227  }
228  if (cornerDetail > 0) {
229  for (int i = 1; i < e; i++) {
230  glPushMatrix();
231  setColor(cols[i]);
232  glTranslated(geom[i].x(), geom[i].y(), 0);
233  drawFilledCircle(width, cornerDetail);
234  glEnd();
235  glPopMatrix();
236  }
237  }
238 }
239 
240 
241 void
243  const PositionVector& geom2,
244  const std::vector<SUMOReal>& rots,
245  const std::vector<SUMOReal>& lengths,
246  SUMOReal width) {
247  int minS = (int) MIN4(rots.size(), lengths.size(), geom1.size(), geom2.size());
248  for (int i = 0; i < minS; i++) {
249  GLHelper::drawBoxLine(geom1[i], geom2[i], rots[i], lengths[i], width);
250  }
251 }
252 
253 
254 void
256  int e = (int) geom.size() - 1;
257  for (int i = 0; i < e; i++) {
258  const Position& f = geom[i];
259  const Position& s = geom[i + 1];
260  drawBoxLine(f,
261  RAD2DEG(atan2((s.x() - f.x()), (f.y() - s.y()))),
262  f.distanceTo(s),
263  width);
264  }
265 }
266 
267 
268 void
269 GLHelper::drawLine(const Position& beg, SUMOReal rot, SUMOReal visLength) {
270  glPushMatrix();
271  glTranslated(beg.x(), beg.y(), 0);
272  glRotated(rot, 0, 0, 1);
273  glBegin(GL_LINES);
274  glVertex2d(0, 0);
275  glVertex2d(0, -visLength);
276  glEnd();
277  glPopMatrix();
278 }
279 
280 
281 void
282 GLHelper::drawLine(const Position& beg1, const Position& beg2,
283  SUMOReal rot, SUMOReal visLength) {
284  glPushMatrix();
285  glTranslated((beg2.x() + beg1.x())*.5, (beg2.y() + beg1.y())*.5, 0);
286  glRotated(rot, 0, 0, 1);
287  glBegin(GL_LINES);
288  glVertex2d(0, 0);
289  glVertex2d(0, -visLength);
290  glEnd();
291  glPopMatrix();
292 }
293 
294 
295 
296 void
298  glBegin(GL_LINES);
299  int e = (int) v.size() - 1;
300  for (int i = 0; i < e; ++i) {
301  glVertex2d(v[i].x(), v[i].y());
302  glVertex2d(v[i + 1].x(), v[i + 1].y());
303  }
304  glEnd();
305 }
306 
307 
308 void
309 GLHelper::drawLine(const PositionVector& v, const std::vector<RGBColor>& cols) {
310  glBegin(GL_LINES);
311  int e = (int) v.size() - 1;
312  for (int i = 0; i < e; ++i) {
313  setColor(cols[i]);
314  glVertex2d(v[i].x(), v[i].y());
315  glVertex2d(v[i + 1].x(), v[i + 1].y());
316  }
317  glEnd();
318 }
319 
320 
321 
322 void
323 GLHelper::drawLine(const Position& beg, const Position& end) {
324  glBegin(GL_LINES);
325  glVertex2d(beg.x(), beg.y());
326  glVertex2d(end.x(), end.y());
327  glEnd();
328 }
329 
330 
331 int
333  const int numCoords = (int)myCircleCoords.size() - 1;
334  int index = ((int)(floor(angleDeg * CIRCLE_RESOLUTION + 0.5))) % numCoords;
335  if (index < 0) {
336  index += numCoords;
337  }
338  assert(index >= 0);
339  return (int)index;
340 }
341 
342 
343 void
345  drawFilledCircle(width, steps, 0, 360);
346 }
347 
348 
349 void
351  if (myCircleCoords.size() == 0) {
352  for (int i = 0; i <= (int)(360 * CIRCLE_RESOLUTION); ++i) {
353  const SUMOReal x = (SUMOReal) sin(DEG2RAD(i / CIRCLE_RESOLUTION));
354  const SUMOReal y = (SUMOReal) cos(DEG2RAD(i / CIRCLE_RESOLUTION));
355  myCircleCoords.push_back(std::pair<SUMOReal, SUMOReal>(x, y));
356  }
357  }
358  const SUMOReal inc = (end - beg) / (SUMOReal)steps;
359  glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
360  std::pair<SUMOReal, SUMOReal> p1 = myCircleCoords[angleLookup(beg)];
361 
362  for (int i = 0; i <= steps; ++i) {
363  const std::pair<SUMOReal, SUMOReal>& p2 = myCircleCoords[angleLookup(beg + i * inc)];
364  glBegin(GL_TRIANGLES);
365  glVertex2d(p1.first * width, p1.second * width);
366  glVertex2d(p2.first * width, p2.second * width);
367  glVertex2d(0, 0);
368  glEnd();
369  p1 = p2;
370  }
371 }
372 
373 
374 void
375 GLHelper::drawOutlineCircle(SUMOReal width, SUMOReal iwidth, int steps) {
376  drawOutlineCircle(width, iwidth, steps, 0, 360);
377 }
378 
379 
380 void
382  SUMOReal beg, SUMOReal end) {
383  if (myCircleCoords.size() == 0) {
384  for (int i = 0; i < 360; i += 10) {
385  SUMOReal x = (SUMOReal) sin(DEG2RAD(i));
386  SUMOReal y = (SUMOReal) cos(DEG2RAD(i));
387  myCircleCoords.push_back(std::pair<SUMOReal, SUMOReal>(x, y));
388  }
389  }
390  glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
391  std::pair<SUMOReal, SUMOReal> p1 =
392  beg == 0 ? myCircleCoords[0] : myCircleCoords[((int) beg / 10) % 36];
393  for (int i = (int)(beg / 10); i < steps && (36.0 / (SUMOReal) steps * (SUMOReal) i) * 10 < end; i++) {
394  const std::pair<SUMOReal, SUMOReal>& p2 =
395  myCircleCoords[(int)(36.0 / (SUMOReal) steps * (SUMOReal) i)];
396  glBegin(GL_TRIANGLES);
397  glVertex2d(p1.first * width, p1.second * width);
398  glVertex2d(p2.first * width, p2.second * width);
399  glVertex2d(p2.first * iwidth, p2.second * iwidth);
400 
401  glVertex2d(p2.first * iwidth, p2.second * iwidth);
402  glVertex2d(p1.first * iwidth, p1.second * iwidth);
403  glVertex2d(p1.first * width, p1.second * width);
404  glEnd();
405  p1 = p2;
406  }
407  const std::pair<SUMOReal, SUMOReal>& p2 =
408  end == 360 ? myCircleCoords[0] : myCircleCoords[((int) end / 10) % 36];
409  glBegin(GL_TRIANGLES);
410  glVertex2d(p1.first * width, p1.second * width);
411  glVertex2d(p2.first * width, p2.second * width);
412  glVertex2d(p2.first * iwidth, p2.second * iwidth);
413 
414  glVertex2d(p2.first * iwidth, p2.second * iwidth);
415  glVertex2d(p1.first * iwidth, p1.second * iwidth);
416  glVertex2d(p1.first * width, p1.second * width);
417  glEnd();
418 }
419 
420 
421 void
423  SUMOReal tLength, SUMOReal tWidth) {
424  const SUMOReal length = p1.distanceTo(p2);
425  if (length < tLength) {
426  tWidth *= length / tLength;
427  tLength = length;
428  }
429  Position rl(PositionVector::positionAtOffset(p1, p2, length - tLength));
430  glPushMatrix();
431  glTranslated(rl.x(), rl.y(), 0);
432  glRotated(-GeomHelper::naviDegree(p1.angleTo2D(p2)), 0, 0, 1);
433  glBegin(GL_TRIANGLES);
434  glVertex2d(0, tLength);
435  glVertex2d(-tWidth, 0);
436  glVertex2d(+tWidth, 0);
437  glEnd();
438  glPopMatrix();
439 }
440 
441 
442 void
444  glColor4ub(c.red(), c.green(), c.blue(), c.alpha());
445 }
446 
447 
448 RGBColor
450  GLdouble current[4];
451  glGetDoublev(GL_CURRENT_COLOR, current);
452  return RGBColor(static_cast<unsigned char>(current[0] * 255. + 0.5),
453  static_cast<unsigned char>(current[1] * 255. + 0.5),
454  static_cast<unsigned char>(current[2] * 255. + 0.5),
455  static_cast<unsigned char>(current[3] * 255. + 0.5));
456 }
457 
458 
459 void
460 GLHelper::drawText(const std::string& text, const Position& pos,
461  const SUMOReal layer, const SUMOReal size,
462  const RGBColor& col, const SUMOReal angle) {
463  glPushMatrix();
464  glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
465  setColor(col);
466  glTranslated(pos.x(), pos.y(), layer);
467  pfSetPosition(0, 0);
468  pfSetScale(size);
469  SUMOReal w = pfdkGetStringWidth(text.c_str());
470  glRotated(180, 1, 0, 0);
471  glRotated(angle, 0, 0, 1);
472  glTranslated(-w / 2., size / 4, 0);
473  pfDrawString(text.c_str());
474  glPopMatrix();
475 }
476 
477 void
478 GLHelper::drawTextBox(const std::string& text, const Position& pos,
479  const SUMOReal layer, const SUMOReal size,
480  const RGBColor& txtColor, const RGBColor& bgColor, const RGBColor& borderColor,
481  const SUMOReal angle) {
482  SUMOReal boxAngle = angle + 90;
483  if (boxAngle > 360) {
484  boxAngle -= 360;
485  }
486  pfSetScale(size);
487  const SUMOReal stringWidth = pfdkGetStringWidth(text.c_str());
488  const SUMOReal borderWidth = size / 20;
489  const SUMOReal boxHeight = size * 0.8;
490  const SUMOReal boxWidth = stringWidth + size / 2;
491  glPushMatrix();
492  glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
493  glTranslated(0, 0, layer);
494  setColor(borderColor);
495  Position left = pos;
496  left.sub(boxWidth / 2, -boxHeight / 2.7);
497  drawBoxLine(left, boxAngle, boxWidth, boxHeight);
498  left.add(borderWidth * 1.5, 0);
499  setColor(bgColor);
500  glTranslated(0, 0, 0.01);
501  drawBoxLine(left, boxAngle, boxWidth - 3 * borderWidth, boxHeight - 2 * borderWidth);
502  // actually we should be able to use drawText here. however, there's
503  // something about the constant 0.4 offset which causes trouble
504  //drawText(text, pos, layer+0.02, size, txtColor, angle);
505  setColor(txtColor);
506  glTranslated(pos.x(), pos.y(), 0.01);
507  pfSetPosition(0, 0);
508  pfSetScale(size);
509  glRotated(180, 1, 0, 0);
510  glRotated(angle, 0, 0, 1);
511  glTranslated(-stringWidth / 2., 0, 0);
512  pfDrawString(text.c_str());
513  glPopMatrix();
514 }
515 
516 
517 void
519  RGBColor color = RGBColor::fromHSV(RandHelper::rand(360), 1, 1);
520  for (int i = 0; i < (int)shape.size(); ++i) {
521  GLHelper::drawText(toString(i), shape[i], layer, size, color, 0);
522  }
523 }
524 /****************************************************************************/
525 
void sub(SUMOReal dx, SUMOReal dy)
Substracts the given position from this one.
Definition: Position.h:139
int pfDrawString(const char *c)
Definition: polyfonts.c:1074
static RGBColor fromHSV(SUMOReal h, SUMOReal s, SUMOReal v)
Converts the given hsv-triplet to rgb.
Definition: RGBColor.cpp:294
SUMOReal angleTo2D(const Position &other) const
returns the angle in the plane of the vector pointing from here to the other position ...
Definition: Position.h:243
void add(const Position &pos)
Adds the given position to this one.
Definition: Position.h:119
static void debugVertices(const PositionVector &shape, SUMOReal size, SUMOReal layer=256)
draw vertex numbers for the given shape (in a random color)
Definition: GLHelper.cpp:518
SUMOReal distanceTo(const Position &p2) const
returns the euclidean distance in 3 dimension
Definition: Position.h:221
unsigned char alpha() const
Returns the alpha-amount of the color.
Definition: RGBColor.h:99
T MIN4(T a, T b, T c, T d)
Definition: StdDefs.h:96
static void drawOutlineCircle(SUMOReal width, SUMOReal iwidth, int steps=8)
Draws an unfilled circle around (0,0)
Definition: GLHelper.cpp:375
static SUMOReal rand()
Returns a random real number in [0, 1)
Definition: RandHelper.h:62
Position positionAtOffset(SUMOReal pos, SUMOReal lateralOffset=0) const
Returns the position at the given length.
void pfSetPosition(SUMOReal x, SUMOReal y)
Definition: polyfonts.c:480
static void drawBoxLines(const PositionVector &geom, const std::vector< SUMOReal > &rots, const std::vector< SUMOReal > &lengths, SUMOReal width, int cornerDetail=0, SUMOReal offset=0)
Draws thick lines.
Definition: GLHelper.cpp:176
static void drawBoxLine(const Position &beg, SUMOReal rot, SUMOReal visLength, SUMOReal width, SUMOReal offset=0)
Draws a thick line.
Definition: GLHelper.cpp:130
static void drawFilledPoly(const PositionVector &v, bool close)
Draws a filled polygon described by the list of points.
Definition: GLHelper.cpp:76
unsigned char blue() const
Returns the blue-amount of the color.
Definition: RGBColor.h:91
#define RAD2DEG(x)
Definition: GeomHelper.h:46
static void drawText(const std::string &text, const Position &pos, const SUMOReal layer, const SUMOReal size, const RGBColor &col=RGBColor::BLACK, const SUMOReal angle=0)
draw Text with given parameters
Definition: GLHelper.cpp:460
#define UNUSED_PARAMETER(x)
Definition: StdDefs.h:39
static void drawTriangleAtEnd(const Position &p1, const Position &p2, SUMOReal tLength, SUMOReal tWidth)
Draws a triangle at the end of the given line.
Definition: GLHelper.cpp:422
static void drawFilledPolyTesselated(const PositionVector &v, bool close)
Draws a filled polygon described by the list of points.
Definition: GLHelper.cpp:95
static bool rightTurn(SUMOReal angle1, SUMOReal angle2)
whether the road makes a right turn (or goes straight)
Definition: GLHelper.cpp:163
static void drawFilledCircle(SUMOReal width, int steps=8)
Draws a filled circle around (0,0)
Definition: GLHelper.cpp:344
static std::vector< std::pair< SUMOReal, SUMOReal > > myCircleCoords
Storage for precomputed sin/cos-values describing a circle.
Definition: GLHelper.h:306
static void setColor(const RGBColor &c)
Sets the gl-color to this value.
Definition: GLHelper.cpp:443
A point in 2D or 3D with translation and scaling methods.
Definition: Position.h:46
A list of positions.
static int angleLookup(SUMOReal angleDeg)
normalize angle for lookup in myCircleCoords
Definition: GLHelper.cpp:332
T MIN2(T a, T b)
Definition: StdDefs.h:69
SUMOReal x() const
Returns the x-position.
Definition: Position.h:63
#define DEG2RAD(x)
Definition: GeomHelper.h:45
std::string toString(const T &t, std::streamsize accuracy=OUTPUT_ACCURACY)
Definition: ToString.h:55
static void drawTextBox(const std::string &text, const Position &pos, const SUMOReal layer, const SUMOReal size, const RGBColor &txtColor=RGBColor::BLACK, const RGBColor &bgColor=RGBColor::WHITE, const RGBColor &borderColor=RGBColor::BLACK, const SUMOReal angle=0)
draw Text box with given parameters
Definition: GLHelper.cpp:478
static SUMOReal naviDegree(const SUMOReal angle)
Definition: GeomHelper.cpp:191
void APIENTRY combCallback(GLdouble coords[3], GLdouble *vertex_data[4], GLfloat weight[4], GLdouble **dataOut)
Definition: GLHelper.cpp:55
void pfSetScale(SUMOReal s)
Definition: polyfonts.c:465
unsigned char green() const
Returns the green-amount of the color.
Definition: RGBColor.h:83
#define CIRCLE_RESOLUTION
Definition: GLHelper.cpp:47
SUMOReal pfdkGetStringWidth(const char *c)
Definition: polyfonts.c:1113
unsigned char red() const
Returns the red-amount of the color.
Definition: RGBColor.h:75
static void drawLine(const Position &beg, SUMOReal rot, SUMOReal visLength)
Draws a thin line.
Definition: GLHelper.cpp:269
#define SUMOReal
Definition: config.h:213
SUMOReal y() const
Returns the y-position.
Definition: Position.h:68
static RGBColor getColor()
gets the gl-color
Definition: GLHelper.cpp:449