SUMO - Simulation of Urban MObility
GUISUMOAbstractView.cpp
Go to the documentation of this file.
1 /****************************************************************************/
11 // The base class for a view
12 /****************************************************************************/
13 // SUMO, Simulation of Urban MObility; see http://sumo.dlr.de/
14 // Copyright (C) 2001-2016 DLR (http://www.dlr.de/) and contributors
15 /****************************************************************************/
16 //
17 // This file is part of SUMO.
18 // SUMO is free software: you can redistribute it and/or modify
19 // it under the terms of the GNU General Public License as published by
20 // the Free Software Foundation, either version 3 of the License, or
21 // (at your option) any later version.
22 //
23 /****************************************************************************/
24 
25 
26 // ===========================================================================
27 // included modules
28 // ===========================================================================
29 #ifdef _MSC_VER
30 #include <windows_config.h>
31 #else
32 #include <config.h>
33 #endif
34 
35 #include <iostream>
36 #include <utility>
37 #include <cmath>
38 #include <cassert>
39 #include <limits>
40 #include <fxkeys.h>
42 #include <gl2ps.h>
46 #include <utils/common/RGBColor.h>
47 #include <utils/common/ToString.h>
54 #include <utils/gui/div/GLHelper.h>
64 
65 #include "GUISUMOAbstractView.h"
66 #include "GUIMainWindow.h"
67 #include "GUIGlChildWindow.h"
69 #include "GUIDialog_EditViewport.h"
70 
71 #ifdef HAVE_GDAL
72 #include <gdal_priv.h>
73 #endif
74 
75 #ifdef CHECK_MEMORY_LEAKS
76 #include <foreign/nvwa/debug_new.h>
77 #endif // CHECK_MEMORY_LEAKS
78 
79 
80 // ===========================================================================
81 // member method definitions
82 // ===========================================================================
83 /* -------------------------------------------------------------------------
84  * GUISUMOAbstractView - FOX callback mapping
85  * ----------------------------------------------------------------------- */
86 FXDEFMAP(GUISUMOAbstractView) GUISUMOAbstractViewMap[] = {
87  FXMAPFUNC(SEL_CONFIGURE, 0, GUISUMOAbstractView::onConfigure),
88  FXMAPFUNC(SEL_PAINT, 0, GUISUMOAbstractView::onPaint),
89  FXMAPFUNC(SEL_LEFTBUTTONPRESS, 0, GUISUMOAbstractView::onLeftBtnPress),
90  FXMAPFUNC(SEL_LEFTBUTTONRELEASE, 0, GUISUMOAbstractView::onLeftBtnRelease),
91  FXMAPFUNC(SEL_MIDDLEBUTTONPRESS, 0, GUISUMOAbstractView::onMiddleBtnPress),
92  FXMAPFUNC(SEL_MIDDLEBUTTONRELEASE, 0, GUISUMOAbstractView::onMiddleBtnRelease),
93  FXMAPFUNC(SEL_RIGHTBUTTONPRESS, 0, GUISUMOAbstractView::onRightBtnPress),
94  FXMAPFUNC(SEL_RIGHTBUTTONRELEASE, 0, GUISUMOAbstractView::onRightBtnRelease),
95  FXMAPFUNC(SEL_MOUSEWHEEL, 0, GUISUMOAbstractView::onMouseWheel),
96  FXMAPFUNC(SEL_MOTION, 0, GUISUMOAbstractView::onMouseMove),
97  FXMAPFUNC(SEL_LEAVE, 0, GUISUMOAbstractView::onMouseLeft),
98  FXMAPFUNC(SEL_KEYPRESS, 0, GUISUMOAbstractView::onKeyPress),
99  FXMAPFUNC(SEL_KEYRELEASE, 0, GUISUMOAbstractView::onKeyRelease),
100 
101 };
102 
103 
104 FXIMPLEMENT_ABSTRACT(GUISUMOAbstractView, FXGLCanvas, GUISUMOAbstractViewMap, ARRAYNUMBER(GUISUMOAbstractViewMap))
105 
106 
107 /* -------------------------------------------------------------------------
108  * GUISUMOAbstractView - methods
109  * ----------------------------------------------------------------------- */
111  GUIMainWindow& app,
112  GUIGlChildWindow* parent,
113  const SUMORTree& grid,
114  FXGLVisual* glVis, FXGLCanvas* share)
115  : FXGLCanvas(p, glVis, share, p, MID_GLCANVAS,
116  LAYOUT_SIDE_TOP | LAYOUT_FILL_X | LAYOUT_FILL_Y, 0, 0, 0, 0),
117  myApp(&app),
118  myParent(parent),
119  myGrid(&((SUMORTree&)grid)),
120  myChanger(0),
121  myMouseHotspotX(app.getDefaultCursor()->getHotX()),
122  myMouseHotspotY(app.getDefaultCursor()->getHotY()),
123  myPopup(0),
124  myUseToolTips(false),
125  myAmInitialised(false),
126  myViewportChooser(0),
127  myWindowCursorPositionX(getWidth() / 2),
128  myWindowCursorPositionY(getHeight() / 2),
129  myVisualizationChanger(0) {
130  setTarget(this);
131  enable();
132  flags |= FLAG_ENABLED;
133  myInEditMode = false;
134  // show the middle at the beginning
135  myChanger = new GUIDanielPerspectiveChanger(*this, *myGrid);
136  myVisualizationSettings = &gSchemeStorage.getDefault();
137  myVisualizationSettings->gaming = myApp->isGaming();
139 }
140 
141 
145  delete myPopup;
146  delete myChanger;
147  delete myViewportChooser;
148  delete myVisualizationChanger;
149  // cleanup decals
150  for (std::vector<GUISUMOAbstractView::Decal>::iterator it = myDecals.begin(); it != myDecals.end(); ++it) {
151  delete it->image;
152  }
153 }
154 
155 
156 bool
158  return myInEditMode;
159 }
160 
161 
162 void
164  if (!myUseToolTips) {
165  return;
166  }
167  update();
168 }
169 
170 
171 Position
173  Boundary bound = myChanger->getViewport();
174  SUMOReal x = bound.xmin() + bound.getWidth() * myWindowCursorPositionX / getWidth();
175  // cursor origin is in the top-left corner
176  SUMOReal y = bound.ymin() + bound.getHeight() * (getHeight() - myWindowCursorPositionY) / getHeight();
177  return Position(x, y);
178 }
179 
180 
181 void
184  std::string text = "x:" + toString(pos.x()) + ", y:" + toString(pos.y());
185  myApp->getCartesianLabel().setText(text.c_str());
187  if (GeoConvHelper::getFinal().usingGeoProjection()) {
188  text = "lat:" + toString(pos.y(), GEO_OUTPUT_ACCURACY) + ", lon:" + toString(pos.x(), GEO_OUTPUT_ACCURACY);
189  } else {
190  text = "x:" + toString(pos.x()) + ", y:" + toString(pos.y());
191  }
192  myApp->getGeoLabel().setText(text.c_str());
193 }
194 
195 
196 Boundary
198  return myChanger->getViewport();
199 }
200 
201 void
203  if (getWidth() == 0 || getHeight() == 0) {
204  return;
205  }
206 
207  if (getTrackedID() > 0) {
208  centerTo(getTrackedID(), false);
209  }
210 
211  unsigned int id = 0;
212  if (myUseToolTips) {
213  id = getObjectUnderCursor();
214  }
215 
216  // draw
217  glClearColor(
222  glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
223  glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
224 
226  glEnable(GL_DITHER);
227  } else {
228  glDisable(GL_DITHER);
229  }
231  glEnable(GL_BLEND);
232  glEnable(GL_POLYGON_SMOOTH);
233  glEnable(GL_LINE_SMOOTH);
234  } else {
235  glDisable(GL_BLEND);
236  glDisable(GL_POLYGON_SMOOTH);
237  glDisable(GL_LINE_SMOOTH);
238  }
239 
241  doPaintGL(GL_RENDER, myChanger->getViewport());
243  displayLegend();
244  }
245  // check whether the select mode /tooltips)
246  // shall be computed, too
247  if (myUseToolTips && id != 0) {
248  showToolTipFor(id);
249  }
250  swapBuffers();
251 }
252 
253 
254 GUIGlID
257 }
258 
259 
260 GUIGlID
262  const SUMOReal SENSITIVITY = 0.1; // meters
263  Boundary selection;
264  selection.add(pos);
265  selection.grow(SENSITIVITY);
266  const std::vector<GUIGlID> ids = getObjectsInBoundary(selection);
267  // Interpret results
268  unsigned int idMax = 0;
270  for (std::vector<GUIGlID>::const_iterator it = ids.begin(); it != ids.end(); it++) {
271  GUIGlID id = *it;
273  if (o == 0) {
274  continue;
275  }
276  if (o->getGlID() == 0) {
277  continue;
278  }
279  //std::cout << "point selection hit " << o->getMicrosimID() << "\n";
280  GUIGlObjectType type = o->getType();
281  if (type != 0) {
282  SUMOReal layer = (SUMOReal)type;
283  // determine an "abstract" layer for shapes
284  // this "layer" resembles the layer of the shape
285  // taking into account the stac of other objects
286  if (type == GLO_POI || type == GLO_POLYGON) {
287  layer = dynamic_cast<Shape*>(o)->getLayer();
288  }
290  // do not select lanes in meso mode
291  continue;
292  }
293  // check whether the current object is above a previous one
294  if (layer > maxLayer) {
295  idMax = id;
296  maxLayer = layer;
297  }
298  }
300  }
301  return idMax;
302 }
303 
304 
305 std::vector<GUIGlID>
307  Boundary selection;
308  selection.add(pos);
309  selection.grow(radius);
310  const std::vector<GUIGlID> ids = getObjectsInBoundary(selection);
311  std::vector<GUIGlID> result;
312  // Interpret results
313  for (std::vector<GUIGlID>::const_iterator it = ids.begin(); it != ids.end(); it++) {
314  GUIGlID id = *it;
316  if (o == 0) {
317  continue;
318  }
319  if (o->getGlID() == 0) {
320  continue;
321  }
322  //std::cout << "point selection hit " << o->getMicrosimID() << "\n";
323  GUIGlObjectType type = o->getType();
324  if (type != 0) {
325  result.push_back(id);
326  }
328  }
329  return result;
330 }
331 
332 
333 std::vector<GUIGlID>
335  const int NB_HITS_MAX = 1024 * 1024;
336  // Prepare the selection mode
337  static GUIGlID hits[NB_HITS_MAX];
338  static GLint nb_hits = 0;
339  glSelectBuffer(NB_HITS_MAX, hits);
340  glInitNames();
341 
342  Boundary oldViewPort = myChanger->getViewport(false); // backup the actual viewPort
343  myChanger->setViewport(bound);
344  applyGLTransform(false);
345 
346  // paint in select mode
348  int hits2 = doPaintGL(GL_SELECT, bound);
350  // Get the results
351  nb_hits = glRenderMode(GL_RENDER);
352  if (nb_hits == -1) {
353  myApp->setStatusBarText("Selection in boundary failed. Try to select fewer than " + toString(hits2) + " items");
354  }
355  std::vector<GUIGlID> result;
356  GLuint numNames;
357  GLuint* ptr = hits;
358  for (int i = 0; i < nb_hits; ++i) {
359  numNames = *ptr;
360  ptr += 3;
361  for (int j = 0; j < (int)numNames; j++) {
362  result.push_back(*ptr);
363  ptr++;
364  }
365  }
366  // switch viewport back to normal
367  myChanger->setViewport(oldViewPort);
368  return result;
369 }
370 
371 
372 void
374  if (id != 0) {
376  if (object != 0) {
378  pos.add(0, p2m(15));
379  GLHelper::drawTextBox(object->getFullName(), pos, GLO_MAX - 1, p2m(20), RGBColor::BLACK, RGBColor(255, 179, 0, 255));
381  }
382  }
383 }
384 
385 
386 void
388  glEnable(GL_DEPTH_TEST);
389  glLineWidth(1);
390 
391  SUMOReal xmin = myGrid->xmin();
392  SUMOReal ymin = myGrid->ymin();
393  SUMOReal ypos = ymin;
394  SUMOReal xpos = xmin;
395  SUMOReal xend = myGrid->xmax();
396  SUMOReal yend = myGrid->ymax();
397 
398  glTranslated(0, 0, .55);
399  glColor3d(0.5, 0.5, 0.5);
400  // draw horizontal lines
401  glBegin(GL_LINES);
402  for (; ypos < yend;) {
403  glVertex2d(xmin, ypos);
404  glVertex2d(xend, ypos);
406  }
407  // draw vertical lines
408  for (; xpos < xend;) {
409  glVertex2d(xpos, ymin);
410  glVertex2d(xpos, yend);
412  }
413  glEnd();
414  glTranslated(0, 0, -.55);
415 }
416 
417 
418 void
420  // compute the scale bar length
421  size_t length = 1;
422  const std::string text("10000000000");
423  size_t noDigits = 1;
424  size_t pixelSize = (size_t) m2p((SUMOReal) length);
425  while (pixelSize <= 20) {
426  length *= 10;
427  noDigits++;
428  if (noDigits > text.length()) {
429  return;
430  }
431  pixelSize = (size_t) m2p((SUMOReal) length);
432  }
433  SUMOReal lineWidth = 1.0;
434  glLineWidth((SUMOReal) lineWidth);
435 
436  glMatrixMode(GL_PROJECTION);
437  glPushMatrix();
438  glLoadIdentity();
439  glMatrixMode(GL_MODELVIEW);
440  glPushMatrix();
441  glLoadIdentity();
442 
443  // draw the scale bar
444  glDisable(GL_TEXTURE_2D);
445  glDisable(GL_ALPHA_TEST);
446  glDisable(GL_BLEND);
447  glEnable(GL_DEPTH_TEST);
448 
449  SUMOReal len = (SUMOReal) pixelSize / (SUMOReal)(getWidth() - 1) * (SUMOReal) 2.0;
450  glColor3d(0, 0, 0);
451  double o = double(15) / double(getHeight());
452  double o2 = o + o;
453  double oo = double(5) / double(getHeight());
454  glBegin(GL_LINES);
455  // vertical
456  glVertex2d(-.98, -1. + o);
457  glVertex2d(-.98 + len, -1. + o);
458  // tick at begin
459  glVertex2d(-.98, -1. + o);
460  glVertex2d(-.98, -1. + o2);
461  // tick at end
462  glVertex2d(-.98 + len, -1. + o);
463  glVertex2d(-.98 + len, -1. + o2);
464  glEnd();
465 
466  SUMOReal w = SUMOReal(35) / SUMOReal(getWidth());
467  SUMOReal h = SUMOReal(35) / SUMOReal(getHeight());
468  pfSetPosition(SUMOReal(-0.99), SUMOReal(1. - o2 - oo));
469  pfSetScaleXY(w, h);
470  glRotated(180, 1, 0, 0);
471  pfDrawString("0m");
472  glRotated(-180, 1, 0, 0);
473 
474  pfSetPosition(SUMOReal(-.99 + len), SUMOReal(1. - o2 - oo));
475  glRotated(180, 1, 0, 0);
476  pfDrawString((text.substr(0, noDigits) + "m").c_str());
477  glRotated(-180, 1, 0, 0);
478 
479  // restore matrices
480  glMatrixMode(GL_PROJECTION);
481  glPopMatrix();
482  glMatrixMode(GL_MODELVIEW);
483  glPopMatrix();
484 }
485 
486 
487 SUMOReal
489  return meter * getWidth() / myChanger->getViewport().getWidth();
490 }
491 
492 
493 SUMOReal
495  return pixel * myChanger->getViewport().getWidth() / getWidth();
496 }
497 
498 
499 void
502 }
503 
504 
505 void
506 GUISUMOAbstractView::centerTo(GUIGlID id, bool applyZoom, SUMOReal zoomDist) {
508  if (o != 0 && dynamic_cast<GUIGlObject*>(o) != 0) {
509  if (applyZoom && zoomDist < 0) {
511  update(); // only update when centering onto an object once
512  } else {
513  // called during tracking. update is triggered somewhere else
514  myChanger->centerTo(o->getCenteringBoundary().getCenter(), zoomDist, applyZoom);
516  }
517  }
519 }
520 
521 
522 void
524  myChanger->setViewport(bound);
525  update();
526 }
527 
528 /*
529 bool
530 GUISUMOAbstractView::allowRotation() const
531 {
532  return myParent->allowRotation();
533 }
534 */
535 
536 void
540 }
541 
542 
543 FXbool
545  FXbool ret = FXGLCanvas::makeCurrent();
546  return ret;
547 }
548 
549 
550 long
551 GUISUMOAbstractView::onConfigure(FXObject*, FXSelector, void*) {
552  if (makeCurrent()) {
553  glViewport(0, 0, getWidth() - 1, getHeight() - 1);
554  glClearColor(
559  doInit();
560  myAmInitialised = true;
561  makeNonCurrent();
562  checkSnapshots();
563  }
564  return 1;
565 }
566 
567 
568 long
569 GUISUMOAbstractView::onPaint(FXObject*, FXSelector, void*) {
570  if (!isEnabled() || !myAmInitialised) {
571  return 1;
572  }
573  if (makeCurrent()) {
574  paintGL();
575  makeNonCurrent();
576  }
577  return 1;
578 }
579 
580 
581 void
583  delete myPopup;
584  myPopup = 0;
585 }
586 
587 
588 long
589 GUISUMOAbstractView::onLeftBtnPress(FXObject*, FXSelector , void* data) {
590  destroyPopup();
591  setFocus();
592  FXEvent* e = (FXEvent*) data;
593  // check whether the selection-mode is activated
594  if ((e->state & CONTROLMASK) != 0) {
595  // try to get the object-id if so
596  if (makeCurrent()) {
597  unsigned int id = getObjectUnderCursor();
598  if (id != 0) {
600  }
601  makeNonCurrent();
602  if (id != 0) {
603  // possibly, the selection-colouring is used,
604  // so we should update the screen again...
605  update();
606  }
607  }
608  }
609  myChanger->onLeftBtnPress(data);
610  grab();
611  return 1;
612 }
613 
614 
615 long
616 GUISUMOAbstractView::onLeftBtnRelease(FXObject*, FXSelector , void* data) {
617  destroyPopup();
619  if (myApp->isGaming()) {
621  }
622  ungrab();
623  return 1;
624 }
625 
626 
627 long
628 GUISUMOAbstractView::onRightBtnPress(FXObject*, FXSelector , void* data) {
629  destroyPopup();
630  myChanger->onRightBtnPress(data);
631  grab();
632  return 1;
633 }
634 
635 
636 long
637 GUISUMOAbstractView::onRightBtnRelease(FXObject* o, FXSelector sel, void* data) {
638  destroyPopup();
639  onMouseMove(o, sel, data);
640  if (!myChanger->onRightBtnRelease(data) && !myApp->isGaming()) {
642  }
643  ungrab();
644  return 1;
645 }
646 
647 
648 long
649 GUISUMOAbstractView::onMouseWheel(FXObject*, FXSelector , void* data) {
650  if (!myApp->isGaming()) {
651  myChanger->onMouseWheel(data);
653  }
654  return 1;
655 }
656 
657 
658 long
659 GUISUMOAbstractView::onMouseMove(FXObject*, FXSelector , void* data) {
661  myChanger->onMouseMove(data);
662  }
663  if (myViewportChooser != 0) {
665  }
667  return 1;
668 }
669 
670 
671 long
672 GUISUMOAbstractView::onMouseLeft(FXObject*, FXSelector , void* /*data*/) {
673  return 1;
674 }
675 
676 
677 void
679  ungrab();
680  if (!isEnabled() || !myAmInitialised) {
681  return;
682  }
683  if (makeCurrent()) {
684  // initialise the select mode
685  unsigned int id = getObjectUnderCursor();
686  GUIGlObject* o = 0;
687  if (id != 0) {
689  } else {
691  }
692  if (o != 0) {
693  myPopup = o->getPopUpMenu(*myApp, *this);
694  int x, y;
695  FXuint b;
696  myApp->getCursorPosition(x, y, b);
697  myPopup->setX(x + myApp->getX());
698  myPopup->setY(y + myApp->getY());
699  myPopup->create();
700  myPopup->show();
703  }
704  makeNonCurrent();
705  }
706 }
707 
708 
709 long
710 GUISUMOAbstractView::onKeyPress(FXObject* o, FXSelector sel, void* data) {
711  FXGLCanvas::onKeyPress(o, sel, data);
712  return myChanger->onKeyPress(data);
713 }
714 
715 
716 long
717 GUISUMOAbstractView::onKeyRelease(FXObject* o, FXSelector sel, void* data) {
718  FXGLCanvas::onKeyRelease(o, sel, data);
719  return myChanger->onKeyRelease(data);
720 }
721 
722 
723 // ------------ Dealing with snapshots
724 void
725 GUISUMOAbstractView::setSnapshots(std::map<SUMOTime, std::string> snaps) {
726  mySnapshots.insert(snaps.begin(), snaps.end());
727 }
728 
729 
730 std::string
731 GUISUMOAbstractView::makeSnapshot(const std::string& destFile) {
732  std::string errorMessage;
733  FXString ext = FXPath::extension(destFile.c_str());
734  const bool useGL2PS = ext == "ps" || ext == "eps" || ext == "pdf" || ext == "svg" || ext == "tex" || ext == "pgf";
735 #ifdef HAVE_FFMPEG
736  const bool useVideo = destFile == "" || ext == "h264" || ext == "hevc";
737 #endif
738  for (int i = 0; i < 10 && !makeCurrent(); ++i) {
740  }
741  // draw
742  glClearColor(
747  glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
748  glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
749 
751  glEnable(GL_DITHER);
752  } else {
753  glDisable(GL_DITHER);
754  }
756  glEnable(GL_BLEND);
757  glEnable(GL_POLYGON_SMOOTH);
758  glEnable(GL_LINE_SMOOTH);
759  } else {
760  glDisable(GL_BLEND);
761  glDisable(GL_POLYGON_SMOOTH);
762  glDisable(GL_LINE_SMOOTH);
763  }
764 
766 
767  if (useGL2PS) {
768  GLint format = GL2PS_PS;
769  if (ext == "ps") {
770  format = GL2PS_PS;
771  } else if (ext == "eps") {
772  format = GL2PS_EPS;
773  } else if (ext == "pdf") {
774  format = GL2PS_PDF;
775  } else if (ext == "tex") {
776  format = GL2PS_TEX;
777  } else if (ext == "svg") {
778  format = GL2PS_SVG;
779  } else if (ext == "pgf") {
780  format = GL2PS_PGF;
781  } else {
782  return "Could not save '" + destFile + "'.\n Unrecognized format '" + std::string(ext.text()) + "'.";
783  }
784  FILE* fp = fopen(destFile.c_str(), "wb");
785  if (fp == 0) {
786  return "Could not save '" + destFile + "'.\n Could not open file for writing";
787  }
788  GLint buffsize = 0, state = GL2PS_OVERFLOW;
789  GLint viewport[4];
790  glGetIntegerv(GL_VIEWPORT, viewport);
791  while (state == GL2PS_OVERFLOW) {
792  buffsize += 1024 * 1024;
793  gl2psBeginPage(destFile.c_str(), "sumo-gui; http://sumo.dlr.de", viewport, format, GL2PS_SIMPLE_SORT,
794  GL2PS_DRAW_BACKGROUND | GL2PS_USE_CURRENT_VIEWPORT,
795  GL_RGBA, 0, NULL, 0, 0, 0, buffsize, fp, "out.eps");
796  glMatrixMode(GL_MODELVIEW);
797  glPushMatrix();
798  glDisable(GL_TEXTURE_2D);
799  glDisable(GL_ALPHA_TEST);
800  glDisable(GL_BLEND);
801  glEnable(GL_DEPTH_TEST);
802  // compute lane width
803  // draw decals (if not in grabbing mode)
804  if (!myUseToolTips) {
805  drawDecals();
807  paintGLGrid();
808  }
809  }
810  glLineWidth(1);
811  glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
812  Boundary viewPort = myChanger->getViewport();
813  float minB[2];
814  float maxB[2];
815  minB[0] = viewPort.xmin();
816  minB[1] = viewPort.ymin();
817  maxB[0] = viewPort.xmax();
818  maxB[1] = viewPort.ymax();
820  glEnable(GL_POLYGON_OFFSET_FILL);
821  glEnable(GL_POLYGON_OFFSET_LINE);
822  myGrid->Search(minB, maxB, *myVisualizationSettings);
823 
825  displayLegend();
826  }
827  state = gl2psEndPage();
828  glFinish();
829  }
830  fclose(fp);
831  } else {
832  doPaintGL(GL_RENDER, myChanger->getViewport());
834  displayLegend();
835  }
836  swapBuffers();
837  glFinish();
838  FXColor* buf;
839  FXMALLOC(&buf, FXColor, getWidth()*getHeight());
840  // read from the back buffer
841  glReadBuffer(GL_BACK);
842  // Read the pixels
843  glReadPixels(0, 0, getWidth(), getHeight(), GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid*)buf);
844  makeNonCurrent();
845  update();
846  // mirror
847  size_t mwidth = getWidth();
848  size_t mheight = getHeight();
849  FXColor* paa = buf;
850  FXColor* pbb = buf + mwidth * (mheight - 1);
851  do {
852  FXColor* pa = paa;
853  paa += mwidth;
854  FXColor* pb = pbb;
855  pbb -= mwidth;
856  do {
857  FXColor t = *pa;
858  *pa++ = *pb;
859  *pb++ = t;
860  } while (pa < paa);
861  } while (paa < pbb);
862  try {
863 #ifdef HAVE_FFMPEG
864  if (useVideo) {
865  try {
866  saveFrame(destFile, buf);
867  errorMessage = "video";
868  } catch (std::runtime_error& err) {
869  errorMessage = err.what();
870  }
871  } else
872 #endif
873  if (!MFXImageHelper::saveImage(destFile, getWidth(), getHeight(), buf)) {
874  errorMessage = "Could not save '" + destFile + "'.";
875  }
876  } catch (InvalidArgument& e) {
877  errorMessage = "Could not save '" + destFile + "'.\n" + e.what();
878  }
879  FXFREE(&buf);
880  }
881  return errorMessage;
882 }
883 
884 
885 void
887  std::map<SUMOTime, std::string>::iterator snapIt = mySnapshots.find(getCurrentTimeStep());
888  if (snapIt != mySnapshots.end()) {
889  std::string error = makeSnapshot(snapIt->second);
890  if (error != "") {
891  WRITE_WARNING(error);
892  }
893  }
894 }
895 
896 
897 void
899  if (myVisualizationChanger == 0) {
904  myVisualizationChanger->create();
905  } else {
907  }
908  myVisualizationChanger->show();
909 }
910 
913  if (myViewportChooser == 0) {
915  new GUIDialog_EditViewport(this, "Edit Viewport...", 0, 0);
916  myViewportChooser->create();
917  }
919  return myViewportChooser;
920 }
921 
922 
923 void
925  getViewportEditor(); // make sure it exists;
928  myViewportChooser->show();
929 }
930 
931 
932 void
933 GUISUMOAbstractView::setViewport(const Position& lookFrom, const Position& /* lookAt */) {
934  myChanger->setViewport(lookFrom.z(), lookFrom.x(), lookFrom.y());
935  update();
936 }
937 
938 
939 void
941  myUseToolTips = val;
942 }
943 
944 
945 
946 SUMOReal
948  return myGrid->getWidth();
949 }
950 
951 
952 SUMOReal
954  return myGrid->getHeight();
955 }
956 
957 
958 FXComboBox&
961 }
962 
963 
964 FXImage*
966 #ifdef HAVE_GDAL
967  GDALAllRegister();
968  GDALDataset* poDataset = (GDALDataset*)GDALOpen(d.filename.c_str(), GA_ReadOnly);
969  if (poDataset == 0) {
970  return 0;
971  }
972  const int xSize = poDataset->GetRasterXSize();
973  const int ySize = poDataset->GetRasterYSize();
974  // checking for geodata in the picture and try to adapt position and scale
975  if (d.width <= 0.) {
976  double adfGeoTransform[6];
977  if (poDataset->GetGeoTransform(adfGeoTransform) == CE_None) {
978  Position topLeft(adfGeoTransform[0], adfGeoTransform[3]);
979  const double horizontalSize = xSize * adfGeoTransform[1];
980  const double verticalSize = ySize * adfGeoTransform[5];
981  Position bottomRight(topLeft.x() + horizontalSize, topLeft.y() + verticalSize);
983  d.width = bottomRight.x() - topLeft.x();
984  d.height = topLeft.y() - bottomRight.y();
985  d.centerX = (topLeft.x() + bottomRight.x()) / 2;
986  d.centerY = (topLeft.y() + bottomRight.y()) / 2;
987  //WRITE_MESSAGE("proj: " + toString(poDataset->GetProjectionRef()) + " dim: " + toString(d.width) + "," + toString(d.height) + " center: " + toString(d.centerX) + "," + toString(d.centerY));
988  } else {
989  WRITE_WARNING("Could not convert coordinates in " + d.filename + ".");
990  }
991  }
992  }
993 #endif
994  if (d.width <= 0.) {
995  d.width = getGridWidth();
996  d.height = getGridHeight();
997  }
998 
999  // trying to read the picture
1000 #ifdef HAVE_GDAL
1001  const int picSize = xSize * ySize;
1002  FXColor* result;
1003  if (!FXMALLOC(&result, FXColor, picSize)) {
1004  WRITE_WARNING("Could not allocate memory for " + d.filename + ".");
1005  return 0;
1006  }
1007  for (int j = 0; j < picSize; j++) {
1008  result[j] = FXRGB(0, 0, 0);
1009  }
1010  bool valid = true;
1011  for (int i = 1; i <= poDataset->GetRasterCount(); i++) {
1012  GDALRasterBand* poBand = poDataset->GetRasterBand(i);
1013  int shift = -1;
1014  if (poBand->GetColorInterpretation() == GCI_RedBand) {
1015  shift = 0;
1016  } else if (poBand->GetColorInterpretation() == GCI_GreenBand) {
1017  shift = 1;
1018  } else if (poBand->GetColorInterpretation() == GCI_BlueBand) {
1019  shift = 2;
1020  } else if (poBand->GetColorInterpretation() == GCI_AlphaBand) {
1021  shift = 3;
1022  } else {
1023  WRITE_MESSAGE("Unknown color band in " + d.filename + ", maybe fox can parse it.");
1024  valid = false;
1025  break;
1026  }
1027  assert(xSize == poBand->GetXSize() && ySize == poBand->GetYSize());
1028  if (poBand->RasterIO(GF_Read, 0, 0, xSize, ySize, ((unsigned char*)result) + shift, xSize, ySize, GDT_Byte, 4, 4 * xSize) == CE_Failure) {
1029  valid = false;
1030  break;
1031  }
1032  }
1033  GDALClose(poDataset);
1034  if (valid) {
1035  return new FXImage(getApp(), result, IMAGE_OWNED | IMAGE_KEEP | IMAGE_SHMI | IMAGE_SHMP, xSize, ySize);
1036  }
1037  FXFREE(&result);
1038 #endif
1039  return 0;
1040 }
1041 
1042 
1043 void
1045  glPushName(0);
1046  myDecalsLock.lock();
1047  for (std::vector<GUISUMOAbstractView::Decal>::iterator l = myDecals.begin(); l != myDecals.end(); ++l) {
1049  if (d.skip2D) {
1050  continue;
1051  }
1052  if (!d.initialised) {
1053  try {
1054  FXImage* img = checkGDALImage(d);
1055  if (img == 0) {
1056  img = MFXImageHelper::loadImage(getApp(), d.filename);
1057  }
1059  WRITE_WARNING("Scaling '" + d.filename + "'.");
1060  }
1061  d.glID = GUITexturesHelper::add(img);
1062  d.initialised = true;
1063  d.image = img;
1064  } catch (InvalidArgument& e) {
1065  WRITE_ERROR("Could not load '" + d.filename + "'.\n" + e.what());
1066  d.skip2D = true;
1067  }
1068  }
1069  glPushMatrix();
1070  glTranslated(d.centerX, d.centerY, d.layer);
1071  glRotated(d.rot, 0, 0, 1);
1072  glColor3d(1, 1, 1);
1073  const SUMOReal halfWidth = d.width / 2.;
1074  const SUMOReal halfHeight = d.height / 2.;
1075  GUITexturesHelper::drawTexturedBox(d.glID, -halfWidth, -halfHeight, halfWidth, halfHeight);
1076  glPopMatrix();
1077  }
1078  myDecalsLock.unlock();
1079  glPopName();
1080 }
1081 
1082 
1083 // ------------ Additional visualisations
1084 bool
1086  if (myAdditionallyDrawn.find(which) == myAdditionallyDrawn.end()) {
1087  myAdditionallyDrawn[which] = 1;
1088  } else {
1089  myAdditionallyDrawn[which] = myAdditionallyDrawn[which] + 1;
1090  }
1091  update();
1092  return true;
1093 }
1094 
1095 
1096 bool
1098  if (getTrackedID() == static_cast<int>(which->getGlID())) {
1099  stopTrack();
1100  }
1101  if (myAdditionallyDrawn.find(which) == myAdditionallyDrawn.end()) {
1102  return false;
1103  }
1104  int cnt = myAdditionallyDrawn[which];
1105  if (cnt == 1) {
1106  myAdditionallyDrawn.erase(which);
1107  } else {
1108  myAdditionallyDrawn[which] = myAdditionallyDrawn[which] - 1;
1109  }
1110  update();
1111  return true;
1112 }
1113 
1114 
1115 void
1117  Boundary bound = myChanger->getViewport(fixRatio);
1118  glMatrixMode(GL_PROJECTION);
1119  glLoadIdentity();
1120  // as a rough rule, each GLObject is drawn at z = -GUIGlObjectType
1121  // thus, objects with a higher value will be closer (drawn on top)
1122  // // @todo last param should be 0 after modifying all glDraw methods
1123  glOrtho(0, getWidth(), 0, getHeight(), -GLO_MAX - 1, GLO_MAX + 1);
1124  glMatrixMode(GL_MODELVIEW);
1125  glLoadIdentity();
1126  SUMOReal scaleX = (SUMOReal)getWidth() / bound.getWidth();
1127  SUMOReal scaleY = (SUMOReal)getHeight() / bound.getHeight();
1128  glScaled(scaleX, scaleY, 1);
1129  glTranslated(-bound.xmin(), -bound.ymin(), 0);
1130 }
1131 
1132 
1133 SUMOReal
1135  return myApp->getDelay();
1136 }
1137 
1138 
1139 void
1141  myApp->setDelay(delay);
1142 }
1143 
1144 /****************************************************************************/
1145 
GUIDialog_EditViewport * getViewportEditor()
get the viewport and create it on first access
void paintGLGrid()
paints a grid
A decal (an image) that can be shown.
virtual long onConfigure(FXObject *, FXSelector, void *)
void setValues(SUMOReal zoom, SUMOReal xoff, SUMOReal yoff)
Sets the given values into the dialog.
int pfDrawString(const char *c)
Definition: polyfonts.c:1074
SUMOReal getHeight() const
Returns the height of the boundary.
Definition: Boundary.cpp:142
GUICompleteSchemeStorage gSchemeStorage
bool showSizeLegend
Information whether the size legend shall be drawn.
void cartesian2geo(Position &cartesian) const
Converts the given cartesian (shifted) position to its geo (lat/long) representation.
FXImage * checkGDALImage(Decal &d)
check whether we can read image data or position with gdal
virtual void setViewport(SUMOReal zoom, SUMOReal xPos, SUMOReal yPos)=0
Sets the viewport Used for: Adapting a new viewport.
FXImage * image
The image pointer for later cleanup.
const SUMOReal SUMO_const_laneWidth
Definition: StdDefs.h:49
SUMOReal getWidth() const
Returns the width of the boudary.
Definition: Boundary.cpp:136
a polygon
void showToolTipFor(unsigned int id)
invokes the tooltip for the given object
virtual SUMOReal getDelay() const
Returns the delay (should be overwritten by subclasses if applicable)
Definition: GUIMainWindow.h:98
virtual void setViewport(const Position &lookFrom, const Position &lookAt)
applies the given viewport settings
void setDefault(const std::string &name)
Makes the scheme with the given name the default.
Position getCenter() const
Returns the center of the boundary.
Definition: Boundary.cpp:106
GUIGlObjectType
virtual void centerTo(GUIGlID id, bool applyZoom, SUMOReal zoomDist=20)
centers to the chosen artifact
bool myAmInitialised
Internal information whether doInit() was called.
void add(const Position &pos)
Adds the given position to this one.
Definition: Position.h:119
virtual void recenterView()
recenters the view
SUMORTree * myGrid
The visualization speed-up.
static GUIGlID add(FXImage *i)
Adds a texture to use.
void toggleSelection(GUIGlID id)
Toggles selection of an object.
bool gaming
whether the application is in gaming mode or not
virtual long onMouseMove(FXObject *, FXSelector, void *)
virtual SUMOReal getZoom() const =0
Returns the zoom factor computed stored in this changer.
SUMOReal ymin() const
Returns minimum y-coordinate.
Definition: Boundary.cpp:124
The dialog to change the view (gui) settings.
static GeoConvHelper & getProcessing()
the coordinate transformation to use for input conversion and processing
Definition: GeoConvHelper.h:98
#define GEO_OUTPUT_ACCURACY
Definition: config.h:16
bool x2cartesian(Position &from, bool includeInBoundary=true)
GUIMainWindow * myApp
The application.
SUMOReal xmin() const
Returns minimum x-coordinate.
Definition: Boundary.cpp:112
virtual SUMOTime getCurrentTimeStep() const
get the current simulation time
MFXMutex myDecalsLock
The mutex to use before accessing the decals list in order to avoid thread conficts.
void pfSetPosition(SUMOReal x, SUMOReal y)
Definition: polyfonts.c:480
SUMOReal p2m(SUMOReal pixel) const
pixels-to-meters conversion method
bool addAdditionalGLVisualisation(GUIGlObject *const which)
Adds an object to call its additional visualisation method.
virtual long onLeftBtnPress(FXObject *, FXSelector, void *)
bool myInEditMode
Information whether too-tip informations shall be generated.
virtual void openObjectDialog()
virtual Boundary getCenteringBoundary() const =0
Returns the boundary to which the view shall be centered in order to show the object.
virtual long onKeyRelease(FXObject *o, FXSelector sel, void *data)
GUIGlObject * getNetObject() const
Returns the network object.
SUMOReal getGridHeight() const
int glID
The gl-id of the texture that holds this image.
void setSnapshots(std::map< SUMOTime, std::string > snaps)
Sets the snapshot time to file map.
static const RGBColor BLACK
Definition: RGBColor.h:197
SUMOReal width
The width of the image (net coordinates in x-direction, in m)
GUIDialog_ViewSettings * myVisualizationChanger
bool isGaming() const
return whether the gui is in gaming mode
Definition: GUIMainWindow.h:84
GUIDialog_EditViewport * myViewportChooser
A RT-tree for efficient storing of SUMO&#39;s GL-objects.
Definition: SUMORTree.h:74
SUMOReal x() const
Returns the x-position.
Definition: Position.h:63
bool dither
Information whether dithering shall be enabled.
GUIGlID getGlID() const
Returns the numerical id of the object.
Definition: GUIGlObject.h:123
SUMOReal xmax() const
Returns maximum x-coordinate.
Definition: Boundary.cpp:118
A class that stores a 2D geometrical boundary.
Definition: Boundary.h:48
int myMouseHotspotX
Offset to the mouse-hotspot from the mouse position.
#define WRITE_WARNING(msg)
Definition: MsgHandler.h:200
SUMOReal scale
information about a lane&#39;s width (temporary, used for a single view)
unsigned char blue() const
Returns the blue-amount of the color.
Definition: RGBColor.h:91
virtual int getTrackedID() const
FXLabel & getCartesianLabel()
virtual void setDelay(SUMOReal)
Sets the delay of the parent application.
std::vector< GUIGlID > getObjectsAtPosition(Position pos, SUMOReal radius)
returns the ids of the object at position within the given (rectangular) radius using GL_SELECT ...
std::vector< Decal > myDecals
The list of decals to show.
GUIGlObjectType getType() const
Returns the type of the object as coded in GUIGlObjectType.
Definition: GUIGlObject.h:180
GUIGlID getObjectAtPosition(Position pos)
returns the id of the object at position using GL_SELECT
static FXbool scalePower2(FXImage *image, int maxSize=(2<< 29))
virtual int doPaintGL(int, const Boundary &)
bool removeAdditionalGLVisualisation(GUIGlObject *const which)
Removes an object from the list of objects that show additional things.
#define max(a, b)
Definition: polyfonts.c:65
virtual long onPaint(FXObject *, FXSelector, void *)
std::string name
The name of this setting.
std::map< GUIGlObject *, int > myAdditionallyDrawn
List of objects for which GUIGlObject::drawGLAdditional is called.
Boundary getVisibleBoundary() const
virtual long onMiddleBtnPress(FXObject *, FXSelector, void *)
static void drawTexturedBox(unsigned int which, SUMOReal size)
Draws a named texture as a box with the given size.
virtual void setStatusBarText(const std::string &)
Definition: GUIMainWindow.h:78
virtual long onKeyPress(FXObject *o, FXSelector sel, void *data)
virtual SUMOReal getXPos() const =0
Returns the x-offset of the field to show stored in this changer.
virtual long onMiddleBtnRelease(FXObject *, FXSelector, void *)
static void sleep(long ms)
bool isInEditMode()
returns true, if the edit button was pressed
A point in 2D or 3D with translation and scaling methods.
Definition: Position.h:46
SUMOReal centerY
The center of the image in y-direction (net coordinates, in m)
virtual GUIGLObjectPopupMenu * getPopUpMenu(GUIMainWindow &app, GUISUMOAbstractView &parent)=0
Returns an own popup-menu.
FXComboBox & getColoringSchemesCombo()
unsigned char alpha() const
Returns the alpha-amount of the color.
Definition: RGBColor.h:99
static GUIGlObjectStorage gIDStorage
A single static instance of this class.
virtual void saveFrame(const std::string &destFile, FXColor *buf)
Adds a frame to a video snapshot which will be initialized if neccessary.
SUMOReal z() const
Returns the z-position.
Definition: Position.h:73
virtual bool onLeftBtnRelease(void *data)
FXComboBox & getColoringSchemesCombo()
bool initialised
Whether this image was initialised (inserted as a texture)
A 2D- or 3D-Shape.
Definition: Shape.h:46
virtual bool onRightBtnRelease(void *data)
FXLabel & getGeoLabel()
virtual long onMouseWheel(FXObject *, FXSelector, void *)
virtual void checkSnapshots()
Checks whether it is time for a snapshot.
virtual ~GUISUMOAbstractView()
destructor
std::string filename
The path to the file the image is located at.
void saveViewport(const SUMOReal x, const SUMOReal y, const SUMOReal zoom)
Makes the given viewport the default.
void pfSetScaleXY(SUMOReal sx, SUMOReal sy)
Definition: polyfonts.c:472
SUMOReal gridXSize
Information about the grid spacings.
std::map< SUMOTime, std::string > mySnapshots
static FXbool saveImage(const std::string &file, int width, int height, FXColor *data)
std::string toString(const T &t, std::streamsize accuracy=OUTPUT_ACCURACY)
Definition: ToString.h:54
void updatePositionInformation() const
static void drawTextBox(const std::string &text, const Position &pos, const SUMOReal layer, const SUMOReal size, const RGBColor &txtColor=RGBColor::BLACK, const RGBColor &bgColor=RGBColor::WHITE, const RGBColor &borderColor=RGBColor::BLACK, const SUMOReal angle=0)
draw Text box with given parameters
Definition: GLHelper.cpp:478
SUMOReal getDelay() const
Returns the delay of the parent application.
GUIPerspectiveChanger * myChanger
The perspective changer.
std::string makeSnapshot(const std::string &destFile)
Takes a snapshots and writes it into the given file.
virtual void onLeftBtnPress(void *data)
GUIGLObjectPopupMenu * myPopup
The current popup-menu.
RGBColor backgroundColor
The background color to use.
void destroyPopup()
destoys the popup
bool antialiase
Information whether antialiase shall be enabled.
FXint myWindowCursorPositionX
Position of the cursor relative to the window.
Boundary getViewport(bool fixRatio=true)
unsigned int GUIGlID
Definition: GUIGlObject.h:49
#define WRITE_ERROR(msg)
Definition: MsgHandler.h:206
void unlock()
release mutex lock
Definition: MFXMutex.cpp:96
virtual void showViewportEditor()
FXbool makeCurrent()
A reimplementation due to some internal reasons.
SUMOReal height
The height of the image (net coordinates in y-direction, in m)
void applyGLTransform(bool fixRatio=true)
virtual long onLeftBtnRelease(FXObject *, FXSelector, void *)
void add(SUMOReal x, SUMOReal y)
Makes the boundary include the given coordinate.
Definition: Boundary.cpp:76
SUMOReal centerX
The center of the image in x-direction (net coordinates, in m)
GUIVisualizationSettings & getDefault()
Returns the default scheme.
Boundary & grow(SUMOReal by)
extends the boundary by the given amount
Definition: Boundary.cpp:201
void setViewport(GUISUMOAbstractView *view)
Sets the default viewport.
GUIVisualizationSettings * myVisualizationSettings
virtual void onMouseWheel(void *data)
SUMOReal m2p(SUMOReal meter) const
meter-to-pixels conversion method
void paintGL()
performs the painting of the simulation
virtual long onKeyPress(void *data)
GLCanvas - ID.
Definition: GUIAppEnum.h:199
SUMOReal y() const
Returns the y-position.
Definition: Position.h:68
void setWindowCursorPosition(FXint x, FXint y)
Returns the information whether rotation is allowd.
void setCurrent(GUIVisualizationSettings *settings)
Sets current settings (called if reopened)
static FXImage * loadImage(FXApp *a, const std::string &file)
SUMOReal getGridWidth() const
static const GeoConvHelper & getFinal()
the coordinate transformation for writing the location element and for tracking the original coordina...
void lock()
lock mutex
Definition: MFXMutex.cpp:86
bool showGrid
Information whether a grid shall be shown.
void drawDecals()
Draws the stored decals.
static int getMaxTextureSize()
return maximum number of pixels in x and y direction
SUMOReal layer
The layer of the image.
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:120
virtual void centerTo(const Position &pos, SUMOReal radius, bool applyZoom=true)=0
Centers the view to the given position, setting it to a size that covers the radius. Used for: Centering of vehicles and junctions.
void setDelay(SUMOReal delay)
Sets the delay of the parent application.
bool skip2D
Whether this image should be skipped in 2D-views.
unsigned char green() const
Returns the green-amount of the color.
Definition: RGBColor.h:83
#define SUMOReal
Definition: config.h:213
virtual void onMouseMove(void *data)
void updateToolTip()
A method that updates the tooltip.
A dialog to change the viewport.
SUMOReal ymax() const
Returns maximum y-coordinate.
Definition: Boundary.cpp:130
virtual void onRightBtnPress(void *data)
virtual void onGamingClick(Position)
empty max
void unblockObject(GUIGlID id)
Marks an object as unblocked.
static bool UseMesoSim
this should be set at the same time as MSGlobals::gUseMesoSim
virtual SUMOReal getYPos() const =0
Returns the y-offset of the field to show stored in this changer.
virtual long onRightBtnPress(FXObject *, FXSelector, void *)
bool haveGrabbed() const
Returns the information whether one of the spin dialers is grabbed.
virtual long onMouseLeft(FXObject *, FXSelector, void *)
Position getPositionInformation() const
Returns the cursor&#39;s x/y position within the network.
GUIGlID getObjectUnderCursor()
returns the id of the object under the cursor using GL_SELECT
bool drawForSelecting
whether drawing is performed for the purpose of selecting objects
#define WRITE_MESSAGE(msg)
Definition: MsgHandler.h:201
GUIGlObject * getObjectBlocking(GUIGlID id)
Returns the object from the container locking it.
virtual long onKeyRelease(void *data)
const std::string & getFullName() const
Returns the full name appearing in the tool tip.
Definition: GUIGlObject.h:108
unsigned char red() const
Returns the red-amount of the color.
Definition: RGBColor.h:75
GUISelectedStorage gSelected
A global holder of selected objects.
FXDEFMAP(GUISUMOAbstractView) GUISUMOAbstractViewMap[]
SUMOReal rot
The rotation of the image in the ground plane (in degrees)
GUIGlChildWindow * myParent
The parent window.
virtual long onRightBtnRelease(FXObject *, FXSelector, void *)
static const Position INVALID
Definition: Position.h:261
std::vector< GUIGlID > getObjectsInBoundary(const Boundary &bound)
returns the ids of all objects in the given boundary
void setOldValues(const Position &lookFrom, const Position &lookAt)
Resets old values.