Eclipse SUMO - Simulation of Urban MObility
GUISUMOAbstractView.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 /****************************************************************************/
22 // The base class for a view
23 /****************************************************************************/
24 #include <config.h>
25 
26 #include <iostream>
27 #include <utility>
28 #include <cmath>
29 #include <cassert>
30 #include <limits>
31 #include <fxkeys.h>
32 #ifdef HAVE_GL2PS
33 #include <gl2ps.h>
34 #endif
38 #include <utils/common/RGBColor.h>
39 #include <utils/common/ToString.h>
42 #include <utils/common/SysUtils.h>
48 #include <utils/gui/div/GLHelper.h>
56 #include <utils/geom/GeomHelper.h>
63 
64 #include <unordered_set>
65 
66 #include "GUISUMOAbstractView.h"
67 #include "GUIMainWindow.h"
68 #include "GUIGlChildWindow.h"
70 #include "GUIDialog_EditViewport.h"
71 
72 #ifdef HAVE_GDAL
73 #ifdef _MSC_VER
74 #pragma warning(push)
75 #pragma warning(disable: 4435 5219 5220)
76 #endif
77 #if __GNUC__ > 3
78 #pragma GCC diagnostic push
79 #pragma GCC diagnostic ignored "-Wpedantic"
80 #endif
81 #include <gdal_priv.h>
82 #if __GNUC__ > 3
83 #pragma GCC diagnostic pop
84 #endif
85 #ifdef _MSC_VER
86 #pragma warning(pop)
87 #endif
88 #endif
89 
90 
91 // ===========================================================================
92 // debug constants
93 // ===========================================================================
94 //#define DEBUG_SNAPSHOT
95 
96 // ===========================================================================
97 // static members
98 // ===========================================================================
99 
100 const double GUISUMOAbstractView::SENSITIVITY = 0.1; // meters
101 
102 
103 // ===========================================================================
104 // member method definitions
105 // ===========================================================================
106 /* -------------------------------------------------------------------------
107  * GUISUMOAbstractView - FOX callback mapping
108  * ----------------------------------------------------------------------- */
109 FXDEFMAP(GUISUMOAbstractView) GUISUMOAbstractViewMap[] = {
110  FXMAPFUNC(SEL_CONFIGURE, 0, GUISUMOAbstractView::onConfigure),
111  FXMAPFUNC(SEL_PAINT, 0, GUISUMOAbstractView::onPaint),
112  FXMAPFUNC(SEL_LEFTBUTTONPRESS, 0, GUISUMOAbstractView::onLeftBtnPress),
113  FXMAPFUNC(SEL_LEFTBUTTONRELEASE, 0, GUISUMOAbstractView::onLeftBtnRelease),
114  FXMAPFUNC(SEL_MIDDLEBUTTONPRESS, 0, GUISUMOAbstractView::onMiddleBtnPress),
115  FXMAPFUNC(SEL_MIDDLEBUTTONRELEASE, 0, GUISUMOAbstractView::onMiddleBtnRelease),
116  FXMAPFUNC(SEL_RIGHTBUTTONPRESS, 0, GUISUMOAbstractView::onRightBtnPress),
117  FXMAPFUNC(SEL_RIGHTBUTTONRELEASE, 0, GUISUMOAbstractView::onRightBtnRelease),
118  FXMAPFUNC(SEL_DOUBLECLICKED, 0, GUISUMOAbstractView::onDoubleClicked),
119  FXMAPFUNC(SEL_MOUSEWHEEL, 0, GUISUMOAbstractView::onMouseWheel),
120  FXMAPFUNC(SEL_MOTION, 0, GUISUMOAbstractView::onMouseMove),
121  FXMAPFUNC(SEL_LEAVE, 0, GUISUMOAbstractView::onMouseLeft),
122  FXMAPFUNC(SEL_KEYPRESS, 0, GUISUMOAbstractView::onKeyPress),
123  FXMAPFUNC(SEL_KEYRELEASE, 0, GUISUMOAbstractView::onKeyRelease),
124  FXMAPFUNC(SEL_COMMAND, MID_CLOSE_LANE, GUISUMOAbstractView::onCmdCloseLane),
125  FXMAPFUNC(SEL_COMMAND, MID_CLOSE_EDGE, GUISUMOAbstractView::onCmdCloseEdge),
130 };
131 
132 
133 FXIMPLEMENT_ABSTRACT(GUISUMOAbstractView, FXGLCanvas, GUISUMOAbstractViewMap, ARRAYNUMBER(GUISUMOAbstractViewMap))
134 
135 
136 /* -------------------------------------------------------------------------
137  * GUISUMOAbstractView - methods
138  * ----------------------------------------------------------------------- */
139 GUISUMOAbstractView::GUISUMOAbstractView(FXComposite* p, GUIMainWindow& app, GUIGlChildWindow* parent, const SUMORTree& grid, FXGLVisual* glVis, FXGLCanvas* share) :
140  FXGLCanvas(p, glVis, share, p, MID_GLCANVAS, LAYOUT_SIDE_TOP | LAYOUT_FILL_X | LAYOUT_FILL_Y, 0, 0, 0, 0),
141  myApp(&app),
142  myGlChildWindowParent(parent),
143  myGrid(&grid),
144  myMouseHotspotX(app.getDefaultCursor()->getHotX()),
145  myMouseHotspotY(app.getDefaultCursor()->getHotY()),
146  myWindowCursorPositionX(getWidth() / 2),
147  myWindowCursorPositionY(getHeight() / 2) {
148  setTarget(this);
149  enable();
150  flags |= FLAG_ENABLED;
151  myChanger = new GUIDanielPerspectiveChanger(*this, *myGrid);
152  myVisualizationSettings = &gSchemeStorage.getDefault();
153  myVisualizationSettings->gaming = myApp->isGaming();
155  myDecals = gSchemeStorage.getDecals();
156 }
157 
158 
163  delete myPopup;
164  delete myChanger;
167  // cleanup decals
168  for (auto& decal : myDecals) {
169  delete decal.image;
170  }
171  // remove all elements
172  for (auto& additional : myAdditionallyDrawn) {
173  additional.first->removeActiveAddVisualisation(this, ~0);
174  }
175 }
176 
177 
178 bool
180  return myInEditMode;
181 }
182 
183 
186  return *myChanger;
187 }
188 
189 
190 void
193  update();
194  }
195 }
196 
197 
198 Position
201 }
202 
203 
204 Position
205 GUISUMOAbstractView::snapToActiveGrid(const Position& pos, bool snapXY) const {
206  Position result = pos;
208  if (snapXY) {
209  const double xRest = std::fmod(pos.x(), myVisualizationSettings->gridXSize) + (pos.x() < 0 ? myVisualizationSettings->gridXSize : 0);
210  const double yRest = std::fmod(pos.y(), myVisualizationSettings->gridYSize) + (pos.y() < 0 ? myVisualizationSettings->gridYSize : 0);
211  result.setx(pos.x() - xRest + (xRest < myVisualizationSettings->gridXSize * 0.5 ? 0 : myVisualizationSettings->gridXSize));
212  result.sety(pos.y() - yRest + (yRest < myVisualizationSettings->gridYSize * 0.5 ? 0 : myVisualizationSettings->gridYSize));
213  } else {
214  // snapZToActiveGrid uses grid Y Size
215  const double zRest = std::fmod(pos.z(), myVisualizationSettings->gridYSize) + (pos.z() < 0 ? myVisualizationSettings->gridYSize : 0);
216  result.setz(pos.z() - zRest + (zRest < myVisualizationSettings->gridYSize * 0.5 ? 0 : myVisualizationSettings->gridYSize));
217  }
218  }
219  return result;
220 }
221 
222 
223 Position
225  Boundary bound = myChanger->getViewport();
226  double xNet = bound.xmin() + bound.getWidth() * x / getWidth();
227  // cursor origin is in the top-left corner
228  double yNet = bound.ymin() + bound.getHeight() * (getHeight() - y) / getHeight();
229  // rotate around the viewport center
230  if (myChanger->getRotation() != 0) {
231  return Position(xNet, yNet).rotateAround2D(-DEG2RAD(myChanger->getRotation()), bound.getCenter());
232  } else {
233  return Position(xNet, yNet);
234  }
235 }
236 
237 
238 void
239 GUISUMOAbstractView::addDecals(const std::vector<Decal>& decals) {
240  myDecals.insert(myDecals.end(), decals.begin(), decals.end());
241 }
242 
243 
244 void
247  // set cartesian position
248  myApp->getCartesianLabel()->setText(("x:" + toString(pos.x()) + ", y:" + toString(pos.y())).c_str());
249  // set geo position
251  if (GeoConvHelper::getFinal().usingGeoProjection()) {
252  myApp->getGeoLabel()->setText(("lat:" + toString(pos.y(), gPrecisionGeo) + ", lon:" + toString(pos.x(), gPrecisionGeo)).c_str());
253  } else {
254  myApp->getGeoLabel()->setText(TL("(No projection defined)"));
255  }
256  // if enabled, set test position
257  if (myApp->getTestFrame()) {
258  if (OptionsCont::getOptions().getBool("gui-testing")) {
259  myApp->getTestFrame()->show();
260  // adjust cursor position (24,25) to show exactly the same position as in function netedit.leftClick(match, X, Y)
261  myApp->getTestLabel()->setText(("Test: x:" + toString(getWindowCursorPosition().x() - 24.0) + " y:" + toString(getWindowCursorPosition().y() - 25.0)).c_str());
262  } else {
263  myApp->getTestFrame()->hide();
264  }
265  }
266 }
267 
268 
269 int
270 GUISUMOAbstractView::doPaintGL(int /*mode*/, const Boundary& /*boundary*/) {
271  return 0;
272 }
273 
274 
275 void
277 }
278 
279 
280 Boundary
282  return myChanger->getViewport();
283 }
284 
285 
286 bool
288  return false;
289 }
290 
291 
292 void GUISUMOAbstractView::zoom2Pos(Position& /* camera */, Position& /* lookAt */, double /* zoom */) {
293 }
294 
295 
296 void
298  // reset debug counters
301  if (getWidth() == 0 || getHeight() == 0) {
302  return;
303  }
304  const long start = SysUtils::getCurrentMillis();
305 
307  centerTo(getTrackedID(), false);
308  }
309  // draw
310  glClearColor(
315  glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
316  glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
317 
319  glEnable(GL_DITHER);
320  } else {
321  glDisable(GL_DITHER);
322  }
323  glEnable(GL_BLEND);
324  glDisable(GL_LINE_SMOOTH);
325 
326  Boundary bound = applyGLTransform();
327  doPaintGL(GL_RENDER, bound);
330  displayLegends();
331  const long end = SysUtils::getCurrentMillis();
332  myFrameDrawTime = end - start;
334  drawFPS();
335  }
336  // check if show tooltip
339  } else {
341  }
342  swapBuffers();
343 }
344 
345 
346 long
347 GUISUMOAbstractView::onCmdCloseLane(FXObject*, FXSelector, void*) {
348  return 1;
349 }
350 
351 
352 long
353 GUISUMOAbstractView::onCmdCloseEdge(FXObject*, FXSelector, void*) {
354  return 1;
355 }
356 
357 
358 long
359 GUISUMOAbstractView::onCmdAddRerouter(FXObject*, FXSelector, void*) {
360  return 1;
361 }
362 
363 
364 long
365 GUISUMOAbstractView::onCmdShowReachability(FXObject*, FXSelector, void*) {
366  return 1;
367 }
368 
369 
370 long
371 GUISUMOAbstractView::onVisualizationChange(FXObject*, FXSelector, void*) {
372  return 1;
373 }
374 
375 
376 GUILane*
378  return nullptr;
379 }
380 
381 
382 GUIGlID
384  return getObjectUnderCursor();
385 }
386 
387 
388 GUIGlID
391 }
392 
393 
394 std::vector<GUIGlID>
397 }
398 
399 
400 
401 std::vector<GUIGlObject*>
404 }
405 
406 
407 std::vector<GUIGlObject*>
410 }
411 
412 
413 GUIGlID
415  // calculate a boundary for the given position
416  Boundary positionBoundary;
417  positionBoundary.add(pos);
418  positionBoundary.grow(SENSITIVITY);
419  const std::vector<GUIGlID> ids = getObjectsInBoundary(positionBoundary);
420  // Interpret results
421  int idMax = 0;
422  double maxLayer = -std::numeric_limits<double>::max();
423  // iterate over obtained GUIGlIDs
424  for (const auto& i : ids) {
425  // obtain GUIGlObject
427  // check that GUIGlObject exist
428  if (o == nullptr) {
429  continue;
430  }
431  // check that GUIGlObject isn't the network
432  if (o->getGlID() == 0) {
433  continue;
434  }
435  //std::cout << "point selection hit " << o->getMicrosimID() << "\n";
436  double layer = o->getClickPriority();
437  // check whether the current object is above a previous one
438  if (layer > maxLayer) {
439  idMax = i;
440  maxLayer = layer;
441  }
442  // unblock object
444  }
445  return idMax;
446 }
447 
448 
449 std::vector<GUIGlID>
451  // declare result vector
452  std::vector<GUIGlID> result;
453  // calculate boundary
454  Boundary selection;
455  selection.add(pos);
456  selection.grow(radius);
457  // obtain GUIGlID of objects in boundary
458  const std::vector<GUIGlID> ids = getObjectsInBoundary(selection);
459  // iterate over obtained GUIGlIDs
460  for (const auto& i : ids) {
461  // obtain GUIGlObject
463  // check that GUIGlObject exist
464  if (o == nullptr) {
465  continue;
466  }
467  // check that GUIGlObject isn't the network
468  if (o->getGlID() == 0) {
469  continue;
470  }
471  //std::cout << "point selection hit " << o->getMicrosimID() << "\n";
472  GUIGlObjectType type = o->getType();
473  // avoid network
474  if (type != GLO_NETWORK) {
475  result.push_back(i);
476  }
477  // unblock object
479  }
480  return result;
481 }
482 
483 
484 std::vector<GUIGlObject*>
486  // declare result vector
487  std::vector<GUIGlObject*> result;
488  // calculate boundary
489  Boundary selection;
490  selection.add(pos);
491  selection.grow(radius);
492  // obtain GUIGlID of objects in boundary
493  const std::vector<GUIGlID> ids = getObjectsInBoundary(selection);
494  // iterate over obtained GUIGlIDs
495  for (const auto& i : ids) {
496  // obtain GUIGlObject
498  // check that GUIGlObject exist
499  if (o == nullptr) {
500  continue;
501  }
502  // check that GUIGlObject isn't the network
503  if (o->getGlID() == 0) {
504  continue;
505  }
506  result.push_back(o);
507  // unblock object
509  }
510  return result;
511 }
512 
513 
514 std::vector<GUIGlID>
516  const int NB_HITS_MAX = 1024 * 1024;
517  // Prepare the selection mode
518  static GUIGlID hits[NB_HITS_MAX];
519  static GLint nb_hits = 0;
520  glSelectBuffer(NB_HITS_MAX, hits);
521  glInitNames();
522 
524  Boundary oldViewPort = myChanger->getViewport(false); // backup the actual viewPort
525  myChanger->setViewport(bound);
526  bound = applyGLTransform(false);
527  // enable draw for selecting (to draw objects with less details)
529  int hits2 = doPaintGL(GL_SELECT, bound);
530  // reset flags
532  // Get the results
533  nb_hits = glRenderMode(GL_RENDER);
534  if (nb_hits == -1) {
535  myApp->setStatusBarText("Selection in boundary failed. Try to select fewer than " + toString(hits2) + " items");
536  }
537  std::vector<GUIGlID> result;
538  GLuint numNames;
539  GLuint* ptr = hits;
540  for (int i = 0; i < nb_hits; ++i) {
541  numNames = *ptr;
542  ptr += 3;
543  for (int j = 0; j < (int)numNames; j++) {
544  result.push_back(*ptr);
545  ptr++;
546  }
547  }
548  // switch viewport back to normal
549  myChanger->setViewport(oldViewPort);
550  return result;
551 }
552 
553 
554 std::vector<GUIGlObject*>
555 GUISUMOAbstractView::filterInternalLanes(const std::vector<GUIGlObject*>& objects) const {
556  // count number of internal lanes
557  size_t internalLanes = 0;
558  for (const auto& object : objects) {
559  if ((object->getType() == GLO_LANE) && (object->getMicrosimID().find(':') != std::string::npos)) {
560  internalLanes++;
561  }
562  }
563  // if all objects are internal lanes, return it all
564  if (objects.size() == internalLanes || !myVisualizationSettings->drawJunctionShape) {
565  return objects;
566  }
567  // in other case filter internal lanes
568  std::vector<GUIGlObject*> filteredObjects;
569  for (const auto& object : objects) {
570  if ((object->getType() == GLO_LANE) && (object->getMicrosimID().find(':') != std::string::npos)) {
571  continue;
572  }
573  filteredObjects.push_back(object);
574  }
575  return filteredObjects;
576 }
577 
578 
579 bool
581  if (idToolTip != GUIGlObject::INVALID_ID) {
583  if (object != nullptr) {
585  return true;
586  }
587  }
588  // nothing to show
590  return false;
591 }
592 
593 
594 void
596  // obtain minimum grid
598  // Check if the distance is enough to draw grid
600  glEnable(GL_DEPTH_TEST);
601  glLineWidth(1);
602  // get multiplication values (2 is the margin)
603  const int multXmin = (int)(myChanger->getViewport().xmin() / myVisualizationSettings->gridXSize) - 2;
604  const int multYmin = (int)(myChanger->getViewport().ymin() / myVisualizationSettings->gridYSize) - 2;
605  const int multXmax = (int)(myChanger->getViewport().xmax() / myVisualizationSettings->gridXSize) + 2;
606  const int multYmax = (int)(myChanger->getViewport().ymax() / myVisualizationSettings->gridYSize) + 2;
607  // obtain references
608  const double xmin = myVisualizationSettings->gridXSize * multXmin;
609  const double ymin = myVisualizationSettings->gridYSize * multYmin;
610  const double xmax = myVisualizationSettings->gridXSize * multXmax;
611  const double ymax = myVisualizationSettings->gridYSize * multYmax;
612  double xp = xmin;
613  double yp = ymin;
614  // move drawing matrix
615  glTranslated(0, 0, .55);
616  glColor3d(0.5, 0.5, 0.5);
617  // draw horizontal lines
618  glBegin(GL_LINES);
619  while (yp <= ymax) {
620  glVertex2d(xmin, yp);
621  glVertex2d(xmax, yp);
623  }
624  // draw vertical lines
625  while (xp <= xmax) {
626  glVertex2d(xp, ymin);
627  glVertex2d(xp, ymax);
629  }
630  glEnd();
631  glTranslated(0, 0, -.55);
632  }
633 }
634 
635 
636 void
638  // compute the scale bar length
639  int length = 1;
640  const std::string text("10000000000");
641  int noDigits = 1;
642  int pixelSize = (int) m2p((double) length);
643  while (pixelSize <= 20) {
644  length *= 10;
645  noDigits++;
646  if (noDigits > (int)text.length()) {
647  return;
648  }
649  pixelSize = (int) m2p((double) length);
650  }
651  glLineWidth(1.0);
652 
653  glMatrixMode(GL_PROJECTION);
655  glLoadIdentity();
656  glMatrixMode(GL_MODELVIEW);
658  glLoadIdentity();
659 
660  // draw the scale bar
661  const double z = -1;
662  glDisable(GL_TEXTURE_2D);
663  glDisable(GL_ALPHA_TEST);
664  glDisable(GL_BLEND);
665  glEnable(GL_DEPTH_TEST);
667  glTranslated(0, 0, z);
668 
669  double len = (double) pixelSize / (double)(getWidth() - 1) * (double) 2.0;
670  glColor3d(0, 0, 0);
671  double o = double(15) / double(getHeight());
672  double o2 = o + o;
673  double oo = double(5) / double(getHeight());
674  glBegin(GL_LINES);
675  // vertical
676  glVertex2d(-.98, -1. + o);
677  glVertex2d(-.98 + len, -1. + o);
678  // tick at begin
679  glVertex2d(-.98, -1. + o);
680  glVertex2d(-.98, -1. + o2);
681  // tick at end
682  glVertex2d(-.98 + len, -1. + o);
683  glVertex2d(-.98 + len, -1. + o2);
684  glEnd();
686 
687  const double fontHeight = 0.1 * 300. / getHeight();
688  const double fontWidth = 0.1 * 300. / getWidth();
689  // draw 0
690  GLHelper::drawText("0", Position(-.99, -0.99 + o2 + oo), z, fontHeight, RGBColor::BLACK, 0, FONS_ALIGN_LEFT, fontWidth);
691 
692  // draw current scale
693  GLHelper::drawText((text.substr(0, noDigits) + "m").c_str(), Position(-.99 + len, -0.99 + o2 + oo), z, fontHeight, RGBColor::BLACK, 0, FONS_ALIGN_LEFT, fontWidth);
694 
695  // restore matrices
696  glMatrixMode(GL_PROJECTION);
698  glMatrixMode(GL_MODELVIEW);
700 }
701 
702 void
705  displayLegend();
706  }
709  }
712  }
713 }
714 
715 void
717  // compute the scale bar length
718  glLineWidth(1.0);
719  glMatrixMode(GL_PROJECTION);
721  glLoadIdentity();
722  glMatrixMode(GL_MODELVIEW);
724  glLoadIdentity();
725 
726  const double z = -1;
727  glEnable(GL_DEPTH_TEST);
728  glEnable(GL_BLEND);
730  glTranslated(0, 0, z);
731 
732  const bool fixed = scheme.isFixed();
733  const int numColors = (int)scheme.getColors().size();
734 
735  // vertical
736  double right = 0.98;
737  double left = 0.95;
738  double textX = left - 0.01;
739  double textDir = 1;
740  FONSalign textAlign = FONS_ALIGN_RIGHT;
741  const double top = -0.7;
742  const double bot = 0.9;
743  const double dy = (top - bot) / numColors;
744  const double bot2 = fixed ? bot : bot + dy / 2;
745  // legend placement
746  if (leftSide) {
747  right = -right;
748  left = -left;
749  std::swap(right, left);
750  textX = right + 0.01;
751  textDir *= -1;
752  textAlign = FONS_ALIGN_LEFT;
753  }
754  // draw black boundary around legend colors
755  glColor3d(0, 0, 0);
756  glBegin(GL_LINES);
757  glVertex2d(right, top);
758  glVertex2d(right, bot2);
759  glVertex2d(left, bot2);
760  glVertex2d(left, top);
761  glVertex2d(right, top);
762  glVertex2d(left, top);
763  glVertex2d(right, bot2);
764  glVertex2d(left, bot2);
765  glEnd();
766 
767  const double fontHeight = 0.20 * 300. / getHeight();
768  const double fontWidth = 0.20 * 300. / getWidth();
769 
770  const int fadeSteps = fixed ? 1 : 10;
771  double colorStep = dy / fadeSteps;
772  for (int i = 0; i < numColors; i++) {
773  RGBColor col = scheme.getColors()[i];
774  const double topi = top - i * dy;
775  //const double boti = top - (i + 1) * dy;
776  //std::cout << " col=" << scheme.getColors()[i] << " i=" << i << " topi=" << topi << " boti=" << boti << "\n";
777  if (i + 1 < numColors) {
778  // fade
779  RGBColor col2 = scheme.getColors()[i + 1];
780  double thresh2 = scheme.getThresholds()[i + 1];
781  if (!fixed && thresh2 == GUIVisualizationSettings::MISSING_DATA) {
782  // draw scale end before missing data
783  GLHelper::setColor(col);
784  glBegin(GL_QUADS);
785  glVertex2d(left, topi);
786  glVertex2d(right, topi);
787  glVertex2d(right, topi - 5 * colorStep);
788  glVertex2d(left, topi - 5 * colorStep);
789  glEnd();
790  glColor3d(0, 0, 0);
791  glBegin(GL_LINES);
792  glVertex2d(right, topi - 10 * colorStep);
793  glVertex2d(left, topi - 10 * colorStep);
794  glEnd();
795  glBegin(GL_LINES);
796  glVertex2d(right, topi - 5 * colorStep);
797  glVertex2d(left, topi - 5 * colorStep);
798  glEnd();
799  } else {
800  // fade colors
801  for (double j = 0.0; j < fadeSteps; j++) {
802  GLHelper::setColor(RGBColor::interpolate(col, col2, j / fadeSteps));
803  glBegin(GL_QUADS);
804  glVertex2d(left, topi - j * colorStep);
805  glVertex2d(right, topi - j * colorStep);
806  glVertex2d(right, topi - (j + 1) * colorStep);
807  glVertex2d(left, topi - (j + 1) * colorStep);
808  glEnd();
809  }
810  }
811  } else {
812  GLHelper::setColor(col);
813  glBegin(GL_QUADS);
814  glVertex2d(left, topi);
815  glVertex2d(right, topi);
816  glVertex2d(right, bot2);
817  glVertex2d(left, bot2);
818  glEnd();
819  }
820 
821  const double threshold = scheme.getThresholds()[i];
822  std::string name = scheme.getNames()[i];
823  std::string text = fixed || threshold == GUIVisualizationSettings::MISSING_DATA ? name : toString(threshold);
824 
825  const double bgShift = 0.0;
826  const double textShift = 0.01;
827  const double textXShift = -0.005;
828 
830  glTranslated(0, 0, 0.1);
831  glBegin(GL_QUADS);
832  glVertex2d(textX, topi + fontHeight * bgShift);
833  glVertex2d(textX - textDir * fontWidth * (double)text.size() / 2.1, topi + fontHeight * bgShift);
834  glVertex2d(textX - textDir * fontWidth * (double)text.size() / 2.1, topi + fontHeight * (0.8 + bgShift));
835  glVertex2d(textX, topi + fontHeight * (0.8 + bgShift));
836  glEnd();
837  glTranslated(0, 0, -0.1);
838  GLHelper::drawText(text, Position(textX + textDir * textXShift, topi + textShift), 0, fontHeight, RGBColor::BLACK, 0, textAlign, fontWidth);
839  }
840  // draw scheme name
841  std::string name = scheme.getName();
842  if (StringUtils::startsWith(name, "by ")) {
843  name = name.substr(3);
844  }
845  const double topN = -0.8;
846  const double bgShift = 0.0;
848  glTranslated(0, 0, 0.1);
849  glBegin(GL_QUADS);
850  glVertex2d(textX + textDir * 0.04, topN + fontHeight * bgShift - 0.01);
851  glVertex2d(textX + textDir * 0.04 - textDir * fontWidth * (double)name.size() / 2.3, topN + fontHeight * bgShift - 0.01);
852  glVertex2d(textX + textDir * 0.04 - textDir * fontWidth * (double)name.size() / 2.3, topN + fontHeight * (0.8 + bgShift));
853  glVertex2d(textX + textDir * 0.04, topN + fontHeight * (0.8 + bgShift));
854  glEnd();
855  glTranslated(0, 0, -0.1);
856  GLHelper::drawText(name, Position(textX + textDir * 0.04, topN), 0, fontHeight, RGBColor::BLACK, 0, textAlign, fontWidth);
857 
859  // restore matrices
860  glMatrixMode(GL_PROJECTION);
862  glMatrixMode(GL_MODELVIEW);
864 }
865 
866 
867 double
869  return 1000.0 / MAX2((long)1, myFrameDrawTime);
870 }
871 
872 
875  return myGlChildWindowParent;
876 }
877 
878 
879 void
881  glMatrixMode(GL_PROJECTION);
883  glLoadIdentity();
884  glMatrixMode(GL_MODELVIEW);
886  glLoadIdentity();
887  const double fontHeight = 0.2 * 300. / getHeight();
888  const double fontWidth = 0.2 * 300. / getWidth();
889  GLHelper::drawText(toString((int)getFPS()) + " FPS", Position(0.82, 0.88), -1, fontHeight, RGBColor::RED, 0, FONS_ALIGN_LEFT, fontWidth);
890 #ifdef CHECK_ELEMENTCOUNTER
891  GLHelper::drawText(toString(GLHelper::getMatrixCounter()) + " matrix", Position(0.82, 0.79), -1, fontHeight, RGBColor::RED, 0, FONS_ALIGN_LEFT, fontWidth);
892  GLHelper::drawText(toString(GLHelper::getVertexCounter()) + " vertex", Position(0.82, 0.71), -1, fontHeight, RGBColor::RED, 0, FONS_ALIGN_LEFT, fontWidth);
893 #endif
894  // restore matrices
895  glMatrixMode(GL_PROJECTION);
897  glMatrixMode(GL_MODELVIEW);
899 }
900 
901 
902 double
903 GUISUMOAbstractView::m2p(double meter) const {
904  return meter * getWidth() / myChanger->getViewport().getWidth();
905 }
906 
907 
908 double
909 GUISUMOAbstractView::p2m(double pixel) const {
910  return pixel * myChanger->getViewport().getWidth() / getWidth();
911 }
912 
913 
914 void
917 }
918 
919 
920 void
921 GUISUMOAbstractView::centerTo(GUIGlID id, bool applyZoom, double zoomDist) {
923  if (o != nullptr && dynamic_cast<GUIGlObject*>(o) != nullptr) {
924  const Boundary& b = o->getCenteringBoundary();
925  if (b.getCenter() != Position::INVALID) {
926  if (applyZoom && zoomDist < 0) {
928  update(); // only update when centering onto an object once
929  } else {
930  // called during tracking. update is triggered somewhere else
931  myChanger->centerTo(b.getCenter(), zoomDist, applyZoom);
933  }
934  }
935  }
937 }
938 
939 
940 void
941 GUISUMOAbstractView::centerTo(const Position& pos, bool applyZoom, double zoomDist) {
942  // called during tracking. update is triggered somewhere else
943  myChanger->centerTo(pos, zoomDist, applyZoom);
945 }
946 
947 
948 void
950  myChanger->setViewport(bound);
951  update();
952 }
953 
954 
957  return myApp;
958 }
959 
960 
961 Position
964 }
965 
966 
967 void
971 }
972 
973 
974 FXbool
976  FXbool ret = FXGLCanvas::makeCurrent();
977  return ret;
978 }
979 
980 
981 long
982 GUISUMOAbstractView::onConfigure(FXObject*, FXSelector, void*) {
983  if (makeCurrent()) {
984  glViewport(0, 0, getWidth() - 1, getHeight() - 1);
985  glClearColor(
990  doInit();
991  myAmInitialised = true;
992  makeNonCurrent();
993  checkSnapshots();
994  }
995  return 1;
996 }
997 
998 
999 long
1000 GUISUMOAbstractView::onPaint(FXObject*, FXSelector, void*) {
1001  if (!isEnabled() || !myAmInitialised) {
1002  return 1;
1003  }
1004  if (makeCurrent()) {
1005  paintGL();
1006  makeNonCurrent();
1007  }
1008  return 1;
1009 }
1010 
1011 
1012 const Position&
1014  return myPopupPosition;
1015 }
1016 
1017 
1018 void
1020  if (myPopup != nullptr) {
1022  delete myPopup;
1023  myPopupPosition.set(0, 0);
1024  myPopup = nullptr;
1025  myCurrentObjectsDialog.clear();
1026  }
1027 }
1028 
1029 
1030 void
1032  // use the same position of old popUp
1033  popUp->move(myPopup->getX(), myPopup->getY());
1034  // delete and replace popup
1036  delete myPopup;
1037  myPopup = popUp;
1038  // create and show popUp
1039  myPopup->create();
1040  myPopup->show();
1041  myChanger->onRightBtnRelease(nullptr);
1042  setFocus();
1043 }
1044 
1045 
1046 long
1047 GUISUMOAbstractView::onLeftBtnPress(FXObject*, FXSelector, void* ptr) {
1048  destroyPopup();
1049  setFocus();
1050  FXEvent* e = (FXEvent*) ptr;
1051  // check whether the selection-mode is activated
1052  if ((e->state & CONTROLMASK) != 0) {
1053  // toggle selection of object under cursor
1054  if (makeCurrent()) {
1055  int id = getObjectUnderCursor();
1056  if (id != 0) {
1058  }
1059  makeNonCurrent();
1060  if (id != 0) {
1061  // possibly, the selection-coloring is used,
1062  // so we should update the screen again...
1063  update();
1064  }
1065  }
1066  }
1067  if ((e->state & SHIFTMASK) != 0) {
1068  // track vehicle or person under cursor
1069  if (makeCurrent()) {
1070  int id = getObjectUnderCursor();
1071  if (id != 0) {
1073  if (o != nullptr) {
1074  if (o->getType() == GLO_VEHICLE || o->getType() == GLO_PERSON) {
1075  startTrack(id);
1076  } else if (o->getType() == GLO_REROUTER_EDGE) {
1077  o->onLeftBtnPress(ptr);
1078  update();
1079  }
1080  }
1081  }
1082  makeNonCurrent();
1083  }
1084  }
1085  myChanger->onLeftBtnPress(ptr);
1086  grab();
1087  // Check there are double click
1088  if (e->click_count == 2) {
1089  handle(this, FXSEL(SEL_DOUBLECLICKED, 0), ptr);
1090  }
1091  return 1;
1092 }
1093 
1094 
1095 long
1096 GUISUMOAbstractView::onLeftBtnRelease(FXObject*, FXSelector, void* ptr) {
1097  destroyPopup();
1099  if (myApp->isGaming()) {
1101  }
1102  ungrab();
1103  return 1;
1104 }
1105 
1106 
1107 long
1108 GUISUMOAbstractView::onMiddleBtnPress(FXObject*, FXSelector, void* ptr) {
1109  destroyPopup();
1110  setFocus();
1111  if (!myApp->isGaming()) {
1113  }
1114  grab();
1115  // enable panning
1116  myPanning = true;
1117  // set cursors
1120  return 1;
1121 }
1122 
1123 
1124 long
1125 GUISUMOAbstractView::onMiddleBtnRelease(FXObject*, FXSelector, void* ptr) {
1126  destroyPopup();
1127  if (!myApp->isGaming()) {
1129  }
1130  ungrab();
1131  // disable panning
1132  myPanning = false;
1133  // restore cursors
1136  return 1;
1137 }
1138 
1139 
1140 long
1141 GUISUMOAbstractView::onRightBtnPress(FXObject*, FXSelector, void* ptr) {
1142  destroyPopup();
1143  if (!myApp->isGaming()) {
1144  myChanger->onRightBtnPress(ptr);
1145  }
1146  grab();
1147  return 1;
1148 }
1149 
1150 
1151 long
1152 GUISUMOAbstractView::onRightBtnRelease(FXObject* o, FXSelector sel, void* ptr) {
1153  destroyPopup();
1154  onMouseMove(o, sel, ptr);
1155  if (!myChanger->onRightBtnRelease(ptr) && !myApp->isGaming()) {
1156  openObjectDialogAtCursor((FXEvent*)ptr);
1157  }
1158  if (myApp->isGaming()) {
1160  }
1161  ungrab();
1162  return 1;
1163 }
1164 
1165 
1166 long
1167 GUISUMOAbstractView::onDoubleClicked(FXObject*, FXSelector, void*) {
1168  return 1;
1169 }
1170 
1171 
1172 long
1173 GUISUMOAbstractView::onMouseWheel(FXObject*, FXSelector, void* ptr) {
1174  if (!myApp->isGaming()) {
1175  myChanger->onMouseWheel(ptr);
1176  // upddate viewport
1177  if (myGUIDialogEditViewport != nullptr) {
1180  myChanger->getRotation());
1181  }
1183  }
1184  return 1;
1185 }
1186 
1187 
1188 long
1189 GUISUMOAbstractView::onMouseMove(FXObject*, FXSelector, void* ptr) {
1190  // check if popup exist
1191  if (myPopup) {
1192  // check if handle front element
1195  myPopup->handle(this, FXSEL(SEL_COMMAND, MID_CURSORDIALOG_FRONT), nullptr);
1196  destroyPopup();
1197  } else if (!myPopup->shown()) {
1198  destroyPopup();
1199  }
1200  }
1201  if (myPopup == nullptr) {
1203  myChanger->onMouseMove(ptr);
1204  }
1205  if (myGUIDialogEditViewport != nullptr) {
1208  myChanger->getRotation());
1209  }
1211  }
1212  return 1;
1213 }
1214 
1215 
1216 long
1217 GUISUMOAbstractView::onMouseLeft(FXObject*, FXSelector, void* /*data*/) {
1218  return 1;
1219 }
1220 
1221 std::vector<GUIGlObject*>
1222 GUISUMOAbstractView::filterContextObjects(const std::vector<GUIGlObject*>& objects) {
1223  // assume input is sorted with ComparatorClickPriority
1224  std::vector<GUIGlObject*> result;
1225  for (GUIGlObject* o : objects) {
1226  if (o->getClickPriority() != GUIGlObject::INVALID_PRIORITY && (result.empty() || result.back() != o)) {
1227  result.push_back(o);
1228  }
1229  }
1230  return result;
1231 }
1232 
1233 
1234 void
1236  // release the mouse grab
1237  ungrab();
1238  // check if alt key is pressed
1239  const bool altKeyPressed = ((ev->state & ALTMASK) != 0);
1240  // check if SUMO is enabled, initialised and Make OpenGL context current
1241  if (isEnabled() && myAmInitialised && makeCurrent()) {
1242  auto objectsUnderCursor = getGUIGlObjectsUnderCursor();
1243  if (objectsUnderCursor.empty()) {
1245  } else {
1246  std::sort(objectsUnderCursor.begin(), objectsUnderCursor.end(), ComparatorClickPriority());
1247  std::vector<GUIGlObject*> filtered = filterContextObjects(objectsUnderCursor);
1248  if (filtered.size() > 1 && (altKeyPressed
1249  || filtered[0]->getClickPriority() == filtered[1]->getClickPriority())) {
1250  // open dialog for picking among objects (without duplicates)
1252  } else {
1253  myPopup = objectsUnderCursor.front()->getPopUpMenu(*myApp, *this);
1254  }
1255  }
1256  openPopupDialog();
1257  makeNonCurrent();
1258  }
1259 }
1260 
1261 
1262 void
1263 GUISUMOAbstractView::openObjectDialog(const std::vector<GUIGlObject*>& objects, const bool filter) {
1264  if (objects.size() > 0) {
1265  // create cursor popup dialog
1266  if (objects.size() == 1) {
1267  myCurrentObjectsDialog = objects;
1268  } else if (filter) {
1269  // declare filtered objects
1270  std::vector<GUIGlObject*> filteredGLObjects;
1271  // fill filtered objects
1272  for (const auto& glObject : objects) {
1273  // compare type with first element type
1274  if (glObject->getType() == objects.front()->getType()) {
1275  filteredGLObjects.push_back(glObject);
1276  }
1277  }
1278  myCurrentObjectsDialog = filteredGLObjects;
1279  } else {
1280  myCurrentObjectsDialog = objects;
1281  }
1282  if (myCurrentObjectsDialog.size() > 1) {
1284  } else {
1285  myPopup = myCurrentObjectsDialog.front()->getPopUpMenu(*myApp, *this);
1286  }
1287  // open popup dialog
1288  openPopupDialog();
1289  }
1290 }
1291 
1292 
1293 long
1294 GUISUMOAbstractView::onKeyPress(FXObject* o, FXSelector sel, void* ptr) {
1295  const FXEvent* e = (FXEvent*) ptr;
1296  if (e->state & ALTMASK) {
1298  // update view (for polygon layers)
1299  update();
1300  } else {
1302  }
1303  // check if process canvas or popup
1304  if (myPopup != nullptr) {
1305  return myPopup->onKeyPress(o, sel, ptr);
1306  } else {
1307  if (e->state & CONTROLMASK) {
1308  if (e->code == FX::KEY_Page_Up) {
1311  update();
1312  return 1;
1313  } else if (e->code == FX::KEY_Page_Down) {
1316  update();
1317  return 1;
1318  }
1319  }
1320  FXGLCanvas::onKeyPress(o, sel, ptr);
1321  return myChanger->onKeyPress(ptr);
1322  }
1323 }
1324 
1325 
1326 long
1327 GUISUMOAbstractView::onKeyRelease(FXObject* o, FXSelector sel, void* ptr) {
1328  const FXEvent* e = (FXEvent*) ptr;
1329  if ((e->state & ALTMASK) == 0) {
1331  // update view (for polygon layers)
1332  update();
1333  }
1334  // check if process canvas or popup
1335  if (myPopup != nullptr) {
1336  return myPopup->onKeyRelease(o, sel, ptr);
1337  } else {
1338  FXGLCanvas::onKeyRelease(o, sel, ptr);
1339  return myChanger->onKeyRelease(ptr);
1340  }
1341 }
1342 
1343 // ------------ Dealing with snapshots
1344 
1345 void
1346 GUISUMOAbstractView::addSnapshot(SUMOTime time, const std::string& file, const int w, const int h) {
1347 #ifdef DEBUG_SNAPSHOT
1348  std::cout << "add snapshot time=" << time << " file=" << file << "\n";
1349 #endif
1350  FXMutexLock lock(mySnapshotsMutex);
1351  mySnapshots[time].push_back(std::make_tuple(file, w, h));
1352 }
1353 
1354 
1355 std::string
1356 GUISUMOAbstractView::makeSnapshot(const std::string& destFile, const int w, const int h) {
1357  if (w >= 0) {
1358  resize(w, h);
1359  repaint();
1360  }
1361  std::string errorMessage;
1362  FXString ext = FXPath::extension(destFile.c_str());
1363  const bool useGL2PS = ext == "ps" || ext == "eps" || ext == "pdf" || ext == "svg" || ext == "tex" || ext == "pgf";
1364 #ifdef HAVE_FFMPEG
1365  const bool useVideo = destFile == "" || ext == "h264" || ext == "hevc" || ext == "mp4";
1366 #endif
1367  for (int i = 0; i < 10 && !makeCurrent(); ++i) {
1369  }
1370  // draw
1371  glClearColor(
1376  glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
1377  glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
1378 
1380  glEnable(GL_DITHER);
1381  } else {
1382  glDisable(GL_DITHER);
1383  }
1384  glEnable(GL_BLEND);
1385  glDisable(GL_LINE_SMOOTH);
1386 
1387  applyGLTransform();
1388 
1389  if (useGL2PS) {
1390 #ifdef HAVE_GL2PS
1391  GLint format = GL2PS_PS;
1392  if (ext == "ps") {
1393  format = GL2PS_PS;
1394  } else if (ext == "eps") {
1395  format = GL2PS_EPS;
1396  } else if (ext == "pdf") {
1397  format = GL2PS_PDF;
1398  } else if (ext == "tex") {
1399  format = GL2PS_TEX;
1400  } else if (ext == "svg") {
1401  format = GL2PS_SVG;
1402  } else if (ext == "pgf") {
1403  format = GL2PS_PGF;
1404  } else {
1405  return "Could not save '" + destFile + "'.\n Unrecognized format '" + std::string(ext.text()) + "'.";
1406  }
1407  FILE* fp = fopen(destFile.c_str(), "wb");
1408  if (fp == 0) {
1409  return "Could not save '" + destFile + "'.\n Could not open file for writing";
1410  }
1412  GLint buffsize = 0, state = GL2PS_OVERFLOW;
1413  GLint viewport[4];
1414  glGetIntegerv(GL_VIEWPORT, viewport);
1415  while (state == GL2PS_OVERFLOW) {
1416  buffsize += 1024 * 1024;
1417  gl2psBeginPage(destFile.c_str(), "sumo-gui; https://sumo.dlr.de", viewport, format, GL2PS_SIMPLE_SORT,
1418  GL2PS_DRAW_BACKGROUND | GL2PS_USE_CURRENT_VIEWPORT,
1419  GL_RGBA, 0, NULL, 0, 0, 0, buffsize, fp, "out.eps");
1420  glMatrixMode(GL_MODELVIEW);
1422  glDisable(GL_TEXTURE_2D);
1423  glDisable(GL_ALPHA_TEST);
1424  glDisable(GL_BLEND);
1425  glEnable(GL_DEPTH_TEST);
1426  // draw decals (if not in grabbing mode)
1427 
1428  drawDecals();
1430  paintGLGrid();
1431  }
1432 
1433  glLineWidth(1);
1434  glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
1435  Boundary viewPort = myChanger->getViewport();
1436  const float minB[2] = { (float)viewPort.xmin(), (float)viewPort.ymin() };
1437  const float maxB[2] = { (float)viewPort.xmax(), (float)viewPort.ymax() };
1439  glEnable(GL_POLYGON_OFFSET_FILL);
1440  glEnable(GL_POLYGON_OFFSET_LINE);
1441  myGrid->Search(minB, maxB, *myVisualizationSettings);
1442 
1443  displayLegends();
1444  state = gl2psEndPage();
1445  glFinish();
1446  }
1447  GLHelper::setGL2PS(false);
1448  fclose(fp);
1449 #else
1450  return "Could not save '" + destFile + "', gl2ps was not enabled at compile time.";
1451 #endif
1452  } else {
1453  doPaintGL(GL_RENDER, myChanger->getViewport());
1454  displayLegends();
1455  swapBuffers();
1456  glFinish();
1457  FXColor* buf;
1458  FXMALLOC(&buf, FXColor, getWidth()*getHeight());
1459  // read from the back buffer
1460  glReadBuffer(GL_BACK);
1461  // Read the pixels
1462  glReadPixels(0, 0, getWidth(), getHeight(), GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid*)buf);
1463  makeNonCurrent();
1464  update();
1465  // mirror
1466  int mwidth = getWidth();
1467  int mheight = getHeight();
1468  FXColor* paa = buf;
1469  FXColor* pbb = buf + mwidth * (mheight - 1);
1470  do {
1471  FXColor* pa = paa;
1472  paa += mwidth;
1473  FXColor* pb = pbb;
1474  pbb -= mwidth;
1475  do {
1476  FXColor t = *pa;
1477  *pa++ = *pb;
1478  *pb++ = t;
1479  } while (pa < paa);
1480  } while (paa < pbb);
1481  try {
1482 #ifdef HAVE_FFMPEG
1483  if (useVideo) {
1484  try {
1485  saveFrame(destFile, buf);
1486  errorMessage = "video";
1487  } catch (std::runtime_error& err) {
1488  errorMessage = err.what();
1489  }
1490  } else
1491 #endif
1492  if (!MFXImageHelper::saveImage(destFile, getWidth(), getHeight(), buf)) {
1493  errorMessage = "Could not save '" + destFile + "'.";
1494  }
1495  } catch (InvalidArgument& e) {
1496  errorMessage = "Could not save '" + destFile + "'.\n" + e.what();
1497  }
1498  FXFREE(&buf);
1499  }
1500  return errorMessage;
1501 }
1502 
1503 
1504 void
1505 GUISUMOAbstractView::saveFrame(const std::string& destFile, FXColor* buf) {
1506  UNUSED_PARAMETER(destFile);
1507  UNUSED_PARAMETER(buf);
1508 }
1509 
1510 
1511 void
1513  const SUMOTime time = getCurrentTimeStep() - DELTA_T;
1514 #ifdef DEBUG_SNAPSHOT
1515  std::cout << "check snapshots time=" << time << " registeredTimes=" << mySnapshots.size() << "\n";
1516 #endif
1517  FXMutexLock lock(mySnapshotsMutex);
1518  const auto snapIt = mySnapshots.find(time);
1519  if (snapIt == mySnapshots.end()) {
1520  return;
1521  }
1522  std::vector<std::tuple<std::string, int, int> > files = snapIt->second;
1523  lock.unlock();
1524  // decouple map access and painting to avoid deadlock
1525  for (const auto& entry : files) {
1526 #ifdef DEBUG_SNAPSHOT
1527  std::cout << "make snapshot time=" << time << " file=" << file << "\n";
1528 #endif
1529  const std::string& error = makeSnapshot(std::get<0>(entry), std::get<1>(entry), std::get<2>(entry));
1530  if (error != "" && error != "video") {
1531  WRITE_WARNING(error);
1532  }
1533  }
1534  // synchronization with a waiting run thread
1535  lock.lock();
1536  mySnapshots.erase(time);
1537  mySnapshotCondition.signal();
1538 #ifdef DEBUG_SNAPSHOT
1539  std::cout << " files=" << toString(files) << " myApplicationSnapshots=" << joinToString(*myApplicationSnapshots, ",") << "\n";
1540 #endif
1541 }
1542 
1543 
1544 void
1546  FXMutexLock lock(mySnapshotsMutex);
1547  if (mySnapshots.count(snapshotTime) > 0) {
1549  }
1550 }
1551 
1552 
1553 SUMOTime
1555  return 0;
1556 }
1557 
1558 
1559 void
1561  if (myGUIDialogViewSettings == nullptr) {
1563  myGUIDialogViewSettings->create();
1564  } else {
1566  }
1567  setFocus();
1569 }
1570 
1571 
1574  if (myGUIDialogEditViewport == nullptr) {
1575  myGUIDialogEditViewport = new GUIDialog_EditViewport(this, TLC("Labels", "Edit Viewport"));
1576  myGUIDialogEditViewport->create();
1577  }
1579  return myGUIDialogEditViewport;
1580 }
1581 
1582 
1586  myChanger->getRotation());
1587 }
1588 
1589 
1590 void
1592  getViewportEditor(); // make sure it exists;
1596 }
1597 
1598 
1599 void
1600 GUISUMOAbstractView::setViewportFromToRot(const Position& lookFrom, const Position& /* lookAt */, double rotation) {
1601  myChanger->setViewportFrom(lookFrom.x(), lookFrom.y(), lookFrom.z());
1602  myChanger->setRotation(rotation);
1603  update();
1604 }
1605 
1606 
1607 void
1609  // look straight down
1612  myChanger->getRotation());
1613 }
1614 
1615 
1616 bool
1618  return true;
1619 }
1620 
1621 
1624  return *myVisualizationSettings;
1625 }
1626 
1627 
1630  return myVisualizationSettings;
1631 }
1632 
1633 
1634 void
1636  myGUIDialogEditViewport = nullptr;
1637 }
1638 
1639 
1640 void
1642  myGUIDialogViewSettings = nullptr;
1643 }
1644 
1645 
1646 double
1648  return myGrid->getWidth();
1649 }
1650 
1651 
1652 double
1654  return myGrid->getHeight();
1655 }
1656 
1657 
1658 void
1660 }
1661 
1662 
1663 void
1665 }
1666 
1667 
1668 GUIGlID
1670  return GUIGlObject::INVALID_ID;
1671 }
1672 
1673 
1674 void
1676 }
1677 
1678 void
1680 }
1681 
1682 
1683 std::vector<GUISUMOAbstractView::Decal>&
1685  return myDecals;
1686 }
1687 
1688 
1689 FXMutex&
1691  return myDecalsLockMutex;
1692 }
1693 
1694 
1698 }
1699 
1700 
1701 FXImage*
1703 #ifdef HAVE_GDAL
1704  GDALAllRegister();
1705  GDALDataset* poDataset = (GDALDataset*)GDALOpen(d.filename.c_str(), GA_ReadOnly);
1706  if (poDataset == 0) {
1707  return 0;
1708  }
1709  const int xSize = poDataset->GetRasterXSize();
1710  const int ySize = poDataset->GetRasterYSize();
1711  // checking for geodata in the picture and try to adapt position and scale
1712  if (d.width <= 0.) {
1713  double adfGeoTransform[6];
1714  if (poDataset->GetGeoTransform(adfGeoTransform) == CE_None) {
1715  Position topLeft(adfGeoTransform[0], adfGeoTransform[3]);
1716  const double horizontalSize = xSize * adfGeoTransform[1];
1717  const double verticalSize = ySize * adfGeoTransform[5];
1718  Position bottomRight(topLeft.x() + horizontalSize, topLeft.y() + verticalSize);
1719  if (GeoConvHelper::getProcessing().x2cartesian(topLeft) && GeoConvHelper::getProcessing().x2cartesian(bottomRight)) {
1720  d.width = bottomRight.x() - topLeft.x();
1721  d.height = topLeft.y() - bottomRight.y();
1722  d.centerX = (topLeft.x() + bottomRight.x()) / 2;
1723  d.centerY = (topLeft.y() + bottomRight.y()) / 2;
1724  //WRITE_MESSAGE("proj: " + toString(poDataset->GetProjectionRef()) + " dim: " + toString(d.width) + "," + toString(d.height) + " center: " + toString(d.centerX) + "," + toString(d.centerY));
1725  } else {
1726  WRITE_WARNINGF(TL("Could not convert coordinates in %."), d.filename);
1727  }
1728  }
1729  }
1730 #endif
1731  if (d.width <= 0.) {
1732  d.width = getGridWidth();
1733  d.height = getGridHeight();
1734  }
1735 
1736  // trying to read the picture
1737 #ifdef HAVE_GDAL
1738  const int picSize = xSize * ySize;
1739  FXColor* result;
1740  if (!FXMALLOC(&result, FXColor, picSize)) {
1741  WRITE_WARNINGF("Could not allocate memory for %.", d.filename);
1742  return 0;
1743  }
1744  for (int j = 0; j < picSize; j++) {
1745  result[j] = FXRGB(0, 0, 0);
1746  }
1747  bool valid = true;
1748  for (int i = 1; i <= poDataset->GetRasterCount(); i++) {
1749  GDALRasterBand* poBand = poDataset->GetRasterBand(i);
1750  int shift = -1;
1751  if (poBand->GetColorInterpretation() == GCI_RedBand) {
1752  shift = 0;
1753  } else if (poBand->GetColorInterpretation() == GCI_GreenBand) {
1754  shift = 1;
1755  } else if (poBand->GetColorInterpretation() == GCI_BlueBand) {
1756  shift = 2;
1757  } else if (poBand->GetColorInterpretation() == GCI_AlphaBand) {
1758  shift = 3;
1759  } else {
1760  valid = false;
1761  break;
1762  }
1763  assert(xSize == poBand->GetXSize() && ySize == poBand->GetYSize());
1764  if (poBand->RasterIO(GF_Read, 0, 0, xSize, ySize, ((unsigned char*)result) + shift, xSize, ySize, GDT_Byte, 4, 4 * xSize) == CE_Failure) {
1765  valid = false;
1766  break;
1767  }
1768  }
1769  GDALClose(poDataset);
1770  if (valid) {
1771  return new FXImage(getApp(), result, IMAGE_OWNED | IMAGE_KEEP | IMAGE_SHMI | IMAGE_SHMP, xSize, ySize);
1772  }
1773  FXFREE(&result);
1774 #endif
1775  return nullptr;
1776 }
1777 
1778 
1779 void
1781  GLHelper::pushName(0);
1782  myDecalsLockMutex.lock();
1783  for (auto& decal : myDecals) {
1784  if (decal.skip2D || decal.filename.empty()) {
1785  continue;
1786  }
1787  if (!decal.initialised) {
1788  try {
1789  FXImage* img = checkGDALImage(decal);
1790  if (img == nullptr) {
1791  img = MFXImageHelper::loadImage(getApp(), decal.filename);
1792  }
1794  decal.glID = GUITexturesHelper::add(img);
1795  decal.initialised = true;
1796  decal.image = img;
1797  } catch (InvalidArgument& e) {
1798  WRITE_ERROR("Could not load '" + decal.filename + "'.\n" + e.what());
1799  decal.skip2D = true;
1800  }
1801  }
1803  if (decal.screenRelative) {
1804  Position center = screenPos2NetPos((int)decal.centerX, (int)decal.centerY);
1805  glTranslated(center.x(), center.y(), decal.layer);
1806  } else {
1807  glTranslated(decal.centerX, decal.centerY, decal.layer);
1808  }
1809  glRotated(decal.rot, 0, 0, 1);
1810  glColor3d(1, 1, 1);
1811  double halfWidth = decal.width / 2.;
1812  double halfHeight = decal.height / 2.;
1813  if (decal.screenRelative) {
1814  halfWidth = p2m(halfWidth);
1815  halfHeight = p2m(halfHeight);
1816  }
1817  GUITexturesHelper::drawTexturedBox(decal.glID, -halfWidth, -halfHeight, halfWidth, halfHeight);
1819  }
1820  myDecalsLockMutex.unlock();
1822 }
1823 
1824 
1825 void
1827  int x, y;
1828  FXuint b;
1829  myApp->getCursorPosition(x, y, b);
1830  int appX = myApp->getX();
1831  int popX = x + appX;
1832  int popY = y + myApp->getY();
1833  myPopup->setX(popX);
1834  myPopup->setY(popY);
1835  myPopup->create();
1836  myPopup->show();
1837  // TODO: try to stay on screen even on a right secondary screen in multi-monitor setup
1838  const int rootWidth = getApp()->getRootWindow()->getWidth();
1839  const int rootHeight = getApp()->getRootWindow()->getHeight();
1840  if (popX <= rootWidth) {
1841  const int maxX = (appX < 0) ? 0 : rootWidth;
1842  popX = MIN2(popX, maxX - myPopup->getWidth() - 10);
1843  }
1844  popY = MIN2(popY, rootHeight - myPopup->getHeight() - 50);
1845  myPopup->move(popX, popY);
1847  myChanger->onRightBtnRelease(nullptr);
1848  setFocus();
1849 }
1850 
1851 // ------------ Additional visualisations
1852 
1853 bool
1855  if (myAdditionallyDrawn.find(which) == myAdditionallyDrawn.end()) {
1856  myAdditionallyDrawn[which] = 1;
1857  } else {
1858  myAdditionallyDrawn[which] = myAdditionallyDrawn[which] + 1;
1859  }
1860  update();
1861  return true;
1862 }
1863 
1864 
1865 bool
1867  if (myAdditionallyDrawn.find(which) == myAdditionallyDrawn.end()) {
1868  return false;
1869  }
1870  int cnt = myAdditionallyDrawn[which];
1871  if (cnt == 1) {
1872  myAdditionallyDrawn.erase(which);
1873  } else {
1874  myAdditionallyDrawn[which] = myAdditionallyDrawn[which] - 1;
1875  }
1876  update();
1877  return true;
1878 }
1879 
1880 
1881 bool
1883  if (myAdditionallyDrawn.find(which) == myAdditionallyDrawn.end()) {
1884  return false;
1885  } else {
1886  return true;
1887  }
1888 }
1889 
1890 
1891 Boundary
1893  Boundary bound = myChanger->getViewport(fixRatio);
1894  glMatrixMode(GL_PROJECTION);
1895  glLoadIdentity();
1896  // as a rough rule, each GLObject is drawn at z = -GUIGlObjectType
1897  // thus, objects with a higher value will be closer (drawn on top)
1898  // // @todo last param should be 0 after modifying all glDraw methods
1899  glOrtho(0, getWidth(), 0, getHeight(), -GLO_MAX - 1, GLO_MAX + 1);
1900  glMatrixMode(GL_MODELVIEW);
1901  glLoadIdentity();
1902  double scaleX = (double)getWidth() / bound.getWidth();
1903  double scaleY = (double)getHeight() / bound.getHeight();
1904  glScaled(scaleX, scaleY, 1);
1905  glTranslated(-bound.xmin(), -bound.ymin(), 0);
1906  // rotate around the center of the screen
1907  //double angle = -90;
1908  if (myChanger->getRotation() != 0) {
1909  glTranslated(bound.getCenter().x(), bound.getCenter().y(), 0);
1910  glRotated(myChanger->getRotation(), 0, 0, 1);
1911  glTranslated(-bound.getCenter().x(), -bound.getCenter().y(), 0);
1912  Boundary rotBound;
1913  double rad = -DEG2RAD(myChanger->getRotation());
1914  rotBound.add(Position(bound.xmin(), bound.ymin()).rotateAround2D(rad, bound.getCenter()));
1915  rotBound.add(Position(bound.xmin(), bound.ymax()).rotateAround2D(rad, bound.getCenter()));
1916  rotBound.add(Position(bound.xmax(), bound.ymin()).rotateAround2D(rad, bound.getCenter()));
1917  rotBound.add(Position(bound.xmax(), bound.ymax()).rotateAround2D(rad, bound.getCenter()));
1918  bound = rotBound;
1919  }
1921  return bound;
1922 }
1923 
1924 
1925 double
1927  return myApp->getDelay();
1928 }
1929 
1930 
1931 void
1933  myApp->setDelay(delay);
1934 }
1935 
1936 
1937 void
1938 GUISUMOAbstractView::setBreakpoints(const std::vector<SUMOTime>& breakpoints) {
1939  myApp->setBreakpoints(breakpoints);
1940 }
1941 
1942 
1943 void
1945  const GUIVisualizationRainbowSettings& rs, double minValue, double maxValue, bool hasMissingData) {
1946  if (rs.hideMin && rs.hideMax && minValue == std::numeric_limits<double>::infinity()) {
1947  minValue = rs.minThreshold;
1948  maxValue = rs.maxThreshold;
1949  }
1950  if (rs.fixRange) {
1951  if (rs.hideMin) {
1952  minValue = rs.minThreshold;
1953  }
1954  if (rs.hideMax) {
1955  maxValue = rs.maxThreshold;
1956  }
1957  }
1958  if (minValue != std::numeric_limits<double>::infinity()) {
1959  scheme.clear();
1960  // add new thresholds
1966  || hasMissingData) {
1967  scheme.addColor(s.COL_MISSING_DATA, s.MISSING_DATA, "missing data");
1968  }
1969  if (rs.hideMin && !rs.fixRange) {
1970  const double rawRange = maxValue - minValue;
1971  minValue = MAX2(rs.minThreshold + MIN2(1.0, rawRange / 100.0), minValue);
1972  scheme.addColor(RGBColor(204, 204, 204), rs.minThreshold);
1973  }
1974  if (rs.hideMax && !rs.fixRange) {
1975  const double rawRange = maxValue - minValue;
1976  maxValue = MIN2(rs.maxThreshold - MIN2(1.0, rawRange / 100.0), maxValue);
1977  scheme.addColor(RGBColor(204, 204, 204), rs.maxThreshold);
1978  }
1979  const double range = maxValue - minValue;
1980  scheme.addColor(rs.colors.front(), minValue);
1981  const int steps = (int)rs.colors.size() - 1;
1982  if (rs.setNeutral) {
1983  const int steps1 = steps / 2;
1984  const int steps2 = steps - steps1;
1985  const double range1 = rs.neutralThreshold - minValue;
1986  const double range2 = maxValue - rs.neutralThreshold;
1987  for (int i = 1; i < steps1; i++) {
1988  scheme.addColor(rs.colors[i], (minValue + range1 * i / steps1));
1989  }
1990  scheme.addColor(rs.colors[steps1], rs.neutralThreshold);
1991  for (int i = 1; i < steps2; i++) {
1992  scheme.addColor(rs.colors[steps1 + i], (rs.neutralThreshold + range2 * i / steps2));
1993  }
1994  } else {
1995  for (int i = 1; i < steps; i++) {
1996  scheme.addColor(rs.colors[i], (minValue + range * i / steps));
1997  }
1998  }
1999  scheme.addColor(rs.colors.back(), maxValue);
2000  }
2001 }
2002 
2003 
2005  myGLObject(object) {
2006  first = layer;
2007  second.first = object->getType();
2008  second.second = object->getMicrosimID();
2009 }
2010 
2011 
2013  myGLObject(object) {
2014  first = object->getType();
2015  second.first = object->getType();
2016  second.second = object->getMicrosimID();
2017 }
2018 
2019 
2020 GUIGlObject*
2022  return myGLObject;
2023 }
2024 
2025 /****************************************************************************/
long long int SUMOTime
Definition: GUI.h:35
@ MID_GLCANVAS
GLCanvas - ID.
Definition: GUIAppEnum.h:409
@ MID_REACHABILITY
show reachability from a given lane
Definition: GUIAppEnum.h:529
@ MID_CLOSE_LANE
close lane
Definition: GUIAppEnum.h:665
@ MID_CURSORDIALOG_FRONT
remove/select/mark front element
Definition: GUIAppEnum.h:440
@ MID_CLOSE_EDGE
close edge
Definition: GUIAppEnum.h:667
@ MID_SIMPLE_VIEW_COLORCHANGE
Informs the dialog about a value's change.
Definition: GUIAppEnum.h:625
@ MID_ADD_REROUTER
add rerouter
Definition: GUIAppEnum.h:669
GUICompleteSchemeStorage gSchemeStorage
@ MOVEVIEW
move view cursor
@ DEFAULT
default cursor
unsigned int GUIGlID
Definition: GUIGlObject.h:43
GUIGlObjectType
@ GLO_REROUTER_EDGE
a Rerouter over edge
@ GLO_MAX
empty max
@ GLO_LANE
a lane
@ GLO_VEHICLE
a vehicle
@ GLO_PERSON
a person
@ GLO_NETWORK
The network - empty.
GUISelectedStorage gSelected
A global holder of selected objects.
FXDEFMAP(GUISUMOAbstractView) GUISUMOAbstractViewMap[]
#define DEG2RAD(x)
Definition: GeomHelper.h:35
#define WRITE_WARNINGF(...)
Definition: MsgHandler.h:296
#define WRITE_ERROR(msg)
Definition: MsgHandler.h:304
#define WRITE_WARNING(msg)
Definition: MsgHandler.h:295
#define TL(string)
Definition: MsgHandler.h:315
SUMOTime DELTA_T
Definition: SUMOTime.cpp:38
int gPrecisionGeo
Definition: StdDefs.cpp:27
const double SUMO_const_laneWidth
Definition: StdDefs.h:48
#define UNUSED_PARAMETER(x)
Definition: StdDefs.h:30
T MIN2(T a, T b)
Definition: StdDefs.h:76
T MAX2(T a, T b)
Definition: StdDefs.h:82
std::string joinToString(const std::vector< T > &v, const T_BETWEEN &between, std::streamsize accuracy=gPrecision)
Definition: ToString.h:283
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition: ToString.h:46
#define TLC(context, string)
Definition: Translation.h:47
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
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
double ymax() const
Returns maximum y-coordinate.
Definition: Boundary.cpp:136
double xmax() const
Returns maximum x-coordinate.
Definition: Boundary.cpp:124
static void resetVertexCounter()
reset vertex counter
Definition: GLHelper.cpp:175
static void setColor(const RGBColor &c)
Sets the gl-color to this value.
Definition: GLHelper.cpp:654
static void pushName(unsigned int name)
push Name
Definition: GLHelper.cpp:139
static void checkCounterMatrix()
check counter matrix (for debug purposes)
Definition: GLHelper.cpp:181
static void popMatrix()
pop matrix
Definition: GLHelper.cpp:130
static int getMatrixCounter()
get matrix counter
Definition: GLHelper.cpp:157
static void checkCounterName()
check counter name (for debug purposes)
Definition: GLHelper.cpp:192
static void popName()
pop Name
Definition: GLHelper.cpp:148
static void pushMatrix()
push matrix
Definition: GLHelper.cpp:117
static void setGL2PS(bool active=true)
set GL2PS
Definition: GLHelper.cpp:678
static int getVertexCounter()
get vertex counter
Definition: GLHelper.cpp:169
static void drawText(const std::string &text, const Position &pos, const double layer, const double size, const RGBColor &col=RGBColor::BLACK, const double angle=0, const int align=0, double width=-1)
Definition: GLHelper.cpp:756
static void resetMatrixCounter()
reset matrix counter
Definition: GLHelper.cpp:163
GUIVisualizationSettings & getDefault()
Returns the default scheme.
void saveViewport(const double x, const double y, const double z, const double rot)
Makes the given viewport the default.
const std::vector< GUISUMOAbstractView::Decal > & getDecals()
Returns the default decals.
void setDefault(const std::string &name)
Makes the scheme with the given name the default.
void saveDecals(const std::vector< GUISUMOAbstractView::Decal > &decals)
Makes the given decals the default.
void setViewport(GUISUMOAbstractView *view)
Sets the default viewport.
Dialog for edit rerouter intervals.
static FXCursor * getCursor(GUICursor which)
returns a cursor previously defined in the enum GUICursor
A dialog to change the viewport.
void setOldValues(const Position &lookFrom, const Position &lookAt, double rotation)
Resets old values.
bool haveGrabbed() const
Returns the information whether one of the spin dialers is grabbed.
void setValues(double zoom, double xoff, double yoff, double rotation)
Sets the given values into the dialog.
void show()
overload show function to focus always in OK Button
The dialog to change the view (gui) settings.
void show()
show view settings dialog
void setCurrent(GUIVisualizationSettings *settings)
Sets current settings (called if reopened)
The popup menu of a globject.
MFXComboBoxIcon * getColoringSchemesCombo()
return combobox with the current coloring schemes (standard, fastest standard, real world....
GUIMainWindow * getGUIMainWindowParent()
Returns the GUIMainWindow parent.
static const double INVALID_PRIORITY
Definition: GUIGlObject.h:73
static const GUIGlID INVALID_ID
Definition: GUIGlObject.h:72
virtual double getClickPriority() const
Returns the priority of receiving mouse clicks.
Definition: GUIGlObject.h:161
virtual Boundary getCenteringBoundary() const =0
virtual void onLeftBtnPress(void *)
notify object about left click
Definition: GUIGlObject.h:218
GUIGlObjectType getType() const
Returns the type of the object as coded in GUIGlObjectType.
Definition: GUIGlObject.h:156
virtual GUIGLObjectPopupMenu * getPopUpMenu(GUIMainWindow &app, GUISUMOAbstractView &parent)=0
Returns an own popup-menu.
GUIGlID getGlID() const
Returns the numerical id of the object.
Definition: GUIGlObject.h:104
void unblockObject(GUIGlID id)
Marks an object as unblocked.
GUIGlObject * getNetObject() const
Returns the network object.
GUIGlObject * getObjectBlocking(GUIGlID id) const
Returns the object from the container locking it.
static GUIGlObjectStorage gIDStorage
A single static instance of this class.
Representation of a lane in the micro simulation (gui-version)
Definition: GUILane.h:60
MFXStaticToolTip * getStaticTooltipView() const
get static toolTip for view
virtual double getDelay() const
Returns the delay (should be overwritten by subclasses if applicable)
FXLabel * getGeoLabel()
get geo label
bool isGaming() const
return whether the gui is in gaming mode
virtual void setBreakpoints(const std::vector< SUMOTime > &)
Sets the breakpoints of the parent application.
FXLabel * getTestLabel()
get test label
virtual void setStatusBarText(const std::string &)
get status bar text (can be implemented in children)
virtual void setDelay(double)
Sets the delay of the parent application.
FXLabel * getCartesianLabel()
get cartesian label
FXHorizontalFrame * getTestFrame()
get test frame
virtual void setViewportFrom(double xPos, double yPos, double zPos)=0
Alternative method for setting the viewport.
virtual long onKeyPress(void *data)
called when user press a key
virtual void setRotation(double rotation)=0
Sets the rotation.
virtual void onRightBtnPress(void *data)
called when user press right button
virtual void centerTo(const Position &pos, double radius, bool applyZoom=true)=0
Centers the view to the given position, setting it to a size that covers the radius....
virtual double getRotation() const =0
Returns the rotation of the canvas stored in this changer.
virtual bool onLeftBtnRelease(void *data)
called when user releases left button
virtual double getZoom() const =0
Returns the zoom factor computed stored in this changer.
virtual void onLeftBtnPress(void *data)
mouse functions
virtual bool onMiddleBtnRelease(void *data)
called when user releases middle button
virtual double getXPos() const =0
Returns the x-offset of the field to show stored in this changer.
virtual double getYPos() const =0
Returns the y-offset of the field to show stored in this changer.
virtual void onMiddleBtnPress(void *data)
called when user press middle button
virtual long onKeyRelease(void *data)
called when user releases a key
virtual void onMouseMove(void *data)
called when user moves mouse
virtual double getZPos() const =0
Returns the camera height corresponding to the current zoom factor.
virtual void onMouseWheel(void *data)
called when user changes mouse wheel
virtual bool onRightBtnRelease(void *data)
called when user releases right button
Boundary getViewport(bool fixRatio=true)
get viewport
virtual void setViewport(double zoom, double xPos, double yPos)=0
Sets the viewport Used for: Adapting a new viewport.
const std::string & getName() const
const std::vector< double > & getThresholds() const
const std::vector< T > & getColors() const
int addColor(const T &color, const double threshold, const std::string &name="")
const std::vector< std::string > & getNames() const
MFXComboBoxIcon * getColoringSchemesCombo()
get coloring schemes combo
bool myAmInitialised
Internal information whether doInit() was called.
Position snapToActiveGrid(const Position &pos, bool snapXY=true) const
Returns a position that is mapped to the closest grid point if the grid is active.
std::vector< GUIGlObject * > myCurrentObjectsDialog
vector with current objects dialog
std::string makeSnapshot(const std::string &destFile, const int w=-1, const int h=-1)
Takes a snapshots and writes it into the given file.
void updateToolTip()
A method that updates the tooltip.
void addDecals(const std::vector< Decal > &decals)
add decals
virtual void checkSnapshots()
Checks whether it is time for a snapshot.
void showViewschemeEditor()
show viewsscheme editor
static const double SENSITIVITY
virtual long onLeftBtnRelease(FXObject *, FXSelector, void *)
void displayLegend()
Draws a line with ticks, and the length information.
virtual long onVisualizationChange(FXObject *, FXSelector, void *)
hook to react on change in visualization settings
std::vector< GUIGlObject * > getGUIGlObjectsUnderCursor()
returns the GUIGlObject under the cursor using GL_SELECT (including overlapped objects)
long myFrameDrawTime
counter for measuring rendering time
void replacePopup(GUIGLObjectPopupMenu *popUp)
replace PopUp
std::vector< GUIGlID > getObjectsAtPosition(Position pos, double radius)
returns the ids of the object at position within the given (rectangular) radius using GL_SELECT
const SUMORTree * myGrid
The visualization speed-up.
void openObjectDialog(const std::vector< GUIGlObject * > &objects, const bool filter=true)
open object dialog for the given object
virtual void saveFrame(const std::string &destFile, FXColor *buf)
Adds a frame to a video snapshot which will be initialized if necessary.
virtual void recenterView()
recenters the view
virtual SUMOTime getCurrentTimeStep() const
get the current simulation time
void paintGLGrid() const
paints a grid
FXbool makeCurrent()
A reimplementation due to some internal reasons.
int myMouseHotspotX
Offset to the mouse-hotspot from the mouse position.
GUIMainWindow * getMainWindow() const
get main window
bool isInEditMode()
returns true, if the edit button was pressed
void buildMinMaxRainbow(const GUIVisualizationSettings &s, GUIColorScheme &scheme, const GUIVisualizationRainbowSettings &rs, double minValue, double maxValue, bool hasMissingData)
helper function for buildColorRainbow
virtual long onMiddleBtnRelease(FXObject *, FXSelector, void *)
virtual long onMouseMove(FXObject *, FXSelector, void *)
bool myPanning
Panning flag.
bool isAdditionalGLVisualisationEnabled(GUIGlObject *const which) const
Check if an object is added in the additional GL visualitation.
FXMutex myDecalsLockMutex
The mutex to use before accessing the decals list in order to avoid thread conflicts.
FXCondition mySnapshotCondition
the semaphore when waiting for snapshots to finish
virtual GUIGlID getToolTipID()
returns the id of object under cursor to show their tooltip
Position myPopupPosition
The current popup-menu position.
virtual void doInit()
doInit
std::vector< GUIGlObject * > filterContextObjects(const std::vector< GUIGlObject * > &objects)
filter out duplicate and forbidden objects
virtual long onCmdCloseEdge(FXObject *, FXSelector, void *)
virtual int doPaintGL(int, const Boundary &)
paint GL
virtual void showViewportEditor()
show viewport editor
const GUIVisualizationSettings & getVisualisationSettings() const
get visualization settings (read only)
void setDelay(double delay)
Sets the delay of the parent application.
Boundary getVisibleBoundary() const
get visible boundary
Position screenPos2NetPos(int x, int y) const
Translate screen position to network position.
void addSnapshot(SUMOTime time, const std::string &file, const int w=-1, const int h=-1)
Sets the snapshot time to file map.
GUIGlID getObjectUnderCursor()
returns the id of the front object under the cursor using GL_SELECT
GUIPerspectiveChanger & getChanger() const
get changer
virtual void centerTo(GUIGlID id, bool applyZoom, double zoomDist=20)
centers to the chosen artifact
GUIMainWindow * myApp
The application.
GUIDialog_EditViewport * getViewportEditor()
get the viewport and create it on first access
virtual void zoom2Pos(Position &camera, Position &lookAt, double zoom)
zoom interface for 3D view
std::vector< GUIGlID > getObjectsInBoundary(Boundary bound)
returns the ids of all objects in the given boundary
virtual long onCmdCloseLane(FXObject *, FXSelector, void *)
interaction with the simulation
void drawFPS()
Draws frames-per-second indicator.
virtual long onMouseWheel(FXObject *, FXSelector, void *)
double getGridWidth() const
get grid width
std::vector< Decal > & getDecals()
The list of decals to show.
bool removeAdditionalGLVisualisation(GUIGlObject *const which)
Removes an object from the list of objects that show additional things.
GUIGlChildWindow * myGlChildWindowParent
The parent window.
GUIGlChildWindow * getGUIGlChildWindow()
get GUIGlChildWindow
double getDelay() const
Returns the delay of the parent application.
virtual void updatePositionInformationLabel() const
update position information labels
std::vector< GUIGlObject * > getGUIGlObjectsAtPosition(Position pos, double radius)
returns the GUIGlObjects at position within the given (rectangular) radius using GL_SELECT
virtual long onLeftBtnPress(FXObject *, FXSelector, void *)
virtual void setViewportFromToRot(const Position &lookFrom, const Position &lookAt, double rotation)
applies the given viewport settings
double p2m(double pixel) const
pixels-to-meters conversion method
std::vector< Decal > myDecals
The list of decals to show.
const Position & getPopupPosition() const
get position of current popup
double m2p(double meter) const
meter-to-pixels conversion method
virtual GUILane * getLaneUnderCursor()
returns the GUILane at cursor position (implementation depends on view)
virtual void openObjectDialogAtCursor(const FXEvent *ev)
open object dialog at the cursor position
virtual void onGamingClick(Position)
on gaming click
bool myInEditMode
Information whether too-tip informations shall be generated.
GUIVisualizationSettings * editVisualisationSettings() const
edit visualization settings (allow modify VisualizationSetings, use carefully)
GUIVisualizationSettings * myVisualizationSettings
visualization settings
void destroyPopup()
destroys the popup
Position getWindowCursorPosition() const
return windows cursor position
virtual long onKeyPress(FXObject *o, FXSelector sel, void *data)
keyboard functions
GUIDialog_EditViewport * myGUIDialogEditViewport
viewport chooser
virtual long onMiddleBtnPress(FXObject *, FXSelector, void *)
void paintGL()
FOX needs this.
virtual void stopTrack()
stop track
virtual Position getPositionInformation() const
Returns the cursor's x/y position within the network.
GUIGlID getObjectAtPosition(Position pos)
returns the id of the object at position using GL_SELECT
std::vector< GUIGlObject * > getGUIGlObjectsUnderSnappedCursor()
returns the GUIGlObject under the gripped cursor using GL_SELECT (including overlapped objects)
bool showToolTipFor(const GUIGlID idToolTip)
invokes the tooltip for the given object
virtual long onKeyRelease(FXObject *o, FXSelector sel, void *data)
GUIDialog_ViewSettings * myGUIDialogViewSettings
Visualization changer.
virtual void onGamingRightClick(Position)
void setWindowCursorPosition(FXint x, FXint y)
Returns the gl-id of the object under the given coordinates.
double getFPS() const
retrieve FPS
virtual long onCmdShowReachability(FXObject *, FXSelector, void *)
highlight edges according to reachability
std::map< GUIGlObject *, int > myAdditionallyDrawn
List of objects for which GUIGlObject::drawGLAdditional is called.
void drawDecals()
Draws the stored decals.
std::vector< GUIGlID > getObjectsUnderCursor()
returns the id of the objects under the cursor using GL_SELECT (including overlapped objects)
Boundary applyGLTransform(bool fixRatio=true)
applies gl-transformations to fit the Boundary given by myChanger onto the canvas....
virtual void updateViewportValues()
update the viewport chooser with the current view values
FXImage * checkGDALImage(Decal &d)
check whether we can read image data or position with gdal
double getGridHeight() const
get grid height
virtual void startTrack(int)
star track
virtual long onDoubleClicked(FXObject *, FXSelector, void *)
FXMutex & getDecalsLockMutex()
The mutex to use before accessing the decals list in order to avoid thread conflicts.
virtual bool is3DView() const
return whether this is a 3D view
void displayLegends()
Draws the configured legends.
void displayColorLegend(const GUIColorScheme &scheme, bool leftSide)
Draws a legend for the given scheme.
FXMutex mySnapshotsMutex
The mutex to use before accessing the decals list in order to avoid thread conflicts.
virtual long onMouseLeft(FXObject *, FXSelector, void *)
virtual long onRightBtnRelease(FXObject *, FXSelector, void *)
FXint myWindowCursorPositionX
Position of the cursor relative to the window.
GUIPerspectiveChanger * myChanger
The perspective changer.
GUIGLObjectPopupMenu * myPopup
The current popup-menu.
virtual void copyViewportTo(GUISUMOAbstractView *view)
copy the viewport to the given view
void setBreakpoints(const std::vector< SUMOTime > &breakpoints)
Sets the breakpoints of the parent application.
void waitForSnapshots(const SUMOTime snapshotTime)
bool addAdditionalGLVisualisation(GUIGlObject *const which)
Adds an object to call its additional visualisation method.
virtual bool setColorScheme(const std::string &)
set color scheme
virtual long onCmdAddRerouter(FXObject *, FXSelector, void *)
std::vector< GUIGlObject * > filterInternalLanes(const std::vector< GUIGlObject * > &objects) const
filter internal lanes in Objects under cursor
virtual long onPaint(FXObject *, FXSelector, void *)
virtual long onRightBtnPress(FXObject *, FXSelector, void *)
virtual ~GUISUMOAbstractView()
destructor
virtual long onConfigure(FXObject *, FXSelector, void *)
mouse functions
std::map< SUMOTime, std::vector< std::tuple< std::string, int, int > > > mySnapshots
Snapshots.
void remove(GUIDialog_EditViewport *)
remove viewport
virtual GUIGlID getTrackedID() const
get tracked id
void openPopupDialog()
open popup dialog
void toggleSelection(GUIGlID id)
Toggles selection of an object.
static void drawTexturedBox(int which, double size)
Draws a named texture as a box with the given size.
static GUIGlID add(FXImage *i)
Adds a texture to use.
static int getMaxTextureSize()
return maximum number of pixels in x and y direction
Stores the information about how to visualize structures.
RGBColor backgroundColor
The background color to use.
static const std::string SCHEME_NAME_DATA_ATTRIBUTE_NUMERICAL
static const std::string SCHEME_NAME_EDGEDATA_NUMERICAL
bool dither
Information whether dithering shall be enabled.
GUIColorer vehicleColorer
The vehicle colorer.
bool drawForRectangleSelection
whether drawing is performed for the purpose of selecting objects using a rectangle
GUIVisualizationSizeSettings addSize
bool altKeyPressed
alt key pressed (only used for draw polygons under other elements in SUMO-GUI, store is not needed)
std::string name
The name of this setting.
bool drawJunctionShape
whether the shape of the junction should be drawn
bool gaming
whether the application is in gaming mode or not
static const std::string SCHEME_NAME_LANE_PARAM_NUMERICAL
bool fps
Information whether frames-per-second should be drawn.
bool showGrid
Information whether a grid shall be shown.
bool showVehicleColorLegend
Information whether the vehicle color legend shall be drawn.
double scale
information about a lane's width (temporary, used for a single view)
GUIColorScheme & getLaneEdgeScheme()
Returns the current lane (edge) coloring schme.
bool showSizeLegend
Information whether the size legend shall be drawn.
double gridXSize
Information about the grid spacings.
bool showColorLegend
Information whether the edge color legend shall be drawn.
static const std::string SCHEME_NAME_EDGE_PARAM_NUMERICAL
scheme names
static const std::string SCHEME_NAME_PARAM_NUMERICAL
double angle
The current view rotation angle.
static GeoConvHelper & getProcessing()
the coordinate transformation to use for input conversion and processing
Definition: GeoConvHelper.h:84
void cartesian2geo(Position &cartesian) const
Converts the given cartesian (shifted) position to its geo (lat/long) representation.
static const GeoConvHelper & getFinal()
the coordinate transformation for writing the location element and for tracking the original coordina...
ComboBox with icon.
static FXImage * loadImage(FXApp *a, const std::string &file)
static FXbool scalePower2(FXImage *image, int maxSize=(2<< 29))
static FXbool saveImage(const std::string &file, int width, int height, FXColor *data)
static void sleep(long ms)
void showStaticToolTip(const FXString &toolTipText)
show static toolTip
void hideStaticToolTip()
hide static toolTip
bool isStaticToolTipEnabled() const
check staticToolTip is enabled
static OptionsCont & getOptions()
Retrieves the options.
Definition: OptionsCont.cpp:60
A point in 2D or 3D with translation and scaling methods.
Definition: Position.h:37
void setx(double x)
set position x
Definition: Position.h:70
void set(double x, double y)
set positions x and y
Definition: Position.h:85
static const Position INVALID
used to indicate that a position is valid
Definition: Position.h:317
double x() const
Returns the x-position.
Definition: Position.h:55
void setz(double z)
set position z
Definition: Position.h:80
Position rotateAround2D(double rad, const Position &origin)
rotate this position by rad around origin and return the result
Definition: Position.cpp:41
double z() const
Returns the z-position.
Definition: Position.h:65
void sety(double y)
set position y
Definition: Position.h:75
double y() const
Returns the y-position.
Definition: Position.h:60
static RGBColor interpolate(const RGBColor &minColor, const RGBColor &maxColor, double weight)
Interpolates between two colors.
Definition: RGBColor.cpp:355
static const RGBColor WHITE
Definition: RGBColor.h:192
unsigned char red() const
Returns the red-amount of the color.
Definition: RGBColor.cpp:74
unsigned char alpha() const
Returns the alpha-amount of the color.
Definition: RGBColor.cpp:92
unsigned char green() const
Returns the green-amount of the color.
Definition: RGBColor.cpp:80
unsigned char blue() const
Returns the blue-amount of the color.
Definition: RGBColor.cpp:86
static const RGBColor BLACK
Definition: RGBColor.h:193
static const RGBColor RED
named colors
Definition: RGBColor.h:185
A RT-tree for efficient storing of SUMO's GL-objects.
Definition: SUMORTree.h:66
virtual int Search(const float a_min[2], const float a_max[2], const GUIVisualizationSettings &c) const
Find all within search rectangle.
Definition: SUMORTree.h:116
static bool startsWith(const std::string &str, const std::string prefix)
Checks whether a given string starts with the prefix.
static long getCurrentMillis()
Returns the current time in milliseconds.
Definition: SysUtils.cpp:44
FONSalign
Definition: fontstash.h:40
@ FONS_ALIGN_LEFT
Definition: fontstash.h:42
@ FONS_ALIGN_RIGHT
Definition: fontstash.h:44
NLOHMANN_BASIC_JSON_TPL_DECLARATION void swap(nlohmann::NLOHMANN_BASIC_JSON_TPL &j1, nlohmann::NLOHMANN_BASIC_JSON_TPL &j2) noexcept(//NOLINT(readability-inconsistent-declaration-parameter-name) is_nothrow_move_constructible< nlohmann::NLOHMANN_BASIC_JSON_TPL >::value &&//NOLINT(misc-redundant-expression) is_nothrow_move_assignable< nlohmann::NLOHMANN_BASIC_JSON_TPL >::value)
exchanges the values of two JSON objects
Definition: json.hpp:21884
comparator for resolving clicks
A decal (an image) that can be shown.
double centerX
The center of the image in x-direction (net coordinates, in m)
double height
The height of the image (net coordinates in y-direction, in m)
double width
The width of the image (net coordinates in x-direction, in m)
double centerY
The center of the image in y-direction (net coordinates, in m)
std::string filename
The path to the file the image is located at.
GUIGlObject * getGLObject() const
get GLObject
LayerObject(double layer, GUIGlObject *object)
constructor for shapes
bool hideMax
whether data above threshold should not be colored
bool setNeutral
whether the scale should be centered at a specific value
bool fixRange
whether the color scale should be fixed to the given min/max values
double minThreshold
threshold below which value should not be colored
std::vector< RGBColor > colors
color steps for the rainbow;
bool hideMin
whether data below threshold should not be colored
double neutralThreshold
neutral point of scale
double maxThreshold
threshold above which value should not be colored
double getExaggeration(const GUIVisualizationSettings &s, const GUIGlObject *o, double factor=20) const
return the drawing size including exaggeration and constantSize values