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-2025 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 <algorithm>
26#include <iostream>
27#include <fstream>
35#define FONTSTASH_IMPLEMENTATION // Expands implementation
36#ifdef _MSC_VER
37#pragma warning(disable: 4505 5219) // do not warn about unused functions and implicit float conversions
38#endif
39#if __GNUC__ > 3
40#pragma GCC diagnostic push
41#pragma GCC diagnostic ignored "-Wunused-function"
42#endif
45#define GLFONTSTASH_IMPLEMENTATION // Expands implementation
47#include <utils/geom/Boundary.h>
48#ifdef HAVE_GL2PS
49#include <gl2ps.h>
50#endif
51#include "Roboto.h"
52#include "GLHelper.h"
53
54#define CIRCLE_RESOLUTION (double)10 // inverse in degrees
55//#define CHECK_PUSHPOP // enable or disable check push and pop matrix/names
56//#define CHECK_ELEMENTCOUNTER // enable or disable element counter (for matrix and vertex)
57
58#ifndef CALLBACK
59#define CALLBACK
60#endif
61
62// ===========================================================================
63// static member definitions
64// ===========================================================================
65
70std::vector<std::pair<double, double> > GLHelper::myCircleCoords;
71std::vector<RGBColor> GLHelper::myDottedcontourColors;
73double GLHelper::myFontSize = 25.0;
74bool GLHelper::myGL2PSActive = false;
75
76void CALLBACK combCallback(GLdouble coords[3],
77 GLdouble* vertex_data[4],
78 GLfloat weight[4], GLdouble** dataOut) {
79 UNUSED_PARAMETER(weight);
80 UNUSED_PARAMETER(*vertex_data);
81 GLdouble* vertex;
82
83 vertex = (GLdouble*)malloc(7 * sizeof(GLdouble));
84
85 vertex[0] = coords[0];
86 vertex[1] = coords[1];
87 vertex[2] = coords[2];
88 *dataOut = vertex;
89}
90
91// ===========================================================================
92// method definitions
93// ===========================================================================
94
95const std::vector<std::pair<double, double> >&
97 // fill in first call
98 if (myCircleCoords.size() == 0) {
99 for (int i = 0; i <= (int)(360 * CIRCLE_RESOLUTION); ++i) {
100 const double x = (double) sin(DEG2RAD(i / CIRCLE_RESOLUTION));
101 const double y = (double) cos(DEG2RAD(i / CIRCLE_RESOLUTION));
102 myCircleCoords.push_back(std::pair<double, double>(x, y));
103 }
104 }
105 return myCircleCoords;
106}
107
108
109int
110GLHelper::angleLookup(double angleDeg) {
111 const int numCoords = (int)getCircleCoords().size() - 1;
112 int index = ((int)(floor(angleDeg * CIRCLE_RESOLUTION + 0.5))) % numCoords;
113 if (index < 0) {
114 index += numCoords;
115 }
116 assert(index >= 0);
117 return (int)index;
118}
119
120
121void
123 glPushMatrix();
124 // update counters
125#ifdef CHECK_ELEMENTCOUNTER
127#endif
128#ifdef CHECK_PUSHPOP
130#endif
131}
132
133
134void
136 glPopMatrix();
137#ifdef CHECK_PUSHPOP
139#endif
140}
141
142
143void
144GLHelper::pushName(unsigned int name) {
145 glPushName(name);
146#ifdef CHECK_PUSHPOP
148#endif
149}
150
151
152void
154 glPopName();
155#ifdef CHECK_PUSHPOP
157#endif
158}
159
160
161int
165
166
167void
171
172
173int
177
178
179void
183
184
185void
187#ifdef CHECK_PUSHPOP
188 if (myMatrixCounterDebug != 0) {
189 WRITE_WARNING("invalid matrix counter. Check that number of pushMatrix and popMatrix functions calls are the same");
190 }
192#endif
193}
194
195
196void
198#ifdef CHECK_PUSHPOP
199 if (myNameCounter != 0) {
200 WRITE_WARNING("invalid Name counter. Check that number of pushName and popName functions calls are the same");
201 }
202 myNameCounter = 0;
203#endif
204}
205
206
207void
209 if (v.size() == 0) {
210 return;
211 }
212 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
213 glBegin(GL_POLYGON);
214 for (PositionVector::const_iterator i = v.begin(); i != v.end(); i++) {
215 const Position& p = *i;
216 glVertex2d(p.x(), p.y());
217#ifdef CHECK_ELEMENTCOUNTER
219#endif
220 }
221 if (close) {
222 const Position& p = *(v.begin());
223 glVertex2d(p.x(), p.y());
224#ifdef CHECK_ELEMENTCOUNTER
226#endif
227 }
228 glEnd();
229}
230
231
232void
234 if (v.size() == 0) {
235 return;
236 }
237 GLUtesselator* tobj = gluNewTess();
238#ifdef _MSC_VER
239#pragma warning(push)
240#pragma warning(disable: 4191)
241#endif
242#if defined(__GNUC__) && __GNUC__ >= 8
243#pragma GCC diagnostic push
244#pragma GCC diagnostic ignored "-Wcast-function-type"
245#endif
246 gluTessCallback(tobj, GLU_TESS_VERTEX, (GLvoid(CALLBACK*)()) &glVertex3dv);
247 gluTessCallback(tobj, GLU_TESS_BEGIN, (GLvoid(CALLBACK*)()) &glBegin);
248 gluTessCallback(tobj, GLU_TESS_END, (GLvoid(CALLBACK*)()) &glEnd);
249 gluTessCallback(tobj, GLU_TESS_COMBINE, (GLvoid(CALLBACK*)()) &combCallback);
250#if defined(__GNUC__) && __GNUC__ >= 8
251#pragma GCC diagnostic pop
252#endif
253#ifdef _MSC_VER
254#pragma warning(pop)
255#endif
256 gluTessProperty(tobj, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_ODD);
257 gluTessBeginPolygon(tobj, nullptr);
258 gluTessBeginContour(tobj);
259 double* points = new double[(v.size() + int(close)) * 3];
260
261 for (int i = 0; i != (int)v.size(); ++i) {
262 points[3 * i] = v[i].x();
263 points[3 * i + 1] = v[i].y();
264 points[3 * i + 2] = 0;
265 gluTessVertex(tobj, points + 3 * i, points + 3 * i);
266 }
267 if (close) {
268 const int i = (int)v.size();
269 points[3 * i] = v[0].x();
270 points[3 * i + 1] = v[0].y();
271 points[3 * i + 2] = 0;
272 gluTessVertex(tobj, points + 3 * i, points + 3 * i);
273 }
274 gluTessEndContour(tobj);
275 gluTessEndPolygon(tobj);
276 gluDeleteTess(tobj);
277 delete[] points;
278}
279
280
281void
282GLHelper::drawRectangle(const Position& center, const double width, const double height) {
283 const double halfWidth = width * 0.5;
284 const double halfHeight = height * 0.5;
286 glTranslated(center.x(), center.y(), 0);
287 glBegin(GL_QUADS);
288 glVertex2d(-halfWidth, halfHeight);
289 glVertex2d(-halfWidth, -halfHeight);
290 glVertex2d(halfWidth, -halfHeight);
291 glVertex2d(halfWidth, halfHeight);
292 glEnd();
294#ifdef CHECK_ELEMENTCOUNTER
295 myVertexCounter += 4;
296#endif
297}
298
299void
300GLHelper::drawBoxLine(const Position& beg, double rot, double visLength,
301 double width, double offset) {
303 glTranslated(beg.x(), beg.y(), 0);
304 glRotated(rot, 0, 0, 1);
305 glBegin(GL_QUADS);
306 glVertex2d(-width - offset, 0);
307 glVertex2d(-width - offset, -visLength);
308 glVertex2d(width - offset, -visLength);
309 glVertex2d(width - offset, 0);
310 glEnd();
312#ifdef CHECK_ELEMENTCOUNTER
313 myVertexCounter += 4;
314#endif
315}
316
317
318void
319GLHelper::drawBoxLine(const Position& beg1, const Position& beg2,
320 double rot, double visLength,
321 double width) {
323 glTranslated((beg2.x() + beg1.x())*.5, (beg2.y() + beg1.y())*.5, 0);
324 glRotated(rot, 0, 0, 1);
325 glBegin(GL_QUADS);
326 glVertex2d(-width, 0);
327 glVertex2d(-width, -visLength);
328 glVertex2d(width, -visLength);
329 glVertex2d(width, 0);
330 glEnd();
332#ifdef CHECK_ELEMENTCOUNTER
333 myVertexCounter += 4;
334#endif
335}
336
337
338bool
339GLHelper::rightTurn(double angle1, double angle2) {
340 double delta = angle2 - angle1;
341 while (delta > 180) {
342 delta -= 360;
343 }
344 while (delta < -180) {
345 delta += 360;
346 }
347 return delta <= 0;
348}
349
350
351void
353 const std::vector<double>& rots,
354 const std::vector<double>& lengths,
355 double width, int cornerDetail, double offset) {
356 // draw the lane
357 int e = (int) geom.size() - 1;
358 for (int i = 0; i < e; i++) {
359 drawBoxLine(geom[i], rots[i], lengths[i], width, offset);
360 }
361 // draw the corner details
362 if (cornerDetail > 0) {
363 for (int i = 1; i < e; i++) {
365 glTranslated(geom[i].x(), geom[i].y(), 0.1);
366 double angleBeg = -rots[i - 1];
367 double angleEnd = 180 - rots[i];
368 if (rightTurn(rots[i - 1], rots[i])) {
369 std::swap(angleBeg, angleEnd);
370 }
371 // only draw the missing piece
372 angleBeg -= 90;
373 angleEnd += 90;
374 // avoid drawing more than 360 degrees
375 if (angleEnd - angleBeg > 360) {
376 angleBeg += 360;
377 }
378 if (angleEnd - angleBeg < -360) {
379 angleEnd += 360;
380 }
381 // draw the right way around
382 if (angleEnd > angleBeg) {
383 angleEnd -= 360;
384 }
385 drawFilledCircle(width + offset, cornerDetail, angleBeg, angleEnd);
387 }
388 }
389}
390
391
392void
394 const std::vector<double>& rots,
395 const std::vector<double>& lengths,
396 const std::vector<RGBColor>& cols,
397 double width, int cornerDetail, double offset) {
398 int e = (int) geom.size() - 1;
399 for (int i = 0; i < e; i++) {
400 setColor(cols[i]);
401 drawBoxLine(geom[i], rots[i], lengths[i], width, offset);
402 }
403 if (cornerDetail > 0) {
404 for (int i = 1; i < e; i++) {
406 setColor(cols[i]);
407 glTranslated(geom[i].x(), geom[i].y(), 0);
408 drawFilledCircle(width, cornerDetail);
410 }
411 }
412}
413
414
415void
417 const PositionVector& geom2,
418 const std::vector<double>& rots,
419 const std::vector<double>& lengths,
420 double width) {
421 int minS = (int) MIN4(rots.size(), lengths.size(), geom1.size(), geom2.size());
422 for (int i = 0; i < minS; i++) {
423 GLHelper::drawBoxLine(geom1[i], geom2[i], rots[i], lengths[i], width);
424 }
425}
426
427
428void
429GLHelper::drawBoxLines(const PositionVector& geom, double width) {
430 // first convert to GUIGeometry to avoid graphical errors with Z value (see #13992)
431 const auto geometry = GUIGeometry(geom);
432 drawBoxLines(geometry.getShape(), geometry.getShapeRotations(), geometry.getShapeLengths(), width);
433}
434
435
436void
437GLHelper::drawLine(const Position& beg, double rot, double visLength) {
439 glTranslated(beg.x(), beg.y(), 0);
440 glRotated(rot, 0, 0, 1);
441 glBegin(GL_LINES);
442 glVertex2d(0, 0);
443 glVertex2d(0, -visLength);
444 glEnd();
446#ifdef CHECK_ELEMENTCOUNTER
447 myVertexCounter += 2;
448#endif
449}
450
451
452void
453GLHelper::drawLine(const Position& beg1, const Position& beg2,
454 double rot, double visLength) {
456 glTranslated((beg2.x() + beg1.x())*.5, (beg2.y() + beg1.y())*.5, 0);
457 glRotated(rot, 0, 0, 1);
458 glBegin(GL_LINES);
459 glVertex2d(0, 0);
460 glVertex2d(0, -visLength);
461 glEnd();
463#ifdef CHECK_ELEMENTCOUNTER
464 myVertexCounter += 2;
465#endif
466}
467
468
469
470void
472 glBegin(GL_LINES);
473 int e = (int) v.size() - 1;
474 for (int i = 0; i < e; ++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
485void
486GLHelper::drawLine(const PositionVector& v, const std::vector<RGBColor>& cols) {
487 glBegin(GL_LINES);
488 int e = (int) v.size() - 1;
489 for (int i = 0; i < e; ++i) {
490 setColor(cols[i]);
491 glVertex2d(v[i].x(), v[i].y());
492 glVertex2d(v[i + 1].x(), v[i + 1].y());
493#ifdef CHECK_ELEMENTCOUNTER
494 myVertexCounter += 2;
495#endif
496 }
497 glEnd();
498}
499
500
501void
502GLHelper::drawLine(const Position& beg, const Position& end) {
503 glBegin(GL_LINES);
504 glVertex2d(beg.x(), beg.y());
505 glVertex2d(end.x(), end.y());
506 glEnd();
507#ifdef CHECK_ELEMENTCOUNTER
508 myVertexCounter += 2;
509#endif
510}
511
512
513void
515 double beg, double end) {
516 // get current resolution level
517 switch (d) {
519 drawFilledCircle(radius, 32, beg, end);
520 break;
522 drawFilledCircle(radius, 16, beg, end);
523 break;
525 drawFilledCircle(radius, 8, beg, end);
526 break;
528 drawFilledCircleDetailled(d, radius);
529 break;
530 default:
531 // nothing to draw
532 break;
533 }
534}
535
536
537void
539 // get current resolution level
540 switch (d) {
542 drawFilledCircle(radius, 32);
543 break;
545 drawFilledCircle(radius, 16);
546 break;
548 drawFilledCircle(radius, 8);
549 break;
550 default:
551 // draw only a square
553 glBegin(GL_QUADS);
554 glVertex2d(-radius, radius);
555 glVertex2d(-radius, -radius);
556 glVertex2d(radius, -radius);
557 glVertex2d(radius, radius);
558 glEnd();
560#ifdef CHECK_ELEMENTCOUNTER
561 myVertexCounter += 4;
562#endif
563 break;
564 }
565}
566
567void
568GLHelper::drawFilledCircle(double const radius, int const steps) {
569 drawFilledCircle(radius, steps, 0, 360);
570}
571
572
573void
574GLHelper::drawFilledCircle(double radius, int steps, double beg, double end) {
575 const double inc = (end - beg) / (double)steps;
576 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
577 std::pair<double, double> p1 = getCircleCoords().at(angleLookup(beg));
578
579 for (int i = 0; i <= steps; ++i) {
580 const std::pair<double, double>& p2 = getCircleCoords().at(angleLookup(beg + i * inc));
581 glBegin(GL_TRIANGLES);
582 glVertex2d(p1.first * radius, p1.second * radius);
583 glVertex2d(p2.first * radius, p2.second * radius);
584 glVertex2d(0, 0);
585 glEnd();
586 p1 = p2;
587#ifdef CHECK_ELEMENTCOUNTER
588 myVertexCounter += 3;
589#endif
590 }
591}
592
593
594void
595GLHelper::drawOutlineCircle(double radius, double iRadius, int steps) {
596 drawOutlineCircle(radius, iRadius, steps, 0, 360);
597}
598
599
600void
601GLHelper::drawOutlineCircle(double radius, double iRadius, int steps,
602 double beg, double end) {
603 const double inc = (end - beg) / (double)steps;
604 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
605 std::pair<double, double> p1 = getCircleCoords().at(angleLookup(beg));
606
607 for (int i = 0; i <= steps; ++i) {
608 const std::pair<double, double>& p2 = getCircleCoords().at(angleLookup(beg + i * inc));
609 glBegin(GL_TRIANGLES);
610 glVertex2d(p1.first * radius, p1.second * radius);
611 glVertex2d(p2.first * radius, p2.second * radius);
612 glVertex2d(p2.first * iRadius, p2.second * iRadius);
613
614 glVertex2d(p2.first * iRadius, p2.second * iRadius);
615 glVertex2d(p1.first * iRadius, p1.second * iRadius);
616 glVertex2d(p1.first * radius, p1.second * radius);
617
618 glEnd();
619 p1 = p2;
620#ifdef CHECK_ELEMENTCOUNTER
621 myVertexCounter += 6;
622#endif
623 }
624}
625
626
627void
628GLHelper::drawTriangleAtEnd(const Position& p1, const Position& p2, double tLength,
629 double tWidth, const double extraOffset) {
630 const double length = p1.distanceTo(p2);
631 if (length < tLength) {
632 tWidth *= length / tLength;
633 tLength = length;
634 }
635 Position rl(PositionVector::positionAtOffset(p1, p2, length - tLength));
637 glTranslated(rl.x(), rl.y(), 0);
638 glRotated(-GeomHelper::naviDegree(p1.angleTo2D(p2)), 0, 0, 1);
639 glTranslated(0, extraOffset, 0);
640 glBegin(GL_TRIANGLES);
641 glVertex2d(0, tLength);
642 glVertex2d(-tWidth, 0);
643 glVertex2d(+tWidth, 0);
644 glEnd();
646#ifdef CHECK_ELEMENTCOUNTER
647 myVertexCounter += 3;
648#endif
649}
650
651
652void
654 glColor4ub(c.red(), c.green(), c.blue(), c.alpha());
655}
656
657
660 GLdouble current[4];
661 glGetDoublev(GL_CURRENT_COLOR, current);
662 return RGBColor(static_cast<unsigned char>(current[0] * 255. + 0.5),
663 static_cast<unsigned char>(current[1] * 255. + 0.5),
664 static_cast<unsigned char>(current[2] * 255. + 0.5),
665 static_cast<unsigned char>(current[3] * 255. + 0.5));
666}
667
668
669void
672 myFont = nullptr;
673}
674
675
676void
677GLHelper::setGL2PS(bool active) {
678 myGL2PSActive = active;
679}
680
681
682void
683GLHelper::drawSpaceOccupancies(const double exaggeration, const Position& pos, const double rotation,
684 const double width, const double length, const bool vehicle) {
685 // declare geometry
686 PositionVector geom;
687 const double w = width / 2. - 0.1 * exaggeration;
688 const double h = length;
689 // set geometry
690 geom.push_back(Position(-w, +0, 0.));
691 geom.push_back(Position(+w, +0, 0.));
692 geom.push_back(Position(+w, +h, 0.));
693 geom.push_back(Position(-w, +h, 0.));
694 geom.push_back(Position(-w, +0, 0.));
695
696 // push matrix
698 // translate
699 glTranslated(pos.x(), pos.y(), pos.z());
700 // rotate
701 glRotated(rotation, 0, 0, 1);
702 // set color
704 // draw box lines
705 GLHelper::drawBoxLines(geom, 0.1 * exaggeration);
706 // pop matrix
708}
709
710
711bool
713 if (myFont == nullptr) {
714 myFontSize = 25.0;
716 if (myFont != nullptr) {
718 fonsSetFont(myFont, fontNormal);
720 }
721 }
722 return myFont != nullptr;
723}
724
725
726const std::vector<RGBColor>&
728 // check if more colors has to be added
729 while ((int)myDottedcontourColors.size() < size) {
732 } else {
734 }
735 }
737}
738
739
740double
741GLHelper::getTextWidth(const std::string& text, double size) {
742 return size / myFontSize * fonsTextBounds(myFont, 0, 0, text.c_str(), nullptr, nullptr);
743}
744
745
746void
747GLHelper::drawText(const std::string& text, const Position& pos, const double layer, const double size,
748 const RGBColor& col, const double angle, const int align, double width) {
749 if (width <= 0) {
750 width = size;
751 }
752 if (!initFont()) {
753 return;
754 }
756 glAlphaFunc(GL_GREATER, 0.5);
757 glEnable(GL_ALPHA_TEST);
758#ifdef HAVE_GL2PS
759 if (myGL2PSActive) {
760 glRasterPos3d(pos.x(), pos.y(), layer);
761 GLfloat color[] = {col.red() / 255.f, col.green() / 255.f, col.blue() / 255.f, col.alpha() / 255.f};
762 gl2psTextOptColor(text.c_str(), "Roboto", 10, align == 0 ? GL2PS_TEXT_C : align, (GLfloat) - angle, color);
764 return;
765 }
766#endif
767 glTranslated(pos.x(), pos.y(), layer);
768 glScaled(width / myFontSize * 2.0, size / myFontSize * 2.0, 1.);
769 glRotated(-angle, 0, 0, 1);
771 fonsSetColor(myFont, glfonsRGBA(col.red(), col.green(), col.blue(), col.alpha()));
772 fonsDrawText(myFont, 0., 0., text.c_str(), nullptr);
774}
775
776
777void
779 const GUIVisualizationTextSettings& settings,
780 const std::string& text, const Position& pos,
781 const double scale,
782 const double angle,
783 const double layer,
784 const int align) {
785 drawTextBox(text, pos, layer,
786 settings.scaledSize(scale),
787 settings.color,
788 settings.bgColor,
790 angle, 0, 0.2, align);
791}
792
793
794void
795GLHelper::drawTextBox(const std::string& text, const Position& pos,
796 const double layer, const double size,
797 const RGBColor& txtColor, const RGBColor& bgColor, const RGBColor& borderColor,
798 const double angle,
799 const double relBorder,
800 const double relMargin,
801 const int align) {
802 if (!initFont()) {
803 return;
804 };
805 if (bgColor.alpha() != 0) {
806 const double boxAngle = 90;
807 const double stringWidth = size / myFontSize * fonsTextBounds(myFont, 0, 0, text.c_str(), nullptr, nullptr);
808 const double borderWidth = size * relBorder;
809 const double boxHeight = size * (0.32 + 0.6 * relMargin);
810 const double boxWidth = stringWidth + size * relMargin;
812 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
813 glTranslated(pos.x(), pos.y(), layer);
814 glRotated(-angle, 0, 0, 1);
815 Position left(-boxWidth * 0.5, 0);
816 setColor(borderColor);
817 drawBoxLine(left, boxAngle, boxWidth, boxHeight);
818 left.add(borderWidth * 1.5, 0);
819 setColor(bgColor);
820 glTranslated(0, 0, 0.01);
821 drawBoxLine(left, boxAngle, boxWidth - 3 * borderWidth, boxHeight - 2 * borderWidth);
823 }
824 drawText(text, pos, layer + 0.02, size, txtColor, angle, align);
825}
826
827
828void
829GLHelper::drawTextAtEnd(const std::string& text, const PositionVector& shape, double x,
830 const GUIVisualizationTextSettings& settings, const double scale) {
832 const Position& end = shape.back();
833 const Position& f = shape[-2];
834 const double rot = RAD2DEG(atan2((end.x() - f.x()), (f.y() - end.y())));
835 glTranslated(end.x(), end.y(), 0);
836 glRotated(rot, 0, 0, 1);
837 drawTextBox(text, Position(x, 0.26), 0,
838 settings.scaledSize(scale, 0.01),
839 settings.color,
840 settings.bgColor,
842 180, 0, 0.2);
844}
845
846
847void
848GLHelper::drawCrossTies(const PositionVector& geom, const std::vector<double>& rots,
849 const std::vector<double>& lengths, double length, double spacing,
850 double halfWidth, double offset, bool lessDetail) {
852 // draw on top of of the white area between the rails
853 glTranslated(0, 0, 0.1);
854 int e = (int) geom.size() - 1;
855 for (int i = 0; i < e; ++i) {
857 glTranslated(geom[i].x(), geom[i].y(), 0.0);
858 glRotated(rots[i], 0, 0, 1);
859 // draw crossing depending of detail
860 if (!lessDetail) {
861 for (double t = 0; t < lengths[i]; t += spacing) {
862 glBegin(GL_QUADS);
863 glVertex2d(-halfWidth - offset, -t);
864 glVertex2d(-halfWidth - offset, -t - length);
865 glVertex2d(halfWidth - offset, -t - length);
866 glVertex2d(halfWidth - offset, -t);
867 glEnd();
868#ifdef CHECK_ELEMENTCOUNTER
869 myVertexCounter += 4;
870#endif
871 }
872 } else {
873 // only draw a single rectangle if it's being drawn only for selecting
874 glBegin(GL_QUADS);
875 glVertex2d(-halfWidth - offset, 0);
876 glVertex2d(-halfWidth - offset, -lengths.back());
877 glVertex2d(halfWidth - offset, -lengths.back());
878 glVertex2d(halfWidth - offset, 0);
879 glEnd();
880#ifdef CHECK_ELEMENTCOUNTER
881 myVertexCounter += 4;
882#endif
883 }
884 // pop three draw matrix
886 }
888}
889
890void
892 const std::vector<double>& rots,
893 const std::vector<double>& lengths,
894 double maxLength, double spacing,
895 double halfWidth, bool cl, bool cr, bool lefthand, double scale) {
896
897 double mw = (halfWidth + SUMO_const_laneMarkWidth * (cl ? 0.6 : 0.2)) * scale;
898 double mw2 = (halfWidth - SUMO_const_laneMarkWidth * (cr ? 0.6 : 0.2)) * scale;
899 if (cl || cr) {
900 if (lefthand) {
901 mw *= -1;
902 mw2 *= -1;
903 }
904 int e = (int) geom.size() - 1;
905 double offset = 0;
906 for (int i = 0; i < e; ++i) {
908 glTranslated(geom[i].x(), geom[i].y(), 2.1);
909 glRotated(rots[i], 0, 0, 1);
910 double t;
911 for (t = offset; t < lengths[i]; t += spacing) {
912 const double length = MIN2((double)maxLength, lengths[i] - t);
913 glBegin(GL_QUADS);
914 glVertex2d(-mw, -t);
915 glVertex2d(-mw, -t - length);
916 glVertex2d(-mw2, -t - length);
917 glVertex2d(-mw2, -t);
918 glEnd();
919#ifdef CHECK_ELEMENTCOUNTER
920 myVertexCounter += 4;
921#endif
922 if (!cl || !cr) {
923 // draw inverse marking between asymmetrical lane markings
924 const double length2 = MIN2((double)6, lengths[i] - t);
925 glBegin(GL_QUADS);
926 glVertex2d(-halfWidth + 0.02, -t - length2);
927 glVertex2d(-halfWidth + 0.02, -t - length);
928 glVertex2d(-halfWidth - 0.02, -t - length);
929 glVertex2d(-halfWidth - 0.02, -t - length2);
930 glEnd();
931#ifdef CHECK_ELEMENTCOUNTER
932 myVertexCounter += 4;
933#endif
934 }
935 }
936 offset = t - lengths[i] - spacing;
938 }
939 }
940}
941
942
943void
944GLHelper::debugVertices(const PositionVector& shape, const GUIVisualizationTextSettings& settings, double scale, double layer) {
945 for (int i = 0; i < (int)shape.size(); ++i) {
946 drawTextBox(toString(i), shape[i], layer,
947 settings.scaledSize(scale),
948 settings.color,
949 settings.bgColor,
951 0, 0, 0.2);
952 }
953}
954
955
956void
958 if (s.drawBoundaries) {
961 // draw on top
962 glTranslated(0, 0, 1024);
963 drawLine(Position(b.xmin(), b.ymax()), Position(b.xmax(), b.ymax()));
964 drawLine(Position(b.xmax(), b.ymax()), Position(b.xmax(), b.ymin()));
965 drawLine(Position(b.xmax(), b.ymin()), Position(b.xmin(), b.ymin()));
966 drawLine(Position(b.xmin(), b.ymin()), Position(b.xmin(), b.ymax()));
968 }
969}
970
971
972/****************************************************************************/
void CALLBACK combCallback(GLdouble coords[3], GLdouble *vertex_data[4], GLfloat weight[4], GLdouble **dataOut)
Definition GLHelper.cpp:76
#define CIRCLE_RESOLUTION
Definition GLHelper.cpp:54
#define CALLBACK
Definition GLHelper.cpp:59
#define DEG2RAD(x)
Definition GeomHelper.h:35
#define RAD2DEG(x)
Definition GeomHelper.h:36
#define WRITE_WARNING(msg)
Definition MsgHandler.h:286
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:107
T MIN2(T a, T b)
Definition StdDefs.h:80
const double SUMO_const_laneMarkWidth
Definition StdDefs.h:55
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:127
double xmin() const
Returns minimum x-coordinate.
Definition Boundary.cpp:115
double ymax() const
Returns maximum y-coordinate.
Definition Boundary.cpp:133
double xmax() const
Returns maximum x-coordinate.
Definition Boundary.cpp:121
static void drawFilledPoly(const PositionVector &v, bool close)
Draws a filled polygon described by the list of points.
Definition GLHelper.cpp:208
static void drawFilledPolyTesselated(const PositionVector &v, bool close)
Draws a filled polygon described by the list of points.
Definition GLHelper.cpp:233
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:795
static void resetVertexCounter()
reset vertex counter
Definition GLHelper.cpp:180
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:437
static void setColor(const RGBColor &c)
Sets the gl-color to this value.
Definition GLHelper.cpp:653
static void drawOutlineCircle(double radius, double iRadius, int steps=8)
Draws an unfilled circle around (0,0)
Definition GLHelper.cpp:595
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:628
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:829
static void resetFont()
to be called when the font context is invalidated
Definition GLHelper.cpp:670
static void pushName(unsigned int name)
push Name
Definition GLHelper.cpp:144
static void checkCounterMatrix()
check counter matrix (for debug purposes)
Definition GLHelper.cpp:186
static void drawFilledCircle(const double widradiusth, const int steps=8)
Draws a filled circle around (0,0)
Definition GLHelper.cpp:568
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:727
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:110
static double getTextWidth(const std::string &text, double size)
get required width of text
Definition GLHelper.cpp:741
static int myMatrixCounter
matrix counter (for debug purposes)
Definition GLHelper.h:424
static void popMatrix()
pop matrix
Definition GLHelper.cpp:135
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:352
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:957
static RGBColor getColor()
gets the gl-color
Definition GLHelper.cpp:659
static int getMatrixCounter()
get matrix counter
Definition GLHelper.cpp:162
static void drawRectangle(const Position &center, const double width, const double height)
Draws a rectangle line.
Definition GLHelper.cpp:282
static const std::vector< std::pair< double, double > > & getCircleCoords()
Storage for precomputed sin/cos-values describing a circle.
Definition GLHelper.cpp:96
static void drawBoxLine(const Position &beg, double rot, double visLength, double width, double offset=0)
Draws a thick line.
Definition GLHelper.cpp:300
static void checkCounterName()
check counter name (for debug purposes)
Definition GLHelper.cpp:197
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:944
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:538
static void popName()
pop Name
Definition GLHelper.cpp:153
static bool rightTurn(double angle1, double angle2)
whether the road makes a right turn (or goes straight)
Definition GLHelper.cpp:339
static int myNameCounter
name counter
Definition GLHelper.h:433
static void pushMatrix()
push matrix
Definition GLHelper.cpp:122
static void setGL2PS(bool active=true)
set GL2PS
Definition GLHelper.cpp:677
static int getVertexCounter()
get vertex counter
Definition GLHelper.cpp:174
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:891
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:747
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:683
static bool initFont()
init myFont
Definition GLHelper.cpp:712
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:778
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:848
static void resetMatrixCounter()
reset matrix counter
Definition GLHelper.cpp:168
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:263
double x() const
Returns the x-position.
Definition Position.h:52
void add(const Position &pos)
Adds the given position to this one.
Definition Position.h:129
double z() const
Returns the z-position.
Definition Position.h:62
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:283
double y() const
Returns the y-position.
Definition Position.h:57
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:195
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:198
unsigned char green() const
Returns the green-amount of the color.
Definition RGBColor.cpp:80
static const RGBColor GREEN
Definition RGBColor.h:189
unsigned char blue() const
Returns the blue-amount of the color.
Definition RGBColor.cpp:86
static const RGBColor BLACK
Definition RGBColor.h:196
static const RGBColor MAGENTA
Definition RGBColor.h:193
static const RGBColor RED
named colors
Definition RGBColor.h:188
#define UNUSED_PARAMETER(x)
@ 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