|
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 <microsim/MSEdge.h> 00039 #include <microsim/MSJunction.h> 00040 #include <microsim/MSLaneChanger.h> 00041 #include <microsim/MSGlobals.h> 00042 #include <utils/gui/globjects/GUIGLObjectPopupMenu.h> 00043 #include <utils/geom/GeomHelper.h> 00044 #include "GUIEdge.h" 00045 #include "GUINet.h" 00046 #include "GUILane.h" 00047 #include <utils/gui/div/GUIParameterTableWindow.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 <microsim/MSGlobals.h> 00058 #endif 00059 00060 #ifdef CHECK_MEMORY_LEAKS 00061 #include <foreign/nvwa/debug_new.h> 00062 #endif // CHECK_MEMORY_LEAKS 00063 00064 00065 // =========================================================================== 00066 // included modules 00067 // =========================================================================== 00068 GUIEdge::GUIEdge(const std::string& id, unsigned int numericalID, const std::string& streetName) 00069 : MSEdge(id, numericalID, streetName), 00070 GUIGlObject(GLO_EDGE, id) {} 00071 00072 00073 GUIEdge::~GUIEdge() { 00074 for (LaneWrapperVector::iterator i = myLaneGeoms.begin(); i != myLaneGeoms.end(); ++i) { 00075 delete(*i); 00076 } 00077 } 00078 00079 00080 void 00081 GUIEdge::initGeometry() { 00082 // don't do this twice 00083 if (myLaneGeoms.size() > 0) { 00084 return; 00085 } 00086 // build the lane wrapper 00087 myLaneGeoms.reserve(myLanes->size()); 00088 for (unsigned int i = 0; i < myLanes->size(); i++) { 00089 myLaneGeoms.push_back(myLanes->at(i)->buildLaneWrapper(i)); 00090 } 00091 } 00092 00093 00094 MSLane& 00095 GUIEdge::getLane(size_t laneNo) { 00096 assert(laneNo < myLanes->size()); 00097 return *((*myLanes)[laneNo]); 00098 } 00099 00100 00101 GUILaneWrapper& 00102 GUIEdge::getLaneGeometry(size_t laneNo) const { 00103 assert(laneNo < myLanes->size()); 00104 return *(myLaneGeoms[laneNo]); 00105 } 00106 00107 00108 GUILaneWrapper& 00109 GUIEdge::getLaneGeometry(const MSLane* lane) const { 00110 LaneWrapperVector::const_iterator i = 00111 find_if(myLaneGeoms.begin(), myLaneGeoms.end(), lane_wrapper_finder(*lane)); 00112 assert(i != myLaneGeoms.end()); 00113 return *(*i); 00114 } 00115 00116 00117 std::vector<GUIGlID> 00118 GUIEdge::getIDs(bool includeInternal) { 00119 std::vector<GUIGlID> ret; 00120 ret.reserve(MSEdge::myDict.size()); 00121 for (MSEdge::DictType::iterator i = MSEdge::myDict.begin(); i != MSEdge::myDict.end(); ++i) { 00122 GUIEdge* edge = dynamic_cast<GUIEdge*>(i->second); 00123 assert(edge); 00124 if (edge->getPurpose() != EDGEFUNCTION_INTERNAL || includeInternal) { 00125 ret.push_back(edge->getGlID()); 00126 } 00127 } 00128 return ret; 00129 } 00130 00131 00132 Boundary 00133 GUIEdge::getBoundary() const { 00134 Boundary ret; 00135 for (LaneWrapperVector::const_iterator i = myLaneGeoms.begin(); i != myLaneGeoms.end(); ++i) { 00136 const PositionVector& g = (*i)->getShape(); 00137 for (unsigned int j = 0; j < g.size(); j++) { 00138 ret.add(g[j]); 00139 } 00140 } 00141 ret.grow(10); 00142 return ret; 00143 } 00144 00145 00146 void 00147 GUIEdge::fill(std::vector<GUIEdge*> &netsWrappers) { 00148 size_t size = MSEdge::dictSize(); 00149 netsWrappers.reserve(size); 00150 for (DictType::iterator i = myDict.begin(); i != myDict.end(); ++i) { 00151 if (i->second->getPurpose() != MSEdge::EDGEFUNCTION_DISTRICT) { 00152 netsWrappers.push_back(static_cast<GUIEdge*>((*i).second)); 00153 } 00154 } 00155 } 00156 00157 00158 00159 GUIGLObjectPopupMenu* 00160 GUIEdge::getPopUpMenu(GUIMainWindow& app, GUISUMOAbstractView& parent) { 00161 GUIGLObjectPopupMenu* ret = new GUIGLObjectPopupMenu(app, parent, *this); 00162 buildPopupHeader(ret, app); 00163 buildCenterPopupEntry(ret); 00164 buildNameCopyPopupEntry(ret); 00165 buildSelectionPopupEntry(ret); 00166 #ifdef HAVE_MESOSIM 00167 if (MSGlobals::gUseMesoSim) { 00168 buildShowParamsPopupEntry(ret); 00169 } 00170 #endif 00171 buildPositionCopyEntry(ret, false); 00172 return ret; 00173 } 00174 00175 00176 GUIParameterTableWindow* 00177 GUIEdge::getParameterWindow(GUIMainWindow& app, 00178 GUISUMOAbstractView&) { 00179 GUIParameterTableWindow* ret = 0; 00180 #ifdef HAVE_MESOSIM 00181 ret = new GUIParameterTableWindow(app, *this, 5); 00182 // add items 00183 ret->mkItem("length [m]", false, (*myLanes)[0]->getLength()); 00184 ret->mkItem("allowed speed [m/s]", false, getAllowedSpeed()); 00185 ret->mkItem("occupancy [%]", true, 00186 new FunctionBinding<GUIEdge, SUMOReal>(this, &GUIEdge::getOccupancy)); 00187 ret->mkItem("mean vehicle speed [m/s]", true, 00188 new FunctionBinding<GUIEdge, SUMOReal>(this, &GUIEdge::getMeanSpeed)); 00189 ret->mkItem("flow [veh/h/lane]", true, 00190 new FunctionBinding<GUIEdge, SUMOReal>(this, &GUIEdge::getFlow)); 00191 ret->mkItem("#vehicles", true, 00192 new CastingFunctionBinding<GUIEdge, SUMOReal, unsigned int>(this, &GUIEdge::getVehicleNo)); 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 // draw the lanes 00215 for (LaneWrapperVector::const_iterator i = myLaneGeoms.begin(); i != myLaneGeoms.end(); ++i) { 00216 #ifdef HAVE_MESOSIM 00217 if (MSGlobals::gUseMesoSim) { 00218 setColor(s); 00219 } 00220 #endif 00221 (*i)->drawGL(s); 00222 } 00223 #ifdef HAVE_MESOSIM 00224 if (MSGlobals::gUseMesoSim) { 00225 size_t idx = 0; 00226 for (LaneWrapperVector::const_iterator l = myLaneGeoms.begin(); l != myLaneGeoms.end(); ++l, ++idx) { 00227 const PositionVector& shape = (*l)->getShape(); 00228 const DoubleVector& shapeRotations = (*l)->getShapeRotations(); 00229 const DoubleVector& shapeLengths = (*l)->getShapeLengths(); 00230 const Position& laneBeg = shape[0]; 00231 00232 glColor3d(1, 1, 0); 00233 glPushMatrix(); 00234 glTranslated(laneBeg.x(), laneBeg.y(), 0); 00235 glRotated(shapeRotations[0], 0, 0, 1); 00236 // go through the vehicles 00237 int shapePos = 0; 00238 SUMOReal positionOffset = 0; 00239 SUMOReal position = 0; 00240 for (MESegment* segment = MSGlobals::gMesoNet->getSegmentForEdge(*this); segment != 0; segment = segment->getNextSegment()) { 00241 const std::vector<size_t> numCars = segment->getQueSizes(); 00242 const SUMOReal length = segment->getLength(); 00243 if (idx < numCars.size()) { 00244 const SUMOReal avgCarSize = segment->getOccupancy() / segment->getCarNumber(); 00245 for (size_t i = 0; i < numCars[idx]; i++) { 00246 SUMOReal vehiclePosition = position + length - i * avgCarSize; 00247 SUMOReal xOff = 0.f; 00248 while (vehiclePosition < position) { 00249 vehiclePosition += length; 00250 xOff += 0.5f; 00251 } 00252 while (shapePos < (int)shapeRotations.size() - 1 && vehiclePosition > positionOffset + shapeLengths[shapePos]) { 00253 glPopMatrix(); 00254 positionOffset += shapeLengths[shapePos]; 00255 shapePos++; 00256 glPushMatrix(); 00257 glTranslated(shape[shapePos].x(), shape[shapePos].y(), 0); 00258 glRotated(shapeRotations[shapePos], 0, 0, 1); 00259 } 00260 glPushMatrix(); 00261 glTranslated(xOff, -(vehiclePosition - positionOffset), 0); 00262 glPushMatrix(); 00263 glScaled(1, avgCarSize, 1); 00264 glBegin(GL_TRIANGLES); 00265 glVertex2d(0, 0); 00266 glVertex2d(0 - 1.25, 1); 00267 glVertex2d(0 + 1.25, 1); 00268 glEnd(); 00269 glPopMatrix(); 00270 glPopMatrix(); 00271 } 00272 } 00273 position += length; 00274 } 00275 glPopMatrix(); 00276 } 00277 } 00278 #endif 00279 // (optionally) draw the name and/or the street name 00280 const bool drawEdgeName = s.edgeName.show && myFunction == EDGEFUNCTION_NORMAL; 00281 const bool drawInternalEdgeName = s.internalEdgeName.show && myFunction != EDGEFUNCTION_NORMAL; 00282 const bool drawStreetName = s.streetName.show && myStreetName != ""; 00283 if (drawEdgeName || drawInternalEdgeName || drawStreetName) { 00284 GUILaneWrapper* lane1 = myLaneGeoms[0]; 00285 GUILaneWrapper* lane2 = myLaneGeoms[myLaneGeoms.size() - 1]; 00286 Position p = lane1->getShape().positionAtLengthPosition(lane1->getShape().length() / (SUMOReal) 2.); 00287 p.add(lane2->getShape().positionAtLengthPosition(lane2->getShape().length() / (SUMOReal) 2.)); 00288 p.mul(.5); 00289 SUMOReal angle = lane1->getShape().rotationDegreeAtLengthPosition(lane1->getShape().length() / (SUMOReal) 2.); 00290 angle += 90; 00291 if (angle > 90 && angle < 270) { 00292 angle -= 180; 00293 } 00294 if (drawEdgeName) { 00295 drawName(p, s.scale, s.edgeName, angle); 00296 } else if (drawInternalEdgeName) { 00297 drawName(p, s.scale, s.internalEdgeName, angle); 00298 } 00299 if (drawStreetName) { 00300 GLHelper::drawText(getStreetName(), p, GLO_MAX, 00301 s.streetName.size / s.scale, s.streetName.color, angle); 00302 } 00303 } 00304 } 00305 00306 #ifdef HAVE_MESOSIM 00307 unsigned int 00308 GUIEdge::getVehicleNo() const { 00309 size_t vehNo = 0; 00310 for (MESegment* segment = MSGlobals::gMesoNet->getSegmentForEdge(*this); segment != 0; segment = segment->getNextSegment()) { 00311 vehNo += segment->getCarNumber(); 00312 } 00313 return (unsigned int)vehNo; 00314 } 00315 00316 00317 SUMOReal 00318 GUIEdge::getFlow() const { 00319 SUMOReal flow = 0; 00320 for (MESegment* segment = MSGlobals::gMesoNet->getSegmentForEdge(*this); segment != 0; segment = segment->getNextSegment()) { 00321 flow += (SUMOReal) segment->getCarNumber() * segment->getMeanSpeed(); 00322 } 00323 return flow * (SUMOReal) 1000. / (*myLanes)[0]->getLength() / (SUMOReal) 3.6; 00324 } 00325 00326 00327 SUMOReal 00328 GUIEdge::getOccupancy() const { 00329 SUMOReal occ = 0; 00330 for (MESegment* segment = MSGlobals::gMesoNet->getSegmentForEdge(*this); segment != 0; segment = segment->getNextSegment()) { 00331 occ += segment->getOccupancy(); 00332 } 00333 return occ / (*myLanes)[0]->getLength() / (SUMOReal)(myLanes->size()); 00334 } 00335 00336 00337 SUMOReal 00338 GUIEdge::getMeanSpeed() const { 00339 SUMOReal v = 0; 00340 SUMOReal no = 0; 00341 for (MESegment* segment = MSGlobals::gMesoNet->getSegmentForEdge(*this); segment != 0; segment = segment->getNextSegment()) { 00342 SUMOReal vehNo = (SUMOReal) segment->getCarNumber(); 00343 v += vehNo * segment->getMeanSpeed(); 00344 no += vehNo; 00345 } 00346 return v / no; 00347 } 00348 00349 00350 SUMOReal 00351 GUIEdge::getAllowedSpeed() const { 00352 return (*myLanes)[0]->getMaxSpeed(); 00353 } 00354 00355 00356 void 00357 GUIEdge::setColor(const GUIVisualizationSettings& s) const { 00358 GLHelper::setColor(s.edgeColorer.getScheme().getColor(getColorValue(s.edgeColorer.getActive()))); 00359 } 00360 00361 00362 SUMOReal 00363 GUIEdge::getColorValue(size_t activeScheme) const { 00364 switch (activeScheme) { 00365 case 1: 00366 return gSelected.isSelected(getType(), getGlID()); 00367 case 2: 00368 return getPurpose(); 00369 case 3: 00370 return getAllowedSpeed(); 00371 case 4: 00372 return getOccupancy(); 00373 case 5: 00374 return getMeanSpeed(); 00375 case 6: 00376 return getFlow(); 00377 } 00378 return 0; 00379 } 00380 00381 #endif 00382 00383 /****************************************************************************/ 00384