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