LCOV - code coverage report
Current view: top level - src/utils/gui/windows - GUIDanielPerspectiveChanger.cpp (source / functions) Coverage Total Hit
Test: lcov.info Lines: 20.6 % 180 37
Test Date: 2024-12-21 15:45:41 Functions: 44.4 % 27 12

            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    GUIDanielPerspectiveChanger.cpp
      15              : /// @author  Daniel Krajzewicz
      16              : /// @author  Jakob Erdmann
      17              : /// @author  Michael Behrisch
      18              : /// @date    Sept 2002
      19              : ///
      20              : // A class that allows to steer the visual output in dependence to
      21              : /****************************************************************************/
      22              : #include <config.h>
      23              : 
      24              : #include <fxkeys.h>
      25              : #include <utils/geom/Boundary.h>
      26              : #include <utils/geom/Position.h>
      27              : #include <utils/geom/GeomHelper.h>
      28              : #include <utils/gui/settings/GUICompleteSchemeStorage.h>
      29              : #include "GUIPerspectiveChanger.h"
      30              : #include "GUIDanielPerspectiveChanger.h"
      31              : 
      32              : 
      33              : // ===========================================================================
      34              : // method definitions
      35              : // ===========================================================================
      36         7152 : GUIDanielPerspectiveChanger::GUIDanielPerspectiveChanger(
      37         7152 :     GUISUMOAbstractView& callBack, const Boundary& viewPort) :
      38              :     GUIPerspectiveChanger(callBack, viewPort),
      39        14304 :     myOrigWidth(viewPort.getWidth()),
      40         7152 :     myOrigHeight(viewPort.getHeight()),
      41         7152 :     myRotation(0),
      42         7152 :     myMouseButtonState(MOUSEBTN_NONE),
      43         7152 :     myMoveOnClick(false),
      44         7152 :     myZoomBase(viewPort.getCenter()),
      45         7152 :     myDragDelay(0) {
      46         7152 : }
      47              : 
      48              : 
      49        14268 : GUIDanielPerspectiveChanger::~GUIDanielPerspectiveChanger() {}
      50              : 
      51              : 
      52              : void
      53            0 : GUIDanielPerspectiveChanger::move(int xdiff, int ydiff) {
      54            0 :     myViewPort.moveby(myCallback.p2m(xdiff), -myCallback.p2m(ydiff));
      55            0 :     myCallback.update();
      56            0 : }
      57              : 
      58              : 
      59              : void
      60            0 : GUIDanielPerspectiveChanger::zoom(double factor) {
      61            0 :     if (myCallback.getApp()->reg().readIntEntry("gui", "zoomAtCenter", 0)) {
      62            0 :         myZoomBase = myViewPort.getCenter();
      63              :     }
      64            0 :     if (factor > 0) {
      65            0 :         myViewPort = Boundary(
      66            0 :                          myZoomBase.x() - (myZoomBase.x() - myViewPort.xmin()) / factor,
      67            0 :                          myZoomBase.y() - (myZoomBase.y() - myViewPort.ymin()) / factor,
      68            0 :                          myZoomBase.x() - (myZoomBase.x() - myViewPort.xmax()) / factor,
      69            0 :                          myZoomBase.y() - (myZoomBase.y() - myViewPort.ymax()) / factor);
      70            0 :         myCallback.update();
      71              :     }
      72            0 : }
      73              : 
      74              : 
      75              : void
      76            0 : GUIDanielPerspectiveChanger::rotate(int /* diff */) {
      77              :     /*
      78              :     if (myCallback.allowRotation()) {
      79              :         myRotation += (double) diff / (double) 10.0;
      80              :         myCallback.update();
      81              :     }
      82              :     */
      83            0 : }
      84              : 
      85              : 
      86              : double
      87      1045869 : GUIDanielPerspectiveChanger::getRotation() const {
      88      1045869 :     return myRotation;
      89              : }
      90              : 
      91              : 
      92              : double
      93         6724 : GUIDanielPerspectiveChanger::getXPos() const {
      94         6724 :     return myViewPort.getCenter().x();
      95              : }
      96              : 
      97              : 
      98              : double
      99         6724 : GUIDanielPerspectiveChanger::getYPos() const {
     100         6724 :     return myViewPort.getCenter().y();
     101              : }
     102              : 
     103              : 
     104              : double
     105            0 : GUIDanielPerspectiveChanger::getZoom() const {
     106            0 :     return myOrigWidth / myViewPort.getWidth() * 100;
     107              : }
     108              : 
     109              : 
     110              : double
     111         6723 : GUIDanielPerspectiveChanger::getZPos() const {
     112         6723 :     return myViewPort.getWidth();
     113              : }
     114              : 
     115              : 
     116              : double
     117            6 : GUIDanielPerspectiveChanger::zoom2ZPos(double zoom) const {
     118            6 :     return myOrigWidth / (zoom / 100);
     119              : }
     120              : 
     121              : 
     122              : double
     123            7 : GUIDanielPerspectiveChanger::zPos2Zoom(double zPos) const {
     124            7 :     return (myOrigWidth / zPos) * 100;
     125              : }
     126              : 
     127              : 
     128              : void
     129            0 : GUIDanielPerspectiveChanger::centerTo(const Position& pos, double radius,
     130              :                                       bool applyZoom) {
     131            0 :     if (applyZoom) {
     132            0 :         myViewPort = Boundary();
     133            0 :         myViewPort.add(pos);
     134            0 :         myViewPort.grow(radius);
     135              :     } else {
     136            0 :         myViewPort.moveby(pos.x() - getXPos(), pos.y() - getYPos());
     137              :     }
     138            0 : }
     139              : 
     140              : 
     141              : void
     142            0 : GUIDanielPerspectiveChanger::onLeftBtnPress(void* data) {
     143            0 :     myMouseButtonState |= MOUSEBTN_LEFT;
     144              :     FXEvent* e = (FXEvent*) data;
     145            0 :     myMouseXPosition = e->win_x;
     146            0 :     myMouseYPosition = e->win_y;
     147            0 :     myMoveOnClick = false;
     148            0 :     myMouseDownTime = FXThread::time();
     149            0 : }
     150              : 
     151              : 
     152              : bool
     153            0 : GUIDanielPerspectiveChanger::onLeftBtnRelease(void* data) {
     154            0 :     myMouseButtonState &= ~MOUSEBTN_LEFT;
     155              :     FXEvent* e = (FXEvent*) data;
     156            0 :     myMouseXPosition = e->win_x;
     157            0 :     myMouseYPosition = e->win_y;
     158            0 :     return myMoveOnClick;
     159              : }
     160              : 
     161              : 
     162              : void
     163            0 : GUIDanielPerspectiveChanger::onMiddleBtnPress(void* data) {
     164            0 :     myMouseButtonState |= MOUSEBTN_MIDDLE;
     165              :     FXEvent* e = (FXEvent*) data;
     166            0 :     myMouseXPosition = e->win_x;
     167            0 :     myMouseYPosition = e->win_y;
     168            0 :     myMoveOnClick = false;
     169            0 :     myMouseDownTime = FXThread::time();
     170            0 :     myZoomBase = myCallback.getPositionInformation();
     171            0 : }
     172              : 
     173              : 
     174              : bool
     175            0 : GUIDanielPerspectiveChanger::onMiddleBtnRelease(void* data) {
     176            0 :     myMouseButtonState &= ~MOUSEBTN_MIDDLE;
     177              :     FXEvent* e = (FXEvent*) data;
     178            0 :     myMouseXPosition = e->win_x;
     179            0 :     myMouseYPosition = e->win_y;
     180            0 :     return myMoveOnClick;
     181              : }
     182              : 
     183              : 
     184              : void
     185            0 : GUIDanielPerspectiveChanger::onRightBtnPress(void* data) {
     186            0 :     myMouseButtonState |= MOUSEBTN_RIGHT;
     187              :     FXEvent* e = (FXEvent*) data;
     188            0 :     myMouseXPosition = e->win_x;
     189            0 :     myMouseYPosition = e->win_y;
     190            0 :     myMoveOnClick = false;
     191            0 :     myMouseDownTime = FXThread::time();
     192            0 :     myZoomBase = myCallback.getPositionInformation();
     193            0 : }
     194              : 
     195              : 
     196              : bool
     197            0 : GUIDanielPerspectiveChanger::onRightBtnRelease(void* data) {
     198            0 :     myMouseButtonState &= ~MOUSEBTN_RIGHT;
     199            0 :     if (data != nullptr) {
     200              :         FXEvent* e = (FXEvent*) data;
     201            0 :         myMouseXPosition = e->win_x;
     202            0 :         myMouseYPosition = e->win_y;
     203              :     }
     204            0 :     return myMoveOnClick;
     205              : }
     206              : 
     207              : 
     208              : void
     209            0 : GUIDanielPerspectiveChanger::onMouseWheel(void* data) {
     210              :     FXEvent* e = (FXEvent*) data;
     211              :     // catch empty ghost events after scroll (seem to occur only on Ubuntu)
     212            0 :     if (e->code == 0) {
     213              :         return;
     214              :     }
     215              :     // zoom scale relative delta and its inverse; is optimized (all literals)
     216              :     const double zScale_rDelta_norm = 0.1;
     217              :     const double zScale_rDelta_inv = -zScale_rDelta_norm / (1. + zScale_rDelta_norm);
     218              :     double zScale_rDelta = zScale_rDelta_norm ;
     219            0 :     if (e->code < 0) {
     220              :         // for inverse zooming direction
     221              :         zScale_rDelta = zScale_rDelta_inv;
     222              :     }
     223              :     // keyboard modifier: slow, fast mouse-zoom
     224            0 :     if ((e->state & CONTROLMASK) != 0) {
     225            0 :         zScale_rDelta /= 4;
     226            0 :     } else if ((e->state & SHIFTMASK) != 0) {
     227            0 :         zScale_rDelta *= 4;
     228              :     }
     229            0 :     myZoomBase = myCallback.getPositionInformation();
     230            0 :     zoom(1.0 + zScale_rDelta);
     231            0 :     myCallback.updateToolTip();
     232              : }
     233              : 
     234              : 
     235              : void
     236            0 : GUIDanielPerspectiveChanger::onMouseMove(void* data) {
     237              :     FXEvent* e = (FXEvent*) data;
     238            0 :     myCallback.setWindowCursorPosition(e->win_x, e->win_y);
     239            0 :     const int xdiff = myMouseXPosition - e->win_x;
     240            0 :     const int ydiff = myMouseYPosition - e->win_y;
     241            0 :     const bool moved = xdiff != 0 || ydiff != 0;
     242            0 :     const bool pastDelay = !gSchemeStorage.getDefault().gaming && FXThread::time() > (myMouseDownTime + myDragDelay);
     243            0 :     switch (myMouseButtonState) {
     244            0 :         case MOUSEBTN_LEFT:
     245              :         case MOUSEBTN_MIDDLE:
     246            0 :             if (pastDelay) {
     247            0 :                 if (myRotation != 0) {
     248            0 :                     Position diffRot = Position(xdiff, ydiff).rotateAround2D(
     249            0 :                                            DEG2RAD(myRotation), Position(0, 0));
     250            0 :                     move((int)diffRot.x(), (int)diffRot.y());
     251              :                 } else {
     252            0 :                     move(xdiff, ydiff);
     253              :                 }
     254            0 :                 if (moved) {
     255            0 :                     myMoveOnClick = true;
     256              :                 }
     257              :             }
     258              :             break;
     259            0 :         case MOUSEBTN_RIGHT:
     260            0 :             if (pastDelay) {
     261            0 :                 zoom(1 + 10.0 * ydiff / myCallback.getWidth());
     262            0 :                 rotate(xdiff);
     263            0 :                 if (moved) {
     264            0 :                     myMoveOnClick = true;
     265              :                 }
     266              :             }
     267              :             break;
     268            0 :         default:
     269            0 :             if (moved) {
     270            0 :                 myCallback.updateToolTip();
     271              :             }
     272              :             break;
     273              :     }
     274            0 :     myMouseXPosition = e->win_x;
     275            0 :     myMouseYPosition = e->win_y;
     276            0 : }
     277              : 
     278              : 
     279              : void
     280            7 : GUIDanielPerspectiveChanger::setViewport(double zoom,
     281              :         double xPos, double yPos) {
     282            7 :     const double zoomFactor = zoom / 50; // /100 to normalize, *2 because growth is added on both sides
     283            7 :     myViewPort = Boundary();
     284            7 :     myViewPort.add(Position(xPos, yPos));
     285            7 :     myViewPort.growHeight(myOrigHeight / zoomFactor);
     286            7 :     myViewPort.growWidth(myOrigWidth / zoomFactor);
     287            7 :     myCallback.update();
     288            7 : }
     289              : 
     290              : 
     291              : void
     292            7 : GUIDanielPerspectiveChanger::setViewportFrom(double xPos, double yPos, double zPos) {
     293            7 :     setViewport(zPos2Zoom(zPos), xPos, yPos);
     294            7 : }
     295              : 
     296              : 
     297              : void
     298            7 : GUIDanielPerspectiveChanger::setRotation(double rotation) {
     299            7 :     myRotation = rotation;
     300            7 : }
     301              : 
     302              : void
     303            0 : GUIDanielPerspectiveChanger::changeCanvasSizeLeft(int change) {
     304            0 :     myViewPort = Boundary(
     305            0 :                      myViewPort.xmin() - myCallback.p2m(change),
     306              :                      myViewPort.ymin(),
     307              :                      myViewPort.xmax(),
     308              :                      myViewPort.ymax());
     309            0 : }
     310              : 
     311              : 
     312              : long
     313            0 : GUIDanielPerspectiveChanger::onKeyPress(void* data) {
     314              :     // ignore key events in gaming mode
     315            0 :     if (gSchemeStorage.getDefault().gaming) {
     316              :         return 0;
     317              :     }
     318              :     FXEvent* e = (FXEvent*) data;
     319              :     double zoomDiff = 0.1;
     320              :     double moveX = 0;
     321              :     double moveY = 0;
     322              :     double moveFactor = 1;
     323            0 :     if (e->state & CONTROLMASK) {
     324              :         zoomDiff /= 2;
     325              :         moveFactor /= 10;
     326            0 :     } else if (e->state & SHIFTMASK) {
     327              :         zoomDiff *= 2;
     328            0 :     } else if (e->state & ALTMASK) {
     329              :         moveFactor *= 10;
     330              :     }
     331            0 :     switch (e->code) {
     332            0 :         case FX::KEY_Left:
     333              :             moveX = -1;
     334            0 :             moveFactor /= 10;
     335            0 :             break;
     336            0 :         case FX::KEY_Right:
     337              :             moveX = 1;
     338            0 :             moveFactor /= 10;
     339            0 :             break;
     340            0 :         case FX::KEY_Up:
     341              :             moveY = -1;
     342            0 :             moveFactor /= 10;
     343            0 :             break;
     344            0 :         case FX::KEY_Down:
     345              :             moveY = 1;
     346            0 :             moveFactor /= 10;
     347            0 :             break;
     348            0 :         case FX::KEY_plus:
     349              :         case FX::KEY_KP_Add:
     350            0 :             myZoomBase = myCallback.getPositionInformation();
     351            0 :             zoom(1.0 + zoomDiff);
     352            0 :             myCallback.updateToolTip();
     353            0 :             return 1;
     354            0 :         case FX::KEY_minus:
     355              :         case FX::KEY_KP_Subtract:
     356              :             zoomDiff = -zoomDiff;
     357            0 :             myZoomBase = myCallback.getPositionInformation();
     358            0 :             zoom(1.0 + zoomDiff);
     359            0 :             myCallback.updateToolTip();
     360            0 :             return 1;
     361            0 :         case FX::KEY_Home:
     362              :         case FX::KEY_KP_Home:
     363            0 :             myCallback.recenterView();
     364            0 :             myCallback.update();
     365            0 :             return 1;
     366              :         default:
     367              :             return 0;
     368              :     }
     369            0 :     myViewPort.moveby(moveX * moveFactor * myViewPort.getWidth(),
     370            0 :                       -moveY * moveFactor * myViewPort.getHeight());
     371            0 :     myCallback.update();
     372            0 :     return 1;
     373              : }
     374              : 
     375              : 
     376              : /****************************************************************************/
        

Generated by: LCOV version 2.0-1