SUMO - Simulation of Urban MObility
|
00001 /****************************************************************************/ 00011 // The base class for a view 00012 /****************************************************************************/ 00013 // SUMO, Simulation of Urban MObility; see http://sumo.sourceforge.net/ 00014 // Copyright (C) 2001-2012 DLR (http://www.dlr.de/) and contributors 00015 /****************************************************************************/ 00016 // 00017 // This file is part of SUMO. 00018 // SUMO is free software: you can redistribute it and/or modify 00019 // it under the terms of the GNU General Public License as published by 00020 // the Free Software Foundation, either version 3 of the License, or 00021 // (at your option) any later version. 00022 // 00023 /****************************************************************************/ 00024 00025 00026 // =========================================================================== 00027 // included modules 00028 // =========================================================================== 00029 #ifdef _MSC_VER 00030 #include <windows_config.h> 00031 #else 00032 #include <config.h> 00033 #endif 00034 00035 #ifdef _WIN32 00036 #include <windows.h> 00037 #endif 00038 00039 #include <iostream> 00040 #include <utility> 00041 #include <cmath> 00042 #include <cassert> 00043 #include <fxkeys.h> 00044 #include <GL/gl.h> 00045 #include <GL/glu.h> 00046 #include <foreign/polyfonts/polyfonts.h> 00047 #include <foreign/gl2ps/gl2ps.h> 00048 #include <utils/foxtools/FXSingleEventThread.h> 00049 #include <utils/foxtools/MFXCheckableButton.h> 00050 #include <utils/foxtools/MFXImageHelper.h> 00051 #include <utils/common/RGBColor.h> 00052 #include <utils/common/ToString.h> 00053 #include <utils/common/StringUtils.h> 00054 #include <utils/common/MsgHandler.h> 00055 #include <utils/gui/windows/GUIAppEnum.h> 00056 #include <utils/gui/globjects/GUIGLObjectPopupMenu.h> 00057 #include <utils/gui/images/GUITexturesHelper.h> 00058 #include <utils/gui/div/GUIGlobalSelection.h> 00059 #include <utils/gui/div/GLHelper.h> 00060 #include <utils/gui/globjects/GUIGlObjectStorage.h> 00061 #include <utils/gui/globjects/GUIGlObject.h> 00062 #include <utils/gui/globjects/GUIGlObjectStorage.h> 00063 #include <utils/shapes/PointOfInterest.h> 00064 #include <utils/gui/globjects/GUIPointOfInterest.h> 00065 #include <utils/gui/globjects/GUIPolygon.h> 00066 #include <utils/gui/windows/GUIDialog_ViewSettings.h> 00067 #include <utils/geom/GeoConvHelper.h> 00068 #include <utils/gui/settings/GUICompleteSchemeStorage.h> 00069 00070 #include "GUISUMOAbstractView.h" 00071 #include "GUIMainWindow.h" 00072 #include "GUIGlChildWindow.h" 00073 #include "GUIDanielPerspectiveChanger.h" 00074 #include "GUIDialog_EditViewport.h" 00075 00076 #ifdef WIN32 00077 #include <windows.h> 00078 #endif 00079 00080 #ifdef CHECK_MEMORY_LEAKS 00081 #include <foreign/nvwa/debug_new.h> 00082 #endif // CHECK_MEMORY_LEAKS 00083 00084 00085 // =========================================================================== 00086 // member method definitions 00087 // =========================================================================== 00088 /* ------------------------------------------------------------------------- 00089 * GUISUMOAbstractView - FOX callback mapping 00090 * ----------------------------------------------------------------------- */ 00091 FXDEFMAP(GUISUMOAbstractView) GUISUMOAbstractViewMap[] = { 00092 FXMAPFUNC(SEL_CONFIGURE, 0, GUISUMOAbstractView::onConfigure), 00093 FXMAPFUNC(SEL_PAINT, 0, GUISUMOAbstractView::onPaint), 00094 FXMAPFUNC(SEL_LEFTBUTTONPRESS, 0, GUISUMOAbstractView::onLeftBtnPress), 00095 FXMAPFUNC(SEL_LEFTBUTTONRELEASE, 0, GUISUMOAbstractView::onLeftBtnRelease), 00096 FXMAPFUNC(SEL_RIGHTBUTTONPRESS, 0, GUISUMOAbstractView::onRightBtnPress), 00097 FXMAPFUNC(SEL_RIGHTBUTTONRELEASE, 0, GUISUMOAbstractView::onRightBtnRelease), 00098 FXMAPFUNC(SEL_MOUSEWHEEL, 0, GUISUMOAbstractView::onMouseWheel), 00099 FXMAPFUNC(SEL_MOTION, 0, GUISUMOAbstractView::onMouseMove), 00100 FXMAPFUNC(SEL_LEAVE, 0, GUISUMOAbstractView::onMouseLeft), 00101 FXMAPFUNC(SEL_KEYPRESS, 0, GUISUMOAbstractView::onKeyPress), 00102 FXMAPFUNC(SEL_KEYRELEASE, 0, GUISUMOAbstractView::onKeyRelease), 00103 00104 }; 00105 00106 00107 FXIMPLEMENT_ABSTRACT(GUISUMOAbstractView, FXGLCanvas, GUISUMOAbstractViewMap, ARRAYNUMBER(GUISUMOAbstractViewMap)) 00108 00109 00110 /* ------------------------------------------------------------------------- 00111 * GUISUMOAbstractView - methods 00112 * ----------------------------------------------------------------------- */ 00113 GUISUMOAbstractView::GUISUMOAbstractView(FXComposite* p, 00114 GUIMainWindow& app, 00115 GUIGlChildWindow* parent, 00116 const SUMORTree& grid, 00117 FXGLVisual* glVis, FXGLCanvas* share) 00118 : FXGLCanvas(p, glVis, share, p, MID_GLCANVAS, 00119 LAYOUT_SIDE_TOP | LAYOUT_FILL_X | LAYOUT_FILL_Y, 0, 0, 0, 0), 00120 myApp(&app), 00121 myParent(parent), 00122 myGrid(&((SUMORTree&)grid)), 00123 myChanger(0), 00124 myMouseHotspotX(app.getDefaultCursor()->getHotX()), 00125 myMouseHotspotY(app.getDefaultCursor()->getHotY()), 00126 myPopup(0), 00127 myUseToolTips(false), 00128 myAmInitialised(false), 00129 myViewportChooser(0), 00130 myVisualizationChanger(0) { 00131 setTarget(this); 00132 enable(); 00133 flags |= FLAG_ENABLED; 00134 myInEditMode = false; 00135 // show the middle at the beginning 00136 myChanger = new GUIDanielPerspectiveChanger(*this, *myGrid); 00137 myVisualizationSettings = &gSchemeStorage.getDefault(); 00138 myVisualizationSettings->gaming = myApp->isGaming(); 00139 gSchemeStorage.setViewport(this); 00140 } 00141 00142 00143 GUISUMOAbstractView::~GUISUMOAbstractView() { 00144 gSchemeStorage.setDefault(myVisualizationSettings->name); 00145 gSchemeStorage.saveViewport(myChanger->getXPos(), myChanger->getYPos(), myChanger->getZoom()); 00146 delete myPopup; 00147 delete myChanger; 00148 delete myViewportChooser; 00149 delete myVisualizationChanger; 00150 } 00151 00152 00153 bool 00154 GUISUMOAbstractView::isInEditMode() { 00155 return myInEditMode; 00156 } 00157 00158 00159 void 00160 GUISUMOAbstractView::updateToolTip() { 00161 if (!myUseToolTips) { 00162 return; 00163 } 00164 update(); 00165 } 00166 00167 00168 Position 00169 GUISUMOAbstractView::getPositionInformation() const { 00170 Boundary bound = myChanger->getViewport(); 00171 SUMOReal x = bound.xmin() + bound.getWidth() * myWindowCursorPositionX / getWidth(); 00172 // cursor origin is in the top-left corner 00173 SUMOReal y = bound.ymin() + bound.getHeight() * (getHeight() - myWindowCursorPositionY) / getHeight(); 00174 return Position(x, y); 00175 } 00176 00177 00178 void 00179 GUISUMOAbstractView::updatePositionInformation() const { 00180 Position pos = getPositionInformation(); 00181 std::string text = "x:" + toString(pos.x()) + ", y:" + toString(pos.y()); 00182 myApp->getCartesianLabel().setText(text.c_str()); 00183 GeoConvHelper::getFinal().cartesian2geo(pos); 00184 if (GeoConvHelper::getFinal().usingGeoProjection()) { 00185 text = "lat:" + toString(pos.y(), GEO_OUTPUT_ACCURACY) + ", lon:" + toString(pos.x(), GEO_OUTPUT_ACCURACY); 00186 } else { 00187 text = "x:" + toString(pos.x()) + ", y:" + toString(pos.y()); 00188 } 00189 myApp->getGeoLabel().setText(text.c_str()); 00190 } 00191 00192 00193 Boundary 00194 GUISUMOAbstractView::getVisibleBoundary() const { 00195 return myChanger->getViewport(); 00196 } 00197 00198 void 00199 GUISUMOAbstractView::paintGL() { 00200 if (getWidth() == 0 || getHeight() == 0) { 00201 return; 00202 } 00203 00204 if (getTrackedID() > 0) { 00205 centerTo(getTrackedID(), false); 00206 } 00207 00208 unsigned int id = 0; 00209 if (myUseToolTips) { 00210 id = getObjectUnderCursor(); 00211 } 00212 00213 // draw 00214 glClearColor( 00215 myVisualizationSettings->backgroundColor.red(), 00216 myVisualizationSettings->backgroundColor.green(), 00217 myVisualizationSettings->backgroundColor.blue(), 00218 1); 00219 glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT); 00220 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); 00221 00222 if (myVisualizationSettings->dither) { 00223 glEnable(GL_DITHER); 00224 } else { 00225 glDisable(GL_DITHER); 00226 } 00227 if (myVisualizationSettings->antialiase) { 00228 glEnable(GL_BLEND); 00229 glEnable(GL_POLYGON_SMOOTH); 00230 glEnable(GL_LINE_SMOOTH); 00231 } else { 00232 glDisable(GL_BLEND); 00233 glDisable(GL_POLYGON_SMOOTH); 00234 glDisable(GL_LINE_SMOOTH); 00235 } 00236 00237 applyGLTransform(); 00238 doPaintGL(GL_RENDER, myChanger->getViewport()); 00239 if (myVisualizationSettings->showSizeLegend) { 00240 displayLegend(); 00241 } 00242 // check whether the select mode /tooltips) 00243 // shall be computed, too 00244 if (myUseToolTips && id != 0) { 00245 showToolTipFor(id); 00246 } 00247 swapBuffers(); 00248 } 00249 00250 00251 GUIGlID 00252 GUISUMOAbstractView::getObjectUnderCursor() { 00253 return getObjectAtPosition(getPositionInformation()); 00254 } 00255 00256 00257 GUIGlID 00258 GUISUMOAbstractView::getObjectAtPosition(Position pos) { 00259 const SUMOReal SENSITIVITY = 0.1; // meters 00260 Boundary selection; 00261 selection.add(pos); 00262 selection.grow(SENSITIVITY); 00263 const std::vector<GUIGlID> ids = getObjectsInBoundary(selection); 00264 // Interpret results 00265 unsigned int idMax = 0; 00266 int prevLayer = -1000; 00267 for (std::vector<GUIGlID>::const_iterator it = ids.begin(); it != ids.end(); it++) { 00268 GUIGlID id = *it; 00269 GUIGlObject* o = GUIGlObjectStorage::gIDStorage.getObjectBlocking(id); 00270 if (o == 0) { 00271 continue; 00272 } 00273 if (o->getGlID() == 0) { 00274 continue; 00275 } 00276 //std::cout << "point selection hit " << o->getMicrosimID() << "\n"; 00277 GUIGlObjectType type = o->getType(); 00278 if (type != 0) { 00279 int clayer = (int) type; 00280 // determine an "abstract" layer for shapes 00281 // this "layer" resembles the layer of the shape 00282 // taking into account the stac of other objects 00283 if (type == GLO_SHAPE) { 00284 if (dynamic_cast<GUIPolygon*>(o) != 0) { 00285 if (dynamic_cast<GUIPolygon*>(o)->getLayer() > 0) { 00286 clayer = GLO_MAX + dynamic_cast<GUIPolygon*>(o)->getLayer(); 00287 } 00288 if (dynamic_cast<GUIPolygon*>(o)->getLayer() < 0) { 00289 clayer = dynamic_cast<GUIPolygon*>(o)->getLayer(); 00290 } 00291 } 00292 if (dynamic_cast<GUIPointOfInterest*>(o) != 0) { 00293 if (dynamic_cast<GUIPointOfInterest*>(o)->getLayer() > 0) { 00294 clayer = GLO_MAX + dynamic_cast<GUIPointOfInterest*>(o)->getLayer(); 00295 } 00296 if (dynamic_cast<GUIPointOfInterest*>(o)->getLayer() < 0) { 00297 clayer = dynamic_cast<GUIPointOfInterest*>(o)->getLayer(); 00298 } 00299 } 00300 } 00301 // check whether the current object is above a previous one 00302 if (prevLayer == -1000 || prevLayer < clayer) { 00303 idMax = id; 00304 prevLayer = clayer; 00305 } 00306 } 00307 GUIGlObjectStorage::gIDStorage.unblockObject(id); 00308 } 00309 return idMax; 00310 } 00311 00312 00313 std::vector<GUIGlID> 00314 GUISUMOAbstractView::getObjectsInBoundary(const Boundary& bound) { 00315 const int NB_HITS_MAX = 1024 * 1024; 00316 // Prepare the selection mode 00317 static GUIGlID hits[NB_HITS_MAX]; 00318 static GLint nb_hits = 0; 00319 glSelectBuffer(NB_HITS_MAX, hits); 00320 glInitNames(); 00321 00322 Boundary oldViewPort = myChanger->getViewport(false); // backup the actual viewPort 00323 myChanger->setViewport(bound); 00324 applyGLTransform(false); 00325 00326 // paint in select mode 00327 int hits2 = doPaintGL(GL_SELECT, bound); 00328 // Get the results 00329 nb_hits = glRenderMode(GL_RENDER); 00330 if (nb_hits == -1) { 00331 myApp->setStatusBarText("Selection in boundary failed. Try to select fewer than " + toString(hits2) + " items"); 00332 } 00333 std::vector<GUIGlID> result; 00334 for (int i = 0; i < nb_hits; ++i) { 00335 assert(i * 4 + 3 < NB_HITS_MAX); 00336 result.push_back(hits[i * 4 + 3]); 00337 } 00338 // switch viewport back to normal 00339 myChanger->setViewport(oldViewPort); 00340 return result; 00341 } 00342 00343 00344 void 00345 GUISUMOAbstractView::showToolTipFor(unsigned int id) { 00346 if (id != 0) { 00347 GUIGlObject* object = GUIGlObjectStorage::gIDStorage.getObjectBlocking(id); 00348 if (object != 0) { 00349 Position pos = getPositionInformation(); 00350 pos.add(0, p2m(15)); 00351 GLHelper::drawTextBox(object->getFullName(), pos, GLO_MAX - 1, p2m(20), RGBColor(0, 0, 0), RGBColor(1, 0.7, 0)); 00352 GUIGlObjectStorage::gIDStorage.unblockObject(id); 00353 } 00354 } 00355 } 00356 00357 00358 void 00359 GUISUMOAbstractView::paintGLGrid() { 00360 glEnable(GL_DEPTH_TEST); 00361 glLineWidth(1); 00362 00363 SUMOReal xmin = myGrid->xmin(); 00364 SUMOReal ymin = myGrid->ymin(); 00365 SUMOReal ypos = ymin; 00366 SUMOReal xpos = xmin; 00367 SUMOReal xend = myGrid->xmax(); 00368 SUMOReal yend = myGrid->ymax(); 00369 00370 glTranslated(0, 0, .55); 00371 glColor3d(0.5, 0.5, 0.5); 00372 // draw horizontal lines 00373 glBegin(GL_LINES); 00374 for (; ypos < yend;) { 00375 glVertex2d(xmin, ypos); 00376 glVertex2d(xend, ypos); 00377 ypos += myVisualizationSettings->gridYSize; 00378 } 00379 // draw vertical lines 00380 for (; xpos < xend;) { 00381 glVertex2d(xpos, ymin); 00382 glVertex2d(xpos, yend); 00383 xpos += myVisualizationSettings->gridXSize; 00384 } 00385 glEnd(); 00386 glTranslated(0, 0, -.55); 00387 } 00388 00389 00390 void 00391 GUISUMOAbstractView::displayLegend() { 00392 // compute the scale bar length 00393 size_t length = 1; 00394 const std::string text("10000000000"); 00395 size_t noDigits = 1; 00396 size_t pixelSize = 0; 00397 while (true) { 00398 pixelSize = (size_t) m2p((SUMOReal) length); 00399 if (pixelSize > 20) { 00400 break; 00401 } 00402 length *= 10; 00403 noDigits++; 00404 if (noDigits > text.length()) { 00405 return; 00406 } 00407 } 00408 SUMOReal lineWidth = 1.0; 00409 glLineWidth((SUMOReal) lineWidth); 00410 00411 glMatrixMode(GL_PROJECTION); 00412 glPushMatrix(); 00413 glLoadIdentity(); 00414 glMatrixMode(GL_MODELVIEW); 00415 glPushMatrix(); 00416 glLoadIdentity(); 00417 00418 // draw the scale bar 00419 glDisable(GL_TEXTURE_2D); 00420 glDisable(GL_ALPHA_TEST); 00421 glDisable(GL_BLEND); 00422 glEnable(GL_DEPTH_TEST); 00423 00424 SUMOReal len = (SUMOReal) pixelSize / (SUMOReal)(getWidth() - 1) * (SUMOReal) 2.0; 00425 glColor3d(0, 0, 0); 00426 double o = double(15) / double(getHeight()); 00427 double o2 = o + o; 00428 double oo = double(5) / double(getHeight()); 00429 glBegin(GL_LINES); 00430 // vertical 00431 glVertex2d(-.98, -1. + o); 00432 glVertex2d(-.98 + len, -1. + o); 00433 // tick at begin 00434 glVertex2d(-.98, -1. + o); 00435 glVertex2d(-.98, -1. + o2); 00436 // tick at end 00437 glVertex2d(-.98 + len, -1. + o); 00438 glVertex2d(-.98 + len, -1. + o2); 00439 glEnd(); 00440 00441 SUMOReal w = SUMOReal(35) / SUMOReal(getWidth()); 00442 SUMOReal h = SUMOReal(35) / SUMOReal(getHeight()); 00443 pfSetPosition(SUMOReal(-0.99), SUMOReal(1. - o2 - oo)); 00444 pfSetScaleXY(w, h); 00445 glRotated(180, 1, 0, 0); 00446 pfDrawString("0m"); 00447 glRotated(-180, 1, 0, 0); 00448 00449 pfSetPosition(SUMOReal(-.99 + len), SUMOReal(1. - o2 - oo)); 00450 glRotated(180, 1, 0, 0); 00451 pfDrawString((text.substr(0, noDigits) + "m").c_str()); 00452 glRotated(-180, 1, 0, 0); 00453 00454 // restore matrices 00455 glMatrixMode(GL_PROJECTION); 00456 glPopMatrix(); 00457 glMatrixMode(GL_MODELVIEW); 00458 glPopMatrix(); 00459 } 00460 00461 00462 SUMOReal 00463 GUISUMOAbstractView::m2p(SUMOReal meter) const { 00464 return meter * getWidth() / myChanger->getViewport().getWidth(); 00465 } 00466 00467 00468 SUMOReal 00469 GUISUMOAbstractView::p2m(SUMOReal pixel) const { 00470 return pixel * myChanger->getViewport().getWidth() / getWidth(); 00471 } 00472 00473 00474 void 00475 GUISUMOAbstractView::recenterView() { 00476 myChanger->setViewport(*myGrid); 00477 } 00478 00479 00480 void 00481 GUISUMOAbstractView::centerTo(GUIGlID id, bool applyZoom, SUMOReal zoomDist) { 00482 GUIGlObject* o = GUIGlObjectStorage::gIDStorage.getObjectBlocking(id); 00483 if (o != 0 && dynamic_cast<GUIGlObject*>(o) != 0) { 00484 if (applyZoom && zoomDist < 0) { 00485 myChanger->setViewport(o->getCenteringBoundary()); 00486 } else { 00487 myChanger->centerTo(o->getCenteringBoundary().getCenter(), zoomDist, applyZoom); 00488 } 00489 } 00490 GUIGlObjectStorage::gIDStorage.unblockObject(id); 00491 } 00492 00493 00494 void 00495 GUISUMOAbstractView::centerTo(const Boundary& bound) { 00496 myChanger->setViewport(bound); 00497 update(); 00498 } 00499 00500 /* 00501 bool 00502 GUISUMOAbstractView::allowRotation() const 00503 { 00504 return myParent->allowRotation(); 00505 } 00506 */ 00507 00508 void 00509 GUISUMOAbstractView::setWindowCursorPosition(FXint x, FXint y) { 00510 myWindowCursorPositionX = x + myMouseHotspotX; 00511 myWindowCursorPositionY = y + myMouseHotspotY; 00512 } 00513 00514 00515 FXbool 00516 GUISUMOAbstractView::makeCurrent() { 00517 FXbool ret = FXGLCanvas::makeCurrent(); 00518 return ret; 00519 } 00520 00521 00522 long 00523 GUISUMOAbstractView::onConfigure(FXObject*, FXSelector, void*) { 00524 if (makeCurrent()) { 00525 glViewport(0, 0, getWidth() - 1, getHeight() - 1); 00526 glClearColor( 00527 myVisualizationSettings->backgroundColor.red(), 00528 myVisualizationSettings->backgroundColor.green(), 00529 myVisualizationSettings->backgroundColor.blue(), 00530 1); 00531 doInit(); 00532 myAmInitialised = true; 00533 makeNonCurrent(); 00534 checkSnapshots(); 00535 } 00536 return 1; 00537 } 00538 00539 00540 long 00541 GUISUMOAbstractView::onPaint(FXObject*, FXSelector, void*) { 00542 if (!isEnabled() || !myAmInitialised) { 00543 return 1; 00544 } 00545 if (makeCurrent()) { 00546 paintGL(); 00547 makeNonCurrent(); 00548 } 00549 return 1; 00550 } 00551 00552 00553 void 00554 GUISUMOAbstractView::destroyPopup() { 00555 delete myPopup; 00556 myPopup = 0; 00557 } 00558 00559 00560 long 00561 GUISUMOAbstractView::onLeftBtnPress(FXObject*, FXSelector , void* data) { 00562 destroyPopup(); 00563 FXEvent* e = (FXEvent*) data; 00564 // check whether the selection-mode is activated 00565 if (e->state & CONTROLMASK) { 00566 // try to get the object-id if so 00567 if (makeCurrent()) { 00568 unsigned int id = getObjectUnderCursor(); 00569 if (id != 0) { 00570 gSelected.toggleSelection(id); 00571 } 00572 makeNonCurrent(); 00573 if (id != 0) { 00574 // possibly, the selection-colouring is used, 00575 // so we should update the screen again... 00576 update(); 00577 } 00578 } 00579 } 00580 myChanger->onLeftBtnPress(data); 00581 grab(); 00582 return 1; 00583 } 00584 00585 00586 long 00587 GUISUMOAbstractView::onLeftBtnRelease(FXObject*, FXSelector , void* data) { 00588 destroyPopup(); 00589 myChanger->onLeftBtnRelease(data); 00590 if (myApp->isGaming()) { 00591 onGamingClick(getPositionInformation()); 00592 } 00593 ungrab(); 00594 return 1; 00595 } 00596 00597 00598 long 00599 GUISUMOAbstractView::onRightBtnPress(FXObject*, FXSelector , void* data) { 00600 destroyPopup(); 00601 myChanger->onRightBtnPress(data); 00602 grab(); 00603 return 1; 00604 } 00605 00606 00607 long 00608 GUISUMOAbstractView::onRightBtnRelease(FXObject*, FXSelector , void* data) { 00609 destroyPopup(); 00610 if (!myChanger->onRightBtnRelease(data) && !myApp->isGaming()) { 00611 openObjectDialog(); 00612 } 00613 ungrab(); 00614 return 1; 00615 } 00616 00617 00618 long 00619 GUISUMOAbstractView::onMouseWheel(FXObject*, FXSelector , void* data) { 00620 myChanger->onMouseWheel(data); 00621 return 1; 00622 } 00623 00624 00625 long 00626 GUISUMOAbstractView::onMouseMove(FXObject*, FXSelector , void* data) { 00627 SUMOReal xpos = myChanger->getXPos(); 00628 SUMOReal ypos = myChanger->getYPos(); 00629 SUMOReal zoom = myChanger->getZoom(); 00630 if (myViewportChooser == 0 || !myViewportChooser->haveGrabbed()) { 00631 myChanger->onMouseMove(data); 00632 } 00633 if (myViewportChooser != 0 && 00634 (xpos != myChanger->getXPos() || ypos != myChanger->getYPos() || zoom != myChanger->getZoom())) { 00635 00636 myViewportChooser->setValues( 00637 myChanger->getZoom(), myChanger->getXPos(), myChanger->getYPos()); 00638 00639 } 00640 updatePositionInformation(); 00641 return 1; 00642 } 00643 00644 00645 long 00646 GUISUMOAbstractView::onMouseLeft(FXObject*, FXSelector , void* /*data*/) { 00647 return 1; 00648 } 00649 00650 00651 void 00652 GUISUMOAbstractView::openObjectDialog() { 00653 ungrab(); 00654 if (!isEnabled() || !myAmInitialised) { 00655 return; 00656 } 00657 if (makeCurrent()) { 00658 // initialise the select mode 00659 unsigned int id = getObjectUnderCursor(); 00660 GUIGlObject* o = 0; 00661 if (id != 0) { 00662 o = GUIGlObjectStorage::gIDStorage.getObjectBlocking(id); 00663 } else { 00664 o = GUIGlObjectStorage::gIDStorage.getNetObject(); 00665 } 00666 if (o != 0) { 00667 myPopup = o->getPopUpMenu(*myApp, *this); 00668 int x, y; 00669 FXuint b; 00670 myApp->getCursorPosition(x, y, b); 00671 myPopup->setX(x + myApp->getX()); 00672 myPopup->setY(y + myApp->getY()); 00673 myPopup->create(); 00674 myPopup->show(); 00675 myChanger->onRightBtnRelease(0); 00676 GUIGlObjectStorage::gIDStorage.unblockObject(id); 00677 } 00678 makeNonCurrent(); 00679 } 00680 } 00681 00682 00683 long 00684 GUISUMOAbstractView::onKeyPress(FXObject* o, FXSelector sel, void* data) { 00685 FXEvent* e = (FXEvent*) data; 00686 if ((e->state & ALTMASK) != 0) { 00687 setDefaultCursor(getApp()->getDefaultCursor(DEF_CROSSHAIR_CURSOR)); 00688 grabKeyboard(); 00689 } 00690 /* 00691 switch(e->code) { 00692 case KEY_Left: 00693 myChanger->move((SUMOReal) -p2m((SUMOReal) getWidth()/10), 0); 00694 break; 00695 case KEY_Right: 00696 myChanger->move((SUMOReal) p2m((SUMOReal) getWidth()/10), 0); 00697 break; 00698 case KEY_Up: 00699 myChanger->move(0, (SUMOReal) -p2m((SUMOReal) getHeight()/10)); 00700 break; 00701 case KEY_Down: 00702 myChanger->move(0, (SUMOReal) p2m((SUMOReal) getHeight()/10)); 00703 break; 00704 default: 00705 break; 00706 } 00707 */ 00708 return FXGLCanvas::onKeyPress(o, sel, data); 00709 } 00710 00711 00712 long 00713 GUISUMOAbstractView::onKeyRelease(FXObject* o, FXSelector sel, void* data) { 00714 FXEvent* e = (FXEvent*) data; 00715 if ((e->state & ALTMASK) == 0) { 00716 ungrabKeyboard(); 00717 setDefaultCursor(getApp()->getDefaultCursor(DEF_ARROW_CURSOR)); 00718 } 00719 return FXGLCanvas::onKeyRelease(o, sel, data); 00720 } 00721 00722 00723 // ------------ Dealing with snapshots 00724 void 00725 GUISUMOAbstractView::setSnapshots(std::map<SUMOTime, std::string> snaps) { 00726 mySnapshots.insert(snaps.begin(), snaps.end()); 00727 } 00728 00729 00730 std::string 00731 GUISUMOAbstractView::makeSnapshot(const std::string& destFile) { 00732 std::string errorMessage; 00733 FXString ext = FXPath::extension(destFile.c_str()); 00734 bool useGL2PS = ext == "ps" || ext == "eps" || ext == "pdf" || ext == "svg" || ext == "tex" || ext == "pgf"; 00735 00736 for (int i = 0; i < 10 && !makeCurrent(); ++i) { 00737 FXSingleEventThread::sleep(100); 00738 } 00739 // draw 00740 glClearColor( 00741 myVisualizationSettings->backgroundColor.red(), 00742 myVisualizationSettings->backgroundColor.green(), 00743 myVisualizationSettings->backgroundColor.blue(), 00744 1); 00745 glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT); 00746 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); 00747 00748 if (myVisualizationSettings->dither) { 00749 glEnable(GL_DITHER); 00750 } else { 00751 glDisable(GL_DITHER); 00752 } 00753 if (myVisualizationSettings->antialiase) { 00754 glEnable(GL_BLEND); 00755 glEnable(GL_POLYGON_SMOOTH); 00756 glEnable(GL_LINE_SMOOTH); 00757 } else { 00758 glDisable(GL_BLEND); 00759 glDisable(GL_POLYGON_SMOOTH); 00760 glDisable(GL_LINE_SMOOTH); 00761 } 00762 00763 applyGLTransform(); 00764 00765 if (useGL2PS) { 00766 GLint format = GL2PS_PS; 00767 if (ext == "ps") { 00768 format = GL2PS_PS; 00769 } else if (ext == "eps") { 00770 format = GL2PS_EPS; 00771 } else if (ext == "pdf") { 00772 format = GL2PS_PDF; 00773 } else if (ext == "tex") { 00774 format = GL2PS_TEX; 00775 } else if (ext == "svg") { 00776 format = GL2PS_SVG; 00777 } else if (ext == "pgf") { 00778 format = GL2PS_PGF; 00779 } else { 00780 return "Could not save '" + destFile + "'.\n Unrecognized format '" + std::string(ext.text()) + "'."; 00781 } 00782 FILE* fp = fopen(destFile.c_str(), "wb"); 00783 if (fp == 0) { 00784 return "Could not save '" + destFile + "'.\n Could not open file for writing"; 00785 } 00786 GLint buffsize = 0, state = GL2PS_OVERFLOW; 00787 GLint viewport[4]; 00788 glGetIntegerv(GL_VIEWPORT, viewport); 00789 while (state == GL2PS_OVERFLOW) { 00790 buffsize += 1024 * 1024; 00791 gl2psBeginPage(destFile.c_str(), "sumo-gui; http://sumo.sf.net", viewport, format, GL2PS_SIMPLE_SORT, 00792 GL2PS_DRAW_BACKGROUND | GL2PS_USE_CURRENT_VIEWPORT, 00793 GL_RGBA, 0, NULL, 0, 0, 0, buffsize, fp, "out.eps"); 00794 glMatrixMode(GL_MODELVIEW); 00795 glPushMatrix(); 00796 glDisable(GL_TEXTURE_2D); 00797 glDisable(GL_ALPHA_TEST); 00798 glDisable(GL_BLEND); 00799 glEnable(GL_DEPTH_TEST); 00800 // compute lane width 00801 // draw decals (if not in grabbing mode) 00802 if (!myUseToolTips) { 00803 drawDecals(); 00804 if (myVisualizationSettings->showGrid) { 00805 paintGLGrid(); 00806 } 00807 } 00808 glLineWidth(1); 00809 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); 00810 Boundary viewPort = myChanger->getViewport(); 00811 float minB[2]; 00812 float maxB[2]; 00813 minB[0] = viewPort.xmin(); 00814 minB[1] = viewPort.ymin(); 00815 maxB[0] = viewPort.xmax(); 00816 maxB[1] = viewPort.ymax(); 00817 myVisualizationSettings->scale = m2p(SUMO_const_laneWidth); 00818 glEnable(GL_POLYGON_OFFSET_FILL); 00819 glEnable(GL_POLYGON_OFFSET_LINE); 00820 myGrid->Search(minB, maxB, *myVisualizationSettings); 00821 00822 if (myVisualizationSettings->showSizeLegend) { 00823 displayLegend(); 00824 } 00825 state = gl2psEndPage(); 00826 glFinish(); 00827 } 00828 fclose(fp); 00829 } else { 00830 doPaintGL(GL_RENDER, myChanger->getViewport()); 00831 if (myVisualizationSettings->showSizeLegend) { 00832 displayLegend(); 00833 } 00834 swapBuffers(); 00835 glFinish(); 00836 FXColor* buf; 00837 FXMALLOC(&buf, FXColor, getWidth()*getHeight()); 00838 // read from the back buffer 00839 glReadBuffer(GL_BACK); 00840 // Read the pixels 00841 glReadPixels(0, 0, getWidth(), getHeight(), GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid*)buf); 00842 makeNonCurrent(); 00843 update(); 00844 // mirror 00845 size_t mwidth = getWidth(); 00846 size_t mheight = getHeight(); 00847 FXColor* paa = buf; 00848 FXColor* pbb = buf + mwidth * (mheight - 1); 00849 do { 00850 FXColor* pa = paa; 00851 paa += mwidth; 00852 FXColor* pb = pbb; 00853 pbb -= mwidth; 00854 do { 00855 FXColor t = *pa; 00856 *pa++ = *pb; 00857 *pb++ = t; 00858 } while (pa < paa); 00859 } while (paa < pbb); 00860 try { 00861 if (!MFXImageHelper::saveImage(destFile, getWidth(), getHeight(), buf)) { 00862 errorMessage = "Could not save '" + destFile + "'."; 00863 } 00864 } catch (InvalidArgument& e) { 00865 errorMessage = "Could not save '" + destFile + "'.\n" + e.what(); 00866 } 00867 FXFREE(&buf); 00868 } 00869 return errorMessage; 00870 } 00871 00872 00873 void 00874 GUISUMOAbstractView::checkSnapshots() { 00875 std::map<SUMOTime, std::string>::iterator snapIt = mySnapshots.find(getCurrentTimeStep()); 00876 if (snapIt != mySnapshots.end()) { 00877 std::string error = makeSnapshot(snapIt->second); 00878 if (error != "") { 00879 WRITE_WARNING(error); 00880 } 00881 } 00882 } 00883 00884 00885 void 00886 GUISUMOAbstractView::showViewportEditor() { 00887 if (myViewportChooser == 0) { 00888 myViewportChooser = 00889 new GUIDialog_EditViewport(this, "Edit Viewport...", 00890 myChanger->getZoom(), myChanger->getXPos(), myChanger->getYPos(), 00891 0, 0); 00892 myViewportChooser->create(); 00893 } 00894 myViewportChooser->setOldValues( 00895 myChanger->getZoom(), myChanger->getXPos(), myChanger->getYPos()); 00896 myViewportChooser->show(); 00897 } 00898 00899 00900 void 00901 GUISUMOAbstractView::setViewport(SUMOReal zoom, SUMOReal xPos, SUMOReal yPos) { 00902 myChanger->setViewport(zoom, xPos, yPos); 00903 update(); 00904 } 00905 00906 00907 void 00908 GUISUMOAbstractView::showToolTips(bool val) { 00909 myUseToolTips = val; 00910 } 00911 00912 00913 00914 SUMOReal 00915 GUISUMOAbstractView::getGridWidth() const { 00916 return myGrid->getWidth(); 00917 } 00918 00919 00920 SUMOReal 00921 GUISUMOAbstractView::getGridHeight() const { 00922 return myGrid->getHeight(); 00923 } 00924 00925 00926 FXComboBox& 00927 GUISUMOAbstractView::getColoringSchemesCombo() { 00928 return myParent->getColoringSchemesCombo(); 00929 } 00930 00931 00932 void 00933 GUISUMOAbstractView::drawDecals() { 00934 glTranslated(0, 0, .99); 00935 myDecalsLock.lock(); 00936 for (std::vector<GUISUMOAbstractView::Decal>::iterator l = myDecals.begin(); l != myDecals.end();) { 00937 GUISUMOAbstractView::Decal& d = *l; 00938 if (!d.initialised) { 00939 try { 00940 FXImage* i = MFXImageHelper::loadImage(getApp(), d.filename); 00941 if (MFXImageHelper::scalePower2(i)) { 00942 WRITE_WARNING("Scaling '" + d.filename + "'."); 00943 } 00944 d.glID = GUITexturesHelper::add(i); 00945 d.initialised = true; 00946 } catch (InvalidArgument& e) { 00947 WRITE_ERROR("Could not load '" + d.filename + "'.\n" + e.what()); 00948 l = myDecals.erase(l); 00949 continue; 00950 } 00951 } 00952 glPushMatrix(); 00953 glTranslated(d.centerX, d.centerY, 0); 00954 glRotated(d.rot, 0, 0, 1); 00955 glColor3d(1, 1, 1); 00956 SUMOReal halfWidth((d.width / 2.)); 00957 SUMOReal halfHeight((d.height / 2.)); 00958 GUITexturesHelper::drawTexturedBox(d.glID, -halfWidth, -halfHeight, halfWidth, halfHeight); 00959 glPopMatrix(); 00960 ++l; 00961 } 00962 myDecalsLock.unlock(); 00963 glTranslated(0, 0, -.99); 00964 } 00965 00966 00967 // ------------ Additional visualisations 00968 bool 00969 GUISUMOAbstractView::addAdditionalGLVisualisation(GUIGlObject* const which) { 00970 if (myAdditionallyDrawn.find(which) == myAdditionallyDrawn.end()) { 00971 myAdditionallyDrawn[which] = 1; 00972 } else { 00973 myAdditionallyDrawn[which] = myAdditionallyDrawn[which] + 1; 00974 } 00975 update(); 00976 return true; 00977 } 00978 00979 00980 bool 00981 GUISUMOAbstractView::removeAdditionalGLVisualisation(GUIGlObject* const which) { 00982 if (getTrackedID() == static_cast<int>(which->getGlID())) { 00983 stopTrack(); 00984 } 00985 if (myAdditionallyDrawn.find(which) == myAdditionallyDrawn.end()) { 00986 return false; 00987 } 00988 int cnt = myAdditionallyDrawn[which]; 00989 if (cnt == 1) { 00990 myAdditionallyDrawn.erase(which); 00991 } else { 00992 myAdditionallyDrawn[which] = myAdditionallyDrawn[which] - 1; 00993 } 00994 update(); 00995 return true; 00996 } 00997 00998 00999 void 01000 GUISUMOAbstractView::applyGLTransform(bool fixRatio) { 01001 Boundary bound = myChanger->getViewport(fixRatio); 01002 glMatrixMode(GL_PROJECTION); 01003 glLoadIdentity(); 01004 // as a rough rule, each GLObject is drawn at z = -GUIGlObjectType 01005 // thus, objects with a higher value will be closer (drawn on top) 01006 // // @todo last param should be 0 after modifying all glDraw methods 01007 glOrtho(0, getWidth(), 0, getHeight(), -GLO_MAX - 1, GLO_MAX + 1); 01008 glMatrixMode(GL_MODELVIEW); 01009 glLoadIdentity(); 01010 SUMOReal scaleX = (SUMOReal)getWidth() / bound.getWidth(); 01011 SUMOReal scaleY = (SUMOReal)getHeight() / bound.getHeight(); 01012 glScaled(scaleX, scaleY, 1); 01013 glTranslated(-bound.xmin(), -bound.ymin(), 0); 01014 } 01015 01016 /****************************************************************************/ 01017