Exemple #1
0
void
ROWdrawAction_drawLinkNo(const GUILaneWrapper &lane) {
    unsigned int noLinks = lane.getLinkNumber();
    if (noLinks==0) {
        return;
    }

    // draw all links
    SUMOReal w = SUMO_const_laneWidth / (SUMOReal) noLinks;
    SUMOReal x1 = SUMO_const_laneWidth / (SUMOReal) 2.;
    glPushMatrix();
    glColor3d(.5, .5, 1);
    const Position2DVector &g = lane.getShape();
    const Position2D &end = g.getEnd();
    const Position2D &f = g[-2];
    const Position2D &s = end;
    SUMOReal rot = (SUMOReal) atan2((s.x()-f.x()), (f.y()-s.y()))*(SUMOReal) 180.0/(SUMOReal) PI;
    glTranslated(end.x(), end.y(), 0);
    glRotated(rot, 0, 0, 1);
    for (unsigned int i=0; i<noLinks; ++i) {
        SUMOReal x2 = x1 - (SUMOReal)(w/2.);
        int linkNo = lane.getLane().getLinkCont()[i]->getRespondIndex();
        glPushMatrix();
        glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
        pfSetPosition(0, 0);
        pfSetScale(1);
        SUMOReal tw = pfdkGetStringWidth(toString(linkNo).c_str());
        glRotated(180, 0, 1, 0);
        glTranslated(x2-tw/2., 0.5, 0);
        pfDrawString(toString(linkNo).c_str());
        glPopMatrix();
        x1 -= w;
    }
    glPopMatrix();
}
void
GUIJunctionWrapper::drawGL(const GUIVisualizationSettings &s) const throw() {
    // check whether it is not too small
    if (s.scale*myMaxSize<1.) {
        return;
    }
    // (optional) set id
    if (s.needsGlID) {
        glPushName(getGlID());
    }
    glColor3d(0, 0, 0);
    glTranslated(0, 0, .01);
    GLHelper::drawFilledPoly(myJunction.getShape(), true);
    glTranslated(0, 0, -.01);
    // (optional) draw name
    if (s.drawJunctionName) {
        glPushMatrix();
        glTranslated(0, 0, -.06);
        Position2D p = myJunction.getPosition();
        glTranslated(p.x(), p.y(), 0);
        glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
        pfSetPosition(0, 0);
        pfSetScale(s.junctionNameSize / s.scale);
        glColor3d(s.junctionNameColor.red(), s.junctionNameColor.green(), s.junctionNameColor.blue());
        SUMOReal w = pfdkGetStringWidth(getMicrosimID().c_str());
        glRotated(180, 1, 0, 0);
        glTranslated(-w/2., 0.4, 0);
        pfDrawString(getMicrosimID().c_str());
        glPopMatrix();
    }
    // (optional) clear id
    if (s.needsGlID) {
        glPopName();
    }
}
Exemple #3
0
void
GLHelper::drawText(const std::string& text, const Position& pos,
                   const SUMOReal layer, const SUMOReal size,
                   const RGBColor& col, const SUMOReal angle) {
    glPushMatrix();
    glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
    setColor(col);
    glTranslated(pos.x(), pos.y(), layer);
    pfSetPosition(0, 0);
    pfSetScale(size);
    SUMOReal w = pfdkGetStringWidth(text.c_str());
    glRotated(180, 1, 0, 0);
    glRotated(angle, 0, 0, 1);
    glTranslated(-w / 2., size / 4, 0);
    pfDrawString(text.c_str());
    glPopMatrix();
}
Exemple #4
0
void
GLHelper::drawTextBox(const std::string& text, const Position& pos,
                      const SUMOReal layer, const SUMOReal size,
                      const RGBColor& txtColor, const RGBColor& bgColor, const RGBColor& borderColor,
                      const SUMOReal angle) {
    SUMOReal boxAngle = angle + 90;
    if (boxAngle > 360) {
        boxAngle -= 360;
    }
    pfSetScale(size);
    const SUMOReal stringWidth = pfdkGetStringWidth(text.c_str());
    const SUMOReal borderWidth = size / 20;
    const SUMOReal boxHeight = size * 0.8;
    const SUMOReal boxWidth = stringWidth + size / 2;
    glPushMatrix();
    glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
    glTranslated(0, 0, layer);
    setColor(borderColor);
    Position left = pos;
    left.sub(boxWidth / 2, -boxHeight / 2.7);
    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);
    // actually we should be able to use drawText here. however, there's
    // something about the constant 0.4 offset which causes trouble
    //drawText(text, pos, layer+0.02, size, txtColor, angle);
    setColor(txtColor);
    glTranslated(pos.x(), pos.y(), 0.01);
    pfSetPosition(0, 0);
    pfSetScale(size);
    glRotated(180, 1, 0, 0);
    glRotated(angle, 0, 0, 1);
    glTranslated(-stringWidth / 2., 0, 0);
    pfDrawString(text.c_str());
    glPopMatrix();
}
void
GUITLLogicPhasesTrackerWindow::drawValues(GUITLLogicPhasesTrackerPanel& caller) {
    // compute what shall be shown (what is visible)
    myFirstPhase2Show = 0;
    myFirstPhaseOffset = 0;
    size_t leftOffset = 0;
    myFirstTime2Show = 0;
    if (!myAmInTrackingMode) {
        myPhases.clear();
        myDurations.clear();
        // insert phases
        const MSSimpleTrafficLightLogic::Phases& phases = static_cast<MSSimpleTrafficLightLogic*>(myTLLogic)->getPhases();
        MSSimpleTrafficLightLogic::Phases::const_iterator j;
        myLastTime = 0;
        myBeginTime = 0;
        for (j = phases.begin(); j != phases.end(); ++j) {
            myPhases.push_back(*(*j));
            myDurations.push_back((*j)->duration);
            myLastTime += (*j)->duration;
        }
        if (myLastTime <= myBeginTime) {
            WRITE_ERROR("Overflow in time computation occured.");
            return;
        }
    } else {
        SUMOTime beginOffset = TIME2STEPS(myBeginOffset->getValue());
        myBeginTime = myLastTime - beginOffset;
        myFirstTime2Show = myBeginTime;
        // check whether no phases are known at all
        if (myDurations.size() != 0) {
            SUMOTime durs = 0;
            size_t phaseOffset = myDurations.size() - 1;
            DurationsVector::reverse_iterator i = myDurations.rbegin();
            while (i != myDurations.rend()) {
                if (durs + (*i) > beginOffset) {
                    myFirstPhase2Show = phaseOffset;
                    myFirstPhaseOffset = (durs + (*i)) - beginOffset;
                    break;
                }
                durs += (*i);
                phaseOffset--;
                ++i;
            }
            if (i == myDurations.rend()) {
                // there are too few information stored;
                myFirstPhase2Show = 0;
                myFirstPhaseOffset = 0;
                leftOffset = beginOffset - durs;
            }
        }
    }
    // begin drawing
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    glTranslated(-1, -1, 0);
    glScaled(2, 2, 1);
    glDisable(GL_TEXTURE_2D);
    // draw the horizontal lines dividing the signal groups
    glColor3d(1, 1, 1);
    // compute some values needed more than once
    const SUMOReal height = (SUMOReal) caller.getHeight();
    const SUMOReal width = (SUMOReal) caller.getWidth();
    pfSetScaleXY((SUMOReal)(.08 * 300. / width), (SUMOReal)(.08 * 300. / height));
    const SUMOReal h4 = ((SUMOReal) 4 / height);
    const SUMOReal h9 = ((SUMOReal) 9 / height);
    const SUMOReal h10 = ((SUMOReal) 10 / height);
    const SUMOReal h11 = ((SUMOReal) 11 / height);
    const SUMOReal h16 = ((SUMOReal) 16 / height);
    const SUMOReal h20 = ((SUMOReal) 20 / height);
    // draw the link names and the lines dividing them
    SUMOReal h = (SUMOReal)(1.0 - h10);
    SUMOReal h2 = 12;
    for (size_t i = 0; i < myTLLogic->getLinks().size() + 1; ++i) {
        // draw the bar
        glBegin(GL_LINES);
        glVertex2d(0, h);
        glVertex2d((SUMOReal)(30. / width), h);
        glEnd();
        // draw the name
        if (i < myTLLogic->getLinks().size()) {
            glRotated(180, 1, 0, 0);
            pfSetPosition(0, 0);
            glTranslated(0.0, -h + h20 - h4, 0);
            pfDrawString(myLinkNames[i].c_str());
            glTranslated(-0.0, h - h20 + h4, 0);
            glRotated(-180, 1, 0, 0);
            h2 += 20;
        }
        h -= h20;
    }
    glBegin(GL_LINES);
    glVertex2d(0, h + h20);
    glVertex2d(1.0, h + h20);
    glEnd();

    // draw the names closure (vertical line)
    h += (SUMOReal) 20 / height;
    glColor3d(1, 1, 1);
    glBegin(GL_LINES);
    glVertex2d((SUMOReal) 30 / width, 1.0);
    glVertex2d((SUMOReal) 30 / width, h);
    glEnd();


    // draw the phases
    // disable value addition while drawing
    myLock.lock();
    // determine the initial offset
    SUMOReal x = ((SUMOReal) 31. / width);
    SUMOReal ta = (SUMOReal) leftOffset / width;
    ta *= (SUMOReal)(((width - 31.0) / ((SUMOReal)(myLastTime - myBeginTime))));
    x += ta;

    // and the initial phase information
    PhasesVector::iterator pi = myPhases.begin() + myFirstPhase2Show;
    DurationsVector::iterator pd = myDurations.begin() + myFirstPhase2Show;
    size_t fpo = myFirstPhaseOffset;

    // start drawing
    for (size_t i = 30; pd != myDurations.end();) {
        // the first phase may be drawn incompletely
        size_t duration = *pd - fpo;
        // compute the heigh and the width of the phase
        h = (SUMOReal)(1.0 - h10);
        SUMOReal a = (SUMOReal) duration / width;
        a *= (SUMOReal)(((width - 31.0) / ((SUMOReal)(myLastTime - myBeginTime))));
        SUMOReal x2 = x + a;

        // go through the links
        for (int j = 0; j < (int) myTLLogic->getLinks().size(); ++j) {
            // determine the current link's color
            LinkState state = pi->getSignalState(j);
            // draw the bar (red is drawn as a line)
            GLHelper::setColor(getLinkColor(state));
            switch (state) {
                case LINKSTATE_TL_RED:
                case LINKSTATE_TL_REDYELLOW:
                    // draw a thin line
                    glBegin(GL_QUADS);
                    glVertex2d(x, h - h11);
                    glVertex2d(x, h - h9);
                    glVertex2d(x2, h - h9);
                    glVertex2d(x2, h - h11);
                    glEnd();
                    break;
                default:
                    // draw a thick block
                    glBegin(GL_QUADS);
                    glVertex2d(x, h - h16);
                    glVertex2d(x, h - h4);
                    glVertex2d(x2, h - h4);
                    glVertex2d(x2, h - h16);
                    glEnd();
                    break;
            }
            // proceed to next link
            h -= h20;
        }
        // proceed to next phase
        i += duration;
        ++pi;
        ++pd;
        x = x2;
        // all further phases are drawn in full
        fpo = 0;
    }
    // allow value addition
    myLock.unlock();

    glColor3d(1, 1, 1);
    if (myPhases.size() != 0) {
        SUMOTime tickDist = TIME2STEPS(10);
        // patch distances - hack
        SUMOReal t = myBeginOffset != 0 ? (SUMOReal) myBeginOffset->getValue() : STEPS2TIME(myLastTime - myBeginTime);
        while (t > (width - 31.) / 4.) {
            tickDist += TIME2STEPS(10);
            t -= (SUMOReal)((width - 31.) / 4.);
        }
        // draw time information
        //h = (SUMOReal)(myTLLogic->getLinks().size() * 20 + 12);
        SUMOReal glh = (SUMOReal)(1.0 - myTLLogic->getLinks().size() * h20 - h10);
        // current begin time
        pfSetScaleXY((SUMOReal)(.05 * 300. / width), (SUMOReal)(.05 * 300. / height));
        // time ticks
        SUMOTime currTime = myFirstTime2Show;
        int pos = 31;// + /*!!!currTime*/ - myFirstTime2Show;
        SUMOReal glpos = (SUMOReal) pos / width;
        while (pos < width + 50) {
            const std::string timeStr = time2string(currTime);
            const SUMOReal w = pfdkGetStringWidth(timeStr.c_str());
            glRotated(180, 1, 0, 0);
            pfSetPosition(0, 0);
            glTranslated(glpos - w / 2., -glh + h20 - h4, 0);
            pfDrawString(timeStr.c_str());
            glTranslated(-glpos + w / 2., glh - h20 + h4, 0);
            glRotated(-180, 1, 0, 0);

            glBegin(GL_LINES);
            glVertex2d(glpos, glh);
            glVertex2d(glpos, glh - h4);
            glEnd();

            const SUMOReal a = STEPS2TIME(tickDist) * (width - 31.0) / STEPS2TIME(myLastTime - myBeginTime);
            pos += (int) a;
            glpos += a / width;
            currTime += tickDist;
        }
    }
}
void
GUITriggeredRerouter::GUITriggeredRerouterEdge::drawGL(const GUIVisualizationSettings& s) const {
    const SUMOReal exaggeration = s.addSize.getExaggeration(s);
    if (s.scale * exaggeration >= 3) {
        glPushName(getGlID());
        const SUMOReal prob = myParent->getProbability();
        if (myAmClosedEdge) {
            // draw closing symbol onto all lanes
            const RerouteInterval* const ri =
                myParent->getCurrentReroute(MSNet::getInstance()->getCurrentTimeStep());
            if (ri != 0 && prob > 0) {
                // draw only if the edge is closed at this time
                if (std::find(ri->closed.begin(), ri->closed.end(), myEdge) != ri->closed.end()) {
                    const size_t noLanes = myFGPositions.size();
                    for (size_t j = 0; j < noLanes; ++j) {
                        Position pos = myFGPositions[j];
                        SUMOReal rot = myFGRotations[j];
                        glPushMatrix();
                        glTranslated(pos.x(), pos.y(), 0);
                        glRotated(rot, 0, 0, 1);
                        glTranslated(0, -1.5, 0);
                        int noPoints = 9;
                        if (s.scale > 25) {
                            noPoints = (int)(9.0 + s.scale / 10.0);
                            if (noPoints > 36) {
                                noPoints = 36;
                            }
                        }
                        glTranslated(0, 0, getType());
                        //glScaled(exaggeration, exaggeration, 1);
                        glColor3d(0.7, 0, 0);
                        GLHelper::drawFilledCircle((SUMOReal) 1.3, noPoints);
                        glTranslated(0, 0, .1);
                        glColor3d(1, 0, 0);
                        GLHelper::drawFilledCircle((SUMOReal) 1.3, noPoints, 0, prob * 360);
                        glTranslated(0, 0, .1);
                        glColor3d(1, 1, 1);
                        glRotated(-90, 0, 0, 1);
                        glBegin(GL_TRIANGLES);
                        glVertex2d(0 - .3, -1.);
                        glVertex2d(0 - .3, 1.);
                        glVertex2d(0 + .3, 1.);
                        glVertex2d(0 + .3, -1.);
                        glVertex2d(0 - .3, -1.);
                        glVertex2d(0 + .3, 1.);
                        glEnd();
                        glPopMatrix();
                    }
                }
            }

        } else {
            // draw rerouter symbol onto all lanes
            for (size_t i = 0; i < myFGPositions.size(); ++i) {
                const Position& pos = myFGPositions[i];
                SUMOReal rot = myFGRotations[i];
                glPushMatrix();
                glTranslated(pos.x(), pos.y(), 0);
                glRotated(rot, 0, 0, 1);
                glTranslated(0, 0, getType());
                glScaled(exaggeration, exaggeration, 1);
                glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);

                glBegin(GL_TRIANGLES);
                glColor3d(1, .8f, 0);
                // base
                glVertex2d(0 - 1.4, 0);
                glVertex2d(0 - 1.4, 6);
                glVertex2d(0 + 1.4, 6);
                glVertex2d(0 + 1.4, 0);
                glVertex2d(0 - 1.4, 0);
                glVertex2d(0 + 1.4, 6);
                glEnd();

                glTranslated(0, 0, .1);
                glColor3d(0, 0, 0);
                pfSetPosition(0, 0);
                pfSetScale(3.f);
                SUMOReal w = pfdkGetStringWidth("U");
                glRotated(180, 0, 1, 0);
                glTranslated(-w / 2., 2, 0);
                pfDrawString("U");

                glTranslated(w / 2., -2, 0);
                std::string str = toString((int)(prob * 100)) + "%";
                pfSetPosition(0, 0);
                pfSetScale(.7f);
                w = pfdkGetStringWidth(str.c_str());
                glTranslated(-w / 2., 4, 0);
                pfDrawString(str.c_str());
                glPopMatrix();
            }
        }
        glPopName();
    }
}
void
GNEVariableSpeedSignal::drawGL(const GUIVisualizationSettings& s) const {
    // Start drawing adding an gl identificator
    glPushName(getGlID());

    // Add a draw matrix for drawing logo
    glPushMatrix();
    glTranslated(myShape[0].x(), myShape[0].y(), getType());
    glColor3d(1, 1, 1);
    glRotated(180, 0, 0, 1);

    // Draw icon depending of rerouter is or isn't selected
    if (isAdditionalSelected()) {
        GUITexturesHelper::drawTexturedBox(GUITextureSubSys::getTexture(GNETEXTURE_VARIABLESPEEDSIGNALSELECTED), 1);
    } else {
        GUITexturesHelper::drawTexturedBox(GUITextureSubSys::getTexture(GNETEXTURE_VARIABLESPEEDSIGNAL), 1);
    }

    // Pop draw icon matrix
    glPopMatrix();

    // Show Lock icon depending of the Edit mode
    drawLockIcon(0.4);

    // Push matrix to draw every symbol over lane
    glPushMatrix();

    // Traslate to 0,0
    glTranslated(0, 0, getType());

    // Obtain exaggeration
    const SUMOReal exaggeration = s.addSize.getExaggeration(s);

    // Iterate over lanes
    for (childLanes::const_iterator i = myChildLanes.begin(); i != myChildLanes.end(); i++) {
        // Draw every signal over Lane
        glPushMatrix();
        glScaled(exaggeration, exaggeration, 1);
        glTranslated(i->positionOverLane.x(), i->positionOverLane.y(), 0);
        glRotated(i->rotationOverLane, 0, 0, 1);
        glTranslated(0, -1.5, 0);

        int noPoints = 9;
        if (s.scale > 25) {
            noPoints = (int)(9.0 + s.scale / 10.0);
            if (noPoints > 36) {
                noPoints = 36;
            }
        }
        glColor3d(1, 0, 0);
        GLHelper::drawFilledCircle((SUMOReal) 1.3, noPoints);
        if (s.scale >= 5) {
            glTranslated(0, 0, .1);
            glColor3d(0, 0, 0);
            GLHelper::drawFilledCircle((SUMOReal) 1.1, noPoints);
            // Draw speed
            SUMOReal speed = i->lane->getSpeed();
            // Show as Km/h
            speed *= 3.6f;
            if (((int) speed + 1) % 10 == 0) {
                speed = (SUMOReal)(((int) speed + 1) / 10 * 10);
            }
            // draw the speed string
            std::string speedToDraw = toString<SUMOReal>(speed);
            glColor3d(1, 1, 0);
            glTranslated(0, 0, .1);
            glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
            pfSetPosition(0, 0);
            pfSetScale(1.2f);
            SUMOReal w = pfdkGetStringWidth(speedToDraw.c_str());
            glRotated(180, 0, 1, 0);
            glTranslated(-w / 2., 0.3, 0);
            pfDrawString(speedToDraw.c_str());
        }
        glPopMatrix();
    }

    // Pop symbol matrix
    glPopMatrix();

    // Draw connections
    drawConnections();

    // Draw name
    drawName(getCenteringBoundary().getCenter(), s.scale, s.addName);

    // Pop name
    glPopName();
}
void
GUIParameterTracker::GUIParameterTrackerPanel::drawValue(TrackerValueDesc &desc,
        SUMOReal /*namePos*/) {
    // apply scaling
    glPushMatrix();

    // apply the positiopn offset of the display
    glScaled(0.8, 0.8, 1);
    // apply value range scaling
    SUMOReal ys = (SUMOReal) 2.0 / (SUMOReal) desc.getRange();
    glScaled(1.0, ys, 1.0);
    glTranslated(-1.0, -desc.getYCenter(), 0);

    // set color
    const RGBColor &col = desc.getColor();
    SUMOReal red = (SUMOReal) col.red();
    SUMOReal green = (SUMOReal) col.green();
    SUMOReal blue = (SUMOReal) col.blue();
    // draw value bounderies
    // draw minimum boundary
    glBegin(GL_LINES);
    glVertex2d(0, desc.getMin());
    glVertex2d(2.0, desc.getMin());
    glEnd();
    glBegin(GL_LINES);
    glVertex2d(0, desc.getMax());
    glVertex2d(2.0, desc.getMax());
    glEnd();
    glColor4f(red, green, blue, 0.3f);
    for (int a=1; a<6; a++) {
        SUMOReal ypos = (desc.getRange()) / (SUMOReal) 6.0 * (SUMOReal) a + desc.getMin();
        glBegin(GL_LINES);
        glVertex2d(0, ypos);
        glVertex2d(2.0, ypos);
        glEnd();
    }
    const std::vector<SUMOReal> &values = desc.getAggregatedValues();
    SUMOReal latest = 0;
    if (values.size()<2) {
        glPopMatrix();
        desc.unlockValues();
        return;
    } else {
        latest = values.back();
        // init values
        SUMOReal xStep = (SUMOReal) 2.0 / (SUMOReal) values.size();
        std::vector<SUMOReal>::const_iterator i = values.begin();
        SUMOReal yp = (*i);
        SUMOReal xp = 0;
        i++;
        glColor4f(red, green, blue, 1.0f);
        for (; i!=values.end(); i++) {
            SUMOReal yn = (*i);
            SUMOReal xn = xp + xStep;
            glBegin(GL_LINES);
            glVertex2d(xp, yp);
            glVertex2d(xn, yn);
            glEnd();
            yp = yn;
            xp = xn;
        }
        desc.unlockValues();
        glPopMatrix();
    }

    // draw value bounderies and descriptions
    glColor3d(red, green, blue);
//    GUITexturesHelper::getFontRenderer().SetColor(red*0.5f, green*0.5f, blue*0.5f);

    // draw min time
    SUMOTime beginStep = desc.getRecordingBegin();
    std::string begStr = time2string(beginStep);
    SUMOReal w = pfdkGetStringWidth(begStr.c_str());
    glRotated(180, 1, 0, 0);
    pfSetPosition(0, 0);
    glTranslated(-0.8-w/2., 0.88, 0);
    pfDrawString(begStr.c_str());
    glTranslated(0.8+w/2., -0.88, 0);
    glRotated(-180, 1, 0, 0);

    // draw max time
    glRotated(180, 1, 0, 0);
    pfSetPosition(0, 0);
    glTranslated(0.75, 0.88, 0);
    pfDrawString(time2string(beginStep + static_cast<SUMOTime>(values.size() * desc.getAggregationSpan())).c_str());
    glTranslated(-0.75, -0.88, 0);
    glRotated(-180, 1, 0, 0);

    // draw min value
    glRotated(180, 1, 0, 0);
    pfSetPosition(0, 0);
    glTranslated(-0.98, 0.82, 0);
    pfDrawString(toString(desc.getMin()).c_str());
    glTranslated(0.98, -0.82, 0);
    glRotated(-180, 1, 0, 0);

    // draw max value
    glRotated(180, 1, 0, 0);
    pfSetPosition(0, 0);
    glTranslated(-0.98, -0.78, 0);
    pfDrawString(toString(desc.getMax()).c_str());
    glTranslated(0.98, 0.78, 0);
    glRotated(-180, 1, 0, 0);

    // draw current value
    glRotated(180, 1, 0, 0);
    pfSetPosition(0, 0);
    SUMOReal p = (SUMOReal) 0.8 -
                 ((SUMOReal) 1.6 / (desc.getMax()-desc.getMin()) * (latest-desc.getMin()));
    glTranslated(-0.98, p+.02, 0);
    pfDrawString(toString(latest).c_str());
    glTranslated(0.98, -(p+.02), 0);
    glRotated(-180, 1, 0, 0);

    // draw name
    glRotated(180, 1, 0, 0);
    pfSetPosition(0, 0);
    glTranslated(-0.98, -.92, 0);
    pfDrawString(desc.getName().c_str());
    glTranslated(0.98, .92, 0);
    glRotated(-180, 1, 0, 0);

    /*

    GUITexturesHelper::getFontRenderer().StringOut(3,
        patchHeightVal(desc, desc.getMin()),
        toString(desc.getMin()));
        // draw maximum boundary
    GUITexturesHelper::getFontRenderer().StringOut(3,
        patchHeightVal(desc, desc.getMax()),
        toString(desc.getMax()));
        // draw some further lines
    glColor4f(red, green, blue, 0.3f);
    for(int a=1; a<6; a++) {
        SUMOReal ypos = (desc.getRange()) / 6.0 * (SUMOReal) a + desc.getMin();
        glBegin( GL_LINES );
        glVertex2d(0, ypos);
        glVertex2d(2.0, ypos);
        glEnd();
    }

    const std::vector<SUMOReal> &values = desc.getAggregatedValues();
    if(values.size()<2) {
        glPopMatrix();
        desc.unlockValues();
        return;
    }

    SUMOTime beginStep = desc.getRecordingBegin();

    // init values
    SUMOReal xStep = 2.0 / ((SUMOReal) values.size());
    std::vector<SUMOReal>::const_iterator i = values.begin();
    SUMOReal yp = (*i);
    SUMOReal xp = 0;
    i++;
    // set color
    glColor4f(red, green, blue, 1.0f);
    for(; i!=values.end(); i++) {
        SUMOReal yn = (*i);
        SUMOReal xn = xp + xStep;
        glBegin( GL_LINES );
        glVertex2d(xp, yp);
        glVertex2d(xn, yn);
        glEnd();
        yp = yn;
        xp = xn;
    }
    desc.unlockValues();
    glPopMatrix();
    // set the begin and the end time step
        // begin
    std::string val = toString(beginStep);
    GUITexturesHelper::getFontRenderer().StringOut(
        (SUMOReal) (getWidth()/10.0*1.0
            - GUITexturesHelper::getFontRenderer().GetStringWidth(val)/2),
        (SUMOReal) (patchHeightVal(desc, desc.getMin())
            + GUITexturesHelper::getFontRenderer().GetHeight()),
        val);
        // end
    val = toString(beginStep + values.size()*desc.getAggregationSpan());
    GUITexturesHelper::getFontRenderer().StringOut(
        (SUMOReal) (getWidth()/10.0*9.0
            - GUITexturesHelper::getFontRenderer().GetStringWidth(val)/2),
        (SUMOReal) (patchHeightVal(desc, desc.getMin())
            + GUITexturesHelper::getFontRenderer().GetHeight()),
        val);
    // add current value string
    GUITexturesHelper::getFontRenderer().StringOut(3,
        patchHeightVal(desc, yp), toString(yp));
    GUITexturesHelper::getFontRenderer().StringOut(namePos+3, 0,
        desc.getName());
        */
}
void
GUICalibrator::drawGL(const GUIVisualizationSettings& s) const {
    glPushName(getGlID());
    std::string flow = "-";
    std::string speed = "-";
    if (isActive()) {
        if (myCurrentStateInterval->v >= 0) {
            speed = toString(myCurrentStateInterval->v) + "m/s";
        }
        if (myCurrentStateInterval->q >= 0) {
            flow = toString((int)myCurrentStateInterval->q) + "v/h";
        }
    }
    for (size_t i = 0; i < myFGPositions.size(); ++i) {
        const Position& pos = myFGPositions[i];
        SUMOReal rot = myFGRotations[i];
        glPushMatrix();
        glTranslated(pos.x(), pos.y(), getType());
        glRotated(rot, 0, 0, 1);
        glTranslated(0, 0, getType());
        glScaled(s.addExaggeration, s.addExaggeration, 1);
        glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);

        glBegin(GL_TRIANGLES);
        glColor3d(1, .8f, 0);
        // base
        glVertex2d(0 - 1.4, 0);
        glVertex2d(0 - 1.4, 6);
        glVertex2d(0 + 1.4, 6);
        glVertex2d(0 + 1.4, 0);
        glVertex2d(0 - 1.4, 0);
        glVertex2d(0 + 1.4, 6);
        glEnd();

        // draw text
        if (s.scale * s.addExaggeration >= 1.) {
            glTranslated(0, 0, .1);
            glColor3d(0, 0, 0);
            pfSetPosition(0, 0);
            pfSetScale(3.f);
            SUMOReal w = pfdkGetStringWidth("C");
            glRotated(180, 0, 1, 0);
            glTranslated(-w / 2., 2, 0);
            pfDrawString("C");
            glTranslated(w / 2., -2, 0);


            pfSetPosition(0, 0);
            pfSetScale(.7f);
            w = pfdkGetStringWidth(flow.c_str());
            glTranslated(-w / 2., 4, 0);
            pfDrawString(flow.c_str());
            glTranslated(w / 2., -4, 0);

            pfSetPosition(0, 0);
            pfSetScale(.7f);
            w = pfdkGetStringWidth(speed.c_str());
            glTranslated(-w / 2., 5, 0);
            pfDrawString(speed.c_str());
            glTranslated(-w / 2., -5, 0);
        }
        glPopMatrix();
    }
    drawName(getCenteringBoundary().getCenter(), s.scale, s.addName);
    glPopName();
}
void
GUILaneSpeedTrigger::drawGL(const GUIVisualizationSettings& s) const {
    glPushName(getGlID());
    glPushMatrix();
    glTranslated(0, 0, getType());
    for (size_t i = 0; i < myFGPositions.size(); ++i) {
        const Position& pos = myFGPositions[i];
        SUMOReal rot = myFGRotations[i];
        glPushMatrix();
        glScaled(s.addExaggeration, s.addExaggeration, 1);
        glTranslated(pos.x(), pos.y(), 0);
        glRotated(rot, 0, 0, 1);
        glTranslated(0, -1.5, 0);

        int noPoints = 9;
        if (s.scale > 25) {
            noPoints = (int)(9.0 + s.scale / 10.0);
            if (noPoints > 36) {
                noPoints = 36;
            }
        }
        glColor3d(1, 0, 0);
        GLHelper::drawFilledCircle((SUMOReal) 1.3, noPoints);
        if (s.scale >= 5) {
            glTranslated(0, 0, .1);
            glColor3d(0, 0, 0);
            GLHelper::drawFilledCircle((SUMOReal) 1.1, noPoints);
            // draw the speed string
            // not if scale to low
            // compute
            SUMOReal value = (SUMOReal) getCurrentSpeed();
            if (myShowAsKMH) {
                value *= 3.6f;
                if (((int) value + 1) % 10 == 0) {
                    value = (SUMOReal)(((int) value + 1) / 10 * 10);
                }
            }
            if (value != myLastValue) {
                myLastValue = value;
                myLastValueString = toString<SUMOReal>(myLastValue);
                size_t idx = myLastValueString.find('.');
                if (idx != std::string::npos) {
                    if (idx > myLastValueString.length()) {
                        idx = myLastValueString.length();
                    }
                    myLastValueString = myLastValueString.substr(0, idx);
                }
            }
            //draw
            glColor3d(1, 1, 0);
            glTranslated(0, 0, .1);
            glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
            pfSetPosition(0, 0);
            pfSetScale(1.2f);
            SUMOReal w = pfdkGetStringWidth(myLastValueString.c_str());
            glRotated(180, 0, 1, 0);
            glTranslated(-w / 2., 0.3, 0);
            pfDrawString(myLastValueString.c_str());
        }
        glPopMatrix();
    }
    glPopMatrix();
    drawName(getCenteringBoundary().getCenter(), s.scale, s.addName);
    glPopName();
}