LCOV - code coverage report
Current view: top level - src/utils/gui/div - GLHelper.cpp (source / functions) Hit Total Coverage
Test: lcov.info Lines: 242 478 50.6 %
Date: 2024-05-02 15:31:40 Functions: 28 51 54.9 %

          Line data    Source code
       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             : /****************************************************************************/
      14             : /// @file    GLHelper.cpp
      15             : /// @author  Daniel Krajzewicz
      16             : /// @author  Jakob Erdmann
      17             : /// @author  Michael Behrisch
      18             : /// @date    Sept 2002
      19             : ///
      20             : // Some methods which help to draw certain geometrical objects in openGL
      21             : /****************************************************************************/
      22             : #include <config.h>
      23             : 
      24             : #include <cassert>
      25             : #include <utils/geom/GeomHelper.h>
      26             : #include <utils/common/StdDefs.h>
      27             : #include <utils/common/MsgHandler.h>
      28             : #include <utils/common/ToString.h>
      29             : #include <utils/options/OptionsCont.h>
      30             : #define FONTSTASH_IMPLEMENTATION // Expands implementation
      31             : #ifdef _MSC_VER
      32             : #pragma warning(disable: 4505 5219) // do not warn about unused functions and implicit float conversions
      33             : #endif
      34             : #if __GNUC__ > 3
      35             : #pragma GCC diagnostic push
      36             : #pragma GCC diagnostic ignored "-Wunused-function"
      37             : #endif
      38             : #include <foreign/fontstash/fontstash.h>
      39             : #include <utils/gui/globjects/GLIncludes.h>
      40             : #define GLFONTSTASH_IMPLEMENTATION // Expands implementation
      41             : #include <foreign/fontstash/glfontstash.h>
      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             : 
      61             : int GLHelper::myMatrixCounter = 0;
      62             : int GLHelper::myVertexCounter = 0;
      63             : int GLHelper::myMatrixCounterDebug = 0;
      64             : int GLHelper::myNameCounter = 0;
      65             : std::vector<std::pair<double, double> > GLHelper::myCircleCoords;
      66             : std::vector<RGBColor> GLHelper::myDottedcontourColors;
      67             : FONScontext* GLHelper::myFont = nullptr;
      68             : double GLHelper::myFontSize = 50.0;
      69             : bool GLHelper::myGL2PSActive = false;
      70             : 
      71           0 : void CALLBACK combCallback(GLdouble coords[3],
      72             :                            GLdouble* vertex_data[4],
      73             :                            GLfloat weight[4], GLdouble** dataOut) {
      74             :     UNUSED_PARAMETER(weight);
      75             :     UNUSED_PARAMETER(*vertex_data);
      76             :     GLdouble* vertex;
      77             : 
      78           0 :     vertex = (GLdouble*)malloc(7 * sizeof(GLdouble));
      79             : 
      80           0 :     vertex[0] = coords[0];
      81           0 :     vertex[1] = coords[1];
      82           0 :     vertex[2] = coords[2];
      83           0 :     *dataOut = vertex;
      84           0 : }
      85             : 
      86             : // ===========================================================================
      87             : // method definitions
      88             : // ===========================================================================
      89             : 
      90             : const std::vector<std::pair<double, double> >&
      91   162562784 : GLHelper::getCircleCoords() {
      92             :     // fill in first call
      93   162562784 :     if (myCircleCoords.size() == 0) {
      94     4480888 :         for (int i = 0; i <= (int)(360 * CIRCLE_RESOLUTION); ++i) {
      95     4479644 :             const double x = (double) sin(DEG2RAD(i / CIRCLE_RESOLUTION));
      96     4479644 :             const double y = (double) cos(DEG2RAD(i / CIRCLE_RESOLUTION));
      97     4479644 :             myCircleCoords.push_back(std::pair<double, double>(x, y));
      98             :         }
      99             :     }
     100   162562784 :     return myCircleCoords;
     101             : }
     102             : 
     103             : 
     104             : int
     105    81281392 : GLHelper::angleLookup(double angleDeg) {
     106    81281392 :     const int numCoords = (int)getCircleCoords().size() - 1;
     107    81281392 :     int index = ((int)(floor(angleDeg * CIRCLE_RESOLUTION + 0.5))) % numCoords;
     108    81281392 :     if (index < 0) {
     109      339166 :         index += numCoords;
     110             :     }
     111             :     assert(index >= 0);
     112    81281392 :     return (int)index;
     113             : }
     114             : 
     115             : 
     116             : void
     117    72125694 : GLHelper::pushMatrix() {
     118    72125694 :     glPushMatrix();
     119             :     // update counters
     120             : #ifdef CHECK_ELEMENTCOUNTER
     121             :     myMatrixCounter++;
     122             : #endif
     123             : #ifdef CHECK_PUSHPOP
     124             :     myMatrixCounterDebug++;
     125             : #endif
     126    72125694 : }
     127             : 
     128             : 
     129             : void
     130    72513445 : GLHelper::popMatrix() {
     131    72513445 :     glPopMatrix();
     132             : #ifdef CHECK_PUSHPOP
     133             :     myMatrixCounterDebug--;
     134             : #endif
     135    72513445 : }
     136             : 
     137             : 
     138             : void
     139    52454277 : GLHelper::pushName(unsigned int name) {
     140    52454277 :     glPushName(name);
     141             : #ifdef CHECK_PUSHPOP
     142             :     myNameCounter++;
     143             : #endif
     144    52454277 : }
     145             : 
     146             : 
     147             : void
     148    52454277 : GLHelper::popName() {
     149    52454277 :     glPopName();
     150             : #ifdef CHECK_PUSHPOP
     151             :     myNameCounter--;
     152             : #endif
     153    52454277 : }
     154             : 
     155             : 
     156             : int
     157           0 : GLHelper::getMatrixCounter() {
     158           0 :     return myMatrixCounter;
     159             : }
     160             : 
     161             : 
     162             : void
     163      491622 : GLHelper::resetMatrixCounter() {
     164      491622 :     myMatrixCounter = 0;
     165      491622 : }
     166             : 
     167             : 
     168             : int
     169           0 : GLHelper::getVertexCounter() {
     170           0 :     return myVertexCounter;
     171             : }
     172             : 
     173             : 
     174             : void
     175      491622 : GLHelper::resetVertexCounter() {
     176      491622 :     myVertexCounter = 0;
     177      491622 : }
     178             : 
     179             : 
     180             : void
     181      491622 : GLHelper::checkCounterMatrix() {
     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             :     }
     186             :     myMatrixCounterDebug = 0;
     187             : #endif
     188      491622 : }
     189             : 
     190             : 
     191             : void
     192      491622 : GLHelper::checkCounterName() {
     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      491622 : }
     200             : 
     201             : 
     202             : void
     203      964421 : GLHelper::drawFilledPoly(const PositionVector& v, bool close) {
     204      964421 :     if (v.size() == 0) {
     205             :         return;
     206             :     }
     207      964421 :     glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
     208      964421 :     glBegin(GL_POLYGON);
     209     6738289 :     for (PositionVector::const_iterator i = v.begin(); i != v.end(); i++) {
     210             :         const Position& p = *i;
     211     5773868 :         glVertex2d(p.x(), p.y());
     212             : #ifdef CHECK_ELEMENTCOUNTER
     213             :         myVertexCounter++;
     214             : #endif
     215             :     }
     216      964421 :     if (close) {
     217             :         const Position& p = *(v.begin());
     218      964421 :         glVertex2d(p.x(), p.y());
     219             : #ifdef CHECK_ELEMENTCOUNTER
     220             :         myVertexCounter++;
     221             : #endif
     222             :     }
     223      964421 :     glEnd();
     224             : }
     225             : 
     226             : 
     227             : void
     228           0 : GLHelper::drawFilledPolyTesselated(const PositionVector& v, bool close) {
     229           0 :     if (v.size() == 0) {
     230             :         return;
     231             :     }
     232           0 :     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           0 :     gluTessCallback(tobj, GLU_TESS_VERTEX, (GLvoid(CALLBACK*)()) &glVertex3dv);
     242           0 :     gluTessCallback(tobj, GLU_TESS_BEGIN, (GLvoid(CALLBACK*)()) &glBegin);
     243           0 :     gluTessCallback(tobj, GLU_TESS_END, (GLvoid(CALLBACK*)()) &glEnd);
     244           0 :     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           0 :     gluTessProperty(tobj, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_ODD);
     252           0 :     gluTessBeginPolygon(tobj, nullptr);
     253           0 :     gluTessBeginContour(tobj);
     254           0 :     double* points = new double[(v.size() + int(close)) * 3];
     255             : 
     256           0 :     for (int i = 0; i != (int)v.size(); ++i) {
     257           0 :         points[3 * i] = v[i].x();
     258           0 :         points[3 * i + 1] = v[i].y();
     259           0 :         points[3 * i + 2] = 0;
     260           0 :         gluTessVertex(tobj, points + 3 * i, points + 3 * i);
     261             :     }
     262           0 :     if (close) {
     263             :         const int i = (int)v.size();
     264           0 :         points[3 * i] = v[0].x();
     265           0 :         points[3 * i + 1] = v[0].y();
     266           0 :         points[3 * i + 2] = 0;
     267           0 :         gluTessVertex(tobj, points + 3 * i, points + 3 * i);
     268             :     }
     269           0 :     gluTessEndContour(tobj);
     270           0 :     gluTessEndPolygon(tobj);
     271           0 :     gluDeleteTess(tobj);
     272           0 :     delete[] points;
     273             : }
     274             : 
     275             : 
     276             : void
     277           0 : GLHelper::drawRectangle(const Position& center, const double width, const double height) {
     278           0 :     const double halfWidth = width * 0.5;
     279           0 :     const double halfHeight = height * 0.5;
     280           0 :     GLHelper::pushMatrix();
     281           0 :     glTranslated(center.x(), center.y(), 0);
     282           0 :     glBegin(GL_QUADS);
     283           0 :     glVertex2d(-halfWidth, halfHeight);
     284           0 :     glVertex2d(-halfWidth, -halfHeight);
     285           0 :     glVertex2d(halfWidth, -halfHeight);
     286           0 :     glVertex2d(halfWidth, halfHeight);
     287           0 :     glEnd();
     288           0 :     GLHelper::popMatrix();
     289             : #ifdef CHECK_ELEMENTCOUNTER
     290             :     myVertexCounter += 4;
     291             : #endif
     292           0 : }
     293             : 
     294             : void
     295    15362788 : GLHelper::drawBoxLine(const Position& beg, double rot, double visLength,
     296             :                       double width, double offset) {
     297    15362788 :     GLHelper::pushMatrix();
     298    15362788 :     glTranslated(beg.x(), beg.y(), 0);
     299    15362788 :     glRotated(rot, 0, 0, 1);
     300    15362788 :     glBegin(GL_QUADS);
     301    15362788 :     glVertex2d(-width - offset, 0);
     302    15362788 :     glVertex2d(-width - offset, -visLength);
     303    15362788 :     glVertex2d(width - offset, -visLength);
     304    15362788 :     glVertex2d(width - offset, 0);
     305    15362788 :     glEnd();
     306    15362788 :     GLHelper::popMatrix();
     307             : #ifdef CHECK_ELEMENTCOUNTER
     308             :     myVertexCounter += 4;
     309             : #endif
     310    15362788 : }
     311             : 
     312             : 
     313             : void
     314           0 : GLHelper::drawBoxLine(const Position& beg1, const Position& beg2,
     315             :                       double rot, double visLength,
     316             :                       double width) {
     317           0 :     GLHelper::pushMatrix();
     318           0 :     glTranslated((beg2.x() + beg1.x())*.5, (beg2.y() + beg1.y())*.5, 0);
     319           0 :     glRotated(rot, 0, 0, 1);
     320           0 :     glBegin(GL_QUADS);
     321           0 :     glVertex2d(-width, 0);
     322           0 :     glVertex2d(-width, -visLength);
     323           0 :     glVertex2d(width, -visLength);
     324           0 :     glVertex2d(width, 0);
     325           0 :     glEnd();
     326           0 :     GLHelper::popMatrix();
     327             : #ifdef CHECK_ELEMENTCOUNTER
     328             :     myVertexCounter += 4;
     329             : #endif
     330           0 : }
     331             : 
     332             : 
     333             : bool
     334       95185 : GLHelper::rightTurn(double angle1, double angle2) {
     335       95185 :     double delta = angle2 - angle1;
     336       95362 :     while (delta > 180) {
     337         177 :         delta -= 360;
     338             :     }
     339       95427 :     while (delta < -180) {
     340         242 :         delta += 360;
     341             :     }
     342       95185 :     return delta <= 0;
     343             : }
     344             : 
     345             : 
     346             : void
     347     5946965 : GLHelper::drawBoxLines(const PositionVector& geom,
     348             :                        const std::vector<double>& rots,
     349             :                        const std::vector<double>& lengths,
     350             :                        double width, int cornerDetail, double offset) {
     351             :     // draw the lane
     352     5946965 :     int e = (int) geom.size() - 1;
     353    20817223 :     for (int i = 0; i < e; i++) {
     354    14870258 :         drawBoxLine(geom[i], rots[i], lengths[i], width, offset);
     355             :     }
     356             :     // draw the corner details
     357     5946965 :     if (cornerDetail > 0) {
     358      266253 :         for (int i = 1; i < e; i++) {
     359       95185 :             GLHelper::pushMatrix();
     360       95185 :             glTranslated(geom[i].x(), geom[i].y(), 0.1);
     361       95185 :             double angleBeg = -rots[i - 1];
     362       95185 :             double angleEnd = 180 - rots[i];
     363       95185 :             if (rightTurn(rots[i - 1], rots[i])) {
     364             :                 std::swap(angleBeg, angleEnd);
     365             :             }
     366             :             // only draw the missing piece
     367       95185 :             angleBeg -= 90;
     368       95185 :             angleEnd += 90;
     369             :             // avoid drawing more than 360 degrees
     370       95185 :             if (angleEnd - angleBeg > 360) {
     371         242 :                 angleBeg += 360;
     372             :             }
     373       95185 :             if (angleEnd - angleBeg < -360) {
     374           0 :                 angleEnd += 360;
     375             :             }
     376             :             // draw the right way around
     377       95185 :             if (angleEnd > angleBeg) {
     378       36327 :                 angleEnd -= 360;
     379             :             }
     380       95185 :             drawFilledCircle(width + offset, cornerDetail, angleBeg, angleEnd);
     381       95185 :             GLHelper::popMatrix();
     382             :         }
     383             :     }
     384     5946965 : }
     385             : 
     386             : 
     387             : void
     388           0 : GLHelper::drawBoxLines(const PositionVector& geom,
     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           0 :     int e = (int) geom.size() - 1;
     394           0 :     for (int i = 0; i < e; i++) {
     395           0 :         setColor(cols[i]);
     396           0 :         drawBoxLine(geom[i], rots[i], lengths[i], width, offset);
     397             :     }
     398           0 :     if (cornerDetail > 0) {
     399           0 :         for (int i = 1; i < e; i++) {
     400           0 :             GLHelper::pushMatrix();
     401           0 :             setColor(cols[i]);
     402           0 :             glTranslated(geom[i].x(), geom[i].y(), 0);
     403           0 :             drawFilledCircle(width, cornerDetail);
     404           0 :             glEnd();
     405           0 :             GLHelper::popMatrix();
     406             :         }
     407             :     }
     408           0 : }
     409             : 
     410             : 
     411             : void
     412           0 : GLHelper::drawBoxLines(const PositionVector& geom1,
     413             :                        const PositionVector& geom2,
     414             :                        const std::vector<double>& rots,
     415             :                        const std::vector<double>& lengths,
     416             :                        double width) {
     417           0 :     int minS = (int) MIN4(rots.size(), lengths.size(), geom1.size(), geom2.size());
     418           0 :     for (int i = 0; i < minS; i++) {
     419           0 :         GLHelper::drawBoxLine(geom1[i], geom2[i], rots[i], lengths[i], width);
     420             :     }
     421           0 : }
     422             : 
     423             : 
     424             : void
     425       19270 : GLHelper::drawBoxLines(const PositionVector& geom, double width) {
     426       19270 :     int e = (int) geom.size() - 1;
     427       85595 :     for (int i = 0; i < e; i++) {
     428       66325 :         const Position& f = geom[i];
     429       66325 :         const Position& s = geom[i + 1];
     430       66325 :         drawBoxLine(f,
     431       66325 :                     RAD2DEG(atan2((s.x() - f.x()), (f.y() - s.y()))),
     432             :                     f.distanceTo(s),
     433             :                     width);
     434             :     }
     435       19270 : }
     436             : 
     437             : 
     438             : void
     439        1098 : GLHelper::drawLine(const Position& beg, double rot, double visLength) {
     440        1098 :     GLHelper::pushMatrix();
     441        1098 :     glTranslated(beg.x(), beg.y(), 0);
     442        1098 :     glRotated(rot, 0, 0, 1);
     443        1098 :     glBegin(GL_LINES);
     444        1098 :     glVertex2d(0, 0);
     445        1098 :     glVertex2d(0, -visLength);
     446        1098 :     glEnd();
     447        1098 :     GLHelper::popMatrix();
     448             : #ifdef CHECK_ELEMENTCOUNTER
     449             :     myVertexCounter += 2;
     450             : #endif
     451        1098 : }
     452             : 
     453             : 
     454             : void
     455           0 : GLHelper::drawLine(const Position& beg1, const Position& beg2,
     456             :                    double rot, double visLength) {
     457           0 :     GLHelper::pushMatrix();
     458           0 :     glTranslated((beg2.x() + beg1.x())*.5, (beg2.y() + beg1.y())*.5, 0);
     459           0 :     glRotated(rot, 0, 0, 1);
     460           0 :     glBegin(GL_LINES);
     461           0 :     glVertex2d(0, 0);
     462           0 :     glVertex2d(0, -visLength);
     463           0 :     glEnd();
     464           0 :     GLHelper::popMatrix();
     465             : #ifdef CHECK_ELEMENTCOUNTER
     466             :     myVertexCounter += 2;
     467             : #endif
     468           0 : }
     469             : 
     470             : 
     471             : 
     472             : void
     473     8126291 : GLHelper::drawLine(const PositionVector& v) {
     474     8126291 :     glBegin(GL_LINES);
     475     8126291 :     int e = (int) v.size() - 1;
     476    21137614 :     for (int i = 0; i < e; ++i) {
     477    13011323 :         glVertex2d(v[i].x(), v[i].y());
     478    13011323 :         glVertex2d(v[i + 1].x(), v[i + 1].y());
     479             : #ifdef CHECK_ELEMENTCOUNTER
     480             :         myVertexCounter += 2;
     481             : #endif
     482             :     }
     483     8126291 :     glEnd();
     484     8126291 : }
     485             : 
     486             : 
     487             : void
     488           0 : GLHelper::drawLine(const PositionVector& v, const std::vector<RGBColor>& cols) {
     489           0 :     glBegin(GL_LINES);
     490           0 :     int e = (int) v.size() - 1;
     491           0 :     for (int i = 0; i < e; ++i) {
     492           0 :         setColor(cols[i]);
     493           0 :         glVertex2d(v[i].x(), v[i].y());
     494           0 :         glVertex2d(v[i + 1].x(), v[i + 1].y());
     495             : #ifdef CHECK_ELEMENTCOUNTER
     496             :         myVertexCounter += 2;
     497             : #endif
     498             :     }
     499           0 :     glEnd();
     500           0 : }
     501             : 
     502             : 
     503             : void
     504           0 : GLHelper::drawLine(const Position& beg, const Position& end) {
     505           0 :     glBegin(GL_LINES);
     506           0 :     glVertex2d(beg.x(), beg.y());
     507           0 :     glVertex2d(end.x(), end.y());
     508           0 :     glEnd();
     509             : #ifdef CHECK_ELEMENTCOUNTER
     510             :     myVertexCounter += 2;
     511             : #endif
     512           0 : }
     513             : 
     514             : 
     515             : void
     516           0 : GLHelper::drawFilledCircleDetailled(const GUIVisualizationSettings::Detail d, const double radius,
     517             :                                     double beg, double end) {
     518             :     // get current resolution level
     519           0 :     switch (d) {
     520           0 :         case GUIVisualizationSettings::Detail::CircleResolution32:
     521           0 :             drawFilledCircle(radius, 32, beg, end);
     522           0 :             break;
     523           0 :         case GUIVisualizationSettings::Detail::CircleResolution16:
     524           0 :             drawFilledCircle(radius, 16, beg, end);
     525           0 :             break;
     526           0 :         case GUIVisualizationSettings::Detail::CircleResolution8:
     527           0 :             drawFilledCircle(radius, 8, beg, end);
     528           0 :             break;
     529           0 :         case GUIVisualizationSettings::Detail::CircleResolution4:
     530           0 :             drawFilledCircleDetailled(d, radius);
     531           0 :             break;
     532             :         default:
     533             :             // nothing to draw
     534             :             break;
     535             :     }
     536           0 : }
     537             : 
     538             : 
     539             : void
     540           0 : GLHelper::drawFilledCircleDetailled(const GUIVisualizationSettings::Detail d, const double radius) {
     541             :     // get current resolution level
     542           0 :     switch (d) {
     543           0 :         case GUIVisualizationSettings::Detail::CircleResolution32:
     544           0 :             drawFilledCircle(radius, 32);
     545           0 :             break;
     546           0 :         case GUIVisualizationSettings::Detail::CircleResolution16:
     547           0 :             drawFilledCircle(radius, 16);
     548           0 :             break;
     549           0 :         case GUIVisualizationSettings::Detail::CircleResolution8:
     550           0 :             drawFilledCircle(radius, 8);
     551           0 :             break;
     552           0 :         default:
     553             :             // draw only a square
     554           0 :             GLHelper::pushMatrix();
     555           0 :             glBegin(GL_QUADS);
     556           0 :             glVertex2d(-radius, radius);
     557           0 :             glVertex2d(-radius, -radius);
     558           0 :             glVertex2d(radius, -radius);
     559           0 :             glVertex2d(radius, radius);
     560           0 :             glEnd();
     561           0 :             GLHelper::popMatrix();
     562             : #ifdef CHECK_ELEMENTCOUNTER
     563             :             myVertexCounter += 4;
     564             : #endif
     565           0 :             break;
     566             :     }
     567           0 : }
     568             : 
     569             : void
     570     9989971 : GLHelper::drawFilledCircle(double const radius, int const steps) {
     571     9989971 :     drawFilledCircle(radius, steps, 0, 360);
     572     9989971 : }
     573             : 
     574             : 
     575             : void
     576    10085165 : GLHelper::drawFilledCircle(double radius, int steps, double beg, double end) {
     577    10085165 :     const double inc = (end - beg) / (double)steps;
     578    10085165 :     glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
     579    10085165 :     std::pair<double, double> p1 = getCircleCoords().at(angleLookup(beg));
     580             : 
     581    81281392 :     for (int i = 0; i <= steps; ++i) {
     582    71196227 :         const std::pair<double, double>& p2 = getCircleCoords().at(angleLookup(beg + i * inc));
     583    71196227 :         glBegin(GL_TRIANGLES);
     584    71196227 :         glVertex2d(p1.first * radius, p1.second * radius);
     585    71196227 :         glVertex2d(p2.first * radius, p2.second * radius);
     586    71196227 :         glVertex2d(0, 0);
     587    71196227 :         glEnd();
     588             :         p1 = p2;
     589             : #ifdef CHECK_ELEMENTCOUNTER
     590             :         myVertexCounter += 3;
     591             : #endif
     592             :     }
     593    10085165 : }
     594             : 
     595             : 
     596             : void
     597           0 : GLHelper::drawOutlineCircle(double radius, double iRadius, int steps) {
     598           0 :     drawOutlineCircle(radius, iRadius, steps, 0, 360);
     599           0 : }
     600             : 
     601             : 
     602             : void
     603           0 : GLHelper::drawOutlineCircle(double radius, double iRadius, int steps,
     604             :                             double beg, double end) {
     605           0 :     const double inc = (end - beg) / (double)steps;
     606           0 :     glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
     607           0 :     std::pair<double, double> p1 = getCircleCoords().at(angleLookup(beg));
     608             : 
     609           0 :     for (int i = 0; i <= steps; ++i) {
     610           0 :         const std::pair<double, double>& p2 = getCircleCoords().at(angleLookup(beg + i * inc));
     611           0 :         glBegin(GL_TRIANGLES);
     612           0 :         glVertex2d(p1.first * radius, p1.second * radius);
     613           0 :         glVertex2d(p2.first * radius, p2.second * radius);
     614           0 :         glVertex2d(p2.first * iRadius, p2.second * iRadius);
     615             : 
     616           0 :         glVertex2d(p2.first * iRadius, p2.second * iRadius);
     617           0 :         glVertex2d(p1.first * iRadius, p1.second * iRadius);
     618           0 :         glVertex2d(p1.first * radius, p1.second * radius);
     619             : 
     620           0 :         glEnd();
     621             :         p1 = p2;
     622             : #ifdef CHECK_ELEMENTCOUNTER
     623             :         myVertexCounter += 6;
     624             : #endif
     625             :     }
     626           0 : }
     627             : 
     628             : 
     629             : void
     630      335520 : GLHelper::drawTriangleAtEnd(const Position& p1, const Position& p2, double tLength,
     631             :                             double tWidth, const double extraOffset) {
     632      335520 :     const double length = p1.distanceTo(p2);
     633      335520 :     if (length < tLength) {
     634           0 :         tWidth *= length / tLength;
     635             :         tLength = length;
     636             :     }
     637      335520 :     Position rl(PositionVector::positionAtOffset(p1, p2, length - tLength));
     638      335520 :     GLHelper::pushMatrix();
     639      335520 :     glTranslated(rl.x(), rl.y(), 0);
     640      335520 :     glRotated(-GeomHelper::naviDegree(p1.angleTo2D(p2)), 0, 0, 1);
     641      335520 :     glTranslated(0, extraOffset, 0);
     642      335520 :     glBegin(GL_TRIANGLES);
     643      335520 :     glVertex2d(0, tLength);
     644      335520 :     glVertex2d(-tWidth, 0);
     645      335520 :     glVertex2d(+tWidth, 0);
     646      335520 :     glEnd();
     647      335520 :     GLHelper::popMatrix();
     648             : #ifdef CHECK_ELEMENTCOUNTER
     649             :     myVertexCounter += 3;
     650             : #endif
     651      335520 : }
     652             : 
     653             : 
     654             : void
     655    35011840 : GLHelper::setColor(const RGBColor& c) {
     656    35011840 :     glColor4ub(c.red(), c.green(), c.blue(), c.alpha());
     657    35011840 : }
     658             : 
     659             : 
     660             : RGBColor
     661     1155749 : GLHelper::getColor() {
     662             :     GLdouble current[4];
     663     1155749 :     glGetDoublev(GL_CURRENT_COLOR, current);
     664     2311498 :     return RGBColor(static_cast<unsigned char>(current[0] * 255. + 0.5),
     665     1155749 :                     static_cast<unsigned char>(current[1] * 255. + 0.5),
     666     1155749 :                     static_cast<unsigned char>(current[2] * 255. + 0.5),
     667     1155749 :                     static_cast<unsigned char>(current[3] * 255. + 0.5));
     668             : }
     669             : 
     670             : 
     671             : void
     672       21292 : GLHelper::resetFont() {
     673       21292 :     glfonsDelete(myFont);
     674       21292 :     myFont = nullptr;
     675       21292 : }
     676             : 
     677             : 
     678             : void
     679           0 : GLHelper::setGL2PS(bool active) {
     680           0 :     myGL2PSActive = active;
     681           0 : }
     682             : 
     683             : 
     684             : void
     685       13810 : GLHelper::drawSpaceOccupancies(const double exaggeration, const Position& pos, const double rotation,
     686             :                                const double width, const double length, const bool vehicle) {
     687             :     // declare colors
     688       13810 :     const RGBColor red(255, 0, 0, 255);
     689       13810 :     const RGBColor green(0, 255, 0, 255);
     690             :     // declare geometry
     691       13810 :     PositionVector geom;
     692       13810 :     const double w = width / 2. - 0.1 * exaggeration;
     693             :     const double h = length;
     694             :     // set geometry
     695       13810 :     geom.push_back(Position(-w, +0, 0.));
     696       13810 :     geom.push_back(Position(+w, +0, 0.));
     697       13810 :     geom.push_back(Position(+w, +h, 0.));
     698       13810 :     geom.push_back(Position(-w, +h, 0.));
     699       13810 :     geom.push_back(Position(-w, +0, 0.));
     700             :     /*
     701             :     geom.push_back(Position(pos.x(), pos.y(), pos.z()));
     702             :     geom.push_back(Position(pos.x() + (*l).second.myWidth, pos.y(), pos.z()));
     703             :     geom.push_back(Position(pos.x() + (*l).second.myWidth, pos.y() - (*l).second.myLength, pos.z()));
     704             :     geom.push_back(Position(pos.x(), pos.y() - (*l).second.myLength, pos.z()));
     705             :     geom.push_back(Position(pos.x(), pos.y(), pos.z()));
     706             :     */
     707             :     // push matrix
     708       13810 :     GLHelper::pushMatrix();
     709             :     // translate
     710       13810 :     glTranslated(pos.x(), pos.y(), pos.z());
     711             :     // rotate
     712       13810 :     glRotated(rotation, 0, 0, 1);
     713             :     // set color
     714       19997 :     GLHelper::setColor(vehicle ? green : red);
     715             :     // draw box lines
     716       13810 :     GLHelper::drawBoxLines(geom, 0.1 * exaggeration);
     717             :     // pop matrix
     718       13810 :     GLHelper::popMatrix();
     719       13810 : }
     720             : 
     721             : 
     722             : bool
     723      991009 : GLHelper::initFont() {
     724      991009 :     if (myFont == nullptr) {
     725        6340 :         myFont = glfonsCreate(2048, 2048, FONS_ZERO_BOTTOMLEFT);
     726        6340 :         if (myFont != nullptr) {
     727        6340 :             const int fontNormal = fonsAddFontMem(myFont, "medium", data_font_Roboto_Medium_ttf, data_font_Roboto_Medium_ttf_len, 0);
     728        6340 :             fonsSetFont(myFont, fontNormal);
     729        6340 :             fonsSetSize(myFont, (float)myFontSize);
     730             :         }
     731             :     }
     732      991009 :     return myFont != nullptr;
     733             : }
     734             : 
     735             : 
     736             : const std::vector<RGBColor>&
     737           0 : GLHelper::getDottedcontourColors(const int size) {
     738             :     // check if more colors has to be added
     739           0 :     while ((int)myDottedcontourColors.size() < size) {
     740           0 :         if (myDottedcontourColors.empty() || myDottedcontourColors.back() == RGBColor::WHITE) {
     741           0 :             myDottedcontourColors.push_back(RGBColor::BLACK);
     742             :         } else {
     743           0 :             myDottedcontourColors.push_back(RGBColor::WHITE);
     744             :         }
     745             :     }
     746           0 :     return myDottedcontourColors;
     747             : }
     748             : 
     749             : 
     750             : double
     751           0 : GLHelper::getTextWidth(const std::string& text, double size) {
     752           0 :     return size / myFontSize * fonsTextBounds(myFont, 0, 0, text.c_str(), nullptr, nullptr);
     753             : }
     754             : 
     755             : 
     756             : void
     757      991009 : GLHelper::drawText(const std::string& text, const Position& pos, const double layer, const double size,
     758             :                    const RGBColor& col, const double angle, const int align, double width) {
     759      991009 :     if (width <= 0) {
     760             :         width = size;
     761             :     }
     762      991009 :     if (!initFont()) {
     763             :         return;
     764             :     }
     765      991009 :     GLHelper::pushMatrix();
     766      991009 :     glAlphaFunc(GL_GREATER, 0.5);
     767      991009 :     glEnable(GL_ALPHA_TEST);
     768             : #ifdef HAVE_GL2PS
     769      991009 :     if (myGL2PSActive) {
     770           0 :         glRasterPos3d(pos.x(), pos.y(), layer);
     771           0 :         GLfloat color[] = {col.red() / 255.f, col.green() / 255.f, col.blue() / 255.f, col.alpha() / 255.f};
     772           0 :         gl2psTextOptColor(text.c_str(), "Roboto", 10, align == 0 ? GL2PS_TEXT_C : align, (GLfloat) - angle, color);
     773           0 :         GLHelper::popMatrix();
     774             :         return;
     775             :     }
     776             : #endif
     777      991009 :     glTranslated(pos.x(), pos.y(), layer);
     778      991009 :     glScaled(width / myFontSize, size / myFontSize, 1.);
     779      991009 :     glRotated(-angle, 0, 0, 1);
     780      997956 :     fonsSetAlign(myFont, align == 0 ? FONS_ALIGN_CENTER | FONS_ALIGN_MIDDLE : align);
     781      991009 :     fonsSetColor(myFont, glfonsRGBA(col.red(), col.green(), col.blue(), col.alpha()));
     782      991009 :     fonsDrawText(myFont, 0., 0., text.c_str(), nullptr);
     783      991007 :     GLHelper::popMatrix();
     784             : }
     785             : 
     786             : 
     787             : void
     788           0 : GLHelper::drawTextSettings(
     789             :     const GUIVisualizationTextSettings& settings,
     790             :     const std::string& text, const Position& pos,
     791             :     const double scale,
     792             :     const double angle,
     793             :     const double layer,
     794             :     const int align) {
     795           0 :     drawTextBox(text, pos, layer,
     796             :                 settings.scaledSize(scale),
     797           0 :                 settings.color,
     798           0 :                 settings.bgColor,
     799             :                 RGBColor::INVISIBLE,
     800             :                 angle, 0, 0.2, align);
     801           0 : }
     802             : 
     803             : 
     804             : void
     805           0 : GLHelper::drawTextBox(const std::string& text, const Position& pos,
     806             :                       const double layer, const double size,
     807             :                       const RGBColor& txtColor, const RGBColor& bgColor, const RGBColor& borderColor,
     808             :                       const double angle,
     809             :                       const double relBorder,
     810             :                       const double relMargin,
     811             :                       const int align) {
     812           0 :     if (!initFont()) {
     813             :         return;
     814             :     };
     815           0 :     if (bgColor.alpha() != 0) {
     816             :         const double boxAngle = 90;
     817           0 :         const double stringWidth = size / myFontSize * fonsTextBounds(myFont, 0, 0, text.c_str(), nullptr, nullptr);
     818           0 :         const double borderWidth = size * relBorder;
     819           0 :         const double boxHeight = size * (0.32 + 0.6 * relMargin);
     820           0 :         const double boxWidth = stringWidth + size * relMargin;
     821           0 :         GLHelper::pushMatrix();
     822           0 :         glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
     823           0 :         glTranslated(pos.x(), pos.y(), layer);
     824           0 :         glRotated(-angle, 0, 0, 1);
     825           0 :         Position left(-boxWidth * 0.5, 0);
     826           0 :         setColor(borderColor);
     827           0 :         drawBoxLine(left, boxAngle, boxWidth, boxHeight);
     828           0 :         left.add(borderWidth * 1.5, 0);
     829           0 :         setColor(bgColor);
     830           0 :         glTranslated(0, 0, 0.01);
     831           0 :         drawBoxLine(left, boxAngle, boxWidth - 3 * borderWidth, boxHeight - 2 * borderWidth);
     832           0 :         GLHelper::popMatrix();
     833             :     }
     834           0 :     drawText(text, pos, layer + 0.02, size, txtColor, angle, align);
     835             : }
     836             : 
     837             : 
     838             : void
     839           0 : GLHelper::drawTextAtEnd(const std::string& text, const PositionVector& shape, double x,
     840             :                         const GUIVisualizationTextSettings& settings, const double scale) {
     841           0 :     GLHelper::pushMatrix();
     842             :     const Position& end = shape.back();
     843           0 :     const Position& f = shape[-2];
     844           0 :     const double rot = RAD2DEG(atan2((end.x() - f.x()), (f.y() - end.y())));
     845           0 :     glTranslated(end.x(), end.y(), 0);
     846           0 :     glRotated(rot, 0, 0, 1);
     847           0 :     drawTextBox(text, Position(x, 0.26), 0,
     848             :                 settings.scaledSize(scale, 0.01),
     849           0 :                 settings.color,
     850           0 :                 settings.bgColor,
     851             :                 RGBColor::INVISIBLE,
     852             :                 180, 0, 0.2);
     853           0 :     GLHelper::popMatrix();
     854           0 : }
     855             : 
     856             : 
     857             : void
     858       20045 : GLHelper::drawCrossTies(const PositionVector& geom, const std::vector<double>& rots,
     859             :                         const std::vector<double>& lengths, double length, double spacing,
     860             :                         double halfWidth, double offset, bool lessDetail) {
     861       20045 :     GLHelper::pushMatrix();
     862             :     // draw on top of of the white area between the rails
     863       20045 :     glTranslated(0, 0, 0.1);
     864       20045 :     int e = (int) geom.size() - 1;
     865       40400 :     for (int i = 0; i < e; ++i) {
     866       20355 :         GLHelper::pushMatrix();
     867       20355 :         glTranslated(geom[i].x(), geom[i].y(), 0.0);
     868       20355 :         glRotated(rots[i], 0, 0, 1);
     869             :         // draw crossing depending of detail
     870       20355 :         if (!lessDetail) {
     871      334605 :             for (double t = 0; t < lengths[i]; t += spacing) {
     872      314250 :                 glBegin(GL_QUADS);
     873      314250 :                 glVertex2d(-halfWidth - offset, -t);
     874      314250 :                 glVertex2d(-halfWidth - offset, -t - length);
     875      314250 :                 glVertex2d(halfWidth - offset, -t - length);
     876      314250 :                 glVertex2d(halfWidth - offset, -t);
     877      314250 :                 glEnd();
     878             : #ifdef CHECK_ELEMENTCOUNTER
     879             :                 myVertexCounter += 4;
     880             : #endif
     881             :             }
     882             :         } else {
     883             :             // only draw a single rectangle if it's being drawn only for selecting
     884           0 :             glBegin(GL_QUADS);
     885           0 :             glVertex2d(-halfWidth - offset, 0);
     886           0 :             glVertex2d(-halfWidth - offset, -lengths.back());
     887           0 :             glVertex2d(halfWidth - offset, -lengths.back());
     888           0 :             glVertex2d(halfWidth - offset, 0);
     889           0 :             glEnd();
     890             : #ifdef CHECK_ELEMENTCOUNTER
     891             :             myVertexCounter += 4;
     892             : #endif
     893             :         }
     894             :         // pop three draw matrix
     895       20355 :         GLHelper::popMatrix();
     896             :     }
     897       20045 :     GLHelper::popMatrix();
     898       20045 : }
     899             : 
     900             : void
     901       52790 : GLHelper::drawInverseMarkings(const PositionVector& geom,
     902             :                               const std::vector<double>& rots,
     903             :                               const std::vector<double>& lengths,
     904             :                               double maxLength, double spacing,
     905             :                               double halfWidth, bool cl, bool cr, bool lefthand, double scale) {
     906             : 
     907       52790 :     double mw = (halfWidth + SUMO_const_laneMarkWidth * (cl ? 0.6 : 0.2)) * scale;
     908       52790 :     double mw2 = (halfWidth - SUMO_const_laneMarkWidth * (cr ? 0.6 : 0.2)) * scale;
     909       52790 :     if (cl || cr) {
     910       52234 :         if (lefthand) {
     911          18 :             mw *= -1;
     912          18 :             mw2 *= -1;
     913             :         }
     914       52234 :         int e = (int) geom.size() - 1;
     915             :         double offset = 0;
     916      127607 :         for (int i = 0; i < e; ++i) {
     917       75373 :             GLHelper::pushMatrix();
     918       75373 :             glTranslated(geom[i].x(), geom[i].y(), 2.1);
     919       75373 :             glRotated(rots[i], 0, 0, 1);
     920             :             double t;
     921      891313 :             for (t = offset; t < lengths[i]; t += spacing) {
     922      815940 :                 const double length = MIN2((double)maxLength, lengths[i] - t);
     923      815940 :                 glBegin(GL_QUADS);
     924      815940 :                 glVertex2d(-mw, -t);
     925      815940 :                 glVertex2d(-mw, -t - length);
     926      815940 :                 glVertex2d(-mw2, -t - length);
     927      815940 :                 glVertex2d(-mw2, -t);
     928      815940 :                 glEnd();
     929             : #ifdef CHECK_ELEMENTCOUNTER
     930             :                 myVertexCounter += 4;
     931             : #endif
     932      815940 :                 if (!cl || !cr) {
     933             :                     // draw inverse marking between asymmetrical lane markings
     934         638 :                     const double length2 = MIN2((double)6, lengths[i] - t);
     935         638 :                     glBegin(GL_QUADS);
     936         638 :                     glVertex2d(-halfWidth + 0.02, -t - length2);
     937         638 :                     glVertex2d(-halfWidth + 0.02, -t - length);
     938         638 :                     glVertex2d(-halfWidth - 0.02, -t - length);
     939         638 :                     glVertex2d(-halfWidth - 0.02, -t - length2);
     940         638 :                     glEnd();
     941             : #ifdef CHECK_ELEMENTCOUNTER
     942             :                     myVertexCounter += 4;
     943             : #endif
     944             :                 }
     945             :             }
     946       75373 :             offset = t - lengths[i] - spacing;
     947       75373 :             GLHelper::popMatrix();
     948             :         }
     949             :     }
     950       52790 : }
     951             : 
     952             : 
     953             : void
     954           0 : GLHelper::debugVertices(const PositionVector& shape, const GUIVisualizationTextSettings& settings, double scale, double layer) {
     955           0 :     RGBColor color = RGBColor::randomHue();
     956           0 :     for (int i = 0; i < (int)shape.size(); ++i) {
     957           0 :         drawTextBox(toString(i), shape[i], layer,
     958             :                     settings.scaledSize(scale),
     959             :                     color,
     960           0 :                     settings.bgColor,
     961             :                     RGBColor::INVISIBLE,
     962             :                     0, 0, 0.2);
     963             :     }
     964           0 : }
     965             : 
     966             : 
     967             : void
     968           0 : GLHelper::drawBoundary(const GUIVisualizationSettings& s, const Boundary& b) {
     969           0 :     if (s.drawBoundaries) {
     970           0 :         GLHelper::pushMatrix();
     971           0 :         GLHelper::setColor(RGBColor::MAGENTA);
     972             :         // draw on top
     973           0 :         glTranslated(0, 0, 1024);
     974           0 :         drawLine(Position(b.xmin(), b.ymax()), Position(b.xmax(), b.ymax()));
     975           0 :         drawLine(Position(b.xmax(), b.ymax()), Position(b.xmax(), b.ymin()));
     976           0 :         drawLine(Position(b.xmax(), b.ymin()), Position(b.xmin(), b.ymin()));
     977           0 :         drawLine(Position(b.xmin(), b.ymin()), Position(b.xmin(), b.ymax()));
     978           0 :         GLHelper::popMatrix();
     979             :     }
     980           0 : }
     981             : 
     982             : 
     983             : /****************************************************************************/

Generated by: LCOV version 1.14