00001
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
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
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
00081 if (myLaneGeoms.size()>0) {
00082 return;
00083 }
00084
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
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
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
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
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
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
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
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