LCOV - code coverage report
Current view: top level - src/osgview - GUIOSGView.cpp (source / functions) Coverage Total Hit
Test: lcov.info Lines: 46.0 % 583 268
Test Date: 2025-12-06 15:35:27 Functions: 44.6 % 65 29

            Line data    Source code
       1              : /****************************************************************************/
       2              : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
       3              : // Copyright (C) 2001-2025 German Aerospace Center (DLR) and others.
       4              : // This program and the accompanying materials are made available under the
       5              : // terms of the Eclipse Public License 2.0 which is available at
       6              : // https://www.eclipse.org/legal/epl-2.0/
       7              : // This Source Code may also be made available under the following Secondary
       8              : // Licenses when the conditions for such availability set forth in the Eclipse
       9              : // Public License 2.0 are satisfied: GNU General Public License, version 2
      10              : // or later which is available at
      11              : // https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
      12              : // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
      13              : /****************************************************************************/
      14              : /// @file    GUIOSGView.cpp
      15              : /// @author  Daniel Krajzewicz
      16              : /// @author  Michael Behrisch
      17              : /// @author  Mirko Barthauer
      18              : /// @date    19.01.2012
      19              : ///
      20              : // An OSG-based 3D view on the simulation
      21              : /****************************************************************************/
      22              : #include <config.h>
      23              : 
      24              : #ifdef HAVE_OSG
      25              : 
      26              : #include <cmath>
      27              : #include <fxkeys.h>
      28              : #include <iostream>
      29              : #include <limits>
      30              : #include <utility>
      31              : #include <foreign/rtree/SUMORTree.h>
      32              : #include <gui/GUIApplicationWindow.h>
      33              : #include <gui/GUISUMOViewParent.h>
      34              : #include <gui/GUIViewTraffic.h>
      35              : #include <guisim/GUIEdge.h>
      36              : #include <guisim/GUIJunctionWrapper.h>
      37              : #include <guisim/GUILane.h>
      38              : #include <guisim/GUINet.h>
      39              : #include <guisim/GUIPerson.h>
      40              : #include <guisim/GUIVehicle.h>
      41              : #include <microsim/MSEdge.h>
      42              : #include <microsim/MSEdgeControl.h>
      43              : #include <microsim/MSLane.h>
      44              : #include <microsim/MSNet.h>
      45              : #include <microsim/MSVehicleControl.h>
      46              : #include <microsim/traffic_lights/MSSimpleTrafficLightLogic.h>
      47              : #include <microsim/traffic_lights/MSTLLogicControl.h>
      48              : #include <microsim/transportables/MSTransportableControl.h>
      49              : #include <utils/common/FileHelpers.h>
      50              : #include <utils/common/MsgHandler.h>
      51              : #include <utils/common/RGBColor.h>
      52              : #include <utils/common/StringUtils.h>
      53              : #include <utils/foxtools/MFXCheckableButton.h>
      54              : #include <utils/foxtools/MFXImageHelper.h>
      55              : #include <utils/geom/GeoConvHelper.h>
      56              : #include <utils/geom/PositionVector.h>
      57              : #include <utils/gui/div/GLHelper.h>
      58              : #include <utils/gui/div/GUIDesigns.h>
      59              : #include <utils/gui/div/GUIGlobalSelection.h>
      60              : #include <utils/gui/globjects/GLIncludes.h>
      61              : #include <utils/gui/globjects/GUIGlObjectStorage.h>
      62              : #include <utils/gui/images/GUIIconSubSys.h>
      63              : #include <utils/gui/images/GUITexturesHelper.h>
      64              : #include <utils/gui/settings/GUICompleteSchemeStorage.h>
      65              : #include <utils/gui/windows/GUIAppEnum.h>
      66              : #include <utils/gui/windows/GUIDialog_EditViewport.h>
      67              : #include <utils/gui/windows/GUIDialog_ViewSettings.h>
      68              : #include <utils/gui/windows/GUIPerspectiveChanger.h>
      69              : #include <utils/gui/windows/GUISUMOAbstractView.h>
      70              : 
      71              : #include "GUIOSGBuilder.h"
      72              : #include "GUIOSGPerspectiveChanger.h"
      73              : #include "GUIOSGView.h"
      74              : 
      75              : //#define DEBUG_GLERRORS
      76              : 
      77              : FXDEFMAP(GUIOSGView) GUIOSGView_Map[] = {
      78              :     //________Message_Type_________        ___ID___                        ________Message_Handler________
      79              :     FXMAPFUNC(SEL_CHORE,                MID_CHORE,                      GUIOSGView::onIdle),
      80              : };
      81       172307 : FXIMPLEMENT(GUIOSGView, GUISUMOAbstractView, GUIOSGView_Map, ARRAYNUMBER(GUIOSGView_Map))
      82              : 
      83              : 
      84              : std::ostream&
      85            0 : operator<<(std::ostream& os, const osg::Vec3d& v) {
      86            0 :     return os << v.x() << "," << v.y() << "," << v.z();
      87              : }
      88              : 
      89              : // ===========================================================================
      90              : // GUIOSGView::Command_TLSChange member method definitions
      91              : // ===========================================================================
      92              : 
      93         3450 : GUIOSGView::Command_TLSChange::Command_TLSChange(const MSLink* const link, osg::Switch* switchNode)
      94         3450 :     : myLink(link), mySwitch(switchNode), myLastState(LINKSTATE_TL_OFF_NOSIGNAL) {
      95         3450 :     execute();
      96         3450 : }
      97              : 
      98              : 
      99         6900 : GUIOSGView::Command_TLSChange::~Command_TLSChange() {}
     100              : 
     101              : 
     102              : void
     103        79054 : GUIOSGView::Command_TLSChange::execute() {
     104        79054 :     switch (myLink->getState()) {
     105        20224 :         case LINKSTATE_TL_GREEN_MAJOR:
     106              :         case LINKSTATE_TL_GREEN_MINOR:
     107        20224 :             mySwitch->setSingleChildOn(0);
     108        20224 :             break;
     109        14306 :         case LINKSTATE_TL_YELLOW_MAJOR:
     110              :         case LINKSTATE_TL_YELLOW_MINOR:
     111        14306 :             mySwitch->setSingleChildOn(1);
     112        14306 :             break;
     113        44484 :         case LINKSTATE_TL_RED:
     114              :         case LINKSTATE_STOP:
     115        44484 :             mySwitch->setSingleChildOn(2);
     116        44484 :             break;
     117            0 :         case LINKSTATE_TL_REDYELLOW:
     118            0 :             mySwitch->setSingleChildOn(3);
     119            0 :             break;
     120           40 :         case LINKSTATE_TL_OFF_BLINKING:
     121              :         case LINKSTATE_TL_OFF_NOSIGNAL:
     122           40 :             mySwitch->setSingleChildOn(3);
     123           40 :             break;
     124            0 :         default:
     125            0 :             mySwitch->setAllChildrenOff();
     126              :     }
     127        79054 :     myLastState = myLink->getState();
     128        79054 : }
     129              : 
     130              : // ===========================================================================
     131              : // GUIOSGView member method definitions
     132              : // ===========================================================================
     133              : 
     134          436 : GUIOSGView::GUIOSGView(
     135              :     FXComposite* p,
     136              :     GUIMainWindow& app,
     137              :     GUISUMOViewParent* parent,
     138              :     GUINet& net, FXGLVisual* glVis,
     139          436 :     FXGLCanvas* share) :
     140              :     GUISUMOAbstractView(p, app, parent, net.getVisualisationSpeedUp(), glVis, share),
     141          436 :     myTracked(0), myLastUpdate(-1),
     142          436 :     myOSGNormalizedCursorX(0.), myOSGNormalizedCursorY(0.) {
     143          436 :     if (myChanger != nullptr) {
     144          436 :         delete (myChanger);
     145              :     }
     146              :     int w = getWidth();
     147              :     int h = getHeight();
     148          436 :     myAdapter = new FXOSGAdapter(this, new FXCursor(parent->getApp(), CURSOR_CROSS));
     149          436 :     myViewer = new osgViewer::Viewer();
     150          436 :     myCameraManipulator = new GUIOSGManipulator(this);
     151          436 :     myChanger = new GUIOSGPerspectiveChanger(*this, *myGrid);
     152          436 :     const char* sumoPath = getenv("SUMO_HOME");
     153          436 :     if (sumoPath != 0) {
     154          872 :         std::string newPath = std::string(sumoPath) + "/data/3D";
     155          872 :         if (FileHelpers::isReadable(newPath)) {
     156          436 :             osgDB::FilePathList path = osgDB::Registry::instance()->getDataFilePathList();
     157          436 :             path.push_back(newPath);
     158          436 :             osgDB::Registry::instance()->setDataFilePathList(path);
     159          436 :         }
     160              :     }
     161              : 
     162          436 :     myGreenLight = osgDB::readNodeFile("tlg.obj");
     163          436 :     myYellowLight = osgDB::readNodeFile("tly.obj");
     164          436 :     myRedLight = osgDB::readNodeFile("tlr.obj");
     165          436 :     myRedYellowLight = osgDB::readNodeFile("tlu.obj");
     166          872 :     myPoleBase = osgDB::readNodeFile("poleBase.obj");
     167          436 :     if (myGreenLight == 0 || myYellowLight == 0 || myRedLight == 0 || myRedYellowLight == 0 || myPoleBase == 0) {
     168            0 :         WRITE_ERROR(TL("Could not load traffic light files."));
     169              :     }
     170              :     // calculate camera frustum to scale the ground plane all across
     171              :     double left, right, bottom, top, zNear, zFar;
     172          436 :     myViewer->getCamera()->getProjectionMatrixAsFrustum(left, right, bottom, top, zNear, zFar);
     173          436 :     myRoot = GUIOSGBuilder::buildOSGScene(myGreenLight, myYellowLight, myRedLight, myRedYellowLight, myPoleBase);
     174          436 :     myPlane = new osg::MatrixTransform();
     175          436 :     myPlane->setCullCallback(new ExcludeFromNearFarComputationCallback());
     176          436 :     myPlane->addChild(GUIOSGBuilder::buildPlane((float)(zFar - zNear)));
     177          872 :     myPlane->addUpdateCallback(new PlaneMoverCallback(myViewer->getCamera()));
     178              :     myRoot->addChild(myPlane);
     179              :     // add the stats handler
     180          436 :     osgViewer::StatsHandler* statsHandler = new osgViewer::StatsHandler();
     181              :     statsHandler->setKeyEventTogglesOnScreenStats(osgGA::GUIEventAdapter::KEY_I);
     182          436 :     myViewer->addEventHandler(statsHandler);
     183          436 :     myViewer->setSceneData(myRoot);
     184          436 :     myViewer->setCameraManipulator(myCameraManipulator);
     185              : 
     186              :     myViewer->setKeyEventSetsDone(0);
     187          436 :     myViewer->getCamera()->setGraphicsContext(myAdapter);
     188          436 :     myViewer->getCamera()->setViewport(0, 0, w, h);
     189              :     myViewer->getCamera()->setNearFarRatio(0.005); // does not work together with setUpDepthPartitionForCamera
     190          436 :     myViewer->setThreadingModel(osgViewer::Viewer::SingleThreaded);
     191          436 :     myViewer->addEventHandler(new PickHandler(this));
     192              :     osg::Vec3d lookFrom, lookAt, up;
     193          436 :     myCameraManipulator->getHomePosition(lookFrom, lookAt, up);
     194          436 :     lookFrom = lookAt + osg::Z_AXIS;
     195          436 :     up = osg::Y_AXIS;
     196          436 :     myCameraManipulator->setHomePosition(lookFrom, lookAt, up);
     197          436 :     myViewer->home();
     198          436 :     recenterView();
     199          436 :     myViewer->home();
     200          436 :     getApp()->addChore(this, MID_CHORE);
     201          436 :     myTextNode = new osg::Geode();
     202          436 :     myText = new osgText::Text;
     203              :     myText->setCharacterSizeMode(osgText::Text::SCREEN_COORDS);
     204          436 :     myText->setShaderTechnique(osgText::NO_TEXT_SHADER);
     205          436 :     osgText::Font* font = osgText::readFontFile("arial.ttf");
     206          436 :     if (font != nullptr) {
     207          436 :         myText->setFont(font);
     208              :     }
     209          436 :     myText->setCharacterSize(16.f);
     210              :     myTextNode->addDrawable(myText);
     211          436 :     myText->setAlignment(osgText::TextBase::AlignmentType::LEFT_TOP);
     212          436 :     myText->setDrawMode(osgText::TextBase::DrawModeMask::FILLEDBOUNDINGBOX | osgText::TextBase::DrawModeMask::TEXT);
     213              :     myText->setBoundingBoxColor(osg::Vec4(0.0f, 0.0f, 0.2f, 0.5f));
     214          436 :     myText->setBoundingBoxMargin(2.0f);
     215              : 
     216          436 :     myHUD = new osg::Camera;
     217          436 :     myHUD->setProjectionMatrixAsOrtho2D(0, 800, 0, 800); // default size will be overwritten
     218          436 :     myHUD->setReferenceFrame(osg::Transform::ABSOLUTE_RF);
     219          436 :     myHUD->setViewMatrix(osg::Matrix::identity());
     220              :     myHUD->setClearMask(GL_DEPTH_BUFFER_BIT);
     221              :     myHUD->setRenderOrder(osg::Camera::POST_RENDER);
     222              :     myHUD->setAllowEventFocus(false);
     223          436 :     myHUD->setGraphicsContext(myAdapter);
     224          436 :     myHUD->addChild(myTextNode);
     225          436 :     myHUD->setViewport(0, 0, w, h);
     226          436 :     myViewer->addSlave(myHUD, false);
     227          436 :     myCameraManipulator->updateHUDText();
     228              : 
     229              :     // adjust the main light
     230          436 :     adoptViewSettings();
     231              :     osgUtil::Optimizer optimizer;
     232              :     optimizer.optimize(myRoot);
     233          436 : }
     234              : 
     235              : 
     236          872 : GUIOSGView::~GUIOSGView() {
     237          436 :     getApp()->removeChore(this, MID_CHORE);
     238              :     myViewer->setDone(true);
     239          436 :     myViewer = 0;
     240              :     myRoot = 0;
     241              :     myAdapter = 0;
     242          436 :     myCameraManipulator = 0;
     243              :     myHUD = 0;
     244              :     myText = 0;
     245              :     myTextNode = 0;
     246              :     myGreenLight = 0;
     247              :     myYellowLight = 0;
     248              :     myRedLight = 0;
     249              :     myRedYellowLight = 0;
     250              :     myPoleBase = 0;
     251          872 : }
     252              : 
     253              : 
     254              : void
     255          436 : GUIOSGView::adoptViewSettings() {
     256              :     // lighting
     257              :     osg::Light* globalLight = myViewer->getLight();
     258          436 :     globalLight->setAmbient(toOSGColorVector(myVisualizationSettings->ambient3DLight));
     259          436 :     globalLight->setDiffuse(toOSGColorVector(myVisualizationSettings->diffuse3DLight));
     260          872 :     myViewer->getCamera()->setClearColor(toOSGColorVector(myVisualizationSettings->skyColor));
     261              : 
     262              :     // ground color
     263          436 :     osg::Geode* planeGeode = dynamic_cast<osg::Geode*>(myPlane->getChild(0));
     264          436 :     osg::Geometry* planeGeom = dynamic_cast<osg::Geometry*>(planeGeode->getChild(0));
     265          436 :     osg::Vec4ubArray* colors = dynamic_cast<osg::Vec4ubArray*>(planeGeom->getColorArray());
     266          436 :     (*colors)[0].set(myVisualizationSettings->backgroundColor.red(),
     267          436 :                      myVisualizationSettings->backgroundColor.green(),
     268          436 :                      myVisualizationSettings->backgroundColor.blue(),
     269          436 :                      myVisualizationSettings->backgroundColor.alpha());
     270              :     planeGeom->setColorArray(colors);
     271              : 
     272              :     // show/hide OSG nodes
     273              :     unsigned int cullMask = 0xFFFFFFFF;
     274          436 :     if (!myVisualizationSettings->show3DTLSDomes) {
     275              :         cullMask &= ~(unsigned int)NODESET_TLSDOMES;
     276              :     }
     277          436 :     if (!myVisualizationSettings->show3DTLSLinkMarkers) {
     278            0 :         cullMask &= ~(unsigned int)NODESET_TLSLINKMARKERS;
     279              :     }
     280          436 :     if (!myVisualizationSettings->generate3DTLSModels) {
     281          436 :         cullMask &= ~(unsigned int)NODESET_TLSMODELS;
     282              :     }
     283              :     myViewer->getCamera()->setCullMask(cullMask);
     284          436 :     unsigned int hudCullMask = (myVisualizationSettings->show3DHeadUpDisplay) ? 0xFFFFFFFF : 0;
     285              :     myHUD->setCullMask(hudCullMask);
     286          436 : }
     287              : 
     288              : 
     289              : Position
     290            0 : GUIOSGView::getPositionInformation() const {
     291              :     Position pos;
     292            0 :     getPositionAtCursor(myOSGNormalizedCursorX, myOSGNormalizedCursorY, pos);
     293            0 :     return pos;
     294              : }
     295              : 
     296              : 
     297              : bool
     298            0 : GUIOSGView::is3DView() const {
     299            0 :     return true;
     300              : }
     301              : 
     302              : 
     303              : void
     304          436 : GUIOSGView::buildViewToolBars(GUIGlChildWindow* v) {
     305              :     // build coloring tools
     306              :     {
     307          436 :         const std::vector<std::string>& names = gSchemeStorage.getNames();
     308         2616 :         for (std::vector<std::string>::const_iterator i = names.begin(); i != names.end(); ++i) {
     309         2180 :             v->getColoringSchemesCombo()->appendIconItem(i->c_str());
     310         2180 :             if ((*i) == myVisualizationSettings->name) {
     311          436 :                 v->getColoringSchemesCombo()->setCurrentItem(v->getColoringSchemesCombo()->getNumItems() - 1);
     312              :             }
     313              :         }
     314              :     }
     315              :     // for junctions
     316          872 :     GUIDesigns::buildFXButton(v->getLocatorPopup(),
     317              :                               "Locate Junction", "Locate a junction within the network.", "",
     318              :                               GUIIconSubSys::getIcon(GUIIcon::LOCATEJUNCTION), v, MID_HOTKEY_SHIFT_J_LOCATEJUNCTION,
     319              :                               GUIDesignButtonPopup);
     320              :     // for edges
     321          872 :     GUIDesigns::buildFXButton(v->getLocatorPopup(),
     322              :                               "Locate Street", "Locate a street within the network.", "",
     323              :                               GUIIconSubSys::getIcon(GUIIcon::LOCATEEDGE), v, MID_HOTKEY_SHIFT_E_LOCATEEDGE,
     324              :                               GUIDesignButtonPopup);
     325              :     // for vehicles
     326          872 :     GUIDesigns::buildFXButton(v->getLocatorPopup(),
     327              :                               "Locate Vehicle", "Locate a vehicle within the network.", "",
     328              :                               GUIIconSubSys::getIcon(GUIIcon::LOCATEVEHICLE), v, MID_HOTKEY_SHIFT_V_LOCATEVEHICLE,
     329              :                               GUIDesignButtonPopup);
     330              :     // for persons
     331          872 :     GUIDesigns::buildFXButton(v->getLocatorPopup(),
     332              :                               "Locate Person", "Locate a person within the network.", "",
     333              :                               GUIIconSubSys::getIcon(GUIIcon::LOCATEPERSON), v, MID_HOTKEY_SHIFT_P_LOCATEPERSON,
     334              :                               GUIDesignButtonPopup);
     335              :     // for containers
     336          872 :     GUIDesigns::buildFXButton(v->getLocatorPopup(),
     337              :                               "Locate Container", "Locate a container within the network.", "",
     338              :                               GUIIconSubSys::getIcon(GUIIcon::LOCATECONTAINER), v, MID_HOTKEY_SHIFT_C_LOCATECONTAINER,
     339              :                               GUIDesignButtonPopup);
     340              :     // for tls
     341          872 :     GUIDesigns::buildFXButton(v->getLocatorPopup(),
     342              :                               "Locate TLS", "Locate a tls within the network.", "",
     343              :                               GUIIconSubSys::getIcon(GUIIcon::LOCATETLS), v, MID_HOTKEY_SHIFT_T_LOCATETLS,
     344              :                               GUIDesignButtonPopup);
     345              :     // for additional stuff
     346          872 :     GUIDesigns::buildFXButton(v->getLocatorPopup(),
     347              :                               "Locate Additional", "Locate an additional structure within the network.", "",
     348              :                               GUIIconSubSys::getIcon(GUIIcon::LOCATEADD), v, MID_HOTKEY_SHIFT_A_LOCATEADDITIONAL,
     349              :                               GUIDesignButtonPopup);
     350              :     // for pois
     351          872 :     GUIDesigns::buildFXButton(v->getLocatorPopup(),
     352              :                               "Locate POI", "Locate a POI within the network.", "",
     353              :                               GUIIconSubSys::getIcon(GUIIcon::LOCATEPOI), v, MID_HOTKEY_SHIFT_O_LOCATEPOI,
     354              :                               GUIDesignButtonPopup);
     355              :     // for polygons
     356          872 :     GUIDesigns::buildFXButton(v->getLocatorPopup(),
     357              :                               "Locate Polygon", "Locate a Polygon within the network.", "",
     358              :                               GUIIconSubSys::getIcon(GUIIcon::LOCATEPOLY), v, MID_HOTKEY_SHIFT_L_LOCATEPOLY,
     359              :                               GUIDesignButtonPopup);
     360          436 : }
     361              : 
     362              : 
     363              : void
     364            0 : GUIOSGView::resize(int w, int h) {
     365            0 :     GUISUMOAbstractView::resize(w, h);
     366            0 :     updateHUDPosition(w, h);
     367            0 : }
     368              : 
     369              : 
     370              : void
     371          360 : GUIOSGView::position(int x, int y, int w, int h) {
     372          360 :     GUISUMOAbstractView::position(x, y, w, h);
     373          360 :     updateHUDPosition(w, h);
     374          360 : }
     375              : 
     376              : 
     377              : void
     378          720 : GUIOSGView::updateHUDPosition(int w, int h) {
     379              :     // keep the HUD text in the left top corner
     380          720 :     myHUD->setProjectionMatrixAsOrtho2D(0, w, 0, h);
     381          720 :     myText->setPosition(osg::Vec3d(0., static_cast<double>(height), 0.));
     382          720 : }
     383              : 
     384              : 
     385              : void
     386          436 : GUIOSGView::updateHUDText(const std::string text) {
     387          436 :     myText->setText(text, osgText::String::ENCODING_UTF8);
     388          436 : }
     389              : 
     390              : 
     391              : void
     392          436 : GUIOSGView::recenterView() {
     393          436 :     stopTrack();
     394          436 :     Position center = myGrid->getCenter();
     395          436 :     double radius = std::max(myGrid->xmax() - myGrid->xmin(), myGrid->ymax() - myGrid->ymin());
     396          436 :     myChanger->centerTo(center, radius);
     397          436 : }
     398              : 
     399              : 
     400              : bool
     401            0 : GUIOSGView::setColorScheme(const std::string& name) {
     402            0 :     if (!gSchemeStorage.contains(name)) {
     403              :         return false;
     404              :     }
     405            0 :     if (myGUIDialogViewSettings != 0) {
     406            0 :         if (myGUIDialogViewSettings->getCurrentScheme() != name) {
     407            0 :             myGUIDialogViewSettings->setCurrentScheme(name);
     408              :         }
     409              :     }
     410            0 :     myVisualizationSettings = &gSchemeStorage.get(name.c_str());
     411            0 :     myVisualizationSettings->gaming = myApp->isGaming();
     412            0 :     adoptViewSettings();
     413            0 :     update();
     414            0 :     return true;
     415              : }
     416              : 
     417              : 
     418              : long
     419        43504 : GUIOSGView::onPaint(FXObject*, FXSelector, void*) {
     420        43504 :     if (!isEnabled()) {
     421              :         return 1;
     422              :     }
     423        43504 :     myDecalsLockMutex.lock();
     424        43504 :     for (GUISUMOAbstractView::Decal& d : myDecals) {
     425            0 :         if (!d.initialised && d.filename.length() > 0) {
     426            0 :             if (d.filename.length() == 6 && d.filename.substr(0, 5) == "light") {
     427            0 :                 GUIOSGBuilder::buildLight(d, *myRoot);
     428            0 :             } else if (d.filename.length() > 3 && d.filename.substr(0, 3) == "tl:") {
     429            0 :                 const int linkStringIdx = (int)d.filename.find(':', 3);
     430            0 :                 GUINet* net = (GUINet*) MSNet::getInstance();
     431              :                 try {
     432            0 :                     const std::string tlLogic = d.filename.substr(3, linkStringIdx - 3);
     433            0 :                     MSTLLogicControl::TLSLogicVariants& vars = net->getTLSControl().get(tlLogic);
     434            0 :                     const int linkIdx = StringUtils::toInt(d.filename.substr(linkStringIdx + 1));
     435            0 :                     if (linkIdx < 0 || linkIdx >= static_cast<int>(vars.getActive()->getLinks().size())) {
     436            0 :                         throw NumberFormatException("");
     437              :                     }
     438            0 :                     const MSLink* const link = vars.getActive()->getLinksAt(linkIdx)[0];
     439            0 :                     osg::Group* tlNode = GUIOSGBuilder::getTrafficLight(d, vars, link, myGreenLight, myYellowLight, myRedLight, myRedYellowLight, myPoleBase, true, 0.5);
     440            0 :                     tlNode->setName("tlLogic:" + tlLogic);
     441            0 :                     myRoot->addChild(tlNode);
     442            0 :                 } catch (NumberFormatException&) {
     443            0 :                     WRITE_ERRORF(TL("Invalid link index in '%'."), d.filename);
     444            0 :                 } catch (InvalidArgument&) {
     445            0 :                     WRITE_ERRORF(TL("Unknown traffic light in '%'."), d.filename);
     446            0 :                 }
     447              :             } else {
     448            0 :                 GUIOSGBuilder::buildDecal(d, *myRoot);
     449              :             }
     450            0 :             d.initialised = true;
     451              :         }
     452              :     }
     453        43504 :     myDecalsLockMutex.unlock();
     454              : 
     455              :     // reset active flag
     456      3692253 :     for (auto& item : myVehicles) {
     457      3648749 :         item.second.active = false;
     458              :     }
     459              : 
     460        43504 :     GUINet* net = static_cast<GUINet*>(MSNet::getInstance());
     461              :     // build edges
     462       881211 :     for (const MSEdge* e : net->getEdgeControl().getEdges()) {
     463      2002857 :         for (const MSLane* l : e->getLanes()) {
     464      1165150 :             const MSLane::VehCont& vehicles = l->getVehiclesSecure();
     465      4817019 :             for (MSVehicle* msVeh : vehicles) {
     466              :                 GUIVehicle* veh = static_cast<GUIVehicle*>(msVeh);
     467      3651869 :                 if (!(veh->isOnRoad() || veh->isParking() || veh->wasRemoteControlled())) {
     468              :                     continue;
     469              :                 }
     470              :                 auto itVeh = myVehicles.find(veh);
     471      3651869 :                 if (itVeh == myVehicles.end()) {
     472        33985 :                     myVehicles[veh] = GUIOSGBuilder::buildMovable(veh->getVehicleType());
     473        33985 :                     myRoot->addChild(myVehicles[veh].pos);
     474        33985 :                     myVehicles[veh].pos->setName("vehicle:" + veh->getID());
     475        33985 :                     veh->setNode(myVehicles[veh].pos);
     476              :                 } else {
     477      3617884 :                     itVeh->second.active = true;
     478              :                 }
     479      3651869 :                 osg::PositionAttitudeTransform* n = myVehicles[veh].pos;
     480      3651869 :                 n->setPosition(osg::Vec3d(veh->getPosition().x(), veh->getPosition().y(), veh->getPosition().z()));
     481      3651869 :                 const double dir = veh->getAngle() + M_PI / 2.;
     482      3651869 :                 const double slope = -veh->getSlope();
     483      3651869 :                 n->setAttitude(osg::Quat(osg::DegreesToRadians(slope), osg::Vec3(1, 0, 0),
     484      3651869 :                                          0, osg::Vec3(0, 1, 0),
     485      3651869 :                                          dir, osg::Vec3(0, 0, 1)));
     486              :                 /*
     487              :                 osg::ref_ptr<osg::AnimationPath> path = new osg::AnimationPath;
     488              :                 // path->setLoopMode( osg::AnimationPath::NO_LOOPING );
     489              :                 osg::AnimationPath::ControlPoint pointA(n->getPosition(), n->getAttitude());
     490              :                 osg::AnimationPath::ControlPoint pointB(osg::Vec3(veh->getPosition().x(), veh->getPosition().y(), veh->getPosition().z()),
     491              :                                                         osg::Quat(dir, osg::Vec3(0, 0, 1)) *
     492              :                                                         osg::Quat(osg::DegreesToRadians(slope), osg::Vec3(0, 1, 0)));
     493              :                 path->insert(0.0f, pointA);
     494              :                 path->insert(0.5f, pointB);
     495              :                 n->setUpdateCallback(new osg::AnimationPathCallback(path));
     496              :                 */
     497              : 
     498      3651869 :                 if (myVisualizationSettings->ignoreColorSchemeFor3DVehicles) {
     499            0 :                     myVehicles[veh].activateMaterial(false);
     500              :                 } else {
     501      3651869 :                     myVehicles[veh].activateMaterial(true);
     502      3651869 :                     RGBColor col;
     503      3651869 :                     if (!GUIBaseVehicle::setFunctionalColor(myVisualizationSettings->vehicleColorer.getActive(), veh, col)) {
     504      3645251 :                         col = myVisualizationSettings->vehicleColorer.getScheme().getColor(veh->getColorValue(*myVisualizationSettings, myVisualizationSettings->vehicleColorer.getActive()));
     505              :                     }
     506      3651869 :                     myVehicles[veh].mat->setDiffuse(osg::Material::FRONT_AND_BACK, osg::Vec4d(col.red() / 255., col.green() / 255., col.blue() / 255., col.alpha() / 255.));
     507              :                 }
     508      3651869 :                 myVehicles[veh].lights->setValue(0, veh->signalSet(MSVehicle::VEH_SIGNAL_BLINKER_RIGHT | MSVehicle::VEH_SIGNAL_BLINKER_EMERGENCY));
     509      3651869 :                 myVehicles[veh].lights->setValue(1, veh->signalSet(MSVehicle::VEH_SIGNAL_BLINKER_LEFT | MSVehicle::VEH_SIGNAL_BLINKER_EMERGENCY));
     510      3651869 :                 myVehicles[veh].lights->setValue(2, veh->signalSet(MSVehicle::VEH_SIGNAL_BRAKELIGHT));
     511              :             }
     512      1165150 :             l->releaseVehicles();
     513              :         }
     514              :     }
     515              :     // remove inactive
     516      3726238 :     for (auto veh = myVehicles.begin(); veh != myVehicles.end();) {
     517      3682734 :         if (!veh->second.active) {
     518        31811 :             removeVeh((veh++)->first);
     519              :         } else {
     520              :             ++veh;
     521              :         }
     522              :     }
     523              : 
     524        43504 :     const SUMOTime now = MSNet::getInstance()->getCurrentTimeStep();
     525        43504 :     if (now != myLastUpdate || (myGUIDialogViewSettings != 0 && myGUIDialogViewSettings->shown())) {
     526        19702 :         GUINet::getGUIInstance()->updateColor(*myVisualizationSettings);
     527              :     }
     528        43504 :     if (now != myLastUpdate && myTracked != 0) {
     529              :         osg::Vec3d lookFrom, lookAt, up;
     530            0 :         lookAt[0] = myTracked->getPosition().x();
     531            0 :         lookAt[1] = myTracked->getPosition().y();
     532            0 :         lookAt[2] = myTracked->getPosition().z();
     533            0 :         const double angle = myTracked->getAngle();
     534            0 :         lookFrom[0] = lookAt[0] + 50. * cos(angle);
     535            0 :         lookFrom[1] = lookAt[1] + 50. * sin(angle);
     536            0 :         lookFrom[2] = lookAt[2] + 10.;
     537              :         osg::Matrix m;
     538            0 :         m.makeLookAt(lookFrom, lookAt, osg::Z_AXIS);
     539            0 :         myViewer->getCameraManipulator()->setByInverseMatrix(m);
     540              :     }
     541              : 
     542              :     // reset active flag
     543        48951 :     for (auto& item : myPersons) {
     544         5447 :         item.second.active = false;
     545              :     }
     546              : 
     547       881211 :     for (const MSEdge* e : net->getEdgeControl().getEdges()) {
     548              :         const GUIEdge* ge = static_cast<const GUIEdge*>(e);
     549              :         const std::set<MSTransportable*, ComparatorNumericalIdLess>& persons = ge->getPersonsSecure();
     550       843309 :         for (auto person : persons) {
     551         5602 :             if (person->hasArrived() || !person->hasDeparted()) {
     552              :                 //std::cout << SIMTIME << " person " << person->getID() << " is loaded but arrived\n";
     553            0 :                 continue;
     554              :             }
     555              :             auto itPers = myPersons.find(person);
     556         5602 :             if (itPers == myPersons.end()) {
     557          518 :                 myPersons[person] = GUIOSGBuilder::buildMovable(person->getVehicleType());
     558          518 :                 myRoot->addChild(myPersons[person].pos);
     559              :             } else {
     560         5084 :                 itPers->second.active = true;
     561              :             }
     562         5602 :             osg::PositionAttitudeTransform* n = myPersons[person].pos;
     563         5602 :             const Position pos = person->getPosition();
     564              :             n->setPosition(osg::Vec3d(pos.x(), pos.y(), pos.z()));
     565         5602 :             const double dir = person->getAngle() + M_PI / 2.;
     566         5602 :             n->setAttitude(osg::Quat(dir, osg::Vec3d(0, 0, 1)));
     567              : 
     568         5602 :             RGBColor col;
     569         5602 :             GUIPerson* actualPerson = dynamic_cast<GUIPerson*>(person);
     570         5602 :             if (!GUIPerson::setFunctionalColor(myVisualizationSettings->personColorer.getActive(), actualPerson, col)) {
     571         5498 :                 col = myVisualizationSettings->personColorer.getScheme().getColor(actualPerson->getColorValue(*myVisualizationSettings, myVisualizationSettings->vehicleColorer.getActive()));
     572              :             }
     573         5602 :             myPersons[person].mat->setDiffuse(osg::Material::FRONT_AND_BACK, osg::Vec4d(col.red() / 255., col.green() / 255., col.blue() / 255., col.alpha() / 255.));
     574              :         }
     575              :         ge->releasePersons();
     576              :     }
     577              : 
     578              :     // remove inactive
     579        49469 :     for (auto person = myPersons.begin(); person != myPersons.end();) {
     580         5965 :         if (!person->second.active) {
     581          363 :             removeTransportable((person++)->first);
     582              :         } else {
     583              :             ++person;
     584              :         }
     585              :     }
     586              : 
     587        43504 :     if (myAdapter->makeCurrent()) {
     588        43504 :         myViewer->frame();
     589        43504 :         makeNonCurrent();
     590              :     }
     591        43504 :     myLastUpdate = now;
     592        43504 :     return 1;
     593              : }
     594              : 
     595              : 
     596              : void
     597        31811 : GUIOSGView::removeVeh(MSVehicle* veh) {
     598        31811 :     if (myTracked == veh) {
     599            0 :         stopTrack();
     600              :     }
     601              :     std::map<MSVehicle*, OSGMovable>::iterator i = myVehicles.find(veh);
     602        31811 :     if (i != myVehicles.end()) {
     603              :         myRoot->removeChild(i->second.pos);
     604              :         myVehicles.erase(i);
     605              :     }
     606        31811 : }
     607              : 
     608              : 
     609              : void
     610          363 : GUIOSGView::removeTransportable(MSTransportable* t) {
     611              :     std::map<MSTransportable*, OSGMovable>::iterator i = myPersons.find(t);
     612          363 :     if (i != myPersons.end()) {
     613              :         myRoot->removeChild(i->second.pos);
     614              :         myPersons.erase(i);
     615              :     }
     616          363 : }
     617              : 
     618              : 
     619            0 : void GUIOSGView::updateViewportValues() {
     620              :     osg::Vec3d lookFrom, lookAt, up;
     621            0 :     myViewer->getCameraManipulator()->getInverseMatrix().getLookAt(lookFrom, lookAt, up);
     622            0 :     myGUIDialogEditViewport->setValues(Position(lookFrom[0], lookFrom[1], lookFrom[2]),
     623            0 :                                        Position(lookAt[0], lookAt[1], lookAt[2]), calculateRotation(lookFrom, lookAt, up));
     624            0 : }
     625              : 
     626              : 
     627              : void
     628            0 : GUIOSGView::showViewportEditor() {
     629            0 :     getViewportEditor(); // make sure it exists;
     630              :     osg::Vec3d lookFrom, lookAt, up;
     631            0 :     myViewer->getCameraManipulator()->getInverseMatrix().getLookAt(lookFrom, lookAt, up);
     632            0 :     Position from(lookFrom[0], lookFrom[1], lookFrom[2]), at(lookAt[0], lookAt[1], lookAt[2]);
     633            0 :     myGUIDialogEditViewport->setOldValues(from, at, calculateRotation(lookFrom, lookAt, up));
     634            0 :     myGUIDialogEditViewport->setZoomValue(100);
     635            0 :     myGUIDialogEditViewport->show();
     636            0 : }
     637              : 
     638              : 
     639              : void
     640            0 : GUIOSGView::setViewportFromToRot(const Position& lookFrom, const Position& lookAt, double rotation) {
     641              :     osg::Vec3d lookFromOSG, lookAtOSG, up;
     642            0 :     lookFromOSG[0] = lookFrom.x();
     643            0 :     lookFromOSG[1] = lookFrom.y();
     644            0 :     lookFromOSG[2] = lookFrom.z();
     645            0 :     lookAtOSG[0] = lookAt.x();
     646            0 :     lookAtOSG[1] = lookAt.y();
     647            0 :     lookAtOSG[2] = lookAt.z();
     648              : 
     649              :     osg::Vec3d viewAxis, viewUp, orthogonal, normal;
     650            0 :     viewAxis = lookFromOSG - lookAtOSG;
     651            0 :     viewAxis.normalize();
     652            0 :     viewUp = (viewAxis[0] + viewAxis[1] == 0.) ? osg::Vec3d(0., 1., 0.) : osg::Vec3d(0., 0., 1.); // check for parallel vectors
     653            0 :     orthogonal = viewUp ^ viewAxis;
     654            0 :     orthogonal.normalize();
     655              :     normal = viewAxis ^ orthogonal;
     656              : 
     657            0 :     rotation = std::fmod(rotation, 360.);
     658            0 :     if (rotation < 0) {
     659            0 :         rotation += 360.;
     660              :     }
     661            0 :     myChanger->setRotation(rotation);
     662            0 :     double angle = DEG2RAD(rotation);
     663            0 :     up = normal * cos(angle) - orthogonal * sin(angle);
     664            0 :     up.normalize();
     665              : 
     666            0 :     double zoom = (myGUIDialogEditViewport != nullptr) ? myGUIDialogEditViewport->getZoomValue() : 100.;
     667            0 :     lookFromOSG = lookFromOSG + viewAxis * (100. - zoom);
     668            0 :     lookAtOSG = lookFromOSG - viewAxis;
     669            0 :     myViewer->getCameraManipulator()->setHomePosition(lookFromOSG, lookAtOSG, up);
     670            0 :     myViewer->home();
     671            0 : }
     672              : 
     673              : 
     674              : void
     675            0 : GUIOSGView::copyViewportTo(GUISUMOAbstractView* view) {
     676              :     osg::Vec3d lookFrom, lookAt, up;
     677            0 :     myViewer->getCameraManipulator()->getHomePosition(lookFrom, lookAt, up);
     678            0 :     view->setViewportFromToRot(Position(lookFrom[0], lookFrom[1], lookFrom[2]),
     679            0 :                                Position(lookAt[0], lookAt[1], lookAt[2]), 0);
     680            0 : }
     681              : 
     682              : 
     683              : void
     684            0 : GUIOSGView::startTrack(int id) {
     685            0 :     if (myTracked == 0 || (int)myTracked->getGlID() != id) {
     686            0 :         myTracked = 0;
     687            0 :         MSVehicleControl::constVehIt it = MSNet::getInstance()->getVehicleControl().loadedVehBegin();
     688            0 :         for (; it != MSNet::getInstance()->getVehicleControl().loadedVehEnd(); it++) {
     689            0 :             GUIVehicle* veh = (GUIVehicle*)(*it).second;
     690            0 :             if ((int)veh->getGlID() == id) {
     691            0 :                 if (!veh->isOnRoad() || myVehicles.find(veh) == myVehicles.end()) {
     692              :                     return;
     693              :                 }
     694            0 :                 myTracked = veh;
     695            0 :                 break;
     696              :             }
     697              :         }
     698            0 :         if (myTracked != 0) {
     699              :             osg::Vec3d lookFrom, lookAt, up;
     700            0 :             lookAt[0] = myTracked->getPosition().x();
     701            0 :             lookAt[1] = myTracked->getPosition().y();
     702            0 :             lookAt[2] = myTracked->getPosition().z();
     703            0 :             lookFrom[0] = lookAt[0] + 50.;
     704            0 :             lookFrom[1] = lookAt[1] + 50.;
     705            0 :             lookFrom[2] = lookAt[2] + 10.;
     706              :             osg::Matrix m;
     707            0 :             m.makeLookAt(lookFrom, lookAt, osg::Z_AXIS);
     708            0 :             myViewer->getCameraManipulator()->setByInverseMatrix(m);
     709              :         }
     710              :     }
     711              : }
     712              : 
     713              : 
     714              : void
     715          436 : GUIOSGView::stopTrack() {
     716          436 :     myTracked = 0;
     717          436 : }
     718              : 
     719              : 
     720              : GUIGlID
     721        28840 : GUIOSGView::getTrackedID() const {
     722        28840 :     return myTracked == 0 ? GUIGlObject::INVALID_ID : myTracked->getGlID();
     723              : }
     724              : 
     725              : 
     726              : void
     727            0 : GUIOSGView::onGamingClick(Position pos) {
     728            0 :     MSTLLogicControl& tlsControl = MSNet::getInstance()->getTLSControl();
     729              :     const MSTrafficLightLogic* minTll = nullptr;
     730              :     double minDist = std::numeric_limits<double>::infinity();
     731            0 :     for (const MSTrafficLightLogic* const tll : tlsControl.getAllLogics()) {
     732            0 :         if (tlsControl.isActive(tll)) {
     733              :             // get the links
     734              :             const MSTrafficLightLogic::LaneVector& lanes = tll->getLanesAt(0);
     735            0 :             if (lanes.size() > 0) {
     736            0 :                 const Position& endPos = lanes[0]->getShape().back();
     737            0 :                 if (endPos.distanceTo(pos) < minDist) {
     738            0 :                     minDist = endPos.distanceTo(pos);
     739              :                     minTll = tll;
     740              :                 }
     741              :             }
     742              :         }
     743            0 :     }
     744            0 :     if (minTll != 0) {
     745            0 :         const MSTLLogicControl::TLSLogicVariants& vars = tlsControl.get(minTll->getID());
     746            0 :         const std::vector<MSTrafficLightLogic*> logics = vars.getAllLogics();
     747            0 :         if (logics.size() > 1) {
     748            0 :             MSSimpleTrafficLightLogic* l = (MSSimpleTrafficLightLogic*) logics[0];
     749            0 :             for (int i = 0; i < (int)logics.size() - 1; i++) {
     750            0 :                 if (minTll->getProgramID() == logics[i]->getProgramID()) {
     751            0 :                     l = (MSSimpleTrafficLightLogic*) logics[i + 1];
     752            0 :                     tlsControl.switchTo(minTll->getID(), l->getProgramID());
     753              :                 }
     754              :             }
     755            0 :             if (l == logics[0]) {
     756            0 :                 tlsControl.switchTo(minTll->getID(), l->getProgramID());
     757              :             }
     758            0 :             l->changeStepAndDuration(tlsControl, MSNet::getInstance()->getCurrentTimeStep(), 0, l->getPhase(0).duration);
     759            0 :             update();
     760              :         }
     761            0 :     }
     762            0 : }
     763              : 
     764              : 
     765              : SUMOTime
     766       326857 : GUIOSGView::getCurrentTimeStep() const {
     767       326857 :     return MSNet::getInstance()->getCurrentTimeStep();
     768              : }
     769              : 
     770              : 
     771          360 : long GUIOSGView::onConfigure(FXObject* sender, FXSelector sel, void* ptr) {
     772              :     // update the window dimensions, in case the window has been resized.
     773              :     const int w = getWidth();
     774              :     const int h = getHeight();
     775          360 :     if (w > 0 && h > 0) {
     776          360 :         myAdapter->getEventQueue()->windowResize(0, 0, w, h);
     777          360 :         myAdapter->resized(0, 0, w, h);
     778          360 :         updateHUDPosition(w, h);
     779              :     }
     780          360 :     return FXGLCanvas::onConfigure(sender, sel, ptr);
     781              : }
     782              : 
     783              : 
     784            0 : long GUIOSGView::onKeyPress(FXObject* sender, FXSelector sel, void* ptr) {
     785            0 :     int key = ((FXEvent*)ptr)->code;
     786            0 :     myAdapter->getEventQueue()->keyPress(key);
     787              :     // leave key handling for some cases to OSG
     788            0 :     if (key == FX::KEY_f || key == FX::KEY_Left || key == FX::KEY_Right || key == FX::KEY_Up || key == FX::KEY_Down) {
     789              :         return 1;
     790              :     }
     791            0 :     return FXGLCanvas::onKeyPress(sender, sel, ptr);
     792              : }
     793              : 
     794              : 
     795            0 : long GUIOSGView::onKeyRelease(FXObject* sender, FXSelector sel, void* ptr) {
     796            0 :     int key = ((FXEvent*)ptr)->code;
     797            0 :     myAdapter->getEventQueue()->keyRelease(key);
     798              :     // leave key handling for some cases to OSG
     799            0 :     if (key == FX::KEY_f || key == FX::KEY_Left || key == FX::KEY_Right || key == FX::KEY_Up || key == FX::KEY_Down) {
     800              :         return 1;
     801              :     }
     802            0 :     return FXGLCanvas::onKeyRelease(sender, sel, ptr);
     803              : }
     804              : 
     805              : 
     806            0 : long GUIOSGView::onLeftBtnPress(FXObject* sender, FXSelector sel, void* ptr) {
     807            0 :     handle(this, FXSEL(SEL_FOCUS_SELF, 0), ptr);
     808              : 
     809              :     FXEvent* event = (FXEvent*)ptr;
     810            0 :     myAdapter->getEventQueue()->mouseButtonPress((float)event->click_x, (float)event->click_y, 1);
     811            0 :     if (myApp->isGaming()) {
     812            0 :         onGamingClick(getPositionInformation());
     813              :     }
     814              : 
     815            0 :     return FXGLCanvas::onLeftBtnPress(sender, sel, ptr);
     816              : }
     817              : 
     818              : 
     819            0 : long GUIOSGView::onLeftBtnRelease(FXObject* sender, FXSelector sel, void* ptr) {
     820              :     FXEvent* event = (FXEvent*)ptr;
     821            0 :     myAdapter->getEventQueue()->mouseButtonRelease((float)event->click_x, (float)event->click_y, 1);
     822            0 :     myChanger->onLeftBtnRelease(ptr);
     823            0 :     return FXGLCanvas::onLeftBtnRelease(sender, sel, ptr);
     824              : }
     825              : 
     826              : 
     827            0 : long GUIOSGView::onMiddleBtnPress(FXObject* sender, FXSelector sel, void* ptr) {
     828            0 :     handle(this, FXSEL(SEL_FOCUS_SELF, 0), ptr);
     829              : 
     830              :     FXEvent* event = (FXEvent*)ptr;
     831            0 :     myAdapter->getEventQueue()->mouseButtonPress((float)event->click_x, (float)event->click_y, 2);
     832              : 
     833            0 :     return FXGLCanvas::onMiddleBtnPress(sender, sel, ptr);
     834              : }
     835              : 
     836              : 
     837            0 : long GUIOSGView::onMiddleBtnRelease(FXObject* sender, FXSelector sel, void* ptr) {
     838              :     FXEvent* event = (FXEvent*)ptr;
     839            0 :     myAdapter->getEventQueue()->mouseButtonRelease((float)event->click_x, (float)event->click_y, 2);
     840            0 :     myChanger->onMiddleBtnRelease(ptr);
     841            0 :     return FXGLCanvas::onMiddleBtnRelease(sender, sel, ptr);
     842              : }
     843              : 
     844              : 
     845            0 : long GUIOSGView::onRightBtnPress(FXObject* sender, FXSelector sel, void* ptr) {
     846            0 :     handle(this, FXSEL(SEL_FOCUS_SELF, 0), ptr);
     847              : 
     848              :     FXEvent* event = (FXEvent*)ptr;
     849            0 :     myAdapter->getEventQueue()->mouseButtonPress((float)event->click_x, (float)event->click_y, 3);
     850              : 
     851            0 :     return FXGLCanvas::onRightBtnPress(sender, sel, ptr);
     852              : }
     853              : 
     854              : 
     855            0 : long GUIOSGView::onRightBtnRelease(FXObject* sender, FXSelector sel, void* ptr) {
     856              :     FXEvent* event = (FXEvent*)ptr;
     857            0 :     myAdapter->getEventQueue()->mouseButtonRelease((float)event->click_x, (float)event->click_y, 3);
     858            0 :     myChanger->onRightBtnRelease(ptr);
     859            0 :     return FXGLCanvas::onRightBtnRelease(sender, sel, ptr);
     860              : }
     861              : 
     862              : 
     863              : long
     864            0 : GUIOSGView::onMouseMove(FXObject* sender, FXSelector sel, void* ptr) {
     865              :     // if popup exist but isn't shown, destroy it first
     866            0 :     if (myPopup && !myPopup->shown()) {
     867            0 :         destroyPopup();
     868              :     }
     869              : 
     870              :     FXEvent* event = (FXEvent*)ptr;
     871            0 :     osgGA::GUIEventAdapter* ea = myAdapter->getEventQueue()->mouseMotion((float)event->win_x, (float)event->win_y);
     872            0 :     setWindowCursorPosition(ea->getXnormalized(), ea->getYnormalized());
     873            0 :     if (myGUIDialogEditViewport != nullptr && myGUIDialogEditViewport->shown()) {
     874            0 :         updateViewportValues();
     875              :     }
     876            0 :     updatePositionInformation();
     877            0 :     return FXGLCanvas::onMotion(sender, sel, ptr);
     878              : }
     879              : 
     880              : 
     881              : long
     882        23177 : GUIOSGView::onIdle(FXObject* /* sender */, FXSelector /* sel */, void*) {
     883        23177 :     forceRefresh();
     884        23177 :     update();
     885        23177 :     getApp()->addChore(this, MID_CHORE);
     886        23177 :     return 1;
     887              : }
     888              : 
     889              : 
     890              : long
     891            0 : GUIOSGView::onCmdCloseLane(FXObject*, FXSelector, void*) {
     892            0 :     GUILane* lane = getLaneUnderCursor();
     893            0 :     if (lane != nullptr) {
     894            0 :         lane->closeTraffic();
     895            0 :         GUIGlObjectStorage::gIDStorage.unblockObject(lane->getGlID());
     896            0 :         GUINet::getGUIInstance()->updateColor(*myVisualizationSettings);
     897            0 :         update();
     898              :     }
     899            0 :     return 1;
     900              : }
     901              : 
     902              : 
     903              : long
     904            0 : GUIOSGView::onCmdCloseEdge(FXObject*, FXSelector, void*) {
     905            0 :     GUILane* lane = getLaneUnderCursor();
     906            0 :     if (lane != nullptr) {
     907            0 :         dynamic_cast<GUIEdge*>(&lane->getEdge())->closeTraffic(lane);
     908            0 :         GUIGlObjectStorage::gIDStorage.unblockObject(lane->getGlID());
     909            0 :         GUINet::getGUIInstance()->updateColor(*myVisualizationSettings);
     910            0 :         update();
     911              :     }
     912            0 :     return 1;
     913              : }
     914              : 
     915              : 
     916              : long
     917            0 : GUIOSGView::onCmdAddRerouter(FXObject*, FXSelector, void*) {
     918            0 :     GUILane* lane = getLaneUnderCursor();
     919            0 :     if (lane != nullptr) {
     920            0 :         dynamic_cast<GUIEdge*>(&lane->getEdge())->addRerouter();
     921            0 :         GUIGlObjectStorage::gIDStorage.unblockObject(lane->getGlID());
     922            0 :         update();
     923              :     }
     924            0 :     return 1;
     925              : }
     926              : 
     927              : 
     928              : long
     929            0 : GUIOSGView::onCmdShowReachability(FXObject* menu, FXSelector selector, void*) {
     930            0 :     GUILane* lane = getLaneUnderCursor();
     931            0 :     if (lane != nullptr) {
     932              :         // reset
     933            0 :         GUIViewTraffic::showLaneReachability(lane, menu, selector);
     934              :         // switch to 'color by selection' unless coloring 'by reachability'
     935            0 :         if (myVisualizationSettings->laneColorer.getActive() != 36) {
     936              :             myVisualizationSettings->laneColorer.setActive(1);
     937            0 :             GUINet::getGUIInstance()->updateColor(*myVisualizationSettings);
     938              :         }
     939            0 :         update();
     940              :     }
     941            0 :     return 1;
     942              : }
     943              : 
     944              : 
     945              : long
     946            0 : GUIOSGView::onVisualizationChange(FXObject*, FXSelector, void*) {
     947            0 :     adoptViewSettings();
     948            0 :     return 1;
     949              : }
     950              : 
     951              : 
     952              : void
     953            0 : GUIOSGView::setWindowCursorPosition(float x, float y) {
     954            0 :     myOSGNormalizedCursorX = x;
     955            0 :     myOSGNormalizedCursorY = y;
     956            0 : }
     957              : 
     958              : 
     959              : double
     960            0 : GUIOSGView::calculateRotation(const osg::Vec3d& lookFrom, const osg::Vec3d& lookAt, const osg::Vec3d& up) {
     961              :     osg::Vec3d viewAxis, viewUp, orthogonal, normal;
     962            0 :     viewAxis = lookFrom - lookAt;
     963            0 :     viewAxis.normalize();
     964            0 :     viewUp = (abs(viewAxis[0]) + abs(viewAxis[1]) == 0.) ? osg::Y_AXIS : osg::Z_AXIS; // check for parallel vectors
     965            0 :     orthogonal = viewUp ^ viewAxis;
     966            0 :     orthogonal.normalize();
     967              :     normal = viewAxis ^ orthogonal;
     968            0 :     double angle = atan2((normal ^ up).length() / (normal.length() * up.length()), (normal * up) / (normal.length() * up.length()));
     969            0 :     if (angle < 0) {
     970            0 :         angle += M_PI;
     971              :     }
     972            0 :     return RAD2DEG(angle);
     973              : }
     974              : 
     975              : 
     976              : void
     977            0 : GUIOSGView::updatePositionInformation() const {
     978              :     Position pos;
     979            0 :     if (getPositionAtCursor(myOSGNormalizedCursorX, myOSGNormalizedCursorY, pos)) {
     980            0 :         myApp->getCartesianLabel()->setText(("x:" + toString(pos.x()) + ", y:" + toString(pos.y())).c_str());
     981              :         // set geo position
     982            0 :         GeoConvHelper::getFinal().cartesian2geo(pos);
     983            0 :         if (GeoConvHelper::getFinal().usingGeoProjection()) {
     984            0 :             myApp->getGeoLabel()->setText(("lat:" + toString(pos.y(), gPrecisionGeo) + ", lon:" + toString(pos.x(), gPrecisionGeo)).c_str());
     985              :         } else {
     986            0 :             myApp->getGeoLabel()->setText(TL("(No projection defined)"));
     987              :         }
     988              :     } else {
     989              :         // set placeholder
     990            0 :         myApp->getCartesianLabel()->setText(TL("N/A"));
     991            0 :         myApp->getGeoLabel()->setText(TL("N/A"));
     992              :     }
     993            0 : }
     994              : 
     995              : 
     996              : bool
     997            0 : GUIOSGView::getPositionAtCursor(float xNorm, float yNorm, Position& pos) const {
     998              :     // only reasonable if view axis points to the ground (not parallel to the ground or in the sky)
     999              :     osg::Vec3d lookFrom, lookAt, up, viewAxis;
    1000            0 :     myViewer->getCameraManipulator()->getInverseMatrix().getLookAt(lookFrom, lookAt, up);
    1001            0 :     if ((lookAt - lookFrom).z() >= 0.) {
    1002              :         // looking to the sky makes position at ground pointless
    1003              :         return false;
    1004              :     }
    1005              :     // solve linear equation of ray crossing the ground plane
    1006            0 :     osg::Matrixd iVP = osg::Matrixd::inverse(myViewer->getCamera()->getViewMatrix() * myViewer->getCamera()->getProjectionMatrix());
    1007            0 :     osg::Vec3 nearPoint = osg::Vec3(xNorm, yNorm, 0.0f) * iVP;
    1008            0 :     osg::Vec3 farPoint = osg::Vec3(xNorm, yNorm, 1.0f) * iVP;
    1009              :     osg::Vec3 ray = farPoint - nearPoint;
    1010              :     osg::Vec3 groundPos = nearPoint - ray * nearPoint.z() / ray.z();
    1011            0 :     pos.setx(groundPos.x());
    1012            0 :     pos.sety(groundPos.y());
    1013              :     pos.setz(0.);
    1014              :     return true;
    1015              : }
    1016              : 
    1017              : 
    1018              : std::vector<GUIGlObject*>
    1019            0 : GUIOSGView::getGUIGlObjectsUnderCursor() {
    1020              :     std::vector<GUIGlObject*> result;
    1021              :     osgUtil::LineSegmentIntersector::Intersections intersections;
    1022            0 :     if (myViewer->computeIntersections(myViewer->getCamera(), osgUtil::Intersector::CoordinateFrame::PROJECTION, myOSGNormalizedCursorX, myOSGNormalizedCursorY, intersections)) {
    1023            0 :         for (auto intersection : intersections) {
    1024            0 :             if (!intersection.nodePath.empty()) {
    1025              :                 // the object is identified by the ID stored in OSG
    1026            0 :                 for (osg::Node* currentNode : intersection.nodePath) {
    1027            0 :                     if (currentNode->getName().length() > 0 && currentNode->getName().find(":") != std::string::npos) {
    1028              :                         const std::string objID = currentNode->getName();
    1029            0 :                         GUIGlObject* o = GUIGlObjectStorage::gIDStorage.getObjectBlocking(objID);
    1030              :                         // check that GUIGlObject exist
    1031            0 :                         if (o == nullptr) {
    1032            0 :                             continue;
    1033              :                         }
    1034              :                         // check that GUIGlObject isn't the network
    1035            0 :                         if (o->getGlID() == 0) {
    1036            0 :                             continue;
    1037              :                         }
    1038            0 :                         result.push_back(o);
    1039              :                         // unblock object
    1040            0 :                         GUIGlObjectStorage::gIDStorage.unblockObject(o->getGlID());
    1041              :                     }
    1042              :                 }
    1043              :             }
    1044            0 :         }
    1045              :     }
    1046            0 :     return result;
    1047            0 : }
    1048              : 
    1049              : 
    1050              : GUILane*
    1051            0 : GUIOSGView::getLaneUnderCursor() {
    1052            0 :     std::vector<GUIGlObject*> objects = getGUIGlObjectsUnderCursor();
    1053            0 :     if (objects.size() > 0) {
    1054            0 :         return dynamic_cast<GUILane*>(objects[0]);
    1055              :     }
    1056              :     return nullptr;
    1057            0 : }
    1058              : 
    1059              : 
    1060              : void
    1061            0 : GUIOSGView::zoom2Pos(Position& camera, Position& lookAt, double zoom) {
    1062              :     osg::Vec3d lookFromOSG, lookAtOSG, viewAxis, up;
    1063            0 :     myViewer->getCameraManipulator()->getInverseMatrix().getLookAt(lookFromOSG, lookAtOSG, up);
    1064            0 :     lookFromOSG[0] = camera.x();
    1065            0 :     lookFromOSG[1] = camera.y();
    1066            0 :     lookFromOSG[2] = camera.z();
    1067            0 :     lookAtOSG[0] = lookAt.x();
    1068            0 :     lookAtOSG[1] = lookAt.y();
    1069            0 :     lookAtOSG[2] = lookAt.z();
    1070            0 :     viewAxis = lookAtOSG - lookFromOSG;
    1071            0 :     viewAxis.normalize();
    1072              : 
    1073              :     // compute new camera and lookAt pos
    1074            0 :     osg::Vec3d cameraUpdate = lookFromOSG + viewAxis * (zoom - 100.);
    1075              :     osg::Vec3d lookAtUpdate = cameraUpdate + viewAxis;
    1076              : 
    1077            0 :     myViewer->getCameraManipulator()->setHomePosition(cameraUpdate, lookAtUpdate, up);
    1078            0 :     myViewer->home();
    1079            0 : }
    1080              : 
    1081              : 
    1082              : osg::Vec4d
    1083         1308 : GUIOSGView::toOSGColorVector(RGBColor c, bool useAlpha) {
    1084         1308 :     return osg::Vec4d(c.red() / 255., c.green() / 255., c.blue() / 255., (useAlpha) ? c.alpha() / 255. : 1.);
    1085              : }
    1086              : 
    1087              : 
    1088          436 : GUIOSGView::FXOSGAdapter::FXOSGAdapter(GUISUMOAbstractView* parent, FXCursor* cursor)
    1089          436 :     : myParent(parent), myOldCursor(cursor) {
    1090          436 :     _traits = new GraphicsContext::Traits();
    1091          436 :     _traits->x = 0;
    1092          436 :     _traits->y = 0;
    1093          436 :     _traits->width = parent->getWidth();
    1094          436 :     _traits->height = parent->getHeight();
    1095          436 :     _traits->windowDecoration = false;
    1096          436 :     _traits->doubleBuffer = true;
    1097          436 :     _traits->sharedContext = 0;
    1098              :     if (valid()) {
    1099          436 :         setState(new osg::State());
    1100          436 :         getState()->setGraphicsContext(this);
    1101              : #ifdef DEBUG_GLERRORS
    1102              :         getState()->setCheckForGLErrors(osg::State::ONCE_PER_ATTRIBUTE);
    1103              :         std::cout << "OSG getCheckForGLErrors " << getState()->getCheckForGLErrors() << std::endl;
    1104              : #endif
    1105          436 :         if (_traits.valid() && _traits->sharedContext != 0) {
    1106              :             getState()->setContextID(_traits->sharedContext->getState()->getContextID());
    1107            0 :             incrementContextIDUsageCount(getState()->getContextID());
    1108              :         } else {
    1109          436 :             getState()->setContextID(createNewContextID());
    1110              :         }
    1111              :     }
    1112          436 : }
    1113              : 
    1114              : 
    1115          872 : GUIOSGView::FXOSGAdapter::~FXOSGAdapter() {
    1116          436 :     delete myOldCursor;
    1117          872 : }
    1118              : 
    1119              : 
    1120              : void
    1121            0 : GUIOSGView::FXOSGAdapter::grabFocus() {
    1122              :     // focus this window
    1123            0 :     myParent->setFocus();
    1124            0 : }
    1125              : 
    1126              : 
    1127              : void
    1128            0 : GUIOSGView::FXOSGAdapter::useCursor(bool cursorOn) {
    1129            0 :     if (cursorOn) {
    1130            0 :         myParent->setDefaultCursor(myOldCursor);
    1131              :     } else {
    1132            0 :         myParent->setDefaultCursor(NULL);
    1133              :     }
    1134            0 : }
    1135              : 
    1136              : 
    1137              : bool
    1138        87444 : GUIOSGView::FXOSGAdapter::makeCurrentImplementation() {
    1139        87444 :     myParent->makeCurrent();
    1140        87444 :     return true;
    1141              : }
    1142              : 
    1143              : 
    1144              : bool
    1145            0 : GUIOSGView::FXOSGAdapter::releaseContext() {
    1146            0 :     myParent->makeNonCurrent();
    1147            0 :     return true;
    1148              : }
    1149              : 
    1150              : 
    1151              : void
    1152        43504 : GUIOSGView::FXOSGAdapter::swapBuffersImplementation() {
    1153        43504 :     myParent->swapBuffers();
    1154        43504 : }
    1155              : 
    1156              : 
    1157              : bool
    1158        43862 : GUIOSGView::PickHandler::handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& /* aa */) {
    1159        43862 :     if (ea.getEventType() == osgGA::GUIEventAdapter::DRAG) {
    1160            0 :         myDrag = true;
    1161        43862 :     } else if (ea.getEventType() == osgGA::GUIEventAdapter::RELEASE && ea.getButton() == osgGA::GUIEventAdapter::RIGHT_MOUSE_BUTTON) {
    1162            0 :         if (!myDrag) {
    1163            0 :             if (myParent->makeCurrent()) {
    1164            0 :                 std::vector<GUIGlObject*> objects = myParent->getGUIGlObjectsUnderCursor();
    1165            0 :                 if (objects.size() > 0) {
    1166            0 :                     myParent->openObjectDialog(objects);
    1167              :                 }
    1168            0 :                 myParent->makeNonCurrent();
    1169            0 :             }
    1170              :         }
    1171            0 :         myDrag = false;
    1172              :     }
    1173        43862 :     return false;
    1174              : }
    1175              : 
    1176              : 
    1177              : #endif
    1178              : 
    1179              : /****************************************************************************/
        

Generated by: LCOV version 2.0-1