SUMO - Simulation of Urban MObility
|
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