#include <config.h>
#include <cassert>
#include <utils/geom/GeomHelper.h>
#include <utils/common/StdDefs.h>
#include <utils/common/MsgHandler.h>
#include <utils/common/ToString.h>
#include <utils/options/OptionsCont.h>
#include <utils/gui/div/GUIGeometry.h>
#define FONTSTASH_IMPLEMENTATION
#ifdef _MSC_VER
#pragma warning(disable: 4505 5219)
#endif
#if __GNUC__ > 3
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-function"
#endif
#include <foreign/fontstash/fontstash.h>
#include <utils/gui/globjects/GLIncludes.h>
#define GLFONTSTASH_IMPLEMENTATION
#include <foreign/fontstash/glfontstash.h>
#include <utils/geom/Boundary.h>
#ifdef HAVE_GL2PS
#include <gl2ps.h>
#endif
#include "Roboto.h"
#include "GLHelper.h"
#define CIRCLE_RESOLUTION (double)10
#ifndef CALLBACK
#define CALLBACK
#endif
int GLHelper::myMatrixCounter = 0;
int GLHelper::myVertexCounter = 0;
int GLHelper::myMatrixCounterDebug = 0;
int GLHelper::myNameCounter = 0;
std::vector<std::pair<double, double> > GLHelper::myCircleCoords;
std::vector<RGBColor> GLHelper::myDottedcontourColors;
FONScontext* GLHelper::myFont = nullptr;
double GLHelper::myFontSize = 50.0;
bool GLHelper::myGL2PSActive = false;
void CALLBACK combCallback(GLdouble coords[3],
GLdouble* vertex_data[4],
GLfloat weight[4], GLdouble** dataOut) {
UNUSED_PARAMETER(weight);
UNUSED_PARAMETER(*vertex_data);
GLdouble* vertex;
vertex = (GLdouble*)malloc(7 * sizeof(GLdouble));
vertex[0] = coords[0];
vertex[1] = coords[1];
vertex[2] = coords[2];
*dataOut = vertex;
}
const std::vector<std::pair<double, double> >&
GLHelper::getCircleCoords() {
if (myCircleCoords.size() == 0) {
for (int i = 0; i <= (int)(360 * CIRCLE_RESOLUTION); ++i) {
const double x = (double) sin(DEG2RAD(i / CIRCLE_RESOLUTION));
const double y = (double) cos(DEG2RAD(i / CIRCLE_RESOLUTION));
myCircleCoords.push_back(std::pair<double, double>(x, y));
}
}
return myCircleCoords;
}
int
GLHelper::angleLookup(double angleDeg) {
const int numCoords = (int)getCircleCoords().size() - 1;
int index = ((int)(floor(angleDeg * CIRCLE_RESOLUTION + 0.5))) % numCoords;
if (index < 0) {
index += numCoords;
}
assert(index >= 0);
return (int)index;
}
void
GLHelper::pushMatrix() {
glPushMatrix();
#ifdef CHECK_ELEMENTCOUNTER
myMatrixCounter++;
#endif
#ifdef CHECK_PUSHPOP
myMatrixCounterDebug++;
#endif
}
void
GLHelper::popMatrix() {
glPopMatrix();
#ifdef CHECK_PUSHPOP
myMatrixCounterDebug--;
#endif
}
void
GLHelper::pushName(unsigned int name) {
glPushName(name);
#ifdef CHECK_PUSHPOP
myNameCounter++;
#endif
}
void
GLHelper::popName() {
glPopName();
#ifdef CHECK_PUSHPOP
myNameCounter--;
#endif
}
int
GLHelper::getMatrixCounter() {
return myMatrixCounter;
}
void
GLHelper::resetMatrixCounter() {
myMatrixCounter = 0;
}
int
GLHelper::getVertexCounter() {
return myVertexCounter;
}
void
GLHelper::resetVertexCounter() {
myVertexCounter = 0;
}
void
GLHelper::checkCounterMatrix() {
#ifdef CHECK_PUSHPOP
if (myMatrixCounterDebug != 0) {
WRITE_WARNING("invalid matrix counter. Check that number of pushMatrix and popMatrix functions calls are the same");
}
myMatrixCounterDebug = 0;
#endif
}
void
GLHelper::checkCounterName() {
#ifdef CHECK_PUSHPOP
if (myNameCounter != 0) {
WRITE_WARNING("invalid Name counter. Check that number of pushName and popName functions calls are the same");
}
myNameCounter = 0;
#endif
}
void
GLHelper::drawFilledPoly(const PositionVector& v, bool close) {
if (v.size() == 0) {
return;
}
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
glBegin(GL_POLYGON);
for (PositionVector::const_iterator i = v.begin(); i != v.end(); i++) {
const Position& p = *i;
glVertex2d(p.x(), p.y());
#ifdef CHECK_ELEMENTCOUNTER
myVertexCounter++;
#endif
}
if (close) {
const Position& p = *(v.begin());
glVertex2d(p.x(), p.y());
#ifdef CHECK_ELEMENTCOUNTER
myVertexCounter++;
#endif
}
glEnd();
}
void
GLHelper::drawFilledPolyTesselated(const PositionVector& v, bool close) {
if (v.size() == 0) {
return;
}
GLUtesselator* tobj = gluNewTess();
#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable: 4191)
#endif
#if defined(__GNUC__) && __GNUC__ >= 8
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wcast-function-type"
#endif
gluTessCallback(tobj, GLU_TESS_VERTEX, (GLvoid(CALLBACK*)()) &glVertex3dv);
gluTessCallback(tobj, GLU_TESS_BEGIN, (GLvoid(CALLBACK*)()) &glBegin);
gluTessCallback(tobj, GLU_TESS_END, (GLvoid(CALLBACK*)()) &glEnd);
gluTessCallback(tobj, GLU_TESS_COMBINE, (GLvoid(CALLBACK*)()) &combCallback);
#if defined(__GNUC__) && __GNUC__ >= 8
#pragma GCC diagnostic pop
#endif
#ifdef _MSC_VER
#pragma warning(pop)
#endif
gluTessProperty(tobj, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_ODD);
gluTessBeginPolygon(tobj, nullptr);
gluTessBeginContour(tobj);
double* points = new double[(v.size() + int(close)) * 3];
for (int i = 0; i != (int)v.size(); ++i) {
points[3 * i] = v[i].x();
points[3 * i + 1] = v[i].y();
points[3 * i + 2] = 0;
gluTessVertex(tobj, points + 3 * i, points + 3 * i);
}
if (close) {
const int i = (int)v.size();
points[3 * i] = v[0].x();
points[3 * i + 1] = v[0].y();
points[3 * i + 2] = 0;
gluTessVertex(tobj, points + 3 * i, points + 3 * i);
}
gluTessEndContour(tobj);
gluTessEndPolygon(tobj);
gluDeleteTess(tobj);
delete[] points;
}
void
GLHelper::drawRectangle(const Position& center, const double width, const double height) {
const double halfWidth = width * 0.5;
const double halfHeight = height * 0.5;
GLHelper::pushMatrix();
glTranslated(center.x(), center.y(), 0);
glBegin(GL_QUADS);
glVertex2d(-halfWidth, halfHeight);
glVertex2d(-halfWidth, -halfHeight);
glVertex2d(halfWidth, -halfHeight);
glVertex2d(halfWidth, halfHeight);
glEnd();
GLHelper::popMatrix();
#ifdef CHECK_ELEMENTCOUNTER
myVertexCounter += 4;
#endif
}
void
GLHelper::drawBoxLine(const Position& beg, double rot, double visLength,
double width, double offset) {
GLHelper::pushMatrix();
glTranslated(beg.x(), beg.y(), 0);
glRotated(rot, 0, 0, 1);
glBegin(GL_QUADS);
glVertex2d(-width - offset, 0);
glVertex2d(-width - offset, -visLength);
glVertex2d(width - offset, -visLength);
glVertex2d(width - offset, 0);
glEnd();
GLHelper::popMatrix();
#ifdef CHECK_ELEMENTCOUNTER
myVertexCounter += 4;
#endif
}
void
GLHelper::drawBoxLine(const Position& beg1, const Position& beg2,
double rot, double visLength,
double width) {
GLHelper::pushMatrix();
glTranslated((beg2.x() + beg1.x())*.5, (beg2.y() + beg1.y())*.5, 0);
glRotated(rot, 0, 0, 1);
glBegin(GL_QUADS);
glVertex2d(-width, 0);
glVertex2d(-width, -visLength);
glVertex2d(width, -visLength);
glVertex2d(width, 0);
glEnd();
GLHelper::popMatrix();
#ifdef CHECK_ELEMENTCOUNTER
myVertexCounter += 4;
#endif
}
bool
GLHelper::rightTurn(double angle1, double angle2) {
double delta = angle2 - angle1;
while (delta > 180) {
delta -= 360;
}
while (delta < -180) {
delta += 360;
}
return delta <= 0;
}
void
GLHelper::drawBoxLines(const PositionVector& geom,
const std::vector<double>& rots,
const std::vector<double>& lengths,
double width, int cornerDetail, double offset) {
int e = (int) geom.size() - 1;
for (int i = 0; i < e; i++) {
drawBoxLine(geom[i], rots[i], lengths[i], width, offset);
}
if (cornerDetail > 0) {
for (int i = 1; i < e; i++) {
GLHelper::pushMatrix();
glTranslated(geom[i].x(), geom[i].y(), 0.1);
double angleBeg = -rots[i - 1];
double angleEnd = 180 - rots[i];
if (rightTurn(rots[i - 1], rots[i])) {
std::swap(angleBeg, angleEnd);
}
angleBeg -= 90;
angleEnd += 90;
if (angleEnd - angleBeg > 360) {
angleBeg += 360;
}
if (angleEnd - angleBeg < -360) {
angleEnd += 360;
}
if (angleEnd > angleBeg) {
angleEnd -= 360;
}
drawFilledCircle(width + offset, cornerDetail, angleBeg, angleEnd);
GLHelper::popMatrix();
}
}
}
void
GLHelper::drawBoxLines(const PositionVector& geom,
const std::vector<double>& rots,
const std::vector<double>& lengths,
const std::vector<RGBColor>& cols,
double width, int cornerDetail, double offset) {
int e = (int) geom.size() - 1;
for (int i = 0; i < e; i++) {
setColor(cols[i]);
drawBoxLine(geom[i], rots[i], lengths[i], width, offset);
}
if (cornerDetail > 0) {
for (int i = 1; i < e; i++) {
GLHelper::pushMatrix();
setColor(cols[i]);
glTranslated(geom[i].x(), geom[i].y(), 0);
drawFilledCircle(width, cornerDetail);
GLHelper::popMatrix();
}
}
}
void
GLHelper::drawBoxLines(const PositionVector& geom1,
const PositionVector& geom2,
const std::vector<double>& rots,
const std::vector<double>& lengths,
double width) {
int minS = (int) MIN4(rots.size(), lengths.size(), geom1.size(), geom2.size());
for (int i = 0; i < minS; i++) {
GLHelper::drawBoxLine(geom1[i], geom2[i], rots[i], lengths[i], width);
}
}
void
GLHelper::drawBoxLines(const PositionVector& geom, double width) {
const auto geometry = GUIGeometry(geom);
drawBoxLines(geometry.getShape(), geometry.getShapeRotations(), geometry.getShapeLengths(), width);
}
void
GLHelper::drawLine(const Position& beg, double rot, double visLength) {
GLHelper::pushMatrix();
glTranslated(beg.x(), beg.y(), 0);
glRotated(rot, 0, 0, 1);
glBegin(GL_LINES);
glVertex2d(0, 0);
glVertex2d(0, -visLength);
glEnd();
GLHelper::popMatrix();
#ifdef CHECK_ELEMENTCOUNTER
myVertexCounter += 2;
#endif
}
void
GLHelper::drawLine(const Position& beg1, const Position& beg2,
double rot, double visLength) {
GLHelper::pushMatrix();
glTranslated((beg2.x() + beg1.x())*.5, (beg2.y() + beg1.y())*.5, 0);
glRotated(rot, 0, 0, 1);
glBegin(GL_LINES);
glVertex2d(0, 0);
glVertex2d(0, -visLength);
glEnd();
GLHelper::popMatrix();
#ifdef CHECK_ELEMENTCOUNTER
myVertexCounter += 2;
#endif
}
void
GLHelper::drawLine(const PositionVector& v) {
glBegin(GL_LINES);
int e = (int) v.size() - 1;
for (int i = 0; i < e; ++i) {
glVertex2d(v[i].x(), v[i].y());
glVertex2d(v[i + 1].x(), v[i + 1].y());
#ifdef CHECK_ELEMENTCOUNTER
myVertexCounter += 2;
#endif
}
glEnd();
}
void
GLHelper::drawLine(const PositionVector& v, const std::vector<RGBColor>& cols) {
glBegin(GL_LINES);
int e = (int) v.size() - 1;
for (int i = 0; i < e; ++i) {
setColor(cols[i]);
glVertex2d(v[i].x(), v[i].y());
glVertex2d(v[i + 1].x(), v[i + 1].y());
#ifdef CHECK_ELEMENTCOUNTER
myVertexCounter += 2;
#endif
}
glEnd();
}
void
GLHelper::drawLine(const Position& beg, const Position& end) {
glBegin(GL_LINES);
glVertex2d(beg.x(), beg.y());
glVertex2d(end.x(), end.y());
glEnd();
#ifdef CHECK_ELEMENTCOUNTER
myVertexCounter += 2;
#endif
}
void
GLHelper::drawFilledCircleDetailled(const GUIVisualizationSettings::Detail d, const double radius,
double beg, double end) {
switch (d) {
case GUIVisualizationSettings::Detail::CircleResolution32:
drawFilledCircle(radius, 32, beg, end);
break;
case GUIVisualizationSettings::Detail::CircleResolution16:
drawFilledCircle(radius, 16, beg, end);
break;
case GUIVisualizationSettings::Detail::CircleResolution8:
drawFilledCircle(radius, 8, beg, end);
break;
case GUIVisualizationSettings::Detail::CircleResolution4:
drawFilledCircleDetailled(d, radius);
break;
default:
break;
}
}
void
GLHelper::drawFilledCircleDetailled(const GUIVisualizationSettings::Detail d, const double radius) {
switch (d) {
case GUIVisualizationSettings::Detail::CircleResolution32:
drawFilledCircle(radius, 32);
break;
case GUIVisualizationSettings::Detail::CircleResolution16:
drawFilledCircle(radius, 16);
break;
case GUIVisualizationSettings::Detail::CircleResolution8:
drawFilledCircle(radius, 8);
break;
default:
GLHelper::pushMatrix();
glBegin(GL_QUADS);
glVertex2d(-radius, radius);
glVertex2d(-radius, -radius);
glVertex2d(radius, -radius);
glVertex2d(radius, radius);
glEnd();
GLHelper::popMatrix();
#ifdef CHECK_ELEMENTCOUNTER
myVertexCounter += 4;
#endif
break;
}
}
void
GLHelper::drawFilledCircle(double const radius, int const steps) {
drawFilledCircle(radius, steps, 0, 360);
}
void
GLHelper::drawFilledCircle(double radius, int steps, double beg, double end) {
const double inc = (end - beg) / (double)steps;
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
std::pair<double, double> p1 = getCircleCoords().at(angleLookup(beg));
for (int i = 0; i <= steps; ++i) {
const std::pair<double, double>& p2 = getCircleCoords().at(angleLookup(beg + i * inc));
glBegin(GL_TRIANGLES);
glVertex2d(p1.first * radius, p1.second * radius);
glVertex2d(p2.first * radius, p2.second * radius);
glVertex2d(0, 0);
glEnd();
p1 = p2;
#ifdef CHECK_ELEMENTCOUNTER
myVertexCounter += 3;
#endif
}
}
void
GLHelper::drawOutlineCircle(double radius, double iRadius, int steps) {
drawOutlineCircle(radius, iRadius, steps, 0, 360);
}
void
GLHelper::drawOutlineCircle(double radius, double iRadius, int steps,
double beg, double end) {
const double inc = (end - beg) / (double)steps;
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
std::pair<double, double> p1 = getCircleCoords().at(angleLookup(beg));
for (int i = 0; i <= steps; ++i) {
const std::pair<double, double>& p2 = getCircleCoords().at(angleLookup(beg + i * inc));
glBegin(GL_TRIANGLES);
glVertex2d(p1.first * radius, p1.second * radius);
glVertex2d(p2.first * radius, p2.second * radius);
glVertex2d(p2.first * iRadius, p2.second * iRadius);
glVertex2d(p2.first * iRadius, p2.second * iRadius);
glVertex2d(p1.first * iRadius, p1.second * iRadius);
glVertex2d(p1.first * radius, p1.second * radius);
glEnd();
p1 = p2;
#ifdef CHECK_ELEMENTCOUNTER
myVertexCounter += 6;
#endif
}
}
void
GLHelper::drawTriangleAtEnd(const Position& p1, const Position& p2, double tLength,
double tWidth, const double extraOffset) {
const double length = p1.distanceTo(p2);
if (length < tLength) {
tWidth *= length / tLength;
tLength = length;
}
Position rl(PositionVector::positionAtOffset(p1, p2, length - tLength));
GLHelper::pushMatrix();
glTranslated(rl.x(), rl.y(), 0);
glRotated(-GeomHelper::naviDegree(p1.angleTo2D(p2)), 0, 0, 1);
glTranslated(0, extraOffset, 0);
glBegin(GL_TRIANGLES);
glVertex2d(0, tLength);
glVertex2d(-tWidth, 0);
glVertex2d(+tWidth, 0);
glEnd();
GLHelper::popMatrix();
#ifdef CHECK_ELEMENTCOUNTER
myVertexCounter += 3;
#endif
}
void
GLHelper::setColor(const RGBColor& c) {
glColor4ub(c.red(), c.green(), c.blue(), c.alpha());
}
RGBColor
GLHelper::getColor() {
GLdouble current[4];
glGetDoublev(GL_CURRENT_COLOR, current);
return RGBColor(static_cast<unsigned char>(current[0] * 255. + 0.5),
static_cast<unsigned char>(current[1] * 255. + 0.5),
static_cast<unsigned char>(current[2] * 255. + 0.5),
static_cast<unsigned char>(current[3] * 255. + 0.5));
}
void
GLHelper::resetFont() {
glfonsDelete(myFont);
myFont = nullptr;
}
void
GLHelper::setGL2PS(bool active) {
myGL2PSActive = active;
}
void
GLHelper::drawSpaceOccupancies(const double exaggeration, const Position& pos, const double rotation,
const double width, const double length, const bool vehicle) {
PositionVector geom;
const double w = width / 2. - 0.1 * exaggeration;
const double h = length;
geom.push_back(Position(-w, +0, 0.));
geom.push_back(Position(+w, +0, 0.));
geom.push_back(Position(+w, +h, 0.));
geom.push_back(Position(-w, +h, 0.));
geom.push_back(Position(-w, +0, 0.));
GLHelper::pushMatrix();
glTranslated(pos.x(), pos.y(), pos.z());
glRotated(rotation, 0, 0, 1);
GLHelper::setColor(vehicle ? RGBColor::RED : RGBColor::GREEN);
GLHelper::drawBoxLines(geom, 0.1 * exaggeration);
GLHelper::popMatrix();
}
bool
GLHelper::initFont() {
if (myFont == nullptr) {
myFont = glfonsCreate(2048, 2048, FONS_ZERO_BOTTOMLEFT);
if (myFont != nullptr) {
const int fontNormal = fonsAddFontMem(myFont, "medium", data_font_Roboto_Medium_ttf, data_font_Roboto_Medium_ttf_len, 0);
fonsSetFont(myFont, fontNormal);
fonsSetSize(myFont, (float)myFontSize);
}
}
return myFont != nullptr;
}
const std::vector<RGBColor>&
GLHelper::getDottedcontourColors(const int size) {
while ((int)myDottedcontourColors.size() < size) {
if (myDottedcontourColors.empty() || myDottedcontourColors.back() == RGBColor::WHITE) {
myDottedcontourColors.push_back(RGBColor::BLACK);
} else {
myDottedcontourColors.push_back(RGBColor::WHITE);
}
}
return myDottedcontourColors;
}
double
GLHelper::getTextWidth(const std::string& text, double size) {
return size / myFontSize * fonsTextBounds(myFont, 0, 0, text.c_str(), nullptr, nullptr);
}
void
GLHelper::drawText(const std::string& text, const Position& pos, const double layer, const double size,
const RGBColor& col, const double angle, const int align, double width) {
if (width <= 0) {
width = size;
}
if (!initFont()) {
return;
}
GLHelper::pushMatrix();
glAlphaFunc(GL_GREATER, 0.5);
glEnable(GL_ALPHA_TEST);
#ifdef HAVE_GL2PS
if (myGL2PSActive) {
glRasterPos3d(pos.x(), pos.y(), layer);
GLfloat color[] = {col.red() / 255.f, col.green() / 255.f, col.blue() / 255.f, col.alpha() / 255.f};
gl2psTextOptColor(text.c_str(), "Roboto", 10, align == 0 ? GL2PS_TEXT_C : align, (GLfloat) - angle, color);
GLHelper::popMatrix();
return;
}
#endif
glTranslated(pos.x(), pos.y(), layer);
glScaled(width / myFontSize, size / myFontSize, 1.);
glRotated(-angle, 0, 0, 1);
fonsSetAlign(myFont, align == 0 ? FONS_ALIGN_CENTER | FONS_ALIGN_MIDDLE : align);
fonsSetColor(myFont, glfonsRGBA(col.red(), col.green(), col.blue(), col.alpha()));
fonsDrawText(myFont, 0., 0., text.c_str(), nullptr);
GLHelper::popMatrix();
}
void
GLHelper::drawTextSettings(
const GUIVisualizationTextSettings& settings,
const std::string& text, const Position& pos,
const double scale,
const double angle,
const double layer,
const int align) {
drawTextBox(text, pos, layer,
settings.scaledSize(scale),
settings.color,
settings.bgColor,
RGBColor::INVISIBLE,
angle, 0, 0.2, align);
}
void
GLHelper::drawTextBox(const std::string& text, const Position& pos,
const double layer, const double size,
const RGBColor& txtColor, const RGBColor& bgColor, const RGBColor& borderColor,
const double angle,
const double relBorder,
const double relMargin,
const int align) {
if (!initFont()) {
return;
};
if (bgColor.alpha() != 0) {
const double boxAngle = 90;
const double stringWidth = size / myFontSize * fonsTextBounds(myFont, 0, 0, text.c_str(), nullptr, nullptr);
const double borderWidth = size * relBorder;
const double boxHeight = size * (0.32 + 0.6 * relMargin);
const double boxWidth = stringWidth + size * relMargin;
GLHelper::pushMatrix();
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
glTranslated(pos.x(), pos.y(), layer);
glRotated(-angle, 0, 0, 1);
Position left(-boxWidth * 0.5, 0);
setColor(borderColor);
drawBoxLine(left, boxAngle, boxWidth, boxHeight);
left.add(borderWidth * 1.5, 0);
setColor(bgColor);
glTranslated(0, 0, 0.01);
drawBoxLine(left, boxAngle, boxWidth - 3 * borderWidth, boxHeight - 2 * borderWidth);
GLHelper::popMatrix();
}
drawText(text, pos, layer + 0.02, size, txtColor, angle, align);
}
void
GLHelper::drawTextAtEnd(const std::string& text, const PositionVector& shape, double x,
const GUIVisualizationTextSettings& settings, const double scale) {
GLHelper::pushMatrix();
const Position& end = shape.back();
const Position& f = shape[-2];
const double rot = RAD2DEG(atan2((end.x() - f.x()), (f.y() - end.y())));
glTranslated(end.x(), end.y(), 0);
glRotated(rot, 0, 0, 1);
drawTextBox(text, Position(x, 0.26), 0,
settings.scaledSize(scale, 0.01),
settings.color,
settings.bgColor,
RGBColor::INVISIBLE,
180, 0, 0.2);
GLHelper::popMatrix();
}
void
GLHelper::drawCrossTies(const PositionVector& geom, const std::vector<double>& rots,
const std::vector<double>& lengths, double length, double spacing,
double halfWidth, double offset, bool lessDetail) {
GLHelper::pushMatrix();
glTranslated(0, 0, 0.1);
int e = (int) geom.size() - 1;
for (int i = 0; i < e; ++i) {
GLHelper::pushMatrix();
glTranslated(geom[i].x(), geom[i].y(), 0.0);
glRotated(rots[i], 0, 0, 1);
if (!lessDetail) {
for (double t = 0; t < lengths[i]; t += spacing) {
glBegin(GL_QUADS);
glVertex2d(-halfWidth - offset, -t);
glVertex2d(-halfWidth - offset, -t - length);
glVertex2d(halfWidth - offset, -t - length);
glVertex2d(halfWidth - offset, -t);
glEnd();
#ifdef CHECK_ELEMENTCOUNTER
myVertexCounter += 4;
#endif
}
} else {
glBegin(GL_QUADS);
glVertex2d(-halfWidth - offset, 0);
glVertex2d(-halfWidth - offset, -lengths.back());
glVertex2d(halfWidth - offset, -lengths.back());
glVertex2d(halfWidth - offset, 0);
glEnd();
#ifdef CHECK_ELEMENTCOUNTER
myVertexCounter += 4;
#endif
}
GLHelper::popMatrix();
}
GLHelper::popMatrix();
}
void
GLHelper::drawInverseMarkings(const PositionVector& geom,
const std::vector<double>& rots,
const std::vector<double>& lengths,
double maxLength, double spacing,
double halfWidth, bool cl, bool cr, bool lefthand, double scale) {
double mw = (halfWidth + SUMO_const_laneMarkWidth * (cl ? 0.6 : 0.2)) * scale;
double mw2 = (halfWidth - SUMO_const_laneMarkWidth * (cr ? 0.6 : 0.2)) * scale;
if (cl || cr) {
if (lefthand) {
mw *= -1;
mw2 *= -1;
}
int e = (int) geom.size() - 1;
double offset = 0;
for (int i = 0; i < e; ++i) {
GLHelper::pushMatrix();
glTranslated(geom[i].x(), geom[i].y(), 2.1);
glRotated(rots[i], 0, 0, 1);
double t;
for (t = offset; t < lengths[i]; t += spacing) {
const double length = MIN2((double)maxLength, lengths[i] - t);
glBegin(GL_QUADS);
glVertex2d(-mw, -t);
glVertex2d(-mw, -t - length);
glVertex2d(-mw2, -t - length);
glVertex2d(-mw2, -t);
glEnd();
#ifdef CHECK_ELEMENTCOUNTER
myVertexCounter += 4;
#endif
if (!cl || !cr) {
const double length2 = MIN2((double)6, lengths[i] - t);
glBegin(GL_QUADS);
glVertex2d(-halfWidth + 0.02, -t - length2);
glVertex2d(-halfWidth + 0.02, -t - length);
glVertex2d(-halfWidth - 0.02, -t - length);
glVertex2d(-halfWidth - 0.02, -t - length2);
glEnd();
#ifdef CHECK_ELEMENTCOUNTER
myVertexCounter += 4;
#endif
}
}
offset = t - lengths[i] - spacing;
GLHelper::popMatrix();
}
}
}
void
GLHelper::debugVertices(const PositionVector& shape, const GUIVisualizationTextSettings& settings, double scale, double layer) {
for (int i = 0; i < (int)shape.size(); ++i) {
drawTextBox(toString(i), shape[i], layer,
settings.scaledSize(scale),
settings.color,
settings.bgColor,
RGBColor::INVISIBLE,
0, 0, 0.2);
}
}
void
GLHelper::drawBoundary(const GUIVisualizationSettings& s, const Boundary& b) {
if (s.drawBoundaries) {
GLHelper::pushMatrix();
GLHelper::setColor(RGBColor::MAGENTA);
glTranslated(0, 0, 1024);
drawLine(Position(b.xmin(), b.ymax()), Position(b.xmax(), b.ymax()));
drawLine(Position(b.xmax(), b.ymax()), Position(b.xmax(), b.ymin()));
drawLine(Position(b.xmax(), b.ymin()), Position(b.xmin(), b.ymin()));
drawLine(Position(b.xmin(), b.ymin()), Position(b.xmin(), b.ymax()));
GLHelper::popMatrix();
}
}