GUIEdge.cpp

Go to the documentation of this file.
00001 /****************************************************************************/
00007 // A road/street connecting two junctions (gui-version)
00008 /****************************************************************************/
00009 // SUMO, Simulation of Urban MObility; see http://sumo.sourceforge.net/
00010 // Copyright 2001-2010 DLR (http://www.dlr.de/) and contributors
00011 /****************************************************************************/
00012 //
00013 //   This program is free software; you can redistribute it and/or modify
00014 //   it under the terms of the GNU General Public License as published by
00015 //   the Free Software Foundation; either version 2 of the License, or
00016 //   (at your option) any later version.
00017 //
00018 /****************************************************************************/
00019 
00020 
00021 // ===========================================================================
00022 // included modules
00023 // ===========================================================================
00024 #ifdef _MSC_VER
00025 #include <windows_config.h>
00026 #else
00027 #include <config.h>
00028 #endif
00029 
00030 #include <vector>
00031 #include <cmath>
00032 #include <string>
00033 #include <algorithm>
00034 #include <microsim/MSEdge.h>
00035 #include <microsim/MSJunction.h>
00036 #include <microsim/MSLaneChanger.h>
00037 #include <microsim/MSGlobals.h>
00038 #include <utils/gui/globjects/GUIGlObjectStorage.h>
00039 #include <utils/gui/globjects/GUIGLObjectPopupMenu.h>
00040 #include <utils/geom/GeomHelper.h>
00041 #include "GUIEdge.h"
00042 #include "GUINet.h"
00043 #include "GUILane.h"
00044 #include <utils/gui/div/GUIParameterTableWindow.h>
00045 #include <microsim/logging/CastingFunctionBinding.h>
00046 #include <microsim/logging/FunctionBinding.h>
00047 #include <utils/gui/div/GLHelper.h>
00048 #include <utils/gui/div/GUIGlobalSelection.h>
00049 #include <foreign/polyfonts/polyfonts.h>
00050 
00051 #ifdef HAVE_MESOSIM
00052 #include <mesosim/MESegment.h>
00053 #include <mesosim/MELoop.h>
00054 #include <microsim/MSGlobals.h>
00055 #endif
00056 
00057 #ifdef CHECK_MEMORY_LEAKS
00058 #include <foreign/nvwa/debug_new.h>
00059 #endif // CHECK_MEMORY_LEAKS
00060 
00061 
00062 // ===========================================================================
00063 // included modules
00064 // ===========================================================================
00065 GUIEdge::GUIEdge(const std::string &id, unsigned int numericalID,
00066                  GUIGlObjectStorage &idStorage) throw()
00067         : MSEdge(id, numericalID),
00068         GUIGlObject(idStorage, "edge:" + id) {}
00069 
00070 
00071 GUIEdge::~GUIEdge() throw() {
00072     for (LaneWrapperVector::iterator i=myLaneGeoms.begin(); i!=myLaneGeoms.end(); ++i) {
00073         delete(*i);
00074     }
00075 }
00076 
00077 
00078 void
00079 GUIEdge::initGeometry(GUIGlObjectStorage &idStorage) throw() {
00080     // don't do this twice
00081     if (myLaneGeoms.size()>0) {
00082         return;
00083     }
00084     // build the lane wrapper
00085     myLaneGeoms.reserve(myLanes->size());
00086     for (std::vector<MSLane*>::const_iterator i=myLanes->begin(); i<myLanes->end(); ++i) {
00087         myLaneGeoms.push_back((*i)->buildLaneWrapper(idStorage));
00088     }
00089 }
00090 
00091 
00092 MSLane &
00093 GUIEdge::getLane(size_t laneNo) {
00094     assert(laneNo<myLanes->size());
00095     return *((*myLanes)[laneNo]);
00096 }
00097 
00098 
00099 GUILaneWrapper &
00100 GUIEdge::getLaneGeometry(size_t laneNo) const {
00101     assert(laneNo<myLanes->size());
00102     return *(myLaneGeoms[laneNo]);
00103 }
00104 
00105 
00106 GUILaneWrapper &
00107 GUIEdge::getLaneGeometry(const MSLane *lane) const {
00108     LaneWrapperVector::const_iterator i=
00109         find_if(myLaneGeoms.begin(), myLaneGeoms.end(), lane_wrapper_finder(*lane));
00110     assert(i!=myLaneGeoms.end());
00111     return *(*i);
00112 }
00113 
00114 
00115 std::vector<GLuint>
00116 GUIEdge::getIDs() {
00117     std::vector<GLuint> ret;
00118     ret.reserve(MSEdge::myDict.size());
00119     for (MSEdge::DictType::iterator i=MSEdge::myDict.begin(); i!=MSEdge::myDict.end(); ++i) {
00120         ret.push_back(static_cast<GUIEdge*>((*i).second)->getGlID());
00121     }
00122     return ret;
00123 }
00124 
00125 
00126 Boundary
00127 GUIEdge::getBoundary() const {
00128     Boundary ret;
00129     for (LaneWrapperVector::const_iterator i=myLaneGeoms.begin(); i!=myLaneGeoms.end(); ++i) {
00130         const Position2DVector &g = (*i)->getShape();
00131         for (unsigned int j=0; j<g.size(); j++) {
00132             ret.add(g[j]);
00133         }
00134     }
00135     ret.grow(10);
00136     return ret;
00137 }
00138 
00139 
00140 void
00141 GUIEdge::fill(std::vector<GUIEdge*> &netsWrappers) {
00142     size_t size = MSEdge::dictSize();
00143     netsWrappers.reserve(size);
00144     for (DictType::iterator i=myDict.begin(); i!=myDict.end(); ++i) {
00145         if (i->second->getPurpose() != MSEdge::EDGEFUNCTION_DISTRICT) {
00146             netsWrappers.push_back(static_cast<GUIEdge*>((*i).second));
00147         }
00148     }
00149 }
00150 
00151 
00152 
00153 GUIGLObjectPopupMenu *
00154 GUIEdge::getPopUpMenu(GUIMainWindow &app, GUISUMOAbstractView &parent) throw() {
00155     GUIGLObjectPopupMenu *ret = new GUIGLObjectPopupMenu(app, parent, *this);
00156     buildPopupHeader(ret, app);
00157     buildCenterPopupEntry(ret);
00158     buildNameCopyPopupEntry(ret);
00159     buildSelectionPopupEntry(ret);
00160 #ifdef HAVE_MESOSIM
00161     if (MSGlobals::gUseMesoSim) {
00162         buildShowParamsPopupEntry(ret);
00163     }
00164 #endif
00165     buildPositionCopyEntry(ret, false);
00166     return ret;
00167 }
00168 
00169 
00170 GUIParameterTableWindow *
00171 GUIEdge::getParameterWindow(GUIMainWindow &app,
00172                             GUISUMOAbstractView &) throw() {
00173     GUIParameterTableWindow *ret = 0;
00174 #ifdef HAVE_MESOSIM
00175     ret = new GUIParameterTableWindow(app, *this, 5);
00176     // add items
00177     ret->mkItem("length [m]", false, (*myLanes)[0]->getLength());
00178     ret->mkItem("allowed speed [m/s]", false, getAllowedSpeed());
00179     ret->mkItem("occupancy [%]", true,
00180                 new FunctionBinding<GUIEdge, SUMOReal>(this, &GUIEdge::getOccupancy));
00181     ret->mkItem("mean vehicle speed [m/s]", true,
00182                 new FunctionBinding<GUIEdge, SUMOReal>(this, &GUIEdge::getMeanSpeed));
00183     ret->mkItem("flow [veh/h/lane]", true,
00184                 new FunctionBinding<GUIEdge, SUMOReal>(this, &GUIEdge::getFlow));
00185     ret->mkItem("#vehicles", true,
00186                 new CastingFunctionBinding<GUIEdge, SUMOReal, unsigned int>(this, &GUIEdge::getVehicleNo));
00187     // close building
00188     ret->closeBuilding();
00189 #endif
00190     return ret;
00191 }
00192 
00193 
00194 const std::string &
00195 GUIEdge::getMicrosimID() const throw() {
00196     return getID();
00197 }
00198 
00199 
00200 Boundary
00201 GUIEdge::getCenteringBoundary() const throw() {
00202     Boundary b = getBoundary();
00203     b.grow(20);
00204     return b;
00205 }
00206 
00207 
00208 void
00209 GUIEdge::drawGL(const GUIVisualizationSettings &s) const throw() {
00210     if (s.hideConnectors&&myFunction==MSEdge::EDGEFUNCTION_CONNECTOR) {
00211         return;
00212     }
00213     // draw the lanes
00214     for (LaneWrapperVector::const_iterator i=myLaneGeoms.begin(); i!=myLaneGeoms.end(); ++i) {
00215 #ifdef HAVE_MESOSIM
00216         if (MSGlobals::gUseMesoSim) {
00217             s.edgeColorer.setGlColor(*this);
00218         }
00219 #endif
00220         (*i)->drawGL(s);
00221     }
00222     // check whether lane boundaries shall be drawn
00223     if (s.scale>1.&&s.laneShowBorders&&myFunction!=MSEdge::EDGEFUNCTION_INTERNAL) {
00224         glTranslated(0, 0, .01);
00225         for (LaneWrapperVector::const_iterator i=myLaneGeoms.begin()+1; i!=myLaneGeoms.end(); ++i) {
00226             (*i)->drawBordersGL(s);
00227         }
00228         glTranslated(0, 0, -.01);
00229         // draw white boundings
00230         glTranslated(0, 0, .02);
00231         glColor3d(1,1,1);
00232         for (LaneWrapperVector::const_iterator i=myLaneGeoms.begin(); i!=myLaneGeoms.end(); ++i) {
00233             GLHelper::drawBoxLines((*i)->getShape(), (*i)->getShapeRotations(), (*i)->getShapeLengths(), SUMO_const_halfLaneAndOffset);
00234         }
00235         glTranslated(0, 0, -.02);
00236     }
00237 #ifdef HAVE_MESOSIM
00238     if (MSGlobals::gUseMesoSim) {
00239         size_t idx = 0;
00240         for (LaneWrapperVector::const_iterator l=myLaneGeoms.begin(); l!=myLaneGeoms.end(); ++l,++idx) {
00241             const Position2DVector& shape = (*l)->getShape();
00242             const DoubleVector& shapeRotations = (*l)->getShapeRotations();
00243             const DoubleVector& shapeLengths = (*l)->getShapeLengths();
00244             const Position2D &laneBeg = shape[0];
00245 
00246             glColor3d(1,1,0);
00247             glPushMatrix();
00248             glTranslated(laneBeg.x(), laneBeg.y(), 0);
00249             glRotated(shapeRotations[0], 0, 0, 1);
00250             // go through the vehicles
00251             int shapePos = 0;
00252             SUMOReal positionOffset = 0;
00253             SUMOReal position = 0;
00254             for (MESegment *segment = MSGlobals::gMesoNet->getSegmentForEdge(*this); segment!=0; segment = segment->getNextSegment()) {
00255                 const std::vector<size_t> numCars = segment->getQueSizes();
00256                 const SUMOReal length = segment->getLength();
00257                 if (idx < numCars.size()) {
00258                     const SUMOReal avgCarSize = segment->getOccupancy() / segment->getCarNumber();
00259                     for (size_t i = 0; i < numCars[idx]; i++) {
00260                         SUMOReal vehiclePosition = position + length - i * avgCarSize;
00261                         SUMOReal xOff = 0.f;
00262                         while (vehiclePosition < position) {
00263                             vehiclePosition += length;
00264                             xOff += 0.5f;
00265                         }
00266                         while (shapePos<(int)shapeRotations.size()-1 && vehiclePosition>positionOffset+shapeLengths[shapePos]) {
00267                             glPopMatrix();
00268                             positionOffset += shapeLengths[shapePos];
00269                             shapePos++;
00270                             glPushMatrix();
00271                             glTranslated(shape[shapePos].x(), shape[shapePos].y(), 0);
00272                             glRotated(shapeRotations[shapePos], 0, 0, 1);
00273                         }
00274                         glPushMatrix();
00275                         glTranslated(xOff, -(vehiclePosition-positionOffset), 0);
00276                         glPushMatrix();
00277                         glScaled(1, avgCarSize, 1);
00278                         glBegin(GL_TRIANGLES);
00279                         glVertex2d(0, 0);
00280                         glVertex2d(0-1.25, 1);
00281                         glVertex2d(0+1.25, 1);
00282                         glEnd();
00283                         glPopMatrix();
00284                         glPopMatrix();
00285                     }
00286                 }
00287                 position += length;
00288             }
00289             glPopMatrix();
00290         }
00291     }
00292 #endif
00293     // (optionally) draw the name
00294     if ((s.drawEdgeName && myFunction == EDGEFUNCTION_NORMAL) || (s.drawInternalEdgeName && myFunction != EDGEFUNCTION_NORMAL)) {
00295         float nameSize = s.edgeNameSize;
00296         if (myFunction == EDGEFUNCTION_NORMAL) {
00297             glColor3d(s.edgeNameColor.red(), s.edgeNameColor.green(), s.edgeNameColor.blue());
00298         } else {
00299             glColor3d(s.internalEdgeNameColor.red(), s.internalEdgeNameColor.green(), s.internalEdgeNameColor.blue());
00300             nameSize = s.internalEdgeNameSize;
00301         }
00302         GUILaneWrapper *lane1 = myLaneGeoms[0];
00303         GUILaneWrapper *lane2 = myLaneGeoms[myLaneGeoms.size()-1];
00304         glPushMatrix();
00305         glTranslated(0, 0, -.06);
00306         Position2D p = lane1->getShape().positionAtLengthPosition(lane1->getShape().length()/(SUMOReal) 2.);
00307         p.add(lane2->getShape().positionAtLengthPosition(lane2->getShape().length()/(SUMOReal) 2.));
00308         p.mul(.5);
00309         glTranslated(p.x(), p.y(), 0);
00310         glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
00311         pfSetPosition(0, 0);
00312         pfSetScale(nameSize / s.scale);
00313         SUMOReal w = pfdkGetStringWidth(getMicrosimID().c_str());
00314         glRotated(180, 1, 0, 0);
00315         SUMOReal angle = lane1->getShape().rotationDegreeAtLengthPosition(lane1->getShape().length()/(SUMOReal) 2.);
00316         angle += 90;
00317         if (angle>90&&angle<270) {
00318             angle -= 180;
00319         }
00320         glRotated(angle, 0, 0, 1);
00321         glTranslated(-w/2., .2*nameSize / s.scale, 0);
00322         pfDrawString(getMicrosimID().c_str());
00323         glTranslated(0, 0, .06);
00324         glPopMatrix();
00325     }
00326 }
00327 
00328 #ifdef HAVE_MESOSIM
00329 unsigned int
00330 GUIEdge::getVehicleNo() const {
00331     size_t vehNo = 0;
00332     for (MESegment *segment = MSGlobals::gMesoNet->getSegmentForEdge(*this); segment!=0; segment = segment->getNextSegment()) {
00333         vehNo += segment->getCarNumber();
00334     }
00335     return (unsigned int)vehNo;
00336 }
00337 
00338 
00339 SUMOReal
00340 GUIEdge::getFlow() const {
00341     SUMOReal flow = 0;
00342     for (MESegment *segment = MSGlobals::gMesoNet->getSegmentForEdge(*this); segment!=0; segment = segment->getNextSegment()) {
00343         flow += (SUMOReal) segment->getCarNumber() * segment->getMeanSpeed();
00344     }
00345     return flow *(SUMOReal) 1000. / (*myLanes)[0]->getLength() / (SUMOReal) 3.6;;
00346 }
00347 
00348 
00349 SUMOReal
00350 GUIEdge::getOccupancy() const {
00351     SUMOReal occ = 0;
00352     for (MESegment *segment = MSGlobals::gMesoNet->getSegmentForEdge(*this); segment!=0; segment = segment->getNextSegment()) {
00353         occ += segment->getOccupancy();
00354     }
00355     return occ/(*myLanes)[0]->getLength()/(SUMOReal)(myLanes->size());
00356 }
00357 
00358 
00359 SUMOReal
00360 GUIEdge::getMeanSpeed() const {
00361     SUMOReal v = 0;
00362     SUMOReal no = 0;
00363     for (MESegment *segment = MSGlobals::gMesoNet->getSegmentForEdge(*this); segment!=0; segment = segment->getNextSegment()) {
00364         SUMOReal vehNo = (SUMOReal) segment->getCarNumber();
00365         v += vehNo * segment->getMeanSpeed();
00366         no += vehNo;
00367     }
00368     return v/no;
00369 }
00370 
00371 
00372 SUMOReal
00373 GUIEdge::getAllowedSpeed() const {
00374     return (*myLanes)[0]->getMaxSpeed();
00375 }
00376 
00377 
00378 GUIEdge::Colorer::Colorer() {
00379     mySchemes.push_back(GUIColorScheme("uniform (streetwise)", RGBColor(0,0,0), "", true));
00380     mySchemes.push_back(GUIColorScheme("by selection (streetwise)", RGBColor(0.7f, 0.7f, 0.7f), "unselected", true));
00381     mySchemes.back().addColor(RGBColor(0, .4f, .8f), 1, "selected");
00382     mySchemes.push_back(GUIColorScheme("by purpose (streetwise)", RGBColor(0,0,0), "normal", true));
00383     mySchemes.back().addColor(RGBColor(.5, 0, .5), MSEdge::EDGEFUNCTION_CONNECTOR, "connector");
00384     mySchemes.back().addColor(RGBColor(0, 0, 1), MSEdge::EDGEFUNCTION_INTERNAL, "internal");
00385     mySchemes.push_back(GUIColorScheme("by allowed speed (streetwise)", RGBColor(1,0,0)));
00386     mySchemes.back().addColor(RGBColor(0, 0, 1), (SUMOReal)(150.0/3.6));
00387     mySchemes.push_back(GUIColorScheme("by current occupancy (streetwise)", RGBColor(0,0,1)));
00388     mySchemes.back().addColor(RGBColor(1, 0, 0), (SUMOReal)0.95);
00389     mySchemes.push_back(GUIColorScheme("by current speed (streetwise)", RGBColor(1,0,0)));
00390     mySchemes.back().addColor(RGBColor(0, 0, 1), (SUMOReal)(150.0/3.6));
00391     mySchemes.push_back(GUIColorScheme("by current flow (streetwise)", RGBColor(0,0,1)));
00392     mySchemes.back().addColor(RGBColor(1, 0, 0), (SUMOReal)5000);
00393 }
00394 
00395 
00396 SUMOReal
00397 GUIEdge::Colorer::getColorValue(const GUIEdge& edge) const {
00398     switch (myActiveScheme) {
00399     case 1:
00400         return gSelected.isSelected(edge.getType(), edge.getGlID());
00401     case 2:
00402         return edge.getPurpose();
00403     case 3:
00404         return edge.getAllowedSpeed();
00405     case 4:
00406         return edge.getOccupancy();
00407     case 5:
00408         return edge.getMeanSpeed();
00409     case 6:
00410         return edge.getFlow();
00411     }
00412     return 0;
00413 }
00414 
00415 #endif
00416 
00417 /****************************************************************************/
00418 

Generated on Wed May 5 00:06:29 2010 for Sumo - Simulation of Urban MObility by  doxygen 1.5.6