SUMO - Simulation of Urban MObility

GUISUMOAbstractView.cpp

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