Eclipse SUMO - Simulation of Urban MObility
GUIDanielPerspectiveChanger.cpp
Go to the documentation of this file.
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 /****************************************************************************/
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>
29 #include "GUIPerspectiveChanger.h"
31 
32 
33 // ===========================================================================
34 // method definitions
35 // ===========================================================================
37  GUISUMOAbstractView& callBack, const Boundary& viewPort) :
38  GUIPerspectiveChanger(callBack, viewPort),
39  myOrigWidth(viewPort.getWidth()),
40  myOrigHeight(viewPort.getHeight()),
41  myRotation(0),
42  myMouseButtonState(MOUSEBTN_NONE),
43  myMoveOnClick(false),
44  myZoomBase(viewPort.getCenter()),
45  myDragDelay(0) {
46 }
47 
48 
50 
51 
52 void
53 GUIDanielPerspectiveChanger::move(int xdiff, int ydiff) {
54  myViewPort.moveby(myCallback.p2m(xdiff), -myCallback.p2m(ydiff));
55  myCallback.update();
56 }
57 
58 
59 void
61  if (myCallback.getApp()->reg().readIntEntry("gui", "zoomAtCenter", 0)) {
63  }
64  if (factor > 0) {
66  myZoomBase.x() - (myZoomBase.x() - myViewPort.xmin()) / factor,
67  myZoomBase.y() - (myZoomBase.y() - myViewPort.ymin()) / factor,
68  myZoomBase.x() - (myZoomBase.x() - myViewPort.xmax()) / factor,
69  myZoomBase.y() - (myZoomBase.y() - myViewPort.ymax()) / factor);
70  myCallback.update();
71  }
72 }
73 
74 
75 void
77  /*
78  if (myCallback.allowRotation()) {
79  myRotation += (double) diff / (double) 10.0;
80  myCallback.update();
81  }
82  */
83 }
84 
85 
86 double
88  return myRotation;
89 }
90 
91 
92 double
94  return myViewPort.getCenter().x();
95 }
96 
97 
98 double
100  return myViewPort.getCenter().y();
101 }
102 
103 
104 double
106  return myOrigWidth / myViewPort.getWidth() * 100;
107 }
108 
109 
110 double
112  return myViewPort.getWidth();
113 }
114 
115 
116 double
118  return myOrigWidth / (zoom / 100);
119 }
120 
121 
122 double
124  return (myOrigWidth / zPos) * 100;
125 }
126 
127 
128 void
130  bool applyZoom) {
131  if (applyZoom) {
132  myViewPort = Boundary();
133  myViewPort.add(pos);
134  myViewPort.grow(radius);
135  } else {
136  myViewPort.moveby(pos.x() - getXPos(), pos.y() - getYPos());
137  }
138 }
139 
140 
141 void
144  FXEvent* e = (FXEvent*) data;
145  myMouseXPosition = e->win_x;
146  myMouseYPosition = e->win_y;
147  myMoveOnClick = false;
148  myMouseDownTime = FXThread::time();
149 }
150 
151 
152 bool
155  FXEvent* e = (FXEvent*) data;
156  myMouseXPosition = e->win_x;
157  myMouseYPosition = e->win_y;
158  return myMoveOnClick;
159 }
160 
161 
162 void
165  FXEvent* e = (FXEvent*) data;
166  myMouseXPosition = e->win_x;
167  myMouseYPosition = e->win_y;
168  myMoveOnClick = false;
169  myMouseDownTime = FXThread::time();
171 }
172 
173 
174 bool
177  FXEvent* e = (FXEvent*) data;
178  myMouseXPosition = e->win_x;
179  myMouseYPosition = e->win_y;
180  return myMoveOnClick;
181 }
182 
183 
184 void
187  FXEvent* e = (FXEvent*) data;
188  myMouseXPosition = e->win_x;
189  myMouseYPosition = e->win_y;
190  myMoveOnClick = false;
191  myMouseDownTime = FXThread::time();
193 }
194 
195 
196 bool
199  if (data != nullptr) {
200  FXEvent* e = (FXEvent*) data;
201  myMouseXPosition = e->win_x;
202  myMouseYPosition = e->win_y;
203  }
204  return myMoveOnClick;
205 }
206 
207 
208 void
210  FXEvent* e = (FXEvent*) data;
211  // catch empty ghost events after scroll (seem to occur only on Ubuntu)
212  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  if (e->code < 0) {
220  // for inverse zooming direction
221  zScale_rDelta = zScale_rDelta_inv;
222  }
223  // keyboard modifier: slow, fast mouse-zoom
224  if ((e->state & CONTROLMASK) != 0) {
225  zScale_rDelta /= 4;
226  } else if ((e->state & SHIFTMASK) != 0) {
227  zScale_rDelta *= 4;
228  }
230  zoom(1.0 + zScale_rDelta);
232 }
233 
234 
235 void
237  FXEvent* e = (FXEvent*) data;
238  myCallback.setWindowCursorPosition(e->win_x, e->win_y);
239  const int xdiff = myMouseXPosition - e->win_x;
240  const int ydiff = myMouseYPosition - e->win_y;
241  const bool moved = xdiff != 0 || ydiff != 0;
242  const bool pastDelay = !gSchemeStorage.getDefault().gaming && FXThread::time() > (myMouseDownTime + myDragDelay);
243  switch (myMouseButtonState) {
244  case MOUSEBTN_LEFT:
245  case MOUSEBTN_MIDDLE:
246  if (pastDelay) {
247  if (myRotation != 0) {
248  Position diffRot = Position(xdiff, ydiff).rotateAround2D(
249  DEG2RAD(myRotation), Position(0, 0));
250  move((int)diffRot.x(), (int)diffRot.y());
251  } else {
252  move(xdiff, ydiff);
253  }
254  if (moved) {
255  myMoveOnClick = true;
256  }
257  }
258  break;
259  case MOUSEBTN_RIGHT:
260  if (pastDelay) {
261  zoom(1 + 10.0 * ydiff / myCallback.getWidth());
262  rotate(xdiff);
263  if (moved) {
264  myMoveOnClick = true;
265  }
266  }
267  break;
268  default:
269  if (moved) {
271  }
272  break;
273  }
274  myMouseXPosition = e->win_x;
275  myMouseYPosition = e->win_y;
276 }
277 
278 
279 void
281  double xPos, double yPos) {
282  const double zoomFactor = zoom / 50; // /100 to normalize, *2 because growth is added on both sides
283  myViewPort = Boundary();
284  myViewPort.add(Position(xPos, yPos));
285  myViewPort.growHeight(myOrigHeight / zoomFactor);
286  myViewPort.growWidth(myOrigWidth / zoomFactor);
287  myCallback.update();
288 }
289 
290 
291 void
292 GUIDanielPerspectiveChanger::setViewportFrom(double xPos, double yPos, double zPos) {
293  setViewport(zPos2Zoom(zPos), xPos, yPos);
294 }
295 
296 
297 void
299  myRotation = rotation;
300 }
301 
302 void
305  myViewPort.xmin() - myCallback.p2m(change),
306  myViewPort.ymin(),
307  myViewPort.xmax(),
308  myViewPort.ymax());
309 }
310 
311 
312 long
314  // ignore key events in gaming mode
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  if (e->state & CONTROLMASK) {
324  zoomDiff /= 2;
325  moveFactor /= 10;
326  } else if (e->state & SHIFTMASK) {
327  zoomDiff *= 2;
328  } else if (e->state & ALTMASK) {
329  moveFactor *= 10;
330  }
331  switch (e->code) {
332  case FX::KEY_Left:
333  moveX = -1;
334  moveFactor /= 10;
335  break;
336  case FX::KEY_Right:
337  moveX = 1;
338  moveFactor /= 10;
339  break;
340  case FX::KEY_Up:
341  moveY = -1;
342  moveFactor /= 10;
343  break;
344  case FX::KEY_Down:
345  moveY = 1;
346  moveFactor /= 10;
347  break;
348  case FX::KEY_plus:
349  case FX::KEY_KP_Add:
351  zoom(1.0 + zoomDiff);
353  return 1;
354  case FX::KEY_minus:
355  case FX::KEY_KP_Subtract:
356  zoomDiff = -zoomDiff;
358  zoom(1.0 + zoomDiff);
360  return 1;
361  case FX::KEY_Home:
362  case FX::KEY_KP_Home:
364  myCallback.update();
365  return 1;
366  default:
367  return 0;
368  }
369  myViewPort.moveby(moveX * moveFactor * myViewPort.getWidth(),
370  -moveY * moveFactor * myViewPort.getHeight());
371  myCallback.update();
372  return 1;
373 }
374 
375 
376 /****************************************************************************/
GUICompleteSchemeStorage gSchemeStorage
#define DEG2RAD(x)
Definition: GeomHelper.h:35
A class that stores a 2D geometrical boundary.
Definition: Boundary.h:39
Position getCenter() const
Returns the center of the boundary.
Definition: Boundary.cpp:112
void add(double x, double y, double z=0)
Makes the boundary include the given coordinate.
Definition: Boundary.cpp:78
void moveby(double x, double y, double z=0)
Moves the boundary by the given amount.
Definition: Boundary.cpp:412
void growHeight(double by)
Increases the height of the boundary (y-axis)
Definition: Boundary.cpp:345
double ymin() const
Returns minimum y-coordinate.
Definition: Boundary.cpp:130
double xmin() const
Returns minimum x-coordinate.
Definition: Boundary.cpp:118
Boundary & grow(double by)
extends the boundary by the given amount
Definition: Boundary.cpp:319
double getHeight() const
Returns the height of the boundary (y-axis)
Definition: Boundary.cpp:160
double getWidth() const
Returns the width of the boudary (x-axis)
Definition: Boundary.cpp:154
void growWidth(double by)
Increases the width of the boundary (x-axis)
Definition: Boundary.cpp:338
double ymax() const
Returns maximum y-coordinate.
Definition: Boundary.cpp:136
double xmax() const
Returns maximum x-coordinate.
Definition: Boundary.cpp:124
GUIVisualizationSettings & getDefault()
Returns the default scheme.
bool myMoveOnClick
Information whether the user has moved the cursor while pressing a mouse button.
virtual double getRotation() const
Returns the rotation of the canvas stored in this changer.
void onRightBtnPress(void *data)
called when user press right button
int myMouseButtonState
the current mouse state
void onMiddleBtnPress(void *data)
called when user press middle button
virtual double getYPos() const
Returns the y-offset of the field to show stored in this changer.
virtual double getZoom() const
Returns the zoom factor computed stored in this changer.
void onMouseWheel(void *data)
called when user changes mouse wheel
virtual double zoom2ZPos(double zoom) const
Returns the camera height at which the given zoom level is reached.
void onMouseMove(void *data)
called when user moves mouse
double myOrigWidth
the original viewport dimensions in m which serve as the reference point for 100% zoom
virtual double getZPos() const
Returns the camera height corresponding to the current zoom factor.
virtual double getXPos() const
Returns the x-offset of the field to show stored in this changer.
bool onMiddleBtnRelease(void *data)
called when user releases middle button
void centerTo(const Position &pos, double radius, bool applyZoom=true)
Centers the view to the given position, setting it to a size that covers the radius.
void setRotation(double rotation)
Sets the rotation.
Position myZoomBase
the network location on which to zoom using right click+drag
double myRotation
the current rotation
void rotate(int diff)
Performs the rotation of the view.
bool onLeftBtnRelease(void *data)
called when user releases left button
bool onRightBtnRelease(void *data)
called when user releases right button
void onLeftBtnPress(void *data)
mouse functions
GUIDanielPerspectiveChanger(GUISUMOAbstractView &callBack, const Boundary &viewPort)
void zoom(double factor)
Performs the zooming of the view.
void setViewport(double zoom, double xPos, double yPos)
Sets the viewport.
long onKeyPress(void *data)
called when user press a key
virtual double zPos2Zoom(double zPos) const
Returns the zoom level that is achieved at a given camera height.
void setViewportFrom(double xPos, double yPos, double zPos)
Alternative method for setting the viewport.
GUISUMOAbstractView & myCallback
The parent window (canvas to scale)
Boundary myViewPort
the intended viewport
FXint myMouseXPosition
the current mouse position
void updateToolTip()
A method that updates the tooltip.
virtual void recenterView()
recenters the view
double p2m(double pixel) const
pixels-to-meters conversion method
virtual Position getPositionInformation() const
Returns the cursor's x/y position within the network.
void setWindowCursorPosition(FXint x, FXint y)
Returns the gl-id of the object under the given coordinates.
bool gaming
whether the application is in gaming mode or not
A point in 2D or 3D with translation and scaling methods.
Definition: Position.h:37
double x() const
Returns the x-position.
Definition: Position.h:55
Position rotateAround2D(double rad, const Position &origin)
rotate this position by rad around origin and return the result
Definition: Position.cpp:41
double y() const
Returns the y-position.
Definition: Position.h:60