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