Eclipse SUMO - Simulation of Urban MObility
GLHelper.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-2022 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 /****************************************************************************/
20 // Some methods which help to draw certain geometrical objects in openGL
21 /****************************************************************************/
22 #include <config.h>
23 
24 #include <cassert>
25 #include <utils/geom/GeomHelper.h>
26 #include <utils/common/StdDefs.h>
28 #include <utils/common/ToString.h>
30 #define FONTSTASH_IMPLEMENTATION // Expands implementation
31 #ifdef _MSC_VER
32 #pragma warning(disable: 4505 5219) // do not warn about unused functions and implicit float conversions
33 #endif
34 #if __GNUC__ > 3
35 #pragma GCC diagnostic push
36 #pragma GCC diagnostic ignored "-Wunused-function"
37 #endif
40 #define GLFONTSTASH_IMPLEMENTATION // Expands implementation
42 #include <utils/geom/Boundary.h>
43 #ifdef HAVE_GL2PS
44 #include <gl2ps.h>
45 #endif
46 #include "Roboto.h"
47 #include "GLHelper.h"
48 
49 #define CIRCLE_RESOLUTION (double)10 // inverse in degrees
50 //#define CHECK_PUSHPOP // enable or disable check push and pop matrix/names
51 //#define CHECK_ELEMENTCOUNTER // enable or disable element counter (for matrix and vertex)
52 
53 #ifndef CALLBACK
54 #define CALLBACK
55 #endif
56 
57 // ===========================================================================
58 // static member definitions
59 // ===========================================================================
60 
65 std::vector<std::pair<double, double> > GLHelper::myCircleCoords;
66 std::vector<RGBColor> GLHelper::myDottedcontourColors;
67 FONScontext* GLHelper::myFont = nullptr;
68 double GLHelper::myFontSize = 50.0;
69 bool GLHelper::myGL2PSActive = false;
70 
71 void CALLBACK combCallback(GLdouble coords[3],
72  GLdouble* vertex_data[4],
73  GLfloat weight[4], GLdouble** dataOut) {
74  UNUSED_PARAMETER(weight);
75  UNUSED_PARAMETER(*vertex_data);
76  GLdouble* vertex;
77 
78  vertex = (GLdouble*)malloc(7 * sizeof(GLdouble));
79 
80  vertex[0] = coords[0];
81  vertex[1] = coords[1];
82  vertex[2] = coords[2];
83  *dataOut = vertex;
84 }
85 
86 // ===========================================================================
87 // method definitions
88 // ===========================================================================
89 
90 const std::vector<std::pair<double, double> >&
92  // fill in first call
93  if (myCircleCoords.size() == 0) {
94  for (int i = 0; i <= (int)(360 * CIRCLE_RESOLUTION); ++i) {
95  const double x = (double) sin(DEG2RAD(i / CIRCLE_RESOLUTION));
96  const double y = (double) cos(DEG2RAD(i / CIRCLE_RESOLUTION));
97  myCircleCoords.push_back(std::pair<double, double>(x, y));
98  }
99  }
100  return myCircleCoords;
101 }
102 
103 
104 int
105 GLHelper::angleLookup(double angleDeg) {
106  const int numCoords = (int)getCircleCoords().size() - 1;
107  int index = ((int)(floor(angleDeg * CIRCLE_RESOLUTION + 0.5))) % numCoords;
108  if (index < 0) {
109  index += numCoords;
110  }
111  assert(index >= 0);
112  return (int)index;
113 }
114 
115 
116 void
118  glPushMatrix();
119  // update counters
120 #ifdef CHECK_ELEMENTCOUNTER
121  myMatrixCounter++;
122 #endif
123 #ifdef CHECK_PUSHPOP
125 #endif
126 }
127 
128 
129 void
131  glPopMatrix();
132 #ifdef CHECK_PUSHPOP
134 #endif
135 }
136 
137 
138 void
139 GLHelper::pushName(unsigned int name) {
140  glPushName(name);
141 #ifdef CHECK_PUSHPOP
142  myNameCounter++;
143 #endif
144 }
145 
146 
147 void
149  glPopName();
150 #ifdef CHECK_PUSHPOP
151  myNameCounter--;
152 #endif
153 }
154 
155 
156 int
158  return myMatrixCounter;
159 }
160 
161 
162 void
164  myMatrixCounter = 0;
165 }
166 
167 
168 int
170  return myVertexCounter;
171 }
172 
173 
174 void
176  myVertexCounter = 0;
177 }
178 
179 
180 void
182 #ifdef CHECK_PUSHPOP
183  if (myMatrixCounterDebug != 0) {
184  WRITE_WARNING(TL("invalid matrix counter. Check that number of pushMatrix and popMatrix functions calls are the same"));
185  }
187 #endif
188 }
189 
190 
191 void
193 #ifdef CHECK_PUSHPOP
194  if (myNameCounter != 0) {
195  WRITE_WARNING(TL("invalid Name counter. Check that number of pushName and popName functions calls are the same"));
196  }
197  myNameCounter = 0;
198 #endif
199 }
200 
201 
202 void
204  if (v.size() == 0) {
205  return;
206  }
207  glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
208  glBegin(GL_POLYGON);
209  for (PositionVector::const_iterator i = v.begin(); i != v.end(); i++) {
210  const Position& p = *i;
211  glVertex2d(p.x(), p.y());
212 #ifdef CHECK_ELEMENTCOUNTER
213  myVertexCounter++;
214 #endif
215  }
216  if (close) {
217  const Position& p = *(v.begin());
218  glVertex2d(p.x(), p.y());
219 #ifdef CHECK_ELEMENTCOUNTER
220  myVertexCounter++;
221 #endif
222  }
223  glEnd();
224 }
225 
226 
227 void
229  if (v.size() == 0) {
230  return;
231  }
232  GLUtesselator* tobj = gluNewTess();
233 #ifdef _MSC_VER
234 #pragma warning(push)
235 #pragma warning(disable: 4191)
236 #endif
237 #if defined(__GNUC__) && __GNUC__ >= 8
238 #pragma GCC diagnostic push
239 #pragma GCC diagnostic ignored "-Wcast-function-type"
240 #endif
241  gluTessCallback(tobj, GLU_TESS_VERTEX, (GLvoid(CALLBACK*)()) &glVertex3dv);
242  gluTessCallback(tobj, GLU_TESS_BEGIN, (GLvoid(CALLBACK*)()) &glBegin);
243  gluTessCallback(tobj, GLU_TESS_END, (GLvoid(CALLBACK*)()) &glEnd);
244  gluTessCallback(tobj, GLU_TESS_COMBINE, (GLvoid(CALLBACK*)()) &combCallback);
245 #if defined(__GNUC__) && __GNUC__ >= 8
246 #pragma GCC diagnostic pop
247 #endif
248 #ifdef _MSC_VER
249 #pragma warning(pop)
250 #endif
251  gluTessProperty(tobj, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_ODD);
252  gluTessBeginPolygon(tobj, nullptr);
253  gluTessBeginContour(tobj);
254  double* points = new double[(v.size() + int(close)) * 3];
255 
256  for (int i = 0; i != (int)v.size(); ++i) {
257  points[3 * i] = v[i].x();
258  points[3 * i + 1] = v[i].y();
259  points[3 * i + 2] = 0;
260  gluTessVertex(tobj, points + 3 * i, points + 3 * i);
261  }
262  if (close) {
263  const int i = (int)v.size();
264  points[3 * i] = v[0].x();
265  points[3 * i + 1] = v[0].y();
266  points[3 * i + 2] = 0;
267  gluTessVertex(tobj, points + 3 * i, points + 3 * i);
268  }
269  gluTessEndContour(tobj);
270  gluTessEndPolygon(tobj);
271  gluDeleteTess(tobj);
272  delete[] points;
273 }
274 
275 
276 void
277 GLHelper::drawBoxLine(const Position& beg, double rot, double visLength,
278  double width, double offset) {
280  glTranslated(beg.x(), beg.y(), 0);
281  glRotated(rot, 0, 0, 1);
282  glBegin(GL_QUADS);
283  glVertex2d(-width - offset, 0);
284  glVertex2d(-width - offset, -visLength);
285  glVertex2d(width - offset, -visLength);
286  glVertex2d(width - offset, 0);
287  glEnd();
289 #ifdef CHECK_ELEMENTCOUNTER
290  myVertexCounter += 4;
291 #endif
292 }
293 
294 
295 void
296 GLHelper::drawBoxLine(const Position& beg1, const Position& beg2,
297  double rot, double visLength,
298  double width) {
300  glTranslated((beg2.x() + beg1.x())*.5, (beg2.y() + beg1.y())*.5, 0);
301  glRotated(rot, 0, 0, 1);
302  glBegin(GL_QUADS);
303  glVertex2d(-width, 0);
304  glVertex2d(-width, -visLength);
305  glVertex2d(width, -visLength);
306  glVertex2d(width, 0);
307  glEnd();
309 #ifdef CHECK_ELEMENTCOUNTER
310  myVertexCounter += 4;
311 #endif
312 }
313 
314 
315 bool
316 GLHelper::rightTurn(double angle1, double angle2) {
317  double delta = angle2 - angle1;
318  while (delta > 180) {
319  delta -= 360;
320  }
321  while (delta < -180) {
322  delta += 360;
323  }
324  return delta <= 0;
325 }
326 
327 
328 void
330  const std::vector<double>& rots,
331  const std::vector<double>& lengths,
332  double width, int cornerDetail, double offset) {
333  // draw the lane
334  int e = (int) geom.size() - 1;
335  for (int i = 0; i < e; i++) {
336  drawBoxLine(geom[i], rots[i], lengths[i], width, offset);
337  }
338  // draw the corner details
339  if (cornerDetail > 0) {
340  for (int i = 1; i < e; i++) {
342  glTranslated(geom[i].x(), geom[i].y(), 0.1);
343  double angleBeg = -rots[i - 1];
344  double angleEnd = 180 - rots[i];
345  if (rightTurn(rots[i - 1], rots[i])) {
346  std::swap(angleBeg, angleEnd);
347  }
348  // only draw the missing piece
349  angleBeg -= 90;
350  angleEnd += 90;
351  // avoid drawing more than 360 degrees
352  if (angleEnd - angleBeg > 360) {
353  angleBeg += 360;
354  }
355  if (angleEnd - angleBeg < -360) {
356  angleEnd += 360;
357  }
358  // draw the right way around
359  if (angleEnd > angleBeg) {
360  angleEnd -= 360;
361  }
362  drawFilledCircle(width + offset, cornerDetail, angleBeg, angleEnd);
364  }
365  }
366 }
367 
368 
369 void
371  const std::vector<double>& rots,
372  const std::vector<double>& lengths,
373  const std::vector<RGBColor>& cols,
374  double width, int cornerDetail, double offset) {
375  int e = (int) geom.size() - 1;
376  for (int i = 0; i < e; i++) {
377  setColor(cols[i]);
378  drawBoxLine(geom[i], rots[i], lengths[i], width, offset);
379  }
380  if (cornerDetail > 0) {
381  for (int i = 1; i < e; i++) {
383  setColor(cols[i]);
384  glTranslated(geom[i].x(), geom[i].y(), 0);
385  drawFilledCircle(width, cornerDetail);
386  glEnd();
388  }
389  }
390 }
391 
392 
393 void
395  const PositionVector& geom2,
396  const std::vector<double>& rots,
397  const std::vector<double>& lengths,
398  double width) {
399  int minS = (int) MIN4(rots.size(), lengths.size(), geom1.size(), geom2.size());
400  for (int i = 0; i < minS; i++) {
401  GLHelper::drawBoxLine(geom1[i], geom2[i], rots[i], lengths[i], width);
402  }
403 }
404 
405 
406 void
407 GLHelper::drawBoxLines(const PositionVector& geom, double width) {
408  int e = (int) geom.size() - 1;
409  for (int i = 0; i < e; i++) {
410  const Position& f = geom[i];
411  const Position& s = geom[i + 1];
412  drawBoxLine(f,
413  RAD2DEG(atan2((s.x() - f.x()), (f.y() - s.y()))),
414  f.distanceTo(s),
415  width);
416  }
417 }
418 
419 
420 void
421 GLHelper::drawLine(const Position& beg, double rot, double visLength) {
423  glTranslated(beg.x(), beg.y(), 0);
424  glRotated(rot, 0, 0, 1);
425  glBegin(GL_LINES);
426  glVertex2d(0, 0);
427  glVertex2d(0, -visLength);
428  glEnd();
430 #ifdef CHECK_ELEMENTCOUNTER
431  myVertexCounter += 2;
432 #endif
433 }
434 
435 
436 void
437 GLHelper::drawLine(const Position& beg1, const Position& beg2,
438  double rot, double visLength) {
440  glTranslated((beg2.x() + beg1.x())*.5, (beg2.y() + beg1.y())*.5, 0);
441  glRotated(rot, 0, 0, 1);
442  glBegin(GL_LINES);
443  glVertex2d(0, 0);
444  glVertex2d(0, -visLength);
445  glEnd();
447 #ifdef CHECK_ELEMENTCOUNTER
448  myVertexCounter += 2;
449 #endif
450 }
451 
452 
453 
454 void
456  glBegin(GL_LINES);
457  int e = (int) v.size() - 1;
458  for (int i = 0; i < e; ++i) {
459  glVertex2d(v[i].x(), v[i].y());
460  glVertex2d(v[i + 1].x(), v[i + 1].y());
461 #ifdef CHECK_ELEMENTCOUNTER
462  myVertexCounter += 2;
463 #endif
464  }
465  glEnd();
466 }
467 
468 
469 void
470 GLHelper::drawLine(const PositionVector& v, const std::vector<RGBColor>& cols) {
471  glBegin(GL_LINES);
472  int e = (int) v.size() - 1;
473  for (int i = 0; i < e; ++i) {
474  setColor(cols[i]);
475  glVertex2d(v[i].x(), v[i].y());
476  glVertex2d(v[i + 1].x(), v[i + 1].y());
477 #ifdef CHECK_ELEMENTCOUNTER
478  myVertexCounter += 2;
479 #endif
480  }
481  glEnd();
482 }
483 
484 
485 void
486 GLHelper::drawLine(const Position& beg, const Position& end) {
487  glBegin(GL_LINES);
488  glVertex2d(beg.x(), beg.y());
489  glVertex2d(end.x(), end.y());
490  glEnd();
491 #ifdef CHECK_ELEMENTCOUNTER
492  myVertexCounter += 2;
493 #endif
494 }
495 
496 
497 void
498 GLHelper::drawFilledCircle(double width, int steps) {
499  drawFilledCircle(width, steps, 0, 360);
500 }
501 
502 
503 void
504 GLHelper::drawFilledCircle(double width, int steps, double beg, double end) {
505  const double inc = (end - beg) / (double)steps;
506  glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
507  std::pair<double, double> p1 = getCircleCoords().at(angleLookup(beg));
508 
509  for (int i = 0; i <= steps; ++i) {
510  const std::pair<double, double>& p2 = getCircleCoords().at(angleLookup(beg + i * inc));
511  glBegin(GL_TRIANGLES);
512  glVertex2d(p1.first * width, p1.second * width);
513  glVertex2d(p2.first * width, p2.second * width);
514  glVertex2d(0, 0);
515  glEnd();
516  p1 = p2;
517 #ifdef CHECK_ELEMENTCOUNTER
518  myVertexCounter += 2;
519 #endif
520  }
521 }
522 
523 
524 void
525 GLHelper::drawOutlineCircle(double width, double iwidth, int steps) {
526  drawOutlineCircle(width, iwidth, steps, 0, 360);
527 }
528 
529 
530 void
531 GLHelper::drawOutlineCircle(double width, double iwidth, int steps,
532  double beg, double end) {
533  const double inc = (end - beg) / (double)steps;
534  glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
535  std::pair<double, double> p1 = getCircleCoords().at(angleLookup(beg));
536 
537  for (int i = 0; i <= steps; ++i) {
538  const std::pair<double, double>& p2 = getCircleCoords().at(angleLookup(beg + i * inc));
539  glBegin(GL_TRIANGLES);
540  glVertex2d(p1.first * width, p1.second * width);
541  glVertex2d(p2.first * width, p2.second * width);
542  glVertex2d(p2.first * iwidth, p2.second * iwidth);
543 
544  glVertex2d(p2.first * iwidth, p2.second * iwidth);
545  glVertex2d(p1.first * iwidth, p1.second * iwidth);
546  glVertex2d(p1.first * width, p1.second * width);
547 
548  glEnd();
549  p1 = p2;
550 #ifdef CHECK_ELEMENTCOUNTER
551  myVertexCounter += 6;
552 #endif
553  }
554 }
555 
556 
557 void
558 GLHelper::drawTriangleAtEnd(const Position& p1, const Position& p2, double tLength,
559  double tWidth, const double extraOffset) {
560  const double length = p1.distanceTo(p2);
561  if (length < tLength) {
562  tWidth *= length / tLength;
563  tLength = length;
564  }
565  Position rl(PositionVector::positionAtOffset(p1, p2, length - tLength));
567  glTranslated(rl.x(), rl.y(), 0);
568  glRotated(-GeomHelper::naviDegree(p1.angleTo2D(p2)), 0, 0, 1);
569  glTranslated(0, extraOffset, 0);
570  glBegin(GL_TRIANGLES);
571  glVertex2d(0, tLength);
572  glVertex2d(-tWidth, 0);
573  glVertex2d(+tWidth, 0);
574  glEnd();
576 #ifdef CHECK_ELEMENTCOUNTER
577  myVertexCounter += 3;
578 #endif
579 }
580 
581 
582 void
584  glColor4ub(c.red(), c.green(), c.blue(), c.alpha());
585 }
586 
587 
588 RGBColor
590  GLdouble current[4];
591  glGetDoublev(GL_CURRENT_COLOR, current);
592  return RGBColor(static_cast<unsigned char>(current[0] * 255. + 0.5),
593  static_cast<unsigned char>(current[1] * 255. + 0.5),
594  static_cast<unsigned char>(current[2] * 255. + 0.5),
595  static_cast<unsigned char>(current[3] * 255. + 0.5));
596 }
597 
598 
599 void
602  myFont = nullptr;
603 }
604 
605 
606 void
607 GLHelper::setGL2PS(bool active) {
608  myGL2PSActive = active;
609 }
610 
611 
612 void
613 GLHelper::drawSpaceOccupancies(const double exaggeration, const Position& pos, const double rotation,
614  const double width, const double length, const bool vehicle) {
615  // declare colors
616  const RGBColor red(255, 0, 0, 255);
617  const RGBColor green(0, 255, 0, 255);
618  // declare geometry
619  PositionVector geom;
620  const double w = width / 2. - 0.1 * exaggeration;
621  const double h = length;
622  // set geometry
623  geom.push_back(Position(-w, +0, 0.));
624  geom.push_back(Position(+w, +0, 0.));
625  geom.push_back(Position(+w, +h, 0.));
626  geom.push_back(Position(-w, +h, 0.));
627  geom.push_back(Position(-w, +0, 0.));
628  /*
629  geom.push_back(Position(pos.x(), pos.y(), pos.z()));
630  geom.push_back(Position(pos.x() + (*l).second.myWidth, pos.y(), pos.z()));
631  geom.push_back(Position(pos.x() + (*l).second.myWidth, pos.y() - (*l).second.myLength, pos.z()));
632  geom.push_back(Position(pos.x(), pos.y() - (*l).second.myLength, pos.z()));
633  geom.push_back(Position(pos.x(), pos.y(), pos.z()));
634  */
635  // push matrix
637  // translate
638  glTranslated(pos.x(), pos.y(), pos.z());
639  // rotate
640  glRotated(rotation, 0, 0, 1);
641  // set color
642  GLHelper::setColor(vehicle ? green : red);
643  // draw box lines
644  GLHelper::drawBoxLines(geom, 0.1 * exaggeration);
645  // pop matrix
647 }
648 
649 
650 bool
652  if (myFont == nullptr) {
654  if (myFont != nullptr) {
656  fonsSetFont(myFont, fontNormal);
657  fonsSetSize(myFont, (float)myFontSize);
658  }
659  }
660  return myFont != nullptr;
661 }
662 
663 
664 const std::vector<RGBColor>&
666  // check if more colors has to be added
667  while ((int)myDottedcontourColors.size() < size) {
670  } else {
672  }
673  }
674  return myDottedcontourColors;
675 }
676 
677 
678 double
679 GLHelper::getTextWidth(const std::string& text, double size) {
680  return size / myFontSize * fonsTextBounds(myFont, 0, 0, text.c_str(), nullptr, nullptr);
681 }
682 
683 
684 void
685 GLHelper::drawText(const std::string& text, const Position& pos, const double layer, const double size,
686  const RGBColor& col, const double angle, const int align, double width) {
687  if (width <= 0) {
688  width = size;
689  }
690  if (!initFont()) {
691  return;
692  }
694  glAlphaFunc(GL_GREATER, 0.5);
695  glEnable(GL_ALPHA_TEST);
696 #ifdef HAVE_GL2PS
697  if (myGL2PSActive) {
698  glRasterPos3d(pos.x(), pos.y(), layer);
699  GLfloat color[] = {col.red() / 255.f, col.green() / 255.f, col.blue() / 255.f, col.alpha() / 255.f};
700  gl2psTextOptColor(text.c_str(), "Roboto", 10, align == 0 ? GL2PS_TEXT_C : align, (GLfloat) - angle, color);
702  return;
703  }
704 #endif
705  glTranslated(pos.x(), pos.y(), layer);
706  glScaled(width / myFontSize, size / myFontSize, 1.);
707  glRotated(-angle, 0, 0, 1);
708  fonsSetAlign(myFont, align == 0 ? FONS_ALIGN_CENTER | FONS_ALIGN_MIDDLE : align);
709  fonsSetColor(myFont, glfonsRGBA(col.red(), col.green(), col.blue(), col.alpha()));
710  fonsDrawText(myFont, 0., 0., text.c_str(), nullptr);
712 }
713 
714 
715 void
717  const GUIVisualizationTextSettings& settings,
718  const std::string& text, const Position& pos,
719  const double scale,
720  const double angle,
721  const double layer,
722  const int align) {
723  drawTextBox(text, pos, layer,
724  settings.scaledSize(scale),
725  settings.color,
726  settings.bgColor,
728  angle, 0, 0.2, align);
729 }
730 
731 
732 void
733 GLHelper::drawTextBox(const std::string& text, const Position& pos,
734  const double layer, const double size,
735  const RGBColor& txtColor, const RGBColor& bgColor, const RGBColor& borderColor,
736  const double angle,
737  const double relBorder,
738  const double relMargin,
739  const int align) {
740  if (!initFont()) {
741  return;
742  };
743  if (bgColor.alpha() != 0) {
744  const double boxAngle = 90;
745  const double stringWidth = size / myFontSize * fonsTextBounds(myFont, 0, 0, text.c_str(), nullptr, nullptr);
746  const double borderWidth = size * relBorder;
747  const double boxHeight = size * (0.32 + 0.6 * relMargin);
748  const double boxWidth = stringWidth + size * relMargin;
750  glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
751  glTranslated(pos.x(), pos.y(), layer);
752  glRotated(-angle, 0, 0, 1);
753  Position left(-boxWidth * 0.5, 0);
754  setColor(borderColor);
755  drawBoxLine(left, boxAngle, boxWidth, boxHeight);
756  left.add(borderWidth * 1.5, 0);
757  setColor(bgColor);
758  glTranslated(0, 0, 0.01);
759  drawBoxLine(left, boxAngle, boxWidth - 3 * borderWidth, boxHeight - 2 * borderWidth);
761  }
762  drawText(text, pos, layer + 0.02, size, txtColor, angle, align);
763 }
764 
765 
766 void
767 GLHelper::drawTextAtEnd(const std::string& text, const PositionVector& shape, double x,
768  const GUIVisualizationTextSettings& settings, const double scale) {
770  const Position& end = shape.back();
771  const Position& f = shape[-2];
772  const double rot = RAD2DEG(atan2((end.x() - f.x()), (f.y() - end.y())));
773  glTranslated(end.x(), end.y(), 0);
774  glRotated(rot, 0, 0, 1);
775  drawTextBox(text, Position(x, 0.26), 0,
776  settings.scaledSize(scale, 0.01),
777  settings.color,
778  settings.bgColor,
780  180, 0, 0.2);
782 }
783 
784 void
786  const std::vector<double>& rots,
787  const std::vector<double>& lengths,
788  double length, double spacing,
789  double halfWidth, bool drawForSelection) {
791  // draw on top of of the white area between the rails
792  glTranslated(0, 0, 0.1);
793  int e = (int) geom.size() - 1;
794  for (int i = 0; i < e; ++i) {
796  glTranslated(geom[i].x(), geom[i].y(), 0.0);
797  glRotated(rots[i], 0, 0, 1);
798  // draw crossing depending if isn't being drawn for selecting
799  if (!drawForSelection) {
800  for (double t = 0; t < lengths[i]; t += spacing) {
801  glBegin(GL_QUADS);
802  glVertex2d(-halfWidth, -t);
803  glVertex2d(-halfWidth, -t - length);
804  glVertex2d(halfWidth, -t - length);
805  glVertex2d(halfWidth, -t);
806  glEnd();
807 #ifdef CHECK_ELEMENTCOUNTER
808  myVertexCounter += 4;
809 #endif
810  }
811  } else {
812  // only draw a single rectangle if it's being drawn only for selecting
813  glBegin(GL_QUADS);
814  glVertex2d(-halfWidth, 0);
815  glVertex2d(-halfWidth, -lengths.back());
816  glVertex2d(halfWidth, -lengths.back());
817  glVertex2d(halfWidth, 0);
818  glEnd();
819 #ifdef CHECK_ELEMENTCOUNTER
820  myVertexCounter += 4;
821 #endif
822  }
823  // pop three draw matrix
825  }
827 }
828 
829 void
831  const std::vector<double>& rots,
832  const std::vector<double>& lengths,
833  double maxLength, double spacing,
834  double halfWidth, bool cl, bool cr, bool lefthand, double scale) {
835 
836  double mw = (halfWidth + SUMO_const_laneMarkWidth * (cl ? 0.6 : 0.2)) * scale;
837  double mw2 = (halfWidth - SUMO_const_laneMarkWidth * (cr ? 0.6 : 0.2)) * scale;
838  if (cl || cr) {
839  if (lefthand) {
840  mw *= -1;
841  mw2 *= -1;
842  }
843  int e = (int) geom.size() - 1;
844  for (int i = 0; i < e; ++i) {
846  glTranslated(geom[i].x(), geom[i].y(), 2.1);
847  glRotated(rots[i], 0, 0, 1);
848  for (double t = 0; t < lengths[i]; t += spacing) {
849  const double length = MIN2((double)maxLength, lengths[i] - t);
850  glBegin(GL_QUADS);
851  glVertex2d(-mw, -t);
852  glVertex2d(-mw, -t - length);
853  glVertex2d(-mw2, -t - length);
854  glVertex2d(-mw2, -t);
855  glEnd();
856 #ifdef CHECK_ELEMENTCOUNTER
857  myVertexCounter += 4;
858 #endif
859  if (!cl || !cr) {
860  // draw inverse marking between asymmetrical lane markings
861  const double length2 = MIN2((double)6, lengths[i] - t);
862  glBegin(GL_QUADS);
863  glVertex2d(-halfWidth + 0.02, -t - length2);
864  glVertex2d(-halfWidth + 0.02, -t - length);
865  glVertex2d(-halfWidth - 0.02, -t - length);
866  glVertex2d(-halfWidth - 0.02, -t - length2);
867  glEnd();
868 #ifdef CHECK_ELEMENTCOUNTER
869  myVertexCounter += 4;
870 #endif
871  }
872  }
874  }
875  }
876 }
877 
878 
879 void
880 GLHelper::debugVertices(const PositionVector& shape, const GUIVisualizationTextSettings& settings, double scale, double layer) {
881  RGBColor color = RGBColor::randomHue();
882  for (int i = 0; i < (int)shape.size(); ++i) {
883  drawTextBox(toString(i), shape[i], layer,
884  settings.scaledSize(scale),
885  color,
886  settings.bgColor,
888  0, 0, 0.2);
889  }
890 }
891 
892 
893 void
897  // draw on top
898  glTranslated(0, 0, 1024);
899  drawLine(Position(b.xmin(), b.ymax()), Position(b.xmax(), b.ymax()));
900  drawLine(Position(b.xmax(), b.ymax()), Position(b.xmax(), b.ymin()));
901  drawLine(Position(b.xmax(), b.ymin()), Position(b.xmin(), b.ymin()));
902  drawLine(Position(b.xmin(), b.ymin()), Position(b.xmin(), b.ymax()));
904 }
905 
906 
907 /****************************************************************************/
void CALLBACK combCallback(GLdouble coords[3], GLdouble *vertex_data[4], GLfloat weight[4], GLdouble **dataOut)
Definition: GLHelper.cpp:71
#define CIRCLE_RESOLUTION
Definition: GLHelper.cpp:49
#define CALLBACK
Definition: GLHelper.cpp:54
#define DEG2RAD(x)
Definition: GeomHelper.h:35
#define RAD2DEG(x)
Definition: GeomHelper.h:36
#define WRITE_WARNING(msg)
Definition: MsgHandler.h:265
#define TL(string)
Definition: MsgHandler.h:282
static unsigned int data_font_Roboto_Medium_ttf_len
Definition: Roboto.h:22
static unsigned char data_font_Roboto_Medium_ttf[]
Definition: Roboto.h:24
T MIN4(T a, T b, T c, T d)
Definition: StdDefs.h:98
#define UNUSED_PARAMETER(x)
Definition: StdDefs.h:30
T MIN2(T a, T b)
Definition: StdDefs.h:71
const double SUMO_const_laneMarkWidth
Definition: StdDefs.h:51
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition: ToString.h:46
A class that stores a 2D geometrical boundary.
Definition: Boundary.h:39
double ymin() const
Returns minimum y-coordinate.
Definition: Boundary.cpp:130
double xmin() const
Returns minimum x-coordinate.
Definition: Boundary.cpp:118
double ymax() const
Returns maximum y-coordinate.
Definition: Boundary.cpp:136
double xmax() const
Returns maximum x-coordinate.
Definition: Boundary.cpp:124
static void drawFilledPoly(const PositionVector &v, bool close)
Draws a filled polygon described by the list of points.
Definition: GLHelper.cpp:203
static void drawBoundary(const Boundary &b)
Draw a boundary (used for debugging)
Definition: GLHelper.cpp:894
static void drawFilledPolyTesselated(const PositionVector &v, bool close)
Draws a filled polygon described by the list of points.
Definition: GLHelper.cpp:228
static void drawTextBox(const std::string &text, const Position &pos, const double layer, const double size, const RGBColor &txtColor=RGBColor::BLACK, const RGBColor &bgColor=RGBColor::WHITE, const RGBColor &borderColor=RGBColor::BLACK, const double angle=0, const double relBorder=0.05, const double relMargin=0.5, const int align=0)
draw Text box with given parameters
Definition: GLHelper.cpp:733
static void resetVertexCounter()
reset vertex counter
Definition: GLHelper.cpp:175
static std::vector< std::pair< double, double > > myCircleCoords
Storage for precomputed sin/cos-values describing a circle.
Definition: GLHelper.h:409
static void drawLine(const Position &beg, double rot, double visLength)
Draws a thin line.
Definition: GLHelper.cpp:421
static void setColor(const RGBColor &c)
Sets the gl-color to this value.
Definition: GLHelper.cpp:583
static void drawFilledCircle(double width, int steps=8)
Draws a filled circle around (0,0)
Definition: GLHelper.cpp:498
static struct FONScontext * myFont
Font context.
Definition: GLHelper.h:412
static void drawTriangleAtEnd(const Position &p1, const Position &p2, double tLength, double tWidth, const double extraOffset=0)
Draws a triangle at the end of the given line.
Definition: GLHelper.cpp:558
static void drawTextAtEnd(const std::string &text, const PositionVector &shape, double x, const GUIVisualizationTextSettings &settings, const double scale)
draw text and the end of shape
Definition: GLHelper.cpp:767
static void resetFont()
to be called when the font context is invalidated
Definition: GLHelper.cpp:600
static void pushName(unsigned int name)
push Name
Definition: GLHelper.cpp:139
static void checkCounterMatrix()
check counter matrix (for debug purposes)
Definition: GLHelper.cpp:181
static void drawOutlineCircle(double width, double iwidth, int steps=8)
Draws an unfilled circle around (0,0)
Definition: GLHelper.cpp:525
static const std::vector< RGBColor > & getDottedcontourColors(const int size)
get dotted contour colors (black and white). Vector will be automatically increased if current size i...
Definition: GLHelper.cpp:665
static std::vector< RGBColor > myDottedcontourColors
static vector with a list of alternated black/white colors (used for contours)
Definition: GLHelper.h:419
static int angleLookup(double angleDeg)
normalize angle for lookup in myCircleCoords
Definition: GLHelper.cpp:105
static double getTextWidth(const std::string &text, double size)
get required width of text
Definition: GLHelper.cpp:679
static int myMatrixCounter
matrix counter (for debug purposes)
Definition: GLHelper.h:397
static void popMatrix()
pop matrix
Definition: GLHelper.cpp:130
static void drawBoxLines(const PositionVector &geom, const std::vector< double > &rots, const std::vector< double > &lengths, double width, int cornerDetail=0, double offset=0)
Draws thick lines.
Definition: GLHelper.cpp:329
static int myMatrixCounterDebug
matrix counter (for debug purposes)
Definition: GLHelper.h:403
static RGBColor getColor()
gets the gl-color
Definition: GLHelper.cpp:589
static int getMatrixCounter()
get matrix counter
Definition: GLHelper.cpp:157
static void drawCrossTies(const PositionVector &geom, const std::vector< double > &rots, const std::vector< double > &lengths, double length, double spacing, double halfWidth, bool drawForSelection)
draw crossties for railroads or pedestrian crossings
Definition: GLHelper.cpp:785
static const std::vector< std::pair< double, double > > & getCircleCoords()
Storage for precomputed sin/cos-values describing a circle.
Definition: GLHelper.cpp:91
static void drawBoxLine(const Position &beg, double rot, double visLength, double width, double offset=0)
Draws a thick line.
Definition: GLHelper.cpp:277
static void checkCounterName()
check counter name (for debug purposes)
Definition: GLHelper.cpp:192
static void debugVertices(const PositionVector &shape, const GUIVisualizationTextSettings &settings, double scale, double layer=1024)
draw vertex numbers for the given shape (in a random color)
Definition: GLHelper.cpp:880
static void popName()
pop Name
Definition: GLHelper.cpp:148
static bool rightTurn(double angle1, double angle2)
whether the road makes a right turn (or goes straight)
Definition: GLHelper.cpp:316
static int myNameCounter
name counter
Definition: GLHelper.h:406
static void pushMatrix()
push matrix
Definition: GLHelper.cpp:117
static void setGL2PS(bool active=true)
set GL2PS
Definition: GLHelper.cpp:607
static int getVertexCounter()
get vertex counter
Definition: GLHelper.cpp:169
static void drawInverseMarkings(const PositionVector &geom, const std::vector< double > &rots, const std::vector< double > &lengths, double maxLength, double spacing, double halfWidth, bool cl, bool cr, bool lefthand, double scale)
@bried draw the space between markings (in road color)
Definition: GLHelper.cpp:830
static bool myGL2PSActive
whether we are currently rendering for gl2ps
Definition: GLHelper.h:416
static void drawText(const std::string &text, const Position &pos, const double layer, const double size, const RGBColor &col=RGBColor::BLACK, const double angle=0, const int align=0, double width=-1)
Definition: GLHelper.cpp:685
static void drawSpaceOccupancies(const double exaggeration, const Position &pos, const double rotation, const double width, const double length, const bool vehicle)
draw
Definition: GLHelper.cpp:613
static bool initFont()
init myFont
Definition: GLHelper.cpp:651
static double myFontSize
Definition: GLHelper.h:413
static int myVertexCounter
matrix counter (for debug purposes)
Definition: GLHelper.h:400
static void drawTextSettings(const GUIVisualizationTextSettings &settings, const std::string &text, const Position &pos, const double scale, const double angle=0, const double layer=2048, const int align=0)
Definition: GLHelper.cpp:716
static void resetMatrixCounter()
reset matrix counter
Definition: GLHelper.cpp:163
static double naviDegree(const double angle)
Definition: GeomHelper.cpp:192
A point in 2D or 3D with translation and scaling methods.
Definition: Position.h:37
double distanceTo(const Position &p2) const
returns the euclidean distance in 3 dimension
Definition: Position.h:242
double x() const
Returns the x-position.
Definition: Position.h:55
void add(const Position &pos)
Adds the given position to this one.
Definition: Position.h:125
double z() const
Returns the z-position.
Definition: Position.h:65
double angleTo2D(const Position &other) const
returns the angle in the plane of the vector pointing from here to the other position
Definition: Position.h:262
double y() const
Returns the y-position.
Definition: Position.h:60
A list of positions.
Position positionAtOffset(double pos, double lateralOffset=0) const
Returns the position at the given length.
static const RGBColor WHITE
Definition: RGBColor.h:192
unsigned char red() const
Returns the red-amount of the color.
Definition: RGBColor.cpp:74
unsigned char alpha() const
Returns the alpha-amount of the color.
Definition: RGBColor.cpp:92
static const RGBColor INVISIBLE
Definition: RGBColor.h:195
unsigned char green() const
Returns the green-amount of the color.
Definition: RGBColor.cpp:80
unsigned char blue() const
Returns the blue-amount of the color.
Definition: RGBColor.cpp:86
static const RGBColor BLACK
Definition: RGBColor.h:193
static const RGBColor MAGENTA
Definition: RGBColor.h:190
static RGBColor randomHue(double s=1, double v=1)
Return color with random hue.
Definition: RGBColor.cpp:403
@ FONS_ZERO_BOTTOMLEFT
Definition: fontstash.h:37
FONS_DEF void fonsSetSize(FONScontext *s, float size)
FONS_DEF float fonsDrawText(FONScontext *s, float x, float y, const char *string, const char *end)
FONS_DEF float fonsTextBounds(FONScontext *s, float x, float y, const char *string, const char *end, float *bounds)
@ FONS_ALIGN_MIDDLE
Definition: fontstash.h:47
@ FONS_ALIGN_CENTER
Definition: fontstash.h:43
FONS_DEF void fonsSetColor(FONScontext *s, unsigned int color)
FONS_DEF void fonsSetAlign(FONScontext *s, int align)
FONS_DEF int fonsAddFontMem(FONScontext *s, const char *name, unsigned char *data, int ndata, int freeData)
FONS_DEF void fonsSetFont(FONScontext *s, int font)
struct FONScontext FONScontext
Definition: fontstash.h:95
unsigned int glfonsRGBA(unsigned char r, unsigned char g, unsigned char b, unsigned char a)
void glfonsDelete(FONScontext *ctx)
FONScontext * glfonsCreate(int width, int height, int flags)
NLOHMANN_BASIC_JSON_TPL_DECLARATION void swap(nlohmann::NLOHMANN_BASIC_JSON_TPL &j1, nlohmann::NLOHMANN_BASIC_JSON_TPL &j2) noexcept(//NOLINT(readability-inconsistent-declaration-parameter-name) is_nothrow_move_constructible< nlohmann::NLOHMANN_BASIC_JSON_TPL >::value &&//NOLINT(misc-redundant-expression) is_nothrow_move_assignable< nlohmann::NLOHMANN_BASIC_JSON_TPL >::value)
exchanges the values of two JSON objects
Definition: json.hpp:21884
RGBColor bgColor
background text color
double scaledSize(double scale, double constFactor=0.1) const
get scale size