Eclipse SUMO - Simulation of Urban MObility
Loading...
Searching...
No Matches
GLHelper.cpp
Go to the documentation of this file.
1/****************************************************************************/
2// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3// Copyright (C) 2001-2024 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>
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
65std::vector<std::pair<double, double> > GLHelper::myCircleCoords;
66std::vector<RGBColor> GLHelper::myDottedcontourColors;
68double GLHelper::myFontSize = 50.0;
69bool GLHelper::myGL2PSActive = false;
70
71void 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
90const 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
104int
105GLHelper::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
116void
118 glPushMatrix();
119 // update counters
120#ifdef CHECK_ELEMENTCOUNTER
122#endif
123#ifdef CHECK_PUSHPOP
125#endif
126}
127
128
129void
131 glPopMatrix();
132#ifdef CHECK_PUSHPOP
134#endif
135}
136
137
138void
139GLHelper::pushName(unsigned int name) {
140 glPushName(name);
141#ifdef CHECK_PUSHPOP
143#endif
144}
145
146
147void
149 glPopName();
150#ifdef CHECK_PUSHPOP
152#endif
153}
154
155
156int
160
161
162void
166
167
168int
172
173
174void
178
179
180void
182#ifdef CHECK_PUSHPOP
183 if (myMatrixCounterDebug != 0) {
184 WRITE_WARNING("invalid matrix counter. Check that number of pushMatrix and popMatrix functions calls are the same");
185 }
187#endif
188}
189
190
191void
193#ifdef CHECK_PUSHPOP
194 if (myNameCounter != 0) {
195 WRITE_WARNING("invalid Name counter. Check that number of pushName and popName functions calls are the same");
196 }
197 myNameCounter = 0;
198#endif
199}
200
201
202void
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
214#endif
215 }
216 if (close) {
217 const Position& p = *(v.begin());
218 glVertex2d(p.x(), p.y());
219#ifdef CHECK_ELEMENTCOUNTER
221#endif
222 }
223 glEnd();
224}
225
226
227void
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
276void
277GLHelper::drawRectangle(const Position& center, const double width, const double height) {
278 const double halfWidth = width * 0.5;
279 const double halfHeight = height * 0.5;
281 glTranslated(center.x(), center.y(), 0);
282 glBegin(GL_QUADS);
283 glVertex2d(-halfWidth, halfHeight);
284 glVertex2d(-halfWidth, -halfHeight);
285 glVertex2d(halfWidth, -halfHeight);
286 glVertex2d(halfWidth, halfHeight);
287 glEnd();
289#ifdef CHECK_ELEMENTCOUNTER
290 myVertexCounter += 4;
291#endif
292}
293
294void
295GLHelper::drawBoxLine(const Position& beg, double rot, double visLength,
296 double width, double offset) {
298 glTranslated(beg.x(), beg.y(), 0);
299 glRotated(rot, 0, 0, 1);
300 glBegin(GL_QUADS);
301 glVertex2d(-width - offset, 0);
302 glVertex2d(-width - offset, -visLength);
303 glVertex2d(width - offset, -visLength);
304 glVertex2d(width - offset, 0);
305 glEnd();
307#ifdef CHECK_ELEMENTCOUNTER
308 myVertexCounter += 4;
309#endif
310}
311
312
313void
314GLHelper::drawBoxLine(const Position& beg1, const Position& beg2,
315 double rot, double visLength,
316 double width) {
318 glTranslated((beg2.x() + beg1.x())*.5, (beg2.y() + beg1.y())*.5, 0);
319 glRotated(rot, 0, 0, 1);
320 glBegin(GL_QUADS);
321 glVertex2d(-width, 0);
322 glVertex2d(-width, -visLength);
323 glVertex2d(width, -visLength);
324 glVertex2d(width, 0);
325 glEnd();
327#ifdef CHECK_ELEMENTCOUNTER
328 myVertexCounter += 4;
329#endif
330}
331
332
333bool
334GLHelper::rightTurn(double angle1, double angle2) {
335 double delta = angle2 - angle1;
336 while (delta > 180) {
337 delta -= 360;
338 }
339 while (delta < -180) {
340 delta += 360;
341 }
342 return delta <= 0;
343}
344
345
346void
348 const std::vector<double>& rots,
349 const std::vector<double>& lengths,
350 double width, int cornerDetail, double offset) {
351 // draw the lane
352 int e = (int) geom.size() - 1;
353 for (int i = 0; i < e; i++) {
354 drawBoxLine(geom[i], rots[i], lengths[i], width, offset);
355 }
356 // draw the corner details
357 if (cornerDetail > 0) {
358 for (int i = 1; i < e; i++) {
360 glTranslated(geom[i].x(), geom[i].y(), 0.1);
361 double angleBeg = -rots[i - 1];
362 double angleEnd = 180 - rots[i];
363 if (rightTurn(rots[i - 1], rots[i])) {
364 std::swap(angleBeg, angleEnd);
365 }
366 // only draw the missing piece
367 angleBeg -= 90;
368 angleEnd += 90;
369 // avoid drawing more than 360 degrees
370 if (angleEnd - angleBeg > 360) {
371 angleBeg += 360;
372 }
373 if (angleEnd - angleBeg < -360) {
374 angleEnd += 360;
375 }
376 // draw the right way around
377 if (angleEnd > angleBeg) {
378 angleEnd -= 360;
379 }
380 drawFilledCircle(width + offset, cornerDetail, angleBeg, angleEnd);
382 }
383 }
384}
385
386
387void
389 const std::vector<double>& rots,
390 const std::vector<double>& lengths,
391 const std::vector<RGBColor>& cols,
392 double width, int cornerDetail, double offset) {
393 int e = (int) geom.size() - 1;
394 for (int i = 0; i < e; i++) {
395 setColor(cols[i]);
396 drawBoxLine(geom[i], rots[i], lengths[i], width, offset);
397 }
398 if (cornerDetail > 0) {
399 for (int i = 1; i < e; i++) {
401 setColor(cols[i]);
402 glTranslated(geom[i].x(), geom[i].y(), 0);
403 drawFilledCircle(width, cornerDetail);
405 }
406 }
407}
408
409
410void
412 const PositionVector& geom2,
413 const std::vector<double>& rots,
414 const std::vector<double>& lengths,
415 double width) {
416 int minS = (int) MIN4(rots.size(), lengths.size(), geom1.size(), geom2.size());
417 for (int i = 0; i < minS; i++) {
418 GLHelper::drawBoxLine(geom1[i], geom2[i], rots[i], lengths[i], width);
419 }
420}
421
422
423void
424GLHelper::drawBoxLines(const PositionVector& geom, double width) {
425 int e = (int) geom.size() - 1;
426 for (int i = 0; i < e; i++) {
427 const Position& f = geom[i];
428 const Position& s = geom[i + 1];
429 drawBoxLine(f,
430 RAD2DEG(atan2((s.x() - f.x()), (f.y() - s.y()))),
431 f.distanceTo(s),
432 width);
433 }
434}
435
436
437void
438GLHelper::drawLine(const Position& beg, double rot, double visLength) {
440 glTranslated(beg.x(), beg.y(), 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
453void
454GLHelper::drawLine(const Position& beg1, const Position& beg2,
455 double rot, double visLength) {
457 glTranslated((beg2.x() + beg1.x())*.5, (beg2.y() + beg1.y())*.5, 0);
458 glRotated(rot, 0, 0, 1);
459 glBegin(GL_LINES);
460 glVertex2d(0, 0);
461 glVertex2d(0, -visLength);
462 glEnd();
464#ifdef CHECK_ELEMENTCOUNTER
465 myVertexCounter += 2;
466#endif
467}
468
469
470
471void
473 glBegin(GL_LINES);
474 int e = (int) v.size() - 1;
475 for (int i = 0; i < e; ++i) {
476 glVertex2d(v[i].x(), v[i].y());
477 glVertex2d(v[i + 1].x(), v[i + 1].y());
478#ifdef CHECK_ELEMENTCOUNTER
479 myVertexCounter += 2;
480#endif
481 }
482 glEnd();
483}
484
485
486void
487GLHelper::drawLine(const PositionVector& v, const std::vector<RGBColor>& cols) {
488 glBegin(GL_LINES);
489 int e = (int) v.size() - 1;
490 for (int i = 0; i < e; ++i) {
491 setColor(cols[i]);
492 glVertex2d(v[i].x(), v[i].y());
493 glVertex2d(v[i + 1].x(), v[i + 1].y());
494#ifdef CHECK_ELEMENTCOUNTER
495 myVertexCounter += 2;
496#endif
497 }
498 glEnd();
499}
500
501
502void
503GLHelper::drawLine(const Position& beg, const Position& end) {
504 glBegin(GL_LINES);
505 glVertex2d(beg.x(), beg.y());
506 glVertex2d(end.x(), end.y());
507 glEnd();
508#ifdef CHECK_ELEMENTCOUNTER
509 myVertexCounter += 2;
510#endif
511}
512
513
514void
516 double beg, double end) {
517 // get current resolution level
518 switch (d) {
520 drawFilledCircle(radius, 32, beg, end);
521 break;
523 drawFilledCircle(radius, 16, beg, end);
524 break;
526 drawFilledCircle(radius, 8, beg, end);
527 break;
529 drawFilledCircleDetailled(d, radius);
530 break;
531 default:
532 // nothing to draw
533 break;
534 }
535}
536
537
538void
540 // get current resolution level
541 switch (d) {
543 drawFilledCircle(radius, 32);
544 break;
546 drawFilledCircle(radius, 16);
547 break;
549 drawFilledCircle(radius, 8);
550 break;
551 default:
552 // draw only a square
554 glBegin(GL_QUADS);
555 glVertex2d(-radius, radius);
556 glVertex2d(-radius, -radius);
557 glVertex2d(radius, -radius);
558 glVertex2d(radius, radius);
559 glEnd();
561#ifdef CHECK_ELEMENTCOUNTER
562 myVertexCounter += 4;
563#endif
564 break;
565 }
566}
567
568void
569GLHelper::drawFilledCircle(double const radius, int const steps) {
570 drawFilledCircle(radius, steps, 0, 360);
571}
572
573
574void
575GLHelper::drawFilledCircle(double radius, int steps, double beg, double end) {
576 const double inc = (end - beg) / (double)steps;
577 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
578 std::pair<double, double> p1 = getCircleCoords().at(angleLookup(beg));
579
580 for (int i = 0; i <= steps; ++i) {
581 const std::pair<double, double>& p2 = getCircleCoords().at(angleLookup(beg + i * inc));
582 glBegin(GL_TRIANGLES);
583 glVertex2d(p1.first * radius, p1.second * radius);
584 glVertex2d(p2.first * radius, p2.second * radius);
585 glVertex2d(0, 0);
586 glEnd();
587 p1 = p2;
588#ifdef CHECK_ELEMENTCOUNTER
589 myVertexCounter += 3;
590#endif
591 }
592}
593
594
595void
596GLHelper::drawOutlineCircle(double radius, double iRadius, int steps) {
597 drawOutlineCircle(radius, iRadius, steps, 0, 360);
598}
599
600
601void
602GLHelper::drawOutlineCircle(double radius, double iRadius, int steps,
603 double beg, double end) {
604 const double inc = (end - beg) / (double)steps;
605 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
606 std::pair<double, double> p1 = getCircleCoords().at(angleLookup(beg));
607
608 for (int i = 0; i <= steps; ++i) {
609 const std::pair<double, double>& p2 = getCircleCoords().at(angleLookup(beg + i * inc));
610 glBegin(GL_TRIANGLES);
611 glVertex2d(p1.first * radius, p1.second * radius);
612 glVertex2d(p2.first * radius, p2.second * radius);
613 glVertex2d(p2.first * iRadius, p2.second * iRadius);
614
615 glVertex2d(p2.first * iRadius, p2.second * iRadius);
616 glVertex2d(p1.first * iRadius, p1.second * iRadius);
617 glVertex2d(p1.first * radius, p1.second * radius);
618
619 glEnd();
620 p1 = p2;
621#ifdef CHECK_ELEMENTCOUNTER
622 myVertexCounter += 6;
623#endif
624 }
625}
626
627
628void
629GLHelper::drawTriangleAtEnd(const Position& p1, const Position& p2, double tLength,
630 double tWidth, const double extraOffset) {
631 const double length = p1.distanceTo(p2);
632 if (length < tLength) {
633 tWidth *= length / tLength;
634 tLength = length;
635 }
636 Position rl(PositionVector::positionAtOffset(p1, p2, length - tLength));
638 glTranslated(rl.x(), rl.y(), 0);
639 glRotated(-GeomHelper::naviDegree(p1.angleTo2D(p2)), 0, 0, 1);
640 glTranslated(0, extraOffset, 0);
641 glBegin(GL_TRIANGLES);
642 glVertex2d(0, tLength);
643 glVertex2d(-tWidth, 0);
644 glVertex2d(+tWidth, 0);
645 glEnd();
647#ifdef CHECK_ELEMENTCOUNTER
648 myVertexCounter += 3;
649#endif
650}
651
652
653void
655 glColor4ub(c.red(), c.green(), c.blue(), c.alpha());
656}
657
658
661 GLdouble current[4];
662 glGetDoublev(GL_CURRENT_COLOR, current);
663 return RGBColor(static_cast<unsigned char>(current[0] * 255. + 0.5),
664 static_cast<unsigned char>(current[1] * 255. + 0.5),
665 static_cast<unsigned char>(current[2] * 255. + 0.5),
666 static_cast<unsigned char>(current[3] * 255. + 0.5));
667}
668
669
670void
673 myFont = nullptr;
674}
675
676
677void
678GLHelper::setGL2PS(bool active) {
679 myGL2PSActive = active;
680}
681
682
683void
684GLHelper::drawSpaceOccupancies(const double exaggeration, const Position& pos, const double rotation,
685 const double width, const double length, const bool vehicle) {
686 // declare colors
687 const RGBColor red(255, 0, 0, 255);
688 const RGBColor green(0, 255, 0, 255);
689 // declare geometry
690 PositionVector geom;
691 const double w = width / 2. - 0.1 * exaggeration;
692 const double h = length;
693 // set geometry
694 geom.push_back(Position(-w, +0, 0.));
695 geom.push_back(Position(+w, +0, 0.));
696 geom.push_back(Position(+w, +h, 0.));
697 geom.push_back(Position(-w, +h, 0.));
698 geom.push_back(Position(-w, +0, 0.));
699 /*
700 geom.push_back(Position(pos.x(), pos.y(), pos.z()));
701 geom.push_back(Position(pos.x() + (*l).second.myWidth, pos.y(), pos.z()));
702 geom.push_back(Position(pos.x() + (*l).second.myWidth, pos.y() - (*l).second.myLength, pos.z()));
703 geom.push_back(Position(pos.x(), pos.y() - (*l).second.myLength, pos.z()));
704 geom.push_back(Position(pos.x(), pos.y(), pos.z()));
705 */
706 // push matrix
708 // translate
709 glTranslated(pos.x(), pos.y(), pos.z());
710 // rotate
711 glRotated(rotation, 0, 0, 1);
712 // set color
713 GLHelper::setColor(vehicle ? green : red);
714 // draw box lines
715 GLHelper::drawBoxLines(geom, 0.1 * exaggeration);
716 // pop matrix
718}
719
720
721bool
723 if (myFont == nullptr) {
725 if (myFont != nullptr) {
727 fonsSetFont(myFont, fontNormal);
729 }
730 }
731 return myFont != nullptr;
732}
733
734
735const std::vector<RGBColor>&
737 // check if more colors has to be added
738 while ((int)myDottedcontourColors.size() < size) {
741 } else {
743 }
744 }
746}
747
748
749double
750GLHelper::getTextWidth(const std::string& text, double size) {
751 return size / myFontSize * fonsTextBounds(myFont, 0, 0, text.c_str(), nullptr, nullptr);
752}
753
754
755void
756GLHelper::drawText(const std::string& text, const Position& pos, const double layer, const double size,
757 const RGBColor& col, const double angle, const int align, double width) {
758 if (width <= 0) {
759 width = size;
760 }
761 if (!initFont()) {
762 return;
763 }
765 glAlphaFunc(GL_GREATER, 0.5);
766 glEnable(GL_ALPHA_TEST);
767#ifdef HAVE_GL2PS
768 if (myGL2PSActive) {
769 glRasterPos3d(pos.x(), pos.y(), layer);
770 GLfloat color[] = {col.red() / 255.f, col.green() / 255.f, col.blue() / 255.f, col.alpha() / 255.f};
771 gl2psTextOptColor(text.c_str(), "Roboto", 10, align == 0 ? GL2PS_TEXT_C : align, (GLfloat) - angle, color);
773 return;
774 }
775#endif
776 glTranslated(pos.x(), pos.y(), layer);
777 glScaled(width / myFontSize, size / myFontSize, 1.);
778 glRotated(-angle, 0, 0, 1);
780 fonsSetColor(myFont, glfonsRGBA(col.red(), col.green(), col.blue(), col.alpha()));
781 fonsDrawText(myFont, 0., 0., text.c_str(), nullptr);
783}
784
785
786void
788 const GUIVisualizationTextSettings& settings,
789 const std::string& text, const Position& pos,
790 const double scale,
791 const double angle,
792 const double layer,
793 const int align) {
794 drawTextBox(text, pos, layer,
795 settings.scaledSize(scale),
796 settings.color,
797 settings.bgColor,
799 angle, 0, 0.2, align);
800}
801
802
803void
804GLHelper::drawTextBox(const std::string& text, const Position& pos,
805 const double layer, const double size,
806 const RGBColor& txtColor, const RGBColor& bgColor, const RGBColor& borderColor,
807 const double angle,
808 const double relBorder,
809 const double relMargin,
810 const int align) {
811 if (!initFont()) {
812 return;
813 };
814 if (bgColor.alpha() != 0) {
815 const double boxAngle = 90;
816 const double stringWidth = size / myFontSize * fonsTextBounds(myFont, 0, 0, text.c_str(), nullptr, nullptr);
817 const double borderWidth = size * relBorder;
818 const double boxHeight = size * (0.32 + 0.6 * relMargin);
819 const double boxWidth = stringWidth + size * relMargin;
821 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
822 glTranslated(pos.x(), pos.y(), layer);
823 glRotated(-angle, 0, 0, 1);
824 Position left(-boxWidth * 0.5, 0);
825 setColor(borderColor);
826 drawBoxLine(left, boxAngle, boxWidth, boxHeight);
827 left.add(borderWidth * 1.5, 0);
828 setColor(bgColor);
829 glTranslated(0, 0, 0.01);
830 drawBoxLine(left, boxAngle, boxWidth - 3 * borderWidth, boxHeight - 2 * borderWidth);
832 }
833 drawText(text, pos, layer + 0.02, size, txtColor, angle, align);
834}
835
836
837void
838GLHelper::drawTextAtEnd(const std::string& text, const PositionVector& shape, double x,
839 const GUIVisualizationTextSettings& settings, const double scale) {
841 const Position& end = shape.back();
842 const Position& f = shape[-2];
843 const double rot = RAD2DEG(atan2((end.x() - f.x()), (f.y() - end.y())));
844 glTranslated(end.x(), end.y(), 0);
845 glRotated(rot, 0, 0, 1);
846 drawTextBox(text, Position(x, 0.26), 0,
847 settings.scaledSize(scale, 0.01),
848 settings.color,
849 settings.bgColor,
851 180, 0, 0.2);
853}
854
855
856void
857GLHelper::drawCrossTies(const PositionVector& geom, const std::vector<double>& rots,
858 const std::vector<double>& lengths, double length, double spacing,
859 double halfWidth, double offset, bool lessDetail) {
861 // draw on top of of the white area between the rails
862 glTranslated(0, 0, 0.1);
863 int e = (int) geom.size() - 1;
864 for (int i = 0; i < e; ++i) {
866 glTranslated(geom[i].x(), geom[i].y(), 0.0);
867 glRotated(rots[i], 0, 0, 1);
868 // draw crossing depending of detail
869 if (!lessDetail) {
870 for (double t = 0; t < lengths[i]; t += spacing) {
871 glBegin(GL_QUADS);
872 glVertex2d(-halfWidth - offset, -t);
873 glVertex2d(-halfWidth - offset, -t - length);
874 glVertex2d(halfWidth - offset, -t - length);
875 glVertex2d(halfWidth - offset, -t);
876 glEnd();
877#ifdef CHECK_ELEMENTCOUNTER
878 myVertexCounter += 4;
879#endif
880 }
881 } else {
882 // only draw a single rectangle if it's being drawn only for selecting
883 glBegin(GL_QUADS);
884 glVertex2d(-halfWidth - offset, 0);
885 glVertex2d(-halfWidth - offset, -lengths.back());
886 glVertex2d(halfWidth - offset, -lengths.back());
887 glVertex2d(halfWidth - offset, 0);
888 glEnd();
889#ifdef CHECK_ELEMENTCOUNTER
890 myVertexCounter += 4;
891#endif
892 }
893 // pop three draw matrix
895 }
897}
898
899void
901 const std::vector<double>& rots,
902 const std::vector<double>& lengths,
903 double maxLength, double spacing,
904 double halfWidth, bool cl, bool cr, bool lefthand, double scale) {
905
906 double mw = (halfWidth + SUMO_const_laneMarkWidth * (cl ? 0.6 : 0.2)) * scale;
907 double mw2 = (halfWidth - SUMO_const_laneMarkWidth * (cr ? 0.6 : 0.2)) * scale;
908 if (cl || cr) {
909 if (lefthand) {
910 mw *= -1;
911 mw2 *= -1;
912 }
913 int e = (int) geom.size() - 1;
914 double offset = 0;
915 for (int i = 0; i < e; ++i) {
917 glTranslated(geom[i].x(), geom[i].y(), 2.1);
918 glRotated(rots[i], 0, 0, 1);
919 double t;
920 for (t = offset; t < lengths[i]; t += spacing) {
921 const double length = MIN2((double)maxLength, lengths[i] - t);
922 glBegin(GL_QUADS);
923 glVertex2d(-mw, -t);
924 glVertex2d(-mw, -t - length);
925 glVertex2d(-mw2, -t - length);
926 glVertex2d(-mw2, -t);
927 glEnd();
928#ifdef CHECK_ELEMENTCOUNTER
929 myVertexCounter += 4;
930#endif
931 if (!cl || !cr) {
932 // draw inverse marking between asymmetrical lane markings
933 const double length2 = MIN2((double)6, lengths[i] - t);
934 glBegin(GL_QUADS);
935 glVertex2d(-halfWidth + 0.02, -t - length2);
936 glVertex2d(-halfWidth + 0.02, -t - length);
937 glVertex2d(-halfWidth - 0.02, -t - length);
938 glVertex2d(-halfWidth - 0.02, -t - length2);
939 glEnd();
940#ifdef CHECK_ELEMENTCOUNTER
941 myVertexCounter += 4;
942#endif
943 }
944 }
945 offset = t - lengths[i] - spacing;
947 }
948 }
949}
950
951
952void
953GLHelper::debugVertices(const PositionVector& shape, const GUIVisualizationTextSettings& settings, double scale, double layer) {
954 for (int i = 0; i < (int)shape.size(); ++i) {
955 drawTextBox(toString(i), shape[i], layer,
956 settings.scaledSize(scale),
957 settings.color,
958 settings.bgColor,
960 0, 0, 0.2);
961 }
962}
963
964
965void
967 if (s.drawBoundaries) {
970 // draw on top
971 glTranslated(0, 0, 1024);
972 drawLine(Position(b.xmin(), b.ymax()), Position(b.xmax(), b.ymax()));
973 drawLine(Position(b.xmax(), b.ymax()), Position(b.xmax(), b.ymin()));
974 drawLine(Position(b.xmax(), b.ymin()), Position(b.xmin(), b.ymin()));
975 drawLine(Position(b.xmin(), b.ymin()), Position(b.xmin(), b.ymax()));
977 }
978}
979
980
981/****************************************************************************/
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:295
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:103
#define UNUSED_PARAMETER(x)
Definition StdDefs.h:30
T MIN2(T a, T b)
Definition StdDefs.h:76
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 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:804
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:436
static void drawLine(const Position &beg, double rot, double visLength)
Draws a thin line.
Definition GLHelper.cpp:438
static void setColor(const RGBColor &c)
Sets the gl-color to this value.
Definition GLHelper.cpp:654
static void drawOutlineCircle(double radius, double iRadius, int steps=8)
Draws an unfilled circle around (0,0)
Definition GLHelper.cpp:596
static struct FONScontext * myFont
Font context.
Definition GLHelper.h:439
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:629
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:838
static void resetFont()
to be called when the font context is invalidated
Definition GLHelper.cpp:671
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 drawFilledCircle(const double widradiusth, const int steps=8)
Draws a filled circle around (0,0)
Definition GLHelper.cpp:569
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:736
static std::vector< RGBColor > myDottedcontourColors
static vector with a list of alternated black/white colors (used for contours)
Definition GLHelper.h:446
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:750
static int myMatrixCounter
matrix counter (for debug purposes)
Definition GLHelper.h:424
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:347
static int myMatrixCounterDebug
matrix counter (for debug purposes)
Definition GLHelper.h:430
static void drawBoundary(const GUIVisualizationSettings &s, const Boundary &b)
Draw a boundary (used for debugging)
Definition GLHelper.cpp:966
static RGBColor getColor()
gets the gl-color
Definition GLHelper.cpp:660
static int getMatrixCounter()
get matrix counter
Definition GLHelper.cpp:157
static void drawRectangle(const Position &center, const double width, const double height)
Draws a rectangle line.
Definition GLHelper.cpp:277
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:295
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:953
static void drawFilledCircleDetailled(const GUIVisualizationSettings::Detail d, const double radius)
Draws a filled circle around (0,0) depending of level of detail.
Definition GLHelper.cpp:539
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:334
static int myNameCounter
name counter
Definition GLHelper.h:433
static void pushMatrix()
push matrix
Definition GLHelper.cpp:117
static void setGL2PS(bool active=true)
set GL2PS
Definition GLHelper.cpp:678
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:900
static bool myGL2PSActive
whether we are currently rendering for gl2ps
Definition GLHelper.h:443
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:756
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:684
static bool initFont()
init myFont
Definition GLHelper.cpp:722
static double myFontSize
Definition GLHelper.h:440
static int myVertexCounter
matrix counter (for debug purposes)
Definition GLHelper.h:427
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:787
static void drawCrossTies(const PositionVector &geom, const std::vector< double > &rots, const std::vector< double > &lengths, double length, double spacing, double halfWidth, double offset, bool lessDetail)
draw crossties for railroads or pedestrian crossings
Definition GLHelper.cpp:857
static void resetMatrixCounter()
reset matrix counter
Definition GLHelper.cpp:163
Stores the information about how to visualize structures.
bool drawBoundaries
enable or disable draw boundaries
static double naviDegree(const double angle)
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 dimensions
Definition Position.h:266
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:132
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 (in radians bet...
Definition Position.h:286
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
@ 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
#define CALLBACK
Definition fxexdefs.h:48
FONScontext * glfonsCreate(int width, int height, int flags)
unsigned int glfonsRGBA(unsigned char r, unsigned char g, unsigned char b, unsigned char a)
void glfonsDelete(FONScontext *ctx)
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