SUMO - Simulation of Urban MObility
GUISUMOAbstractView.cpp
Go to the documentation of this file.
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 
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Friends Defines