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.org/sumo
3 // Copyright (C) 2001-2020 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  if (data != nullptr) {
178  FXEvent* e = (FXEvent*) data;
179  myMouseXPosition = e->win_x;
180  myMouseYPosition = e->win_y;
181  }
182  return myMoveOnClick;
183 }
184 
185 
186 void
188  FXEvent* e = (FXEvent*) data;
189  // catch empty ghost events after scroll (seem to occur only on Ubuntu)
190  if (e->code == 0) {
191  return;
192  }
193  // zoom scale relative delta and its inverse; is optimized (all literals)
194  const double zScale_rDelta_norm = 0.1;
195  const double zScale_rDelta_inv = -zScale_rDelta_norm / (1. + zScale_rDelta_norm);
196  double zScale_rDelta = zScale_rDelta_norm ;
197  if (e->code < 0) {
198  // for inverse zooming direction
199  zScale_rDelta = zScale_rDelta_inv;
200  }
201  // keyboard modifier: slow, fast mouse-zoom
202  if ((e->state & CONTROLMASK) != 0) {
203  zScale_rDelta /= 4;
204  } else if ((e->state & SHIFTMASK) != 0) {
205  zScale_rDelta *= 4;
206  }
208  zoom(1.0 + zScale_rDelta);
210 }
211 
212 
213 void
215  FXEvent* e = (FXEvent*) data;
216  myCallback.setWindowCursorPosition(e->win_x, e->win_y);
217  const int xdiff = myMouseXPosition - e->win_x;
218  const int ydiff = myMouseYPosition - e->win_y;
219  const bool moved = xdiff != 0 || ydiff != 0;
220  const bool pastDelay = !gSchemeStorage.getDefault().gaming && FXThread::time() > (myMouseDownTime + myDragDelay);
221  switch (myMouseButtonState) {
222  case MOUSEBTN_LEFT:
223  if (pastDelay) {
224  if (myRotation != 0) {
225  Position diffRot = Position(xdiff, ydiff).rotateAround2D(
226  DEG2RAD(myRotation), Position(0, 0));
227  move((int)diffRot.x(), (int)diffRot.y());
228  } else {
229  move(xdiff, ydiff);
230  }
231  if (moved) {
232  myMoveOnClick = true;
233  }
234  }
235  break;
236  case MOUSEBTN_RIGHT:
237  if (pastDelay) {
238  zoom(1 + 10.0 * ydiff / myCallback.getWidth());
239  rotate(xdiff);
240  if (moved) {
241  myMoveOnClick = true;
242  }
243  }
244  break;
245  default:
246  if (moved) {
248  }
249  break;
250  }
251  myMouseXPosition = e->win_x;
252  myMouseYPosition = e->win_y;
253 }
254 
255 
256 void
258  double xPos, double yPos) {
259  const double zoomFactor = zoom / 50; // /100 to normalize, *2 because growth is added on both sides
260  myViewPort = Boundary();
261  myViewPort.add(Position(xPos, yPos));
262  myViewPort.growHeight(myOrigHeight / zoomFactor);
263  myViewPort.growWidth(myOrigWidth / zoomFactor);
264  myCallback.update();
265 }
266 
267 
268 void
269 GUIDanielPerspectiveChanger::setViewportFrom(double xPos, double yPos, double zPos) {
270  setViewport(zPos2Zoom(zPos), xPos, yPos);
271 }
272 
273 
274 void
276  myRotation = rotation;
277 }
278 
279 void
282  myViewPort.xmin() - myCallback.p2m(change),
283  myViewPort.ymin(),
284  myViewPort.xmax(),
285  myViewPort.ymax());
286 }
287 
288 
289 long
291  // ignore key events in gaming mode
293  return 0;
294  }
295  FXEvent* e = (FXEvent*) data;
296  double zoomDiff = 0.1;
297  double moveX = 0;
298  double moveY = 0;
299  double moveFactor = 1;
300  bool pageVertical = true;
301  if (e->state & CONTROLMASK) {
302  zoomDiff /= 2;
303  moveFactor /= 10;
304  } else if (e->state & SHIFTMASK) {
305  pageVertical = false;
306  zoomDiff *= 2;
307  }
308  switch (e->code) {
309  case FX::KEY_Left:
310  moveX = -1;
311  moveFactor /= 10;
312  break;
313  case FX::KEY_Right:
314  moveX = 1;
315  moveFactor /= 10;
316  break;
317  case FX::KEY_Up:
318  moveY = -1;
319  moveFactor /= 10;
320  break;
321  case FX::KEY_Down:
322  moveY = 1;
323  moveFactor /= 10;
324  break;
325  case FX::KEY_Page_Up:
326  if (pageVertical) {
327  moveY = -1;
328  } else {
329  moveX = -1;
330  }
331  break;
332  case FX::KEY_Page_Down:
333  if (pageVertical) {
334  moveY = 1;
335  } else {
336  moveX = 1;
337  }
338  break;
339  case FX::KEY_plus:
340  case FX::KEY_KP_Add:
342  zoom(1.0 + zoomDiff);
344  return 1;
345  case FX::KEY_minus:
346  case FX::KEY_KP_Subtract:
347  zoomDiff = -zoomDiff;
349  zoom(1.0 + zoomDiff);
351  return 1;
352  case FX::KEY_Home:
353  case FX::KEY_KP_Home:
355  myCallback.update();
356  return 1;
357  default:
358  return 0;
359  }
360  myViewPort.moveby(moveX * moveFactor * myViewPort.getWidth(),
361  -moveY * moveFactor * myViewPort.getHeight());
362  myCallback.update();
363  return 1;
364 }
365 
366 
367 /****************************************************************************/
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:111
void add(double x, double y, double z=0)
Makes the boundary include the given coordinate.
Definition: Boundary.cpp:77
void moveby(double x, double y, double z=0)
Moves the boundary by the given amount.
Definition: Boundary.cpp:367
void growHeight(double by)
Increases the height of the boundary (y-axis)
Definition: Boundary.cpp:315
double ymin() const
Returns minimum y-coordinate.
Definition: Boundary.cpp:129
double xmin() const
Returns minimum x-coordinate.
Definition: Boundary.cpp:117
Boundary & grow(double by)
extends the boundary by the given amount
Definition: Boundary.cpp:299
double getHeight() const
Returns the height of the boundary (y-axis)
Definition: Boundary.cpp:159
double getWidth() const
Returns the width of the boudary (x-axis)
Definition: Boundary.cpp:153
void growWidth(double by)
Increases the width of the boundary (x-axis)
Definition: Boundary.cpp:308
double ymax() const
Returns maximum y-coordinate.
Definition: Boundary.cpp:135
double xmax() const
Returns maximum x-coordinate.
Definition: Boundary.cpp:123
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
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.
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
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:36
double x() const
Returns the x-position.
Definition: Position.h:54
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:59