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

Generated by: LCOV version 2.0-1