00001
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #ifdef _MSC_VER
00023 #include <windows_config.h>
00024 #else
00025 #include <config.h>
00026 #endif
00027
00028 #ifdef _WIN32
00029 #include <windows.h>
00030 #endif
00031
00032 #include <GL/gl.h>
00033
00034 #include <string>
00035 #include <utils/common/MsgHandler.h>
00036 #include <utils/geom/Position2DVector.h>
00037 #include <utils/geom/Line2D.h>
00038 #include <utils/geom/Boundary.h>
00039 #include <utils/gui/div/GLHelper.h>
00040 #include <utils/common/ToString.h>
00041 #include <microsim/MSNet.h>
00042 #include <microsim/MSLane.h>
00043 #include <microsim/MSEdge.h>
00044 #include <guisim/GUINet.h>
00045 #include <guisim/GUIEdge.h>
00046 #include "GUIEmitter.h"
00047 #include <utils/gui/globjects/GUIGLObjectPopupMenu.h>
00048 #include <utils/gui/images/GUIIconSubSys.h>
00049 #include <utils/gui/windows/GUIAppEnum.h>
00050 #include <gui/GUIGlobals.h>
00051 #include <utils/gui/div/GUIParameterTableWindow.h>
00052 #include <gui/GUIApplicationWindow.h>
00053 #include <utils/gui/images/GUITexturesHelper.h>
00054 #include <microsim/logging/FunctionBinding.h>
00055 #include <utils/gui/div/GUIGlobalSelection.h>
00056 #include <utils/gui/globjects/GUIGlObjectStorage.h>
00057 #include <foreign/polyfonts/polyfonts.h>
00058 #include <utils/common/WrappingCommand.h>
00059
00060 #ifdef CHECK_MEMORY_LEAKS
00061 #include <foreign/nvwa/debug_new.h>
00062 #endif // CHECK_MEMORY_LEAKS
00063
00064
00065
00066
00067
00068
00069
00070
00071 FXDEFMAP(GUIEmitter::GUIEmitterPopupMenu)
00072 GUIEmitterPopupMenuMap[]= {
00073 FXMAPFUNC(SEL_COMMAND, MID_MANIP, GUIEmitter::GUIEmitterPopupMenu::onCmdOpenManip),
00074 FXMAPFUNC(SEL_COMMAND, MID_DRAWROUTE, GUIEmitter::GUIEmitterPopupMenu::onCmdDrawRoute),
00075
00076 };
00077
00078
00079 FXIMPLEMENT(GUIEmitter::GUIEmitterPopupMenu, GUIGLObjectPopupMenu, GUIEmitterPopupMenuMap, ARRAYNUMBER(GUIEmitterPopupMenuMap))
00080
00081
00082
00083
00084
00085 FXDEFMAP(GUIEmitter::GUIManip_TriggeredEmitter) GUIManip_TriggeredEmitterMap[]= {
00086 FXMAPFUNC(SEL_COMMAND, GUIEmitter::GUIManip_TriggeredEmitter::MID_USER_DEF, GUIEmitter::GUIManip_TriggeredEmitter::onCmdUserDef),
00087 FXMAPFUNC(SEL_UPDATE, GUIEmitter::GUIManip_TriggeredEmitter::MID_USER_DEF, GUIEmitter::GUIManip_TriggeredEmitter::onUpdUserDef),
00088 FXMAPFUNC(SEL_COMMAND, GUIEmitter::GUIManip_TriggeredEmitter::MID_OPTION, GUIEmitter::GUIManip_TriggeredEmitter::onCmdChangeOption),
00089 FXMAPFUNC(SEL_COMMAND, GUIEmitter::GUIManip_TriggeredEmitter::MID_CLOSE, GUIEmitter::GUIManip_TriggeredEmitter::onCmdClose),
00090 };
00091
00092 FXIMPLEMENT(GUIEmitter::GUIManip_TriggeredEmitter, GUIManipulator, GUIManip_TriggeredEmitterMap, ARRAYNUMBER(GUIManip_TriggeredEmitterMap))
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102 GUIEmitter::GUIEmitterChild_UserTriggeredChild::GUIEmitterChild_UserTriggeredChild(
00103 MSEmitter_FileTriggeredChild &s,
00104 MSEmitter &parent, MSVehicleControl &vc,
00105 SUMOReal flow) throw()
00106 : MSEmitter::MSEmitterChild(parent, vc), myUserFlow(flow),
00107 myVehicle(0), mySource(s) {
00108 if (myUserFlow>0) {
00109 Command* c = new WrappingCommand< GUIEmitterChild_UserTriggeredChild >(this, &GUIEmitterChild_UserTriggeredChild::wrappedExecute);
00110 MSNet::getInstance()->getEmissionEvents().addEvent(
00111 c, (SUMOTime)(1. / (flow / 3600.))+MSNet::getInstance()->getCurrentTimeStep(),
00112 MSEventControl::ADAPT_AFTER_EXECUTION);
00113 }
00114 }
00115
00116
00117 GUIEmitter::GUIEmitterChild_UserTriggeredChild::~GUIEmitterChild_UserTriggeredChild() throw() {
00118 }
00119
00120
00121 SUMOTime
00122 GUIEmitter::GUIEmitterChild_UserTriggeredChild::wrappedExecute(SUMOTime currentTime) throw(ProcessError) {
00123 if (myUserFlow<=0) {
00124 return 0;
00125 }
00126 if (!mySource.isInitialised()) {
00127 mySource.init();
00128 }
00129 if (myVehicle==0) {
00130 SUMOVehicleParameter* p = new SUMOVehicleParameter();
00131 p->id = myParent.getID() + "_user_" + toString(currentTime);
00132 const MSRoute *aRoute = myRouteDist.getOverallProb()!=0
00133 ? myRouteDist.get()
00134 : mySource.hasRoutes()
00135 ? mySource.getRndRoute()
00136 : 0;
00137 if (aRoute==0) {
00138 MsgHandler::getErrorInstance()->inform("Emitter '" + myParent.getID() + "' has no valid route.");
00139 return 0;
00140 }
00141 MSVehicleType *aType = myVTypeDist.getOverallProb()!=0
00142 ? myVTypeDist.get()
00143 : mySource.hasVTypes()
00144 ? mySource.getRndVType()
00145 : MSNet::getInstance()->getVehicleControl().getVType();
00146 if (aType==0) {
00147 MsgHandler::getErrorInstance()->inform("Emitter '" + myParent.getID() + "' has no valid vehicle type.");
00148 return 0;
00149 }
00150 p->depart = currentTime;
00151 myVehicle = MSNet::getInstance()->getVehicleControl().buildVehicle(p, aRoute, aType);
00152 myParent.schedule(this, myVehicle, -1);
00153 }
00154 if (myParent.childCheckEmit(this)) {
00155 myVehicle = 0;
00156 return (SUMOTime) computeOffset(myUserFlow);
00157 }
00158 return 1;
00159 }
00160
00161
00162 SUMOReal
00163 GUIEmitter::GUIEmitterChild_UserTriggeredChild::getUserFlow() const {
00164 return myUserFlow;
00165 }
00166
00167
00168
00169 GUIEmitter::GUIManip_TriggeredEmitter::GUIManip_TriggeredEmitter(
00170 GUIMainWindow &app,
00171 const std::string &name, GUIEmitter &o,
00172 int , int )
00173 : GUIManipulator(app, name, 0, 0), myParent(&app),
00174 myChosenValue(0), myChosenTarget(myChosenValue, this, MID_OPTION),
00175 myFlowFactor(o.getUserFlow()), myFlowFactorTarget(myFlowFactor),
00176 myObject(&o) {
00177 FXVerticalFrame *f1 =
00178 new FXVerticalFrame(this, LAYOUT_FILL_X|LAYOUT_FILL_Y,0,0,0,0, 0,0,0,0);
00179
00180 myChosenValue = (FXint) o.getActiveChildIndex();
00181
00182 FXGroupBox *gp = new FXGroupBox(f1, "Change Flow",
00183 GROUPBOX_TITLE_LEFT|FRAME_SUNKEN|FRAME_RIDGE,
00184 0, 0, 0, 0, 4, 4, 1, 1, 2, 0);
00185 {
00186
00187 FXHorizontalFrame *gf1 =
00188 new FXHorizontalFrame(gp, LAYOUT_TOP|LAYOUT_LEFT,0,0,0,0, 10,10,5,5);
00189 new FXRadioButton(gf1, "Default", &myChosenTarget, FXDataTarget::ID_OPTION+0,
00190 ICON_BEFORE_TEXT|LAYOUT_SIDE_TOP,
00191 0, 0, 0, 0, 2, 2, 0, 0);
00192 }
00193 {
00194
00195 FXHorizontalFrame *gf12 =
00196 new FXHorizontalFrame(gp, LAYOUT_TOP|LAYOUT_LEFT,0,0,0,0, 10,10,5,5);
00197 new FXRadioButton(gf12, "User Defined Flow: ", &myChosenTarget, FXDataTarget::ID_OPTION+1,
00198 ICON_BEFORE_TEXT|LAYOUT_SIDE_TOP|LAYOUT_CENTER_Y,
00199 0, 0, 0, 0, 2, 2, 0, 0);
00200 myFlowFactorDial =
00201 new FXRealSpinDial(gf12, 8, this, MID_USER_DEF,
00202 LAYOUT_TOP|FRAME_SUNKEN|FRAME_THICK);
00203 myFlowFactorDial->setFormatString("%.0f");
00204 myFlowFactorDial->setIncrements(1,10,100);
00205 myFlowFactorDial->setRange(0,4000);
00206 myFlowFactorDial->setValue(myObject->getUserFlow());
00207 }
00208 new FXButton(f1,"Close",NULL,this,MID_CLOSE,
00209 BUTTON_INITIAL|BUTTON_DEFAULT|FRAME_RAISED|FRAME_THICK|LAYOUT_TOP|LAYOUT_LEFT|LAYOUT_CENTER_X,0,0,0,0, 30,30,4,4);
00210 }
00211
00212
00213 GUIEmitter::GUIManip_TriggeredEmitter::~GUIManip_TriggeredEmitter() {}
00214
00215
00216 long
00217 GUIEmitter::GUIManip_TriggeredEmitter::onCmdClose(FXObject*,FXSelector,void*) {
00218 destroy();
00219 return 1;
00220 }
00221
00222
00223 long
00224 GUIEmitter::GUIManip_TriggeredEmitter::onCmdUserDef(FXObject*,FXSelector,void*) {
00225 static_cast<GUIEmitter*>(myObject)->setUserFlow(
00226 (SUMOReal)(myFlowFactorDial->getValue()));
00227 static_cast<GUIEmitter*>(myObject)->setActiveChild(1);
00228 myParent->updateChildren();
00229 return 1;
00230 }
00231
00232
00233 long
00234 GUIEmitter::GUIManip_TriggeredEmitter::onUpdUserDef(FXObject *sender,FXSelector,void*ptr) {
00235 sender->handle(this,
00236 myChosenValue!=1 ? FXSEL(SEL_COMMAND,ID_DISABLE):FXSEL(SEL_COMMAND,ID_ENABLE),
00237 ptr);
00238 myParent->updateChildren();
00239 return 1;
00240 }
00241
00242
00243 long
00244 GUIEmitter::GUIManip_TriggeredEmitter::onCmdChangeOption(FXObject*,FXSelector,void*) {
00245 static_cast<GUIEmitter*>(myObject)->setUserFlow((SUMOReal) myFlowFactorDial->getValue());
00246 switch (myChosenValue) {
00247 case 0:
00248 static_cast<GUIEmitter*>(myObject)->setActiveChild(0);
00249 break;
00250 case 1:
00251 static_cast<GUIEmitter*>(myObject)->setActiveChild(1);
00252 break;
00253 default:
00254
00255 break;
00256 }
00257 myParent->updateChildren();
00258 return 1;
00259 }
00260
00261
00262
00263
00264
00265 GUIEmitter::GUIEmitterPopupMenu::GUIEmitterPopupMenu(
00266 GUIMainWindow &app, GUISUMOAbstractView &parent,
00267 GUIGlObject &o)
00268 : GUIGLObjectPopupMenu(app, parent, o) {}
00269
00270
00271 GUIEmitter::GUIEmitterPopupMenu::~GUIEmitterPopupMenu() throw() {}
00272
00273
00274 long
00275 GUIEmitter::GUIEmitterPopupMenu::onCmdOpenManip(FXObject*,
00276 FXSelector,
00277 void*) {
00278 static_cast<GUIEmitter*>(myObject)->openManipulator(
00279 *myApplication, *myParent);
00280 return 1;
00281 }
00282
00283
00284 long
00285 GUIEmitter::GUIEmitterPopupMenu::onCmdDrawRoute(FXObject*,
00286 FXSelector,
00287 void*) {
00288 static_cast<GUIEmitter*>(myObject)->toggleDrawRoutes();
00289 myParent->update();
00290 return 1;
00291 }
00292
00293
00294
00295
00296
00297 GUIEmitter::GUIEmitter(const std::string &id,
00298 MSNet &net, MSLane *destLanes, SUMOReal pos,
00299 const std::string &file) throw()
00300 : MSEmitter(id, net, destLanes, pos, file),
00301 GUIGlObject_AbstractAdd(GUIGlObjectStorage::gIDStorage,
00302 "emitter:" + id, GLO_TRIGGER), myUserFlow(-1), myDrawRoutes(false) {
00303 const Position2DVector &v = destLanes->getShape();
00304 if (pos<0) {
00305 pos = destLanes->getLength()+ pos;
00306 }
00307 myFGPosition = v.positionAtLengthPosition(pos);
00308 Line2D l(v.getBegin(), v.getEnd());
00309 myFGRotation = -v.rotationDegreeAtLengthPosition(pos);
00310
00311 myUserEmitChild =
00312 new GUIEmitterChild_UserTriggeredChild(
00313 static_cast<MSEmitter_FileTriggeredChild&>(*myFileBasedEmitter),
00314 *this, net.getVehicleControl(), 0);
00315 }
00316
00317
00318 GUIEmitter::~GUIEmitter() throw() {}
00319
00320
00321 void
00322 GUIEmitter::setUserFlow(SUMOReal factor) {
00323
00324 myUserFlow = factor;
00325 if (myUserFlow>0) {
00326 delete myUserEmitChild;
00327 myUserEmitChild =
00328 new GUIEmitterChild_UserTriggeredChild(
00329 static_cast<MSEmitter_FileTriggeredChild&>(*myFileBasedEmitter),
00330 *this, myNet.getVehicleControl(), factor);
00331 }
00332 }
00333
00334
00335 SUMOReal
00336 GUIEmitter::getUserFlow() const {
00337 if (myUserFlow<0&&static_cast<MSEmitter_FileTriggeredChild*>(myFileBasedEmitter)->getLoadedFlow()>0) {
00338 myUserFlow = static_cast<MSEmitter_FileTriggeredChild*>(myFileBasedEmitter)->getLoadedFlow();
00339 }
00340 return myUserFlow;
00341 }
00342
00343
00344 GUIGLObjectPopupMenu *
00345 GUIEmitter::getPopUpMenu(GUIMainWindow &app,
00346 GUISUMOAbstractView &parent) throw() {
00347 GUIGLObjectPopupMenu *ret = new GUIEmitterPopupMenu(app, parent, *this);
00348 buildPopupHeader(ret, app);
00349 buildCenterPopupEntry(ret);
00350
00351 buildShowManipulatorPopupEntry(ret, false);
00352 if (!myDrawRoutes) {
00353 new FXMenuCommand(ret, "Show Routes...", GUIIconSubSys::getIcon(ICON_MANIP), ret, MID_DRAWROUTE);
00354 } else {
00355 new FXMenuCommand(ret, "Hide Routes...", GUIIconSubSys::getIcon(ICON_MANIP), ret, MID_DRAWROUTE);
00356 }
00357 new FXMenuSeparator(ret);
00358
00359 buildNameCopyPopupEntry(ret);
00360 buildSelectionPopupEntry(ret);
00361 buildPositionCopyEntry(ret, false);
00362 return ret;
00363 }
00364
00365
00366 GUIParameterTableWindow *
00367 GUIEmitter::getParameterWindow(GUIMainWindow &,
00368 GUISUMOAbstractView &) throw() {
00369 return 0;
00370 }
00371
00372
00373 const std::string &
00374 GUIEmitter::getMicrosimID() const throw() {
00375 return getID();
00376 }
00377
00378
00379 void
00380 GUIEmitter::toggleDrawRoutes() {
00381 myDrawRoutes = !myDrawRoutes;
00382 }
00383
00384
00385 std::map<const MSEdge*, SUMOReal>
00386 GUIEmitter::getEdgeProbs() const {
00387 std::map<const MSEdge*, SUMOReal> ret;
00388 const std::vector<const MSRoute*> &routes = myFileBasedEmitter->getRouteDist().getVals();
00389 const std::vector<SUMOReal> &probs = myFileBasedEmitter->getRouteDist().getProbs();
00390 size_t j;
00391
00392 for (j=0; j<routes.size(); ++j) {
00393 SUMOReal prob = probs[j];
00394 const MSRoute *r = routes[j];
00395 MSRouteIterator i = r->begin();
00396 for (; i!=r->end(); ++i) {
00397 const MSEdge *e = *i;
00398 if (ret.find(e)==ret.end()) {
00399 ret[e] = 0;
00400 }
00401 ret[e] = ret[e] + prob;
00402 }
00403 }
00404 return ret;
00405 }
00406
00407
00408 void
00409 GUIEmitter::drawGL(const GUIVisualizationSettings &s) const throw() {
00410
00411 if (s.needsGlID) {
00412 glPushName(getGlID());
00413 }
00414 glPushMatrix();
00415 glTranslated(myFGPosition.x(), myFGPosition.y(), 0);
00416 glScaled(s.addExaggeration, s.addExaggeration, 1);
00417 glRotated(myFGRotation, 0, 0, 1);
00418
00419 glColor3d(1, 0, 0);
00420
00421 glTranslated(0, 0, -.03);
00422 glBegin(GL_TRIANGLES);
00423 glVertex2d(0-1.5, 0);
00424 glVertex2d(0-1.5, 8);
00425 glVertex2d(0+1.5, 8);
00426 glVertex2d(0+1.5, 0);
00427 glVertex2d(0-1.5, 0);
00428 glVertex2d(0+1.5, 8);
00429 glEnd();
00430
00431
00432 glTranslated(0, 0, -.01);
00433 glBegin(GL_TRIANGLES);
00434 glColor3d(1, 1, 0);
00435 glVertex2d(0, 1-.5);
00436 glVertex2d(0-1.25, 1+2-.5);
00437 glVertex2d(0+1.25, 1+2-.5);
00438
00439 glVertex2d(0, 3-.5);
00440 glVertex2d(0-1.25, 3+2-.5);
00441 glVertex2d(0+1.25, 3+2-.5);
00442
00443 glVertex2d(0, 5-.5);
00444 glVertex2d(0-1.25, 5+2-.5);
00445 glVertex2d(0+1.25, 5+2-.5);
00446
00447 glEnd();
00448 glTranslated(0, 0, .04);
00449 glPopMatrix();
00450
00451 if (myDrawRoutes) {
00452 std::map<const MSEdge*, SUMOReal> e2prob = getEdgeProbs();
00453 for (std::map<const MSEdge*, SUMOReal>::iterator k=e2prob.begin(); k!=e2prob.end(); ++k) {
00454 double c = (*k).second;
00455 glColor3d(1.-c, 1.-c, 0);
00456 const MSEdge *e = (*k).first;
00457 const GUIEdge *ge = static_cast<const GUIEdge*>(e);
00458 const GUILaneWrapper &lane = ge->getLaneGeometry((size_t) 0);
00459 GLHelper::drawBoxLines(lane.getShape(), lane.getShapeRotations(), lane.getShapeLengths(), 0.5);
00460 }
00461 }
00462
00463 if (s.drawAddName) {
00464 drawGLName(getCenteringBoundary().getCenter(), getMicrosimID(), s.addNameSize / s.scale);
00465 }
00466
00467 if (s.needsGlID) {
00468 glPopName();
00469 }
00470 }
00471
00472
00473 Boundary
00474 GUIEmitter::getCenteringBoundary() const throw() {
00475 Boundary b(myFGPosition.x(), myFGPosition.y(), myFGPosition.x(), myFGPosition.y());
00476 b.grow(20);
00477 return b;
00478 }
00479
00480
00481 GUIManipulator *
00482 GUIEmitter::openManipulator(GUIMainWindow &app,
00483 GUISUMOAbstractView &) {
00484 GUIManip_TriggeredEmitter *gui =
00485 new GUIManip_TriggeredEmitter(app, getFullName(), *this, 0, 0);
00486 gui->create();
00487 gui->show();
00488 return gui;
00489 }
00490
00491
00492 void
00493 GUIEmitter::setActiveChild(int index) {
00494 switch (index) {
00495 case 0:
00496 myActiveChild = myFileBasedEmitter;
00497 break;
00498 case 1:
00499 myActiveChild = myUserEmitChild;
00500 break;
00501 }
00502 }
00503
00504
00505
00506
00507