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.org/sumo
3 // Copyright (C) 2001-2022 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>
47 #include <utils/gui/div/GLHelper.h>
55 #include <utils/geom/GeomHelper.h>
60 
61 #include "GUISUMOAbstractView.h"
62 #include "GUIMainWindow.h"
63 #include "GUIGlChildWindow.h"
65 #include "GUIDialog_EditViewport.h"
66 
67 #ifdef HAVE_GDAL
68 #if __GNUC__ > 3
69 #pragma GCC diagnostic push
70 #pragma GCC diagnostic ignored "-Wpedantic"
71 #endif
72 #include <gdal_priv.h>
73 #if __GNUC__ > 3
74 #pragma GCC diagnostic pop
75 #endif
76 #endif
77 
78 
79 // ===========================================================================
80 // debug constants
81 // ===========================================================================
82 //#define DEBUG_SNAPSHOT
83 
84 // ===========================================================================
85 // static members
86 // ===========================================================================
87 
88 const double GUISUMOAbstractView::SENSITIVITY = 0.1; // meters
89 
90 
91 // ===========================================================================
92 // member method definitions
93 // ===========================================================================
94 /* -------------------------------------------------------------------------
95  * GUISUMOAbstractView - FOX callback mapping
96  * ----------------------------------------------------------------------- */
97 FXDEFMAP(GUISUMOAbstractView) GUISUMOAbstractViewMap[] = {
98  FXMAPFUNC(SEL_CONFIGURE, 0, GUISUMOAbstractView::onConfigure),
99  FXMAPFUNC(SEL_PAINT, 0, GUISUMOAbstractView::onPaint),
100  FXMAPFUNC(SEL_LEFTBUTTONPRESS, 0, GUISUMOAbstractView::onLeftBtnPress),
101  FXMAPFUNC(SEL_LEFTBUTTONRELEASE, 0, GUISUMOAbstractView::onLeftBtnRelease),
102  FXMAPFUNC(SEL_MIDDLEBUTTONPRESS, 0, GUISUMOAbstractView::onMiddleBtnPress),
103  FXMAPFUNC(SEL_MIDDLEBUTTONRELEASE, 0, GUISUMOAbstractView::onMiddleBtnRelease),
104  FXMAPFUNC(SEL_RIGHTBUTTONPRESS, 0, GUISUMOAbstractView::onRightBtnPress),
105  FXMAPFUNC(SEL_RIGHTBUTTONRELEASE, 0, GUISUMOAbstractView::onRightBtnRelease),
106  FXMAPFUNC(SEL_DOUBLECLICKED, 0, GUISUMOAbstractView::onDoubleClicked),
107  FXMAPFUNC(SEL_MOUSEWHEEL, 0, GUISUMOAbstractView::onMouseWheel),
108  FXMAPFUNC(SEL_MOTION, 0, GUISUMOAbstractView::onMouseMove),
109  FXMAPFUNC(SEL_LEAVE, 0, GUISUMOAbstractView::onMouseLeft),
110  FXMAPFUNC(SEL_KEYPRESS, 0, GUISUMOAbstractView::onKeyPress),
111  FXMAPFUNC(SEL_KEYRELEASE, 0, GUISUMOAbstractView::onKeyRelease),
112 
113 };
114 
115 
116 FXIMPLEMENT_ABSTRACT(GUISUMOAbstractView, FXGLCanvas, GUISUMOAbstractViewMap, ARRAYNUMBER(GUISUMOAbstractViewMap))
117 
118 
119 /* -------------------------------------------------------------------------
120  * GUISUMOAbstractView - methods
121  * ----------------------------------------------------------------------- */
122 GUISUMOAbstractView::GUISUMOAbstractView(FXComposite* p, GUIMainWindow& app, GUIGlChildWindow* parent, const SUMORTree& grid, FXGLVisual* glVis, FXGLCanvas* share) :
123  FXGLCanvas(p, glVis, share, p, MID_GLCANVAS, LAYOUT_SIDE_TOP | LAYOUT_FILL_X | LAYOUT_FILL_Y, 0, 0, 0, 0),
124  myApp(&app),
125  myParent(parent),
126  myGrid(&grid),
127  myChanger(nullptr),
128  myMouseHotspotX(app.getDefaultCursor()->getHotX()),
129  myMouseHotspotY(app.getDefaultCursor()->getHotY()),
130  myPopup(nullptr),
131  myPopupPosition(Position(0, 0)),
132  myUseToolTips(false),
133  myAmInitialised(false),
134  myViewportChooser(nullptr),
135  myWindowCursorPositionX(getWidth() / 2),
136  myWindowCursorPositionY(getHeight() / 2),
137  myVisualizationChanger(nullptr),
138  myFrameDrawTime(0) {
139  setTarget(this);
140  enable();
141  flags |= FLAG_ENABLED;
142  myInEditMode = false;
143  // show the middle at the beginning
144  myChanger = new GUIDanielPerspectiveChanger(*this, *myGrid);
145  myVisualizationSettings = &gSchemeStorage.getDefault();
146  myVisualizationSettings->gaming = myApp->isGaming();
148 }
149 
150 
154  delete myPopup;
155  delete myChanger;
156  delete myViewportChooser;
157  delete myVisualizationChanger;
158  // cleanup decals
159  for (std::vector<GUISUMOAbstractView::Decal>::iterator it = myDecals.begin(); it != myDecals.end(); ++it) {
160  delete it->image;
161  }
162  for (auto i : myAdditionallyDrawn) {
163  i.first->removeActiveAddVisualisation(this, ~0); // remove all
164  }
165 }
166 
167 
168 bool
170  return myInEditMode;
171 }
172 
173 
176  return *myChanger;
177 }
178 
179 
180 void
182  if (!myUseToolTips) {
183  return;
184  }
185  update();
186 }
187 
188 
189 Position
192 }
193 
194 
195 Position
196 GUISUMOAbstractView::snapToActiveGrid(const Position& pos, bool snapXY) const {
197  Position result = pos;
199  if (snapXY) {
200  const double xRest = std::fmod(pos.x(), myVisualizationSettings->gridXSize) + (pos.x() < 0 ? myVisualizationSettings->gridXSize : 0);
201  const double yRest = std::fmod(pos.y(), myVisualizationSettings->gridYSize) + (pos.y() < 0 ? myVisualizationSettings->gridYSize : 0);
202  result.setx(pos.x() - xRest + (xRest < myVisualizationSettings->gridXSize * 0.5 ? 0 : myVisualizationSettings->gridXSize));
203  result.sety(pos.y() - yRest + (yRest < myVisualizationSettings->gridYSize * 0.5 ? 0 : myVisualizationSettings->gridYSize));
204  } else {
205  // snapZToActiveGrid uses grid Y Size
206  const double zRest = std::fmod(pos.z(), myVisualizationSettings->gridYSize) + (pos.z() < 0 ? myVisualizationSettings->gridYSize : 0);
207  result.setz(pos.z() - zRest + (zRest < myVisualizationSettings->gridYSize * 0.5 ? 0 : myVisualizationSettings->gridYSize));
208  }
209  }
210  return result;
211 }
212 
213 
214 Position
216  Boundary bound = myChanger->getViewport();
217  double xNet = bound.xmin() + bound.getWidth() * x / getWidth();
218  // cursor origin is in the top-left corner
219  double yNet = bound.ymin() + bound.getHeight() * (getHeight() - y) / getHeight();
220  // rotate around the viewport center
221  if (myChanger->getRotation() != 0) {
222  return Position(xNet, yNet).rotateAround2D(-DEG2RAD(myChanger->getRotation()), bound.getCenter());
223  } else {
224  return Position(xNet, yNet);
225  }
226 }
227 
228 
229 void
230 GUISUMOAbstractView::addDecals(const std::vector<Decal>& decals) {
231  myDecals.insert(myDecals.end(), decals.begin(), decals.end());
232 }
233 
234 
235 void
238  std::string text = "x:" + toString(pos.x()) + ", y:" + toString(pos.y());
239  myApp->getCartesianLabel().setText(text.c_str());
241  if (GeoConvHelper::getFinal().usingGeoProjection()) {
242  text = "lat:" + toString(pos.y(), gPrecisionGeo) + ", lon:" + toString(pos.x(), gPrecisionGeo);
243  } else {
244  text = "x:" + toString(pos.x()) + ", y:" + toString(pos.y());
245  }
246  myApp->getGeoLabel().setText(text.c_str());
247 }
248 
249 
250 int
251 GUISUMOAbstractView::doPaintGL(int /*mode*/, const Boundary& /*boundary*/) {
252  return 0;
253 }
254 
255 
256 void
258 }
259 
260 
261 Boundary
263  return myChanger->getViewport();
264 }
265 
266 
267 void
269  if (getWidth() == 0 || getHeight() == 0) {
270  return;
271  }
272  const long start = SysUtils::getCurrentMillis();
273 
275  centerTo(getTrackedID(), false);
276  }
277 
279  if (myUseToolTips) {
280  id = getObjectUnderCursor();
281  }
282 
283  // draw
284  glClearColor(
289  glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
290  glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
291 
293  glEnable(GL_DITHER);
294  } else {
295  glDisable(GL_DITHER);
296  }
297  glEnable(GL_BLEND);
298  glDisable(GL_LINE_SMOOTH);
299 
300  Boundary bound = applyGLTransform();
301  doPaintGL(GL_RENDER, bound);
304  displayLegends();
305  const long end = SysUtils::getCurrentMillis();
306  myFrameDrawTime = end - start;
308  drawFPS();
309  }
310  // check whether the select mode /tooltips)
311  // shall be computed, too
312  if (myUseToolTips && id != GUIGlObject::INVALID_ID) {
313  showToolTipFor(id);
314  }
315  swapBuffers();
316 }
317 
318 
319 GUIGlID
322 }
323 
324 
325 std::vector<GUIGlID>
328 }
329 
330 
331 std::vector<GUIGlObject*>
334 }
335 
336 
337 std::vector<GUIGlObject*>
340 }
341 
342 
343 GUIGlID
345  // calculate a boundary for the given position
346  Boundary positionBoundary;
347  positionBoundary.add(pos);
348  positionBoundary.grow(SENSITIVITY);
349  const std::vector<GUIGlID> ids = getObjectsInBoundary(positionBoundary, true);
350  // Interpret results
351  int idMax = 0;
352  double maxLayer = -std::numeric_limits<double>::max();
353  // iterate over obtained GUIGlIDs
354  for (const auto& i : ids) {
355  // obtain GUIGlObject
357  // check that GUIGlObject exist
358  if (o == nullptr) {
359  continue;
360  }
361  // check that GUIGlObject isn't the network
362  if (o->getGlID() == 0) {
363  continue;
364  }
365  //std::cout << "point selection hit " << o->getMicrosimID() << "\n";
366  GUIGlObjectType type = o->getType();
367  // avoid network
368  if (type != GLO_NETWORK) {
369  double layer = (double)type;
370  // determine an "abstract" layer for shapes
371  // this "layer" resembles the layer of the shape
372  // taking into account the stac of other objects
373  if (type == GLO_POI || type == GLO_POLYGON) {
374  layer = dynamic_cast<Shape*>(o)->getShapeLayer();
375  }
377  // do not select lanes in meso mode
378  continue;
379  }
380  // check whether the current object is above a previous one
381  if (layer > maxLayer) {
382  idMax = i;
383  maxLayer = layer;
384  }
385  }
386  // unblock object
388  }
389  return idMax;
390 }
391 
392 
393 std::vector<GUIGlID>
395  // declare result vector
396  std::vector<GUIGlID> result;
397  // calculate boundary
398  Boundary selection;
399  selection.add(pos);
400  selection.grow(radius);
401  // obtain GUIGlID of objects in boundary
402  const std::vector<GUIGlID> ids = getObjectsInBoundary(selection, true);
403  // iterate over obtained GUIGlIDs
404  for (const auto& i : ids) {
405  // obtain GUIGlObject
407  // check that GUIGlObject exist
408  if (o == nullptr) {
409  continue;
410  }
411  // check that GUIGlObject isn't the network
412  if (o->getGlID() == 0) {
413  continue;
414  }
415  //std::cout << "point selection hit " << o->getMicrosimID() << "\n";
416  GUIGlObjectType type = o->getType();
417  // avoid network
418  if (type != GLO_NETWORK) {
419  result.push_back(i);
420  }
421  // unblock object
423  }
424  return result;
425 }
426 
427 
428 std::vector<GUIGlObject*>
430  // declare result vector
431  std::vector<GUIGlObject*> result;
432  // calculate boundary
433  Boundary selection;
434  selection.add(pos);
435  selection.grow(radius);
436  // obtain GUIGlID of objects in boundary
437  const std::vector<GUIGlID> ids = getObjectsInBoundary(selection, true);
438  // iterate over obtained GUIGlIDs
439  for (const auto& i : ids) {
440  // obtain GUIGlObject
442  // check that GUIGlObject exist
443  if (o == nullptr) {
444  continue;
445  }
446  // check that GUIGlObject isn't the network
447  if (o->getGlID() == 0) {
448  continue;
449  }
450  result.push_back(o);
451  // unblock object
453  }
454  return result;
455 }
456 
457 
458 std::vector<GUIGlID>
460  const int NB_HITS_MAX = 1024 * 1024;
461  // Prepare the selection mode
462  static GUIGlID hits[NB_HITS_MAX];
463  static GLint nb_hits = 0;
464  glSelectBuffer(NB_HITS_MAX, hits);
465  glInitNames();
466 
468  Boundary oldViewPort = myChanger->getViewport(false); // backup the actual viewPort
469  myChanger->setViewport(bound);
470  bound = applyGLTransform(false);
471  // enable draw for selecting (to draw objects with less details)
472  if (singlePosition) {
474  } else {
476  }
477  int hits2 = doPaintGL(GL_SELECT, bound);
478  // reset flags
481  // Get the results
482  nb_hits = glRenderMode(GL_RENDER);
483  if (nb_hits == -1) {
484  myApp->setStatusBarText("Selection in boundary failed. Try to select fewer than " + toString(hits2) + " items");
485  }
486  std::vector<GUIGlID> result;
487  GLuint numNames;
488  GLuint* ptr = hits;
489  for (int i = 0; i < nb_hits; ++i) {
490  numNames = *ptr;
491  ptr += 3;
492  for (int j = 0; j < (int)numNames; j++) {
493  result.push_back(*ptr);
494  ptr++;
495  }
496  }
497  // switch viewport back to normal
498  myChanger->setViewport(oldViewPort);
499  return result;
500 }
501 
502 
503 void
505  if (id != 0) {
507  if (object != nullptr) {
509  pos.add(0, p2m(15));
510  std::string label = object->getFullName();
511  if (myVisualizationSettings->edgeValue.show(object) &&
512  (object->getType() == GLO_EDGE || object->getType() == GLO_LANE)) {
513  const int activeScheme = myVisualizationSettings->getLaneEdgeMode();
514  label += " (" + toString(object->getColorValue(*myVisualizationSettings, activeScheme)) + ")";
515  }
516  GLHelper::drawTextBox(label, pos, GLO_MAX - 1, p2m(20), RGBColor::BLACK, RGBColor(255, 179, 0, 255));
518  }
519  }
520 }
521 
522 
523 void
525  // obtain minimum grid
527  // Check if the distance is enought to draw grid
529  glEnable(GL_DEPTH_TEST);
530  glLineWidth(1);
531  // get multiplication values (2 is the marging)
532  const int multXmin = (int)(myChanger->getViewport().xmin() / myVisualizationSettings->gridXSize) - 2;
533  const int multYmin = (int)(myChanger->getViewport().ymin() / myVisualizationSettings->gridYSize) - 2;
534  const int multXmax = (int)(myChanger->getViewport().xmax() / myVisualizationSettings->gridXSize) + 2;
535  const int multYmax = (int)(myChanger->getViewport().ymax() / myVisualizationSettings->gridYSize) + 2;
536  // obtain references
537  const double xmin = myVisualizationSettings->gridXSize * multXmin;
538  const double ymin = myVisualizationSettings->gridYSize * multYmin;
539  const double xmax = myVisualizationSettings->gridXSize * multXmax;
540  const double ymax = myVisualizationSettings->gridYSize * multYmax;
541  double xp = xmin;
542  double yp = ymin;
543  // move drawing matrix
544  glTranslated(0, 0, .55);
545  glColor3d(0.5, 0.5, 0.5);
546  // draw horizontal lines
547  glBegin(GL_LINES);
548  while (yp <= ymax) {
549  glVertex2d(xmin, yp);
550  glVertex2d(xmax, yp);
552  }
553  // draw vertical lines
554  while (xp <= xmax) {
555  glVertex2d(xp, ymin);
556  glVertex2d(xp, ymax);
558  }
559  glEnd();
560  glTranslated(0, 0, -.55);
561  }
562 }
563 
564 
565 void
567  // compute the scale bar length
568  int length = 1;
569  const std::string text("10000000000");
570  int noDigits = 1;
571  int pixelSize = (int) m2p((double) length);
572  while (pixelSize <= 20) {
573  length *= 10;
574  noDigits++;
575  if (noDigits > (int)text.length()) {
576  return;
577  }
578  pixelSize = (int) m2p((double) length);
579  }
580  glLineWidth(1.0);
581 
582  glMatrixMode(GL_PROJECTION);
584  glLoadIdentity();
585  glMatrixMode(GL_MODELVIEW);
587  glLoadIdentity();
588 
589  // draw the scale bar
590  const double z = -1;
591  glDisable(GL_TEXTURE_2D);
592  glDisable(GL_ALPHA_TEST);
593  glDisable(GL_BLEND);
594  glEnable(GL_DEPTH_TEST);
596  glTranslated(0, 0, z);
597 
598  double len = (double) pixelSize / (double)(getWidth() - 1) * (double) 2.0;
599  glColor3d(0, 0, 0);
600  double o = double(15) / double(getHeight());
601  double o2 = o + o;
602  double oo = double(5) / double(getHeight());
603  glBegin(GL_LINES);
604  // vertical
605  glVertex2d(-.98, -1. + o);
606  glVertex2d(-.98 + len, -1. + o);
607  // tick at begin
608  glVertex2d(-.98, -1. + o);
609  glVertex2d(-.98, -1. + o2);
610  // tick at end
611  glVertex2d(-.98 + len, -1. + o);
612  glVertex2d(-.98 + len, -1. + o2);
613  glEnd();
615 
616  const double fontHeight = 0.1 * 300. / getHeight();
617  const double fontWidth = 0.1 * 300. / getWidth();
618  // draw 0
619  GLHelper::drawText("0", Position(-.99, -0.99 + o2 + oo), z, fontHeight, RGBColor::BLACK, 0, FONS_ALIGN_LEFT, fontWidth);
620 
621  // draw current scale
622  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);
623 
624  // restore matrices
625  glMatrixMode(GL_PROJECTION);
627  glMatrixMode(GL_MODELVIEW);
629 }
630 
631 void
634  displayLegend();
635  }
638  }
641  }
642 }
643 
644 void
646  // compute the scale bar length
647  glLineWidth(1.0);
648  glMatrixMode(GL_PROJECTION);
650  glLoadIdentity();
651  glMatrixMode(GL_MODELVIEW);
653  glLoadIdentity();
654 
655  const double z = -1;
656  glEnable(GL_DEPTH_TEST);
657  glEnable(GL_BLEND);
659  glTranslated(0, 0, z);
660 
661  const bool fixed = scheme.isFixed();
662  const int numColors = (int)scheme.getColors().size();
663 
664  // vertical
665  double right = 0.98;
666  double left = 0.95;
667  double textX = left - 0.01;
668  FONSalign textAlign = FONS_ALIGN_RIGHT;
669  const double top = -0.8;
670  const double bot = 0.8;
671  const double dy = (top - bot) / numColors;
672  const double bot2 = fixed ? bot : bot + dy / 2;
673  // legend placement
674  if (leftSide) {
675  right = -right;
676  left = -left;
677  std::swap(right, left);
678  textX = right + 0.01;
679  textAlign = FONS_ALIGN_LEFT;
680  }
681  // draw black boundary around legend colors
682  glColor3d(0, 0, 0);
683  glBegin(GL_LINES);
684  glVertex2d(right, top);
685  glVertex2d(right, bot2);
686  glVertex2d(left, bot2);
687  glVertex2d(left, top);
688  glVertex2d(right, top);
689  glVertex2d(left, top);
690  glVertex2d(right, bot2);
691  glVertex2d(left, bot2);
692  glEnd();
693 
694  const double fontHeight = 0.20 * 300. / getHeight();
695  const double fontWidth = 0.20 * 300. / getWidth();
696 
697  const int fadeSteps = fixed ? 1 : 10;
698  double colorStep = dy / fadeSteps;
699  for (int i = 0; i < numColors; i++) {
700  RGBColor col = scheme.getColors()[i];
701  const double topi = top - i * dy;
702  //const double boti = top - (i + 1) * dy;
703  //std::cout << " col=" << scheme.getColors()[i] << " i=" << i << " topi=" << topi << " boti=" << boti << "\n";
704  if (i + 1 < numColors) {
705  // fade
706  RGBColor col2 = scheme.getColors()[i + 1];
707  for (double j = 0.0; j < fadeSteps; j++) {
708  GLHelper::setColor(RGBColor::interpolate(col, col2, j / fadeSteps));
709  glBegin(GL_QUADS);
710  glVertex2d(left, topi - j * colorStep);
711  glVertex2d(right, topi - j * colorStep);
712  glVertex2d(right, topi - (j + 1) * colorStep);
713  glVertex2d(left, topi - (j + 1) * colorStep);
714  glEnd();
715  }
716  } else {
717  GLHelper::setColor(col);
718  glBegin(GL_QUADS);
719  glVertex2d(left, topi);
720  glVertex2d(right, topi);
721  glVertex2d(right, bot2);
722  glVertex2d(left, bot2);
723  glEnd();
724  }
725 
726  const double threshold = scheme.getThresholds()[i];
727  std::string name = scheme.getNames()[i];
728  std::string text = fixed || threshold == GUIVisualizationSettings::MISSING_DATA ? name : toString(threshold);
729 
730  const double bgShift = 0.0;
731  const double textShift = 0.02;
732 
734  glTranslated(0, 0, 0.1);
735  glBegin(GL_QUADS);
736  glVertex2d(left, topi + fontHeight * bgShift);
737  glVertex2d(left - fontWidth * text.size() / 2, topi + fontHeight * bgShift);
738  glVertex2d(left - fontWidth * text.size() / 2, topi + fontHeight * (1 + bgShift));
739  glVertex2d(left, topi + fontHeight * (1 + bgShift));
740  glEnd();
741  glTranslated(0, 0, -0.1);
742  GLHelper::drawText(text, Position(textX, topi + textShift), 0, fontHeight, RGBColor::BLACK, 0, textAlign, fontWidth);
743  }
745  // restore matrices
746  glMatrixMode(GL_PROJECTION);
748  glMatrixMode(GL_MODELVIEW);
750 }
751 
752 
753 double
755  return 1000.0 / MAX2((long)1, myFrameDrawTime);
756 }
757 
758 void
760  glMatrixMode(GL_PROJECTION);
762  glLoadIdentity();
763  glMatrixMode(GL_MODELVIEW);
765  glLoadIdentity();
766  const double fontHeight = 0.2 * 300. / getHeight();
767  const double fontWidth = 0.2 * 300. / getWidth();
768  GLHelper::drawText(toString((int)getFPS()) + " FPS", Position(0.82, 0.88), -1, fontHeight, RGBColor::RED, 0, FONS_ALIGN_LEFT, fontWidth);
769 
770  // restore matrices
771  glMatrixMode(GL_PROJECTION);
773  glMatrixMode(GL_MODELVIEW);
775 }
776 
777 
778 double
779 GUISUMOAbstractView::m2p(double meter) const {
780  return meter * getWidth() / myChanger->getViewport().getWidth();
781 }
782 
783 
784 double
785 GUISUMOAbstractView::p2m(double pixel) const {
786  return pixel * myChanger->getViewport().getWidth() / getWidth();
787 }
788 
789 
790 void
793 }
794 
795 
796 void
797 GUISUMOAbstractView::centerTo(GUIGlID id, bool applyZoom, double zoomDist) {
799  if (o != nullptr && dynamic_cast<GUIGlObject*>(o) != nullptr) {
800  if (applyZoom && zoomDist < 0) {
802  update(); // only update when centering onto an object once
803  } else {
804  // called during tracking. update is triggered somewhere else
805  myChanger->centerTo(o->getCenteringBoundary().getCenter(), zoomDist, applyZoom);
807  }
808  }
810 }
811 
812 
813 void
814 GUISUMOAbstractView::centerTo(const Position& pos, bool applyZoom, double zoomDist) {
815  // called during tracking. update is triggered somewhere else
816  myChanger->centerTo(pos, zoomDist, applyZoom);
818 }
819 
820 
821 void
823  myChanger->setViewport(bound);
824  update();
825 }
826 
827 /*
828 bool
829 GUISUMOAbstractView::allowRotation() const
830 {
831  return myParent->allowRotation();
832 }
833 */
834 
835 Position
838 }
839 
840 
841 void
845 }
846 
847 
848 FXbool
850  FXbool ret = FXGLCanvas::makeCurrent();
851  return ret;
852 }
853 
854 
855 long
856 GUISUMOAbstractView::onConfigure(FXObject*, FXSelector, void*) {
857  if (makeCurrent()) {
858  glViewport(0, 0, getWidth() - 1, getHeight() - 1);
859  glClearColor(
864  doInit();
865  myAmInitialised = true;
866  makeNonCurrent();
867  checkSnapshots();
868  }
869  return 1;
870 }
871 
872 
873 long
874 GUISUMOAbstractView::onPaint(FXObject*, FXSelector, void*) {
875  if (!isEnabled() || !myAmInitialised) {
876  return 1;
877  }
878  if (makeCurrent()) {
879  paintGL();
880  makeNonCurrent();
881  }
882  return 1;
883 }
884 
885 
886 const Position&
888  return myPopupPosition;
889 }
890 
891 void
893  if (myPopup != nullptr) {
894  delete myPopup;
895  myPopupPosition.set(0, 0);
896  myPopup = nullptr;
897  }
898 }
899 
900 
901 long
902 GUISUMOAbstractView::onLeftBtnPress(FXObject*, FXSelector, void* ptr) {
903  destroyPopup();
904  setFocus();
905  FXEvent* e = (FXEvent*) ptr;
906  // check whether the selection-mode is activated
907  if ((e->state & CONTROLMASK) != 0) {
908  // toggle selection of object under cursor
909  if (makeCurrent()) {
910  int id = getObjectUnderCursor();
911  if (id != 0) {
913  }
914  makeNonCurrent();
915  if (id != 0) {
916  // possibly, the selection-colouring is used,
917  // so we should update the screen again...
918  update();
919  }
920  }
921  }
922  if ((e->state & SHIFTMASK) != 0) {
923  // track vehicle or person under cursor
924  if (makeCurrent()) {
925  int id = getObjectUnderCursor();
926  if (id != 0) {
928  if (o != nullptr) {
929  if (o->getType() == GLO_VEHICLE || o->getType() == GLO_PERSON) {
930  startTrack(id);
931  } else if (o->getType() == GLO_REROUTER_EDGE) {
932  o->onLeftBtnPress(ptr);
933  update();
934  }
935  }
936  }
937  makeNonCurrent();
938  }
939  }
941  grab();
942  // Check there are double click
943  if (e->click_count == 2) {
944  handle(this, FXSEL(SEL_DOUBLECLICKED, 0), ptr);
945  }
946  return 1;
947 }
948 
949 
950 long
951 GUISUMOAbstractView::onLeftBtnRelease(FXObject*, FXSelector, void* ptr) {
952  destroyPopup();
954  if (myApp->isGaming()) {
956  }
957  ungrab();
958  return 1;
959 }
960 
961 
962 long
963 GUISUMOAbstractView::onMiddleBtnPress(FXObject*, FXSelector, void*) {
964  return 1;
965 }
966 
967 
968 long
969 GUISUMOAbstractView::onMiddleBtnRelease(FXObject*, FXSelector, void*) {
970  return 1;
971 }
972 
973 
974 long
975 GUISUMOAbstractView::onRightBtnPress(FXObject*, FXSelector, void* ptr) {
976  destroyPopup();
978  grab();
979  return 1;
980 }
981 
982 
983 long
984 GUISUMOAbstractView::onRightBtnRelease(FXObject* o, FXSelector sel, void* ptr) {
985  destroyPopup();
986  onMouseMove(o, sel, ptr);
987  if (!myChanger->onRightBtnRelease(ptr) && !myApp->isGaming()) {
989  }
990  if (myApp->isGaming()) {
992  }
993  ungrab();
994  return 1;
995 }
996 
997 
998 long
999 GUISUMOAbstractView::onDoubleClicked(FXObject*, FXSelector, void*) {
1000  return 1;
1001 }
1002 
1003 
1004 long
1005 GUISUMOAbstractView::onMouseWheel(FXObject*, FXSelector, void* ptr) {
1006  if (!myApp->isGaming()) {
1007  myChanger->onMouseWheel(ptr);
1008  // upddate viewport
1009  if (myViewportChooser != nullptr) {
1012  myChanger->getRotation());
1013  }
1015  }
1016  return 1;
1017 }
1018 
1019 
1020 long
1021 GUISUMOAbstractView::onMouseMove(FXObject*, FXSelector, void* ptr) {
1022  // if popup exist but isn't shown, destroy it first
1023  if (myPopup && (myPopup->shown() == false)) {
1024  destroyPopup();
1025  }
1026  if (myPopup == nullptr) {
1027  if (myViewportChooser == nullptr || !myViewportChooser->haveGrabbed()) {
1028  myChanger->onMouseMove(ptr);
1029  }
1030  if (myViewportChooser != nullptr) {
1033  myChanger->getRotation());
1034  }
1036  }
1037  return 1;
1038 }
1039 
1040 
1041 long
1042 GUISUMOAbstractView::onMouseLeft(FXObject*, FXSelector, void* /*data*/) {
1043  return 1;
1044 }
1045 
1046 
1047 void
1049  ungrab();
1050  if (!isEnabled() || !myAmInitialised) {
1051  return;
1052  }
1053  if (makeCurrent()) {
1054  // initialise the select mode
1055  int id = getObjectUnderCursor();
1056  GUIGlObject* o = nullptr;
1057  if (id != 0) {
1059  } else {
1061  }
1062  openObjectDialog(o);
1063  makeNonCurrent();
1064  }
1065 }
1066 
1067 void
1069  if (o != nullptr) {
1070  myPopup = o->getPopUpMenu(*myApp, *this);
1071  int x, y;
1072  FXuint b;
1073  myApp->getCursorPosition(x, y, b);
1074  int popX = x + myApp->getX();
1075  int popY = y + myApp->getY();
1076  myPopup->setX(popX);
1077  myPopup->setY(popY);
1078  myPopup->create();
1079  myPopup->show();
1080  // try to stay on screen unless click appears to come from a multi-screen setup
1081  const int rootWidth = getApp()->getRootWindow()->getWidth();
1082  const int rootHeight = getApp()->getRootWindow()->getHeight();
1083  if (popX <= rootWidth) {
1084  popX = MAX2(0, MIN2(popX, rootWidth - myPopup->getWidth() - 10));
1085  }
1086  if (popY <= rootHeight) {
1087  popY = MAX2(0, MIN2(popY, rootHeight - myPopup->getHeight() - 50));
1088  }
1089  myPopup->move(popX, popY);
1091  myChanger->onRightBtnRelease(nullptr);
1093  setFocus();
1094  }
1095 }
1096 
1097 
1098 long
1099 GUISUMOAbstractView::onKeyPress(FXObject* o, FXSelector sel, void* ptr) {
1100  if (myPopup != nullptr) {
1101  return myPopup->onKeyPress(o, sel, ptr);
1102  } else {
1103  FXEvent* e = (FXEvent*) ptr;
1104  if (e->state & CONTROLMASK) {
1105  if (e->code == FX::KEY_Page_Up) {
1108  update();
1109  return 1;
1110  } else if (e->code == FX::KEY_Page_Down) {
1113  update();
1114  return 1;
1115  }
1116  }
1117  FXGLCanvas::onKeyPress(o, sel, ptr);
1118  return myChanger->onKeyPress(ptr);
1119  }
1120 }
1121 
1122 
1123 long
1124 GUISUMOAbstractView::onKeyRelease(FXObject* o, FXSelector sel, void* ptr) {
1125  if (myPopup != nullptr) {
1126  return myPopup->onKeyRelease(o, sel, ptr);
1127  } else {
1128  FXGLCanvas::onKeyRelease(o, sel, ptr);
1129  return myChanger->onKeyRelease(ptr);
1130  }
1131 }
1132 
1133 
1134 // ------------ Dealing with snapshots
1135 void
1136 GUISUMOAbstractView::addSnapshot(SUMOTime time, const std::string& file, const int w, const int h) {
1137 #ifdef DEBUG_SNAPSHOT
1138  std::cout << "add snapshot time=" << time << " file=" << file << "\n";
1139 #endif
1140  FXMutexLock lock(mySnapshotsMutex);
1141  mySnapshots[time].push_back(std::make_tuple(file, w, h));
1142 }
1143 
1144 
1145 std::string
1146 GUISUMOAbstractView::makeSnapshot(const std::string& destFile, const int w, const int h) {
1147  if (w >= 0) {
1148  resize(w, h);
1149  repaint();
1150  }
1151  std::string errorMessage;
1152  FXString ext = FXPath::extension(destFile.c_str());
1153  const bool useGL2PS = ext == "ps" || ext == "eps" || ext == "pdf" || ext == "svg" || ext == "tex" || ext == "pgf";
1154 #ifdef HAVE_FFMPEG
1155  const bool useVideo = destFile == "" || ext == "h264" || ext == "hevc" || ext == "mp4";
1156 #endif
1157  for (int i = 0; i < 10 && !makeCurrent(); ++i) {
1159  }
1160  // draw
1161  glClearColor(
1166  glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
1167  glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
1168 
1170  glEnable(GL_DITHER);
1171  } else {
1172  glDisable(GL_DITHER);
1173  }
1174  glEnable(GL_BLEND);
1175  glDisable(GL_LINE_SMOOTH);
1176 
1177  applyGLTransform();
1178 
1179  if (useGL2PS) {
1180 #ifdef HAVE_GL2PS
1181  GLint format = GL2PS_PS;
1182  if (ext == "ps") {
1183  format = GL2PS_PS;
1184  } else if (ext == "eps") {
1185  format = GL2PS_EPS;
1186  } else if (ext == "pdf") {
1187  format = GL2PS_PDF;
1188  } else if (ext == "tex") {
1189  format = GL2PS_TEX;
1190  } else if (ext == "svg") {
1191  format = GL2PS_SVG;
1192  } else if (ext == "pgf") {
1193  format = GL2PS_PGF;
1194  } else {
1195  return "Could not save '" + destFile + "'.\n Unrecognized format '" + std::string(ext.text()) + "'.";
1196  }
1197  FILE* fp = fopen(destFile.c_str(), "wb");
1198  if (fp == 0) {
1199  return "Could not save '" + destFile + "'.\n Could not open file for writing";
1200  }
1202  GLint buffsize = 0, state = GL2PS_OVERFLOW;
1203  GLint viewport[4];
1204  glGetIntegerv(GL_VIEWPORT, viewport);
1205  while (state == GL2PS_OVERFLOW) {
1206  buffsize += 1024 * 1024;
1207  gl2psBeginPage(destFile.c_str(), "sumo-gui; https://sumo.dlr.de", viewport, format, GL2PS_SIMPLE_SORT,
1208  GL2PS_DRAW_BACKGROUND | GL2PS_USE_CURRENT_VIEWPORT,
1209  GL_RGBA, 0, NULL, 0, 0, 0, buffsize, fp, "out.eps");
1210  glMatrixMode(GL_MODELVIEW);
1212  glDisable(GL_TEXTURE_2D);
1213  glDisable(GL_ALPHA_TEST);
1214  glDisable(GL_BLEND);
1215  glEnable(GL_DEPTH_TEST);
1216  // draw decals (if not in grabbing mode)
1217 
1218  drawDecals();
1220  paintGLGrid();
1221  }
1222 
1223  glLineWidth(1);
1224  glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
1225  Boundary viewPort = myChanger->getViewport();
1226  const float minB[2] = { (float)viewPort.xmin(), (float)viewPort.ymin() };
1227  const float maxB[2] = { (float)viewPort.xmax(), (float)viewPort.ymax() };
1229  glEnable(GL_POLYGON_OFFSET_FILL);
1230  glEnable(GL_POLYGON_OFFSET_LINE);
1231  myGrid->Search(minB, maxB, *myVisualizationSettings);
1232 
1233  displayLegends();
1234  state = gl2psEndPage();
1235  glFinish();
1236  }
1237  GLHelper::setGL2PS(false);
1238  fclose(fp);
1239 #else
1240  return "Could not save '" + destFile + "', gl2ps was not enabled at compile time.";
1241 #endif
1242  } else {
1243  doPaintGL(GL_RENDER, myChanger->getViewport());
1244  displayLegends();
1245  swapBuffers();
1246  glFinish();
1247  FXColor* buf;
1248  FXMALLOC(&buf, FXColor, getWidth()*getHeight());
1249  // read from the back buffer
1250  glReadBuffer(GL_BACK);
1251  // Read the pixels
1252  glReadPixels(0, 0, getWidth(), getHeight(), GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid*)buf);
1253  makeNonCurrent();
1254  update();
1255  // mirror
1256  int mwidth = getWidth();
1257  int mheight = getHeight();
1258  FXColor* paa = buf;
1259  FXColor* pbb = buf + mwidth * (mheight - 1);
1260  do {
1261  FXColor* pa = paa;
1262  paa += mwidth;
1263  FXColor* pb = pbb;
1264  pbb -= mwidth;
1265  do {
1266  FXColor t = *pa;
1267  *pa++ = *pb;
1268  *pb++ = t;
1269  } while (pa < paa);
1270  } while (paa < pbb);
1271  try {
1272 #ifdef HAVE_FFMPEG
1273  if (useVideo) {
1274  try {
1275  saveFrame(destFile, buf);
1276  errorMessage = "video";
1277  } catch (std::runtime_error& err) {
1278  errorMessage = err.what();
1279  }
1280  } else
1281 #endif
1282  if (!MFXImageHelper::saveImage(destFile, getWidth(), getHeight(), buf)) {
1283  errorMessage = "Could not save '" + destFile + "'.";
1284  }
1285  } catch (InvalidArgument& e) {
1286  errorMessage = "Could not save '" + destFile + "'.\n" + e.what();
1287  }
1288  FXFREE(&buf);
1289  }
1290  return errorMessage;
1291 }
1292 
1293 
1294 void
1295 GUISUMOAbstractView::saveFrame(const std::string& destFile, FXColor* buf) {
1296  UNUSED_PARAMETER(destFile);
1297  UNUSED_PARAMETER(buf);
1298 }
1299 
1300 
1301 void
1303  const SUMOTime time = getCurrentTimeStep() - DELTA_T;
1304 #ifdef DEBUG_SNAPSHOT
1305  std::cout << "check snapshots time=" << time << " registeredTimes=" << mySnapshots.size() << "\n";
1306 #endif
1307  FXMutexLock lock(mySnapshotsMutex);
1308  const auto snapIt = mySnapshots.find(time);
1309  if (snapIt == mySnapshots.end()) {
1310  return;
1311  }
1312  std::vector<std::tuple<std::string, int, int> > files = snapIt->second;
1313  lock.unlock();
1314  // decouple map access and painting to avoid deadlock
1315  for (const auto& entry : files) {
1316 #ifdef DEBUG_SNAPSHOT
1317  std::cout << "make snapshot time=" << time << " file=" << file << "\n";
1318 #endif
1319  const std::string& error = makeSnapshot(std::get<0>(entry), std::get<1>(entry), std::get<2>(entry));
1320  if (error != "" && error != "video") {
1321  WRITE_WARNING(error);
1322  }
1323  }
1324  // synchronization with a waiting run thread
1325  lock.lock();
1326  mySnapshots.erase(time);
1327  mySnapshotCondition.signal();
1328 #ifdef DEBUG_SNAPSHOT
1329  std::cout << " files=" << toString(files) << " myApplicationSnapshots=" << joinToString(*myApplicationSnapshots, ",") << "\n";
1330 #endif
1331 }
1332 
1333 
1334 void
1336  FXMutexLock lock(mySnapshotsMutex);
1337  if (mySnapshots.count(snapshotTime) > 0) {
1339  }
1340 }
1341 
1342 
1343 SUMOTime
1345  return 0;
1346 }
1347 
1348 
1349 void
1351  if (myVisualizationChanger == nullptr) {
1355  &myDecals, &myDecalsLock);
1356  myVisualizationChanger->create();
1357  } else {
1359  }
1361 }
1362 
1363 
1366  if (myViewportChooser == nullptr) {
1367  const FXint minSize = 100;
1368  const FXint minTitlebarHeight = 20;
1369  int x = MAX2(0, MIN2(getApp()->reg().readIntEntry(
1370  "VIEWPORT_DIALOG_SETTINGS", "x", 150),
1371  getApp()->getRootWindow()->getWidth() - minSize));
1372  int y = MAX2(minTitlebarHeight, MIN2(getApp()->reg().readIntEntry(
1373  "VIEWPORT_DIALOG_SETTINGS", "y", 150),
1374  getApp()->getRootWindow()->getHeight() - minSize));
1375  myViewportChooser = new GUIDialog_EditViewport(this, "Edit Viewport", x, y);
1376  myViewportChooser->create();
1377  }
1380  myChanger->getRotation());
1381  return myViewportChooser;
1382 }
1383 
1384 
1385 void
1387  getViewportEditor(); // make sure it exists;
1391 }
1392 
1393 
1394 void
1395 GUISUMOAbstractView::setViewportFromToRot(const Position& lookFrom, const Position& /* lookAt */, double rotation) {
1396  myChanger->setViewportFrom(lookFrom.x(), lookFrom.y(), lookFrom.z());
1397  myChanger->setRotation(rotation);
1398  update();
1399 }
1400 
1401 
1402 void
1404  // look straight down
1407  myChanger->getRotation());
1408 }
1409 
1410 
1411 void
1413  myUseToolTips = val;
1414 }
1415 
1416 
1417 bool
1419  return true;
1420 }
1421 
1422 
1425  return *myVisualizationSettings;
1426 }
1427 
1428 
1429 void
1431  myViewportChooser = nullptr;
1432 }
1433 
1434 
1435 void
1437  myVisualizationChanger = nullptr;
1438 }
1439 
1440 
1441 double
1443  return myGrid->getWidth();
1444 }
1445 
1446 
1447 double
1449  return myGrid->getHeight();
1450 }
1451 
1452 
1453 void
1455 }
1456 
1457 
1458 void
1460 }
1461 
1462 
1463 GUIGlID
1465  return GUIGlObject::INVALID_ID;
1466 }
1467 
1468 
1469 void
1471 }
1472 
1473 void
1475 }
1476 
1477 
1478 FXComboBox*
1481 }
1482 
1483 
1484 FXImage*
1486 #ifdef HAVE_GDAL
1487  GDALAllRegister();
1488  GDALDataset* poDataset = (GDALDataset*)GDALOpen(d.filename.c_str(), GA_ReadOnly);
1489  if (poDataset == 0) {
1490  return 0;
1491  }
1492  const int xSize = poDataset->GetRasterXSize();
1493  const int ySize = poDataset->GetRasterYSize();
1494  // checking for geodata in the picture and try to adapt position and scale
1495  if (d.width <= 0.) {
1496  double adfGeoTransform[6];
1497  if (poDataset->GetGeoTransform(adfGeoTransform) == CE_None) {
1498  Position topLeft(adfGeoTransform[0], adfGeoTransform[3]);
1499  const double horizontalSize = xSize * adfGeoTransform[1];
1500  const double verticalSize = ySize * adfGeoTransform[5];
1501  Position bottomRight(topLeft.x() + horizontalSize, topLeft.y() + verticalSize);
1502  if (GeoConvHelper::getProcessing().x2cartesian(topLeft) && GeoConvHelper::getProcessing().x2cartesian(bottomRight)) {
1503  d.width = bottomRight.x() - topLeft.x();
1504  d.height = topLeft.y() - bottomRight.y();
1505  d.centerX = (topLeft.x() + bottomRight.x()) / 2;
1506  d.centerY = (topLeft.y() + bottomRight.y()) / 2;
1507  //WRITE_MESSAGE("proj: " + toString(poDataset->GetProjectionRef()) + " dim: " + toString(d.width) + "," + toString(d.height) + " center: " + toString(d.centerX) + "," + toString(d.centerY));
1508  } else {
1509  WRITE_WARNING("Could not convert coordinates in " + d.filename + ".");
1510  }
1511  }
1512  }
1513 #endif
1514  if (d.width <= 0.) {
1515  d.width = getGridWidth();
1516  d.height = getGridHeight();
1517  }
1518 
1519  // trying to read the picture
1520 #ifdef HAVE_GDAL
1521  const int picSize = xSize * ySize;
1522  FXColor* result;
1523  if (!FXMALLOC(&result, FXColor, picSize)) {
1524  WRITE_WARNING("Could not allocate memory for " + d.filename + ".");
1525  return 0;
1526  }
1527  for (int j = 0; j < picSize; j++) {
1528  result[j] = FXRGB(0, 0, 0);
1529  }
1530  bool valid = true;
1531  for (int i = 1; i <= poDataset->GetRasterCount(); i++) {
1532  GDALRasterBand* poBand = poDataset->GetRasterBand(i);
1533  int shift = -1;
1534  if (poBand->GetColorInterpretation() == GCI_RedBand) {
1535  shift = 0;
1536  } else if (poBand->GetColorInterpretation() == GCI_GreenBand) {
1537  shift = 1;
1538  } else if (poBand->GetColorInterpretation() == GCI_BlueBand) {
1539  shift = 2;
1540  } else if (poBand->GetColorInterpretation() == GCI_AlphaBand) {
1541  shift = 3;
1542  } else {
1543  valid = false;
1544  break;
1545  }
1546  assert(xSize == poBand->GetXSize() && ySize == poBand->GetYSize());
1547  if (poBand->RasterIO(GF_Read, 0, 0, xSize, ySize, ((unsigned char*)result) + shift, xSize, ySize, GDT_Byte, 4, 4 * xSize) == CE_Failure) {
1548  valid = false;
1549  break;
1550  }
1551  }
1552  GDALClose(poDataset);
1553  if (valid) {
1554  return new FXImage(getApp(), result, IMAGE_OWNED | IMAGE_KEEP | IMAGE_SHMI | IMAGE_SHMP, xSize, ySize);
1555  }
1556  FXFREE(&result);
1557 #endif
1558  return nullptr;
1559 }
1560 
1561 
1562 void
1564  GLHelper::pushName(0);
1565  myDecalsLock.lock();
1566  for (std::vector<GUISUMOAbstractView::Decal>::iterator l = myDecals.begin(); l != myDecals.end(); ++l) {
1568  if (d.skip2D) {
1569  continue;
1570  }
1571  if (!d.initialised) {
1572  try {
1573  FXImage* img = checkGDALImage(d);
1574  if (img == nullptr) {
1575  img = MFXImageHelper::loadImage(getApp(), d.filename);
1576  }
1578  d.glID = GUITexturesHelper::add(img);
1579  d.initialised = true;
1580  d.image = img;
1581  } catch (InvalidArgument& e) {
1582  WRITE_ERROR("Could not load '" + d.filename + "'.\n" + e.what());
1583  d.skip2D = true;
1584  }
1585  }
1587  if (d.screenRelative) {
1588  Position center = screenPos2NetPos((int)d.centerX, (int)d.centerY);
1589  glTranslated(center.x(), center.y(), d.layer);
1590  } else {
1591  glTranslated(d.centerX, d.centerY, d.layer);
1592  }
1593  glRotated(d.rot, 0, 0, 1);
1594  glColor3d(1, 1, 1);
1595  double halfWidth = d.width / 2.;
1596  double halfHeight = d.height / 2.;
1597  if (d.screenRelative) {
1598  halfWidth = p2m(halfWidth);
1599  halfHeight = p2m(halfHeight);
1600  }
1601  GUITexturesHelper::drawTexturedBox(d.glID, -halfWidth, -halfHeight, halfWidth, halfHeight);
1603  }
1604  myDecalsLock.unlock();
1606 }
1607 
1608 
1609 // ------------ Additional visualisations
1610 bool
1612  if (myAdditionallyDrawn.find(which) == myAdditionallyDrawn.end()) {
1613  myAdditionallyDrawn[which] = 1;
1614  } else {
1615  myAdditionallyDrawn[which] = myAdditionallyDrawn[which] + 1;
1616  }
1617  update();
1618  return true;
1619 }
1620 
1621 
1622 bool
1624  if (myAdditionallyDrawn.find(which) == myAdditionallyDrawn.end()) {
1625  return false;
1626  }
1627  int cnt = myAdditionallyDrawn[which];
1628  if (cnt == 1) {
1629  myAdditionallyDrawn.erase(which);
1630  } else {
1631  myAdditionallyDrawn[which] = myAdditionallyDrawn[which] - 1;
1632  }
1633  update();
1634  return true;
1635 }
1636 
1637 
1638 bool
1640  if (myAdditionallyDrawn.find(which) == myAdditionallyDrawn.end()) {
1641  return false;
1642  } else {
1643  return true;
1644  }
1645 }
1646 
1647 
1648 Boundary
1650  Boundary bound = myChanger->getViewport(fixRatio);
1651  glMatrixMode(GL_PROJECTION);
1652  glLoadIdentity();
1653  // as a rough rule, each GLObject is drawn at z = -GUIGlObjectType
1654  // thus, objects with a higher value will be closer (drawn on top)
1655  // // @todo last param should be 0 after modifying all glDraw methods
1656  glOrtho(0, getWidth(), 0, getHeight(), -GLO_MAX - 1, GLO_MAX + 1);
1657  glMatrixMode(GL_MODELVIEW);
1658  glLoadIdentity();
1659  double scaleX = (double)getWidth() / bound.getWidth();
1660  double scaleY = (double)getHeight() / bound.getHeight();
1661  glScaled(scaleX, scaleY, 1);
1662  glTranslated(-bound.xmin(), -bound.ymin(), 0);
1663  // rotate around the center of the screen
1664  //double angle = -90;
1665  if (myChanger->getRotation() != 0) {
1666  glTranslated(bound.getCenter().x(), bound.getCenter().y(), 0);
1667  glRotated(myChanger->getRotation(), 0, 0, 1);
1668  glTranslated(-bound.getCenter().x(), -bound.getCenter().y(), 0);
1669  Boundary rotBound;
1670  double rad = -DEG2RAD(myChanger->getRotation());
1671  rotBound.add(Position(bound.xmin(), bound.ymin()).rotateAround2D(rad, bound.getCenter()));
1672  rotBound.add(Position(bound.xmin(), bound.ymax()).rotateAround2D(rad, bound.getCenter()));
1673  rotBound.add(Position(bound.xmax(), bound.ymin()).rotateAround2D(rad, bound.getCenter()));
1674  rotBound.add(Position(bound.xmax(), bound.ymax()).rotateAround2D(rad, bound.getCenter()));
1675  bound = rotBound;
1676  }
1678  return bound;
1679 }
1680 
1681 
1682 double
1684  return myApp->getDelay();
1685 }
1686 
1687 
1688 void
1690  myApp->setDelay(delay);
1691 }
1692 
1693 
1694 void
1695 GUISUMOAbstractView::setBreakpoints(const std::vector<SUMOTime>& breakpoints) {
1696  myApp->setBreakpoints(breakpoints);
1697 }
1698 
1699 
1701  filename(),
1702  centerX(0),
1703  centerY(0),
1704  centerZ(0),
1705  width(0),
1706  height(0),
1707  altitude(0),
1708  rot(0),
1709  tilt(0),
1710  roll(0),
1711  layer(0),
1712  initialised(false),
1713  skip2D(false),
1714  screenRelative(false),
1715  glID(-1),
1716  image(nullptr) {
1717 }
1718 
1719 
1720 /****************************************************************************/
@ MID_GLCANVAS
GLCanvas - ID.
Definition: GUIAppEnum.h:390
GUICompleteSchemeStorage gSchemeStorage
unsigned int GUIGlID
Definition: GUIGlObject.h:40
GUIGlObjectType
@ GLO_REROUTER_EDGE
a Rerouter over edge
@ GLO_MAX
empty max
@ GLO_LANE
a lane
@ GLO_EDGE
an edge
@ GLO_VEHICLE
a vehicle
@ GLO_PERSON
a person
@ GLO_NETWORK
The network - empty.
@ GLO_POI
a poi
@ GLO_POLYGON
a polygon
GUISelectedStorage gSelected
A global holder of selected objects.
FXDEFMAP(GUISUMOAbstractView) GUISUMOAbstractViewMap[]
#define DEG2RAD(x)
Definition: GeomHelper.h:35
#define WRITE_ERROR(msg)
Definition: MsgHandler.h:288
#define WRITE_WARNING(msg)
Definition: MsgHandler.h:280
SUMOTime DELTA_T
Definition: SUMOTime.cpp:37
long long int SUMOTime
Definition: SUMOTime.h:32
int gPrecisionGeo
Definition: StdDefs.cpp:26
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:74
T MAX2(T a, T b)
Definition: StdDefs.h:80
std::string joinToString(const std::vector< T > &v, const T_BETWEEN &between, std::streamsize accuracy=gPrecision)
Definition: ToString.h:269
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition: ToString.h:46
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
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
double ymax() const
Returns maximum y-coordinate.
Definition: Boundary.cpp:135
double xmax() const
Returns maximum x-coordinate.
Definition: Boundary.cpp:123
static void sleep(long ms)
static void drawTextBox(const std::string &text, const Position &pos, const double layer, const double size, const RGBColor &txtColor=RGBColor::BLACK, const RGBColor &bgColor=RGBColor::WHITE, const RGBColor &borderColor=RGBColor::BLACK, const double angle=0, const double relBorder=0.05, const double relMargin=0.5, const int align=0)
draw Text box with given parameters
Definition: GLHelper.cpp:657
static void setColor(const RGBColor &c)
Sets the gl-color to this value.
Definition: GLHelper.cpp:507
static void pushName(unsigned int name)
push Name
Definition: GLHelper.cpp:132
static void checkCounterMatrix()
check counter matrix
Definition: GLHelper.cpp:150
static void popMatrix()
pop matrix
Definition: GLHelper.cpp:123
static void checkCounterName()
check counter name
Definition: GLHelper.cpp:160
static void popName()
pop Name
Definition: GLHelper.cpp:141
static void pushMatrix()
push matrix
Definition: GLHelper.cpp:114
static void setGL2PS(bool active=true)
set GL2PS
Definition: GLHelper.cpp:531
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:609
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.
void setDefault(const std::string &name)
Makes the scheme with the given name the default.
void setViewport(GUISUMOAbstractView *view)
Sets the default viewport.
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)
FXComboBox * getColoringSchemesCombo()
return combobox with the current coloring schemes (standard, fastest standard, real world....
virtual double getColorValue(const GUIVisualizationSettings &, int) const
Definition: GUIGlObject.h:152
static const GUIGlID INVALID_ID
Definition: GUIGlObject.h:67
virtual Boundary getCenteringBoundary() const =0
virtual void onLeftBtnPress(void *)
notify object about left click
Definition: GUIGlObject.h:167
GUIGlObjectType getType() const
Returns the type of the object as coded in GUIGlObjectType.
virtual GUIGLObjectPopupMenu * getPopUpMenu(GUIMainWindow &app, GUISUMOAbstractView &parent)=0
Returns an own popup-menu.
GUIGlID getGlID() const
Returns the numerical id of the object.
void unblockObject(GUIGlID id)
Marks an object as unblocked.
GUIGlObject * getNetObject() const
Returns the network object.
static GUIGlObjectStorage gIDStorage
A single static instance of this class.
GUIGlObject * getObjectBlocking(GUIGlID id)
Returns the object from the container locking it.
FXLabel & getCartesianLabel()
get cartesian label
virtual double getDelay() const
Returns the delay (should be overwritten by subclasses if applicable)
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.
virtual void setStatusBarText(const std::string &)
get status bar text (can be implemented in children)
Definition: GUIMainWindow.h:99
virtual void setDelay(double)
Sets the delay of the parent application.
FXLabel & getGeoLabel()
get geo label
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 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 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::vector< double > & getThresholds() const
const std::vector< T > & getColors() const
const std::vector< std::string > & getNames() const
void paintGLGrid()
paints a grid
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::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 *)
FXMutex myDecalsLock
The mutex to use before accessing the decals list in order to avoid thread conflicts.
void displayLegend()
Draws a line with ticks, and the length information.
std::vector< GUIGlObject * > getGUIGlObjectsUnderCursor()
returns the GUIGlObject under the cursor using GL_SELECT (including overlapped objects)
long myFrameDrawTime
counter for measuring rendering time
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.
virtual void saveFrame(const std::string &destFile, FXColor *buf)
Adds a frame to a video snapshot which will be initialized if neccessary.
virtual void recenterView()
recenters the view
virtual SUMOTime getCurrentTimeStep() const
get the current simulation time
GUIDialog_ViewSettings * myVisualizationChanger
Visualization changer.
std::vector< GUIGlID > getObjectsInBoundary(Boundary bound, bool singlePosition)
returns the ids of all objects in the given boundary
FXbool makeCurrent()
A reimplementation due to some internal reasons.
int myMouseHotspotX
Offset to the mouse-hotspot from the mouse position.
bool isInEditMode()
returns true, if the edit button was pressed
void updatePositionInformation() const
update position information
virtual long onMiddleBtnRelease(FXObject *, FXSelector, void *)
virtual long onMouseMove(FXObject *, FXSelector, void *)
GUIDialog_EditViewport * myViewportChooser
viewport chooser
GUIVisualizationSettings & getVisualisationSettings() const
get visualization settings
bool isAdditionalGLVisualisationEnabled(GUIGlObject *const which) const
Check if an object is added in the additional GL visualitation.
FXCondition mySnapshotCondition
the semaphore when waiting for snapshots to finish
Position myPopupPosition
The current popup-menu position.
virtual void doInit()
doInit
virtual int doPaintGL(int, const Boundary &)
paint GL
virtual void showViewportEditor()
show viewport editor
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
void showToolTips(bool val)
show tool tips
void drawFPS()
Draws frames-per-second indicator.
virtual long onMouseWheel(FXObject *, FXSelector, void *)
double getGridWidth() const
get grid width
bool removeAdditionalGLVisualisation(GUIGlObject *const which)
Removes an object from the list of objects that show additional things.
double getDelay() const
Returns the delay of the parent application.
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 *)
bool myUseToolTips
use tool tips
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
const Position & getPopupPosition() const
get position of current popup
double m2p(double meter) const
meter-to-pixels conversion method
virtual void onGamingClick(Position)
on gaming click
bool myInEditMode
Information whether too-tip informations shall be generated.
GUIVisualizationSettings * myVisualizationSettings
visualization settings
void destroyPopup()
destoys the popup
Position getWindowCursorPosition() const
Returns the information whether rotation is allowd.
virtual long onKeyPress(FXObject *o, FXSelector sel, void *data)
keyboard functions
virtual long onMiddleBtnPress(FXObject *, FXSelector, void *)
void paintGL()
performs the painting of the simulation
virtual void stopTrack()
stop track
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)
virtual long onKeyRelease(FXObject *o, FXSelector sel, void *data)
void showToolTipFor(const GUIGlID id)
invokes the tooltip for the given object
virtual void onGamingRightClick(Position)
virtual void openObjectDialogAtCursor()
open object dialog at the cursor position
void setWindowCursorPosition(FXint x, FXint y)
Returns the gl-id of the object under the given coordinates.
double getFPS() const
retrieve FPS
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....
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 *)
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.
FXComboBox * getColoringSchemesCombo()
get coloring schemes combo
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
GUIGlChildWindow * myParent
The parent window.
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 openObjectDialog(GUIGlObject *o)
open object dialog for the given object
void remove(GUIDialog_EditViewport *)
remove viewport
virtual GUIGlID getTrackedID() const
get tracked id
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.
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
std::string name
The name of this setting.
bool drawForPositionSelection
whether drawing is performed for the purpose of selecting objects with a single click
bool gaming
whether the application is in gaming mode or not
GUIVisualizationTextSettings edgeValue
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.
static bool UseMesoSim
this should be set at the same time as MSGlobals::gUseMesoSim
int getLaneEdgeMode() const
Returns the number of the active lane (edge) coloring schme.
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.
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...
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)
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:293
double x() const
Returns the x-position.
Definition: Position.h:55
void add(const Position &pos)
Adds the given position to this one.
Definition: Position.h:125
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:352
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
A 2D- or 3D-Shape.
Definition: Shape.h:37
static long getCurrentMillis()
Returns the current time in milliseconds.
Definition: SysUtils.cpp:39
FONSalign
Definition: fontstash.h:40
@ FONS_ALIGN_LEFT
Definition: fontstash.h:42
@ FONS_ALIGN_RIGHT
Definition: fontstash.h:44
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)
bool skip2D
Whether this image should be skipped in 2D-views.
double width
The width of the image (net coordinates in x-direction, in m)
bool initialised
Whether this image was initialised (inserted as a texture)
FXImage * image
The image pointer for later cleanup.
double rot
The rotation of the image in the ground plane (in degrees)
double layer
The layer of the image.
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.
int glID
whether the decal shall be drawn in screen coordinates, rather than network coordinates
bool screenRelative
Whether this image should be skipped in 2D-views.
double getExaggeration(const GUIVisualizationSettings &s, const GUIGlObject *o, double factor=20) const
return the drawing size including exaggeration and constantSize values
bool show(const GUIGlObject *o) const
whether to show the text