LCOV - code coverage report
Current view: top level - src/utils/gui/div - GLHelper.cpp (source / functions) Coverage Total Hit
Test: lcov.info Lines: 50.1 % 471 236
Test Date: 2025-12-06 15:35:27 Functions: 54.9 % 51 28

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

Generated by: LCOV version 2.0-1