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-2015 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  }
289 #ifdef HAVE_INTERNAL
290  if (type == GLO_LANE && GUIVisualizationSettings::UseMesoSim) {
291  // do not select lanes in meso mode
292  continue;
293  }
294 #endif
295  // check whether the current object is above a previous one
296  if (layer > maxLayer) {
297  idMax = id;
298  maxLayer = layer;
299  }
300  }
302  }
303  return idMax;
304 }
305 
306 
307 std::vector<GUIGlID>
309  Boundary selection;
310  selection.add(pos);
311  selection.grow(radius);
312  const std::vector<GUIGlID> ids = getObjectsInBoundary(selection);
313  std::vector<GUIGlID> result;
314  // Interpret results
315  for (std::vector<GUIGlID>::const_iterator it = ids.begin(); it != ids.end(); it++) {
316  GUIGlID id = *it;
318  if (o == 0) {
319  continue;
320  }
321  if (o->getGlID() == 0) {
322  continue;
323  }
324  //std::cout << "point selection hit " << o->getMicrosimID() << "\n";
325  GUIGlObjectType type = o->getType();
326  if (type != 0) {
327  result.push_back(id);
328  }
330  }
331  return result;
332 }
333 
334 
335 std::vector<GUIGlID>
337  const int NB_HITS_MAX = 1024 * 1024;
338  // Prepare the selection mode
339  static GUIGlID hits[NB_HITS_MAX];
340  static GLint nb_hits = 0;
341  glSelectBuffer(NB_HITS_MAX, hits);
342  glInitNames();
343 
344  Boundary oldViewPort = myChanger->getViewport(false); // backup the actual viewPort
345  myChanger->setViewport(bound);
346  applyGLTransform(false);
347 
348  // paint in select mode
350  int hits2 = doPaintGL(GL_SELECT, bound);
352  // Get the results
353  nb_hits = glRenderMode(GL_RENDER);
354  if (nb_hits == -1) {
355  myApp->setStatusBarText("Selection in boundary failed. Try to select fewer than " + toString(hits2) + " items");
356  }
357  std::vector<GUIGlID> result;
358  GLuint numNames;
359  GLuint* ptr = hits;
360  for (int i = 0; i < nb_hits; ++i) {
361  numNames = *ptr;
362  ptr += 3;
363  for (int j = 0; j < (int)numNames; j++) {
364  result.push_back(*ptr);
365  ptr++;
366  }
367  }
368  // switch viewport back to normal
369  myChanger->setViewport(oldViewPort);
370  return result;
371 }
372 
373 
374 void
376  if (id != 0) {
378  if (object != 0) {
380  pos.add(0, p2m(15));
381  GLHelper::drawTextBox(object->getFullName(), pos, GLO_MAX - 1, p2m(20), RGBColor::BLACK, RGBColor(255, 179, 0, 255));
383  }
384  }
385 }
386 
387 
388 void
390  glEnable(GL_DEPTH_TEST);
391  glLineWidth(1);
392 
393  SUMOReal xmin = myGrid->xmin();
394  SUMOReal ymin = myGrid->ymin();
395  SUMOReal ypos = ymin;
396  SUMOReal xpos = xmin;
397  SUMOReal xend = myGrid->xmax();
398  SUMOReal yend = myGrid->ymax();
399 
400  glTranslated(0, 0, .55);
401  glColor3d(0.5, 0.5, 0.5);
402  // draw horizontal lines
403  glBegin(GL_LINES);
404  for (; ypos < yend;) {
405  glVertex2d(xmin, ypos);
406  glVertex2d(xend, ypos);
408  }
409  // draw vertical lines
410  for (; xpos < xend;) {
411  glVertex2d(xpos, ymin);
412  glVertex2d(xpos, yend);
414  }
415  glEnd();
416  glTranslated(0, 0, -.55);
417 }
418 
419 
420 void
422  // compute the scale bar length
423  size_t length = 1;
424  const std::string text("10000000000");
425  size_t noDigits = 1;
426  size_t pixelSize = (size_t) m2p((SUMOReal) length);
427  while (pixelSize <= 20) {
428  length *= 10;
429  noDigits++;
430  if (noDigits > text.length()) {
431  return;
432  }
433  pixelSize = (size_t) m2p((SUMOReal) length);
434  }
435  SUMOReal lineWidth = 1.0;
436  glLineWidth((SUMOReal) lineWidth);
437 
438  glMatrixMode(GL_PROJECTION);
439  glPushMatrix();
440  glLoadIdentity();
441  glMatrixMode(GL_MODELVIEW);
442  glPushMatrix();
443  glLoadIdentity();
444 
445  // draw the scale bar
446  glDisable(GL_TEXTURE_2D);
447  glDisable(GL_ALPHA_TEST);
448  glDisable(GL_BLEND);
449  glEnable(GL_DEPTH_TEST);
450 
451  SUMOReal len = (SUMOReal) pixelSize / (SUMOReal)(getWidth() - 1) * (SUMOReal) 2.0;
452  glColor3d(0, 0, 0);
453  double o = double(15) / double(getHeight());
454  double o2 = o + o;
455  double oo = double(5) / double(getHeight());
456  glBegin(GL_LINES);
457  // vertical
458  glVertex2d(-.98, -1. + o);
459  glVertex2d(-.98 + len, -1. + o);
460  // tick at begin
461  glVertex2d(-.98, -1. + o);
462  glVertex2d(-.98, -1. + o2);
463  // tick at end
464  glVertex2d(-.98 + len, -1. + o);
465  glVertex2d(-.98 + len, -1. + o2);
466  glEnd();
467 
468  SUMOReal w = SUMOReal(35) / SUMOReal(getWidth());
469  SUMOReal h = SUMOReal(35) / SUMOReal(getHeight());
470  pfSetPosition(SUMOReal(-0.99), SUMOReal(1. - o2 - oo));
471  pfSetScaleXY(w, h);
472  glRotated(180, 1, 0, 0);
473  pfDrawString("0m");
474  glRotated(-180, 1, 0, 0);
475 
476  pfSetPosition(SUMOReal(-.99 + len), SUMOReal(1. - o2 - oo));
477  glRotated(180, 1, 0, 0);
478  pfDrawString((text.substr(0, noDigits) + "m").c_str());
479  glRotated(-180, 1, 0, 0);
480 
481  // restore matrices
482  glMatrixMode(GL_PROJECTION);
483  glPopMatrix();
484  glMatrixMode(GL_MODELVIEW);
485  glPopMatrix();
486 }
487 
488 
489 SUMOReal
491  return meter * getWidth() / myChanger->getViewport().getWidth();
492 }
493 
494 
495 SUMOReal
497  return pixel * myChanger->getViewport().getWidth() / getWidth();
498 }
499 
500 
501 void
504 }
505 
506 
507 void
508 GUISUMOAbstractView::centerTo(GUIGlID id, bool applyZoom, SUMOReal zoomDist) {
510  if (o != 0 && dynamic_cast<GUIGlObject*>(o) != 0) {
511  if (applyZoom && zoomDist < 0) {
513  update(); // only update when centering onto an object once
514  } else {
515  // called during tracking. update is triggered somewhere else
516  myChanger->centerTo(o->getCenteringBoundary().getCenter(), zoomDist, applyZoom);
517  }
518  }
520 }
521 
522 
523 void
525  myChanger->setViewport(bound);
526  update();
527 }
528 
529 /*
530 bool
531 GUISUMOAbstractView::allowRotation() const
532 {
533  return myParent->allowRotation();
534 }
535 */
536 
537 void
541 }
542 
543 
544 FXbool
546  FXbool ret = FXGLCanvas::makeCurrent();
547  return ret;
548 }
549 
550 
551 long
552 GUISUMOAbstractView::onConfigure(FXObject*, FXSelector, void*) {
553  if (makeCurrent()) {
554  glViewport(0, 0, getWidth() - 1, getHeight() - 1);
555  glClearColor(
560  doInit();
561  myAmInitialised = true;
562  makeNonCurrent();
563  checkSnapshots();
564  }
565  return 1;
566 }
567 
568 
569 long
570 GUISUMOAbstractView::onPaint(FXObject*, FXSelector, void*) {
571  if (!isEnabled() || !myAmInitialised) {
572  return 1;
573  }
574  if (makeCurrent()) {
575  paintGL();
576  makeNonCurrent();
577  }
578  return 1;
579 }
580 
581 
582 void
584  delete myPopup;
585  myPopup = 0;
586 }
587 
588 
589 long
590 GUISUMOAbstractView::onLeftBtnPress(FXObject*, FXSelector , void* data) {
591  destroyPopup();
592  setFocus();
593  FXEvent* e = (FXEvent*) data;
594  // check whether the selection-mode is activated
595  if ((e->state & CONTROLMASK) != 0) {
596  // try to get the object-id if so
597  if (makeCurrent()) {
598  unsigned int id = getObjectUnderCursor();
599  if (id != 0) {
601  }
602  makeNonCurrent();
603  if (id != 0) {
604  // possibly, the selection-colouring is used,
605  // so we should update the screen again...
606  update();
607  }
608  }
609  }
610  myChanger->onLeftBtnPress(data);
611  grab();
612  return 1;
613 }
614 
615 
616 long
617 GUISUMOAbstractView::onLeftBtnRelease(FXObject*, FXSelector , void* data) {
618  destroyPopup();
620  if (myApp->isGaming()) {
622  }
623  ungrab();
624  return 1;
625 }
626 
627 
628 long
629 GUISUMOAbstractView::onRightBtnPress(FXObject*, FXSelector , void* data) {
630  destroyPopup();
631  myChanger->onRightBtnPress(data);
632  grab();
633  return 1;
634 }
635 
636 
637 long
638 GUISUMOAbstractView::onRightBtnRelease(FXObject* o, FXSelector sel, void* data) {
639  destroyPopup();
640  onMouseMove(o, sel, data);
641  if (!myChanger->onRightBtnRelease(data) && !myApp->isGaming()) {
643  }
644  ungrab();
645  return 1;
646 }
647 
648 
649 long
650 GUISUMOAbstractView::onMouseWheel(FXObject*, FXSelector , void* data) {
651  if (!myApp->isGaming()) {
652  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  bool useGL2PS = ext == "ps" || ext == "eps" || ext == "pdf" || ext == "svg" || ext == "tex" || ext == "pgf";
735 
736  for (int i = 0; i < 10 && !makeCurrent(); ++i) {
738  }
739  // draw
740  glClearColor(
745  glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
746  glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
747 
749  glEnable(GL_DITHER);
750  } else {
751  glDisable(GL_DITHER);
752  }
754  glEnable(GL_BLEND);
755  glEnable(GL_POLYGON_SMOOTH);
756  glEnable(GL_LINE_SMOOTH);
757  } else {
758  glDisable(GL_BLEND);
759  glDisable(GL_POLYGON_SMOOTH);
760  glDisable(GL_LINE_SMOOTH);
761  }
762 
764 
765  if (useGL2PS) {
766  GLint format = GL2PS_PS;
767  if (ext == "ps") {
768  format = GL2PS_PS;
769  } else if (ext == "eps") {
770  format = GL2PS_EPS;
771  } else if (ext == "pdf") {
772  format = GL2PS_PDF;
773  } else if (ext == "tex") {
774  format = GL2PS_TEX;
775  } else if (ext == "svg") {
776  format = GL2PS_SVG;
777  } else if (ext == "pgf") {
778  format = GL2PS_PGF;
779  } else {
780  return "Could not save '" + destFile + "'.\n Unrecognized format '" + std::string(ext.text()) + "'.";
781  }
782  FILE* fp = fopen(destFile.c_str(), "wb");
783  if (fp == 0) {
784  return "Could not save '" + destFile + "'.\n Could not open file for writing";
785  }
786  GLint buffsize = 0, state = GL2PS_OVERFLOW;
787  GLint viewport[4];
788  glGetIntegerv(GL_VIEWPORT, viewport);
789  while (state == GL2PS_OVERFLOW) {
790  buffsize += 1024 * 1024;
791  gl2psBeginPage(destFile.c_str(), "sumo-gui; http://sumo.dlr.de", viewport, format, GL2PS_SIMPLE_SORT,
792  GL2PS_DRAW_BACKGROUND | GL2PS_USE_CURRENT_VIEWPORT,
793  GL_RGBA, 0, NULL, 0, 0, 0, buffsize, fp, "out.eps");
794  glMatrixMode(GL_MODELVIEW);
795  glPushMatrix();
796  glDisable(GL_TEXTURE_2D);
797  glDisable(GL_ALPHA_TEST);
798  glDisable(GL_BLEND);
799  glEnable(GL_DEPTH_TEST);
800  // compute lane width
801  // draw decals (if not in grabbing mode)
802  if (!myUseToolTips) {
803  drawDecals();
805  paintGLGrid();
806  }
807  }
808  glLineWidth(1);
809  glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
810  Boundary viewPort = myChanger->getViewport();
811  float minB[2];
812  float maxB[2];
813  minB[0] = viewPort.xmin();
814  minB[1] = viewPort.ymin();
815  maxB[0] = viewPort.xmax();
816  maxB[1] = viewPort.ymax();
818  glEnable(GL_POLYGON_OFFSET_FILL);
819  glEnable(GL_POLYGON_OFFSET_LINE);
820  myGrid->Search(minB, maxB, *myVisualizationSettings);
821 
823  displayLegend();
824  }
825  state = gl2psEndPage();
826  glFinish();
827  }
828  fclose(fp);
829  } else {
830  doPaintGL(GL_RENDER, myChanger->getViewport());
832  displayLegend();
833  }
834  swapBuffers();
835  glFinish();
836  FXColor* buf;
837  FXMALLOC(&buf, FXColor, getWidth()*getHeight());
838  // read from the back buffer
839  glReadBuffer(GL_BACK);
840  // Read the pixels
841  glReadPixels(0, 0, getWidth(), getHeight(), GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid*)buf);
842  makeNonCurrent();
843  update();
844  // mirror
845  size_t mwidth = getWidth();
846  size_t mheight = getHeight();
847  FXColor* paa = buf;
848  FXColor* pbb = buf + mwidth * (mheight - 1);
849  do {
850  FXColor* pa = paa;
851  paa += mwidth;
852  FXColor* pb = pbb;
853  pbb -= mwidth;
854  do {
855  FXColor t = *pa;
856  *pa++ = *pb;
857  *pb++ = t;
858  } while (pa < paa);
859  } while (paa < pbb);
860  try {
861  if (!MFXImageHelper::saveImage(destFile, getWidth(), getHeight(), buf)) {
862  errorMessage = "Could not save '" + destFile + "'.";
863  }
864  } catch (InvalidArgument& e) {
865  errorMessage = "Could not save '" + destFile + "'.\n" + e.what();
866  }
867  FXFREE(&buf);
868  }
869  return errorMessage;
870 }
871 
872 
873 void
875  std::map<SUMOTime, std::string>::iterator snapIt = mySnapshots.find(getCurrentTimeStep());
876  if (snapIt != mySnapshots.end()) {
877  std::string error = makeSnapshot(snapIt->second);
878  if (error != "") {
879  WRITE_WARNING(error);
880  }
881  }
882 }
883 
884 
885 void
887  if (myVisualizationChanger == 0) {
892  myVisualizationChanger->create();
893  } else {
895  }
896  myVisualizationChanger->show();
897 }
898 
901  if (myViewportChooser == 0) {
903  new GUIDialog_EditViewport(this, "Edit Viewport...", 0, 0);
904  myViewportChooser->create();
905  }
907  return myViewportChooser;
908 }
909 
910 
911 void
913  getViewportEditor(); // make sure it exists;
916  myViewportChooser->show();
917 }
918 
919 
920 void
921 GUISUMOAbstractView::setViewport(const Position& lookFrom, const Position& /* lookAt */) {
922  myChanger->setViewport(lookFrom.z(), lookFrom.x(), lookFrom.y());
923  update();
924 }
925 
926 
927 void
929  myUseToolTips = val;
930 }
931 
932 
933 
934 SUMOReal
936  return myGrid->getWidth();
937 }
938 
939 
940 SUMOReal
942  return myGrid->getHeight();
943 }
944 
945 
946 FXComboBox&
949 }
950 
951 
952 FXImage*
954 #ifdef HAVE_GDAL
955  GDALAllRegister();
956  GDALDataset* poDataset = (GDALDataset*)GDALOpen(d.filename.c_str(), GA_ReadOnly);
957  if (poDataset == 0) {
958  return 0;
959  }
960  const int xSize = poDataset->GetRasterXSize();
961  const int ySize = poDataset->GetRasterYSize();
962  // checking for geodata in the picture and try to adapt position and scale
963  if (d.width <= 0.) {
964  double adfGeoTransform[6];
965  if (poDataset->GetGeoTransform(adfGeoTransform) == CE_None) {
966  Position topLeft(adfGeoTransform[0], adfGeoTransform[3]);
967  const double horizontalSize = xSize * adfGeoTransform[1];
968  const double verticalSize = ySize * adfGeoTransform[5];
969  Position bottomRight(topLeft.x() + horizontalSize, topLeft.y() + verticalSize);
971  d.width = bottomRight.x() - topLeft.x();
972  d.height = topLeft.y() - bottomRight.y();
973  d.centerX = (topLeft.x() + bottomRight.x()) / 2;
974  d.centerY = (topLeft.y() + bottomRight.y()) / 2;
975  //WRITE_MESSAGE("proj: " + toString(poDataset->GetProjectionRef()) + " dim: " + toString(d.width) + "," + toString(d.height) + " center: " + toString(d.centerX) + "," + toString(d.centerY));
976  } else {
977  WRITE_WARNING("Could not convert coordinates in " + d.filename + ".");
978  }
979  }
980  }
981 #endif
982  if (d.width <= 0.) {
983  d.width = getGridWidth();
984  d.height = getGridHeight();
985  }
986 
987  // trying to read the picture
988 #ifdef HAVE_GDAL
989  const int picSize = xSize * ySize;
990  FXColor* result;
991  if (!FXMALLOC(&result, FXColor, picSize)) {
992  WRITE_WARNING("Could not allocate memory for " + d.filename + ".");
993  return 0;
994  }
995  for (int j = 0; j < picSize; j++) {
996  result[j] = FXRGB(0, 0, 0);
997  }
998  bool valid = true;
999  for (int i = 1; i <= poDataset->GetRasterCount(); i++) {
1000  GDALRasterBand* poBand = poDataset->GetRasterBand(i);
1001  int shift = -1;
1002  if (poBand->GetColorInterpretation() == GCI_RedBand) {
1003  shift = 0;
1004  } else if (poBand->GetColorInterpretation() == GCI_GreenBand) {
1005  shift = 1;
1006  } else if (poBand->GetColorInterpretation() == GCI_BlueBand) {
1007  shift = 2;
1008  } else if (poBand->GetColorInterpretation() == GCI_AlphaBand) {
1009  shift = 3;
1010  } else {
1011  WRITE_MESSAGE("Unknown color band in " + d.filename + ", maybe fox can parse it.");
1012  valid = false;
1013  break;
1014  }
1015  assert(xSize == poBand->GetXSize() && ySize == poBand->GetYSize());
1016  if (poBand->RasterIO(GF_Read, 0, 0, xSize, ySize, ((unsigned char*)result) + shift, xSize, ySize, GDT_Byte, 4, 4 * xSize) == CE_Failure) {
1017  valid = false;
1018  break;
1019  }
1020  }
1021  GDALClose(poDataset);
1022  if (valid) {
1023  return new FXImage(getApp(), result, IMAGE_OWNED | IMAGE_KEEP | IMAGE_SHMI | IMAGE_SHMP, xSize, ySize);
1024  }
1025  FXFREE(&result);
1026 #endif
1027  return 0;
1028 }
1029 
1030 
1031 void
1033  glPushName(0);
1034  myDecalsLock.lock();
1035  for (std::vector<GUISUMOAbstractView::Decal>::iterator l = myDecals.begin(); l != myDecals.end(); ++l) {
1037  if (d.skip2D) {
1038  continue;
1039  }
1040  if (!d.initialised) {
1041  try {
1042  FXImage* img = checkGDALImage(d);
1043  if (img == 0) {
1044  img = MFXImageHelper::loadImage(getApp(), d.filename);
1045  }
1047  WRITE_WARNING("Scaling '" + d.filename + "'.");
1048  }
1049  d.glID = GUITexturesHelper::add(img);
1050  d.initialised = true;
1051  d.image = img;
1052  } catch (InvalidArgument& e) {
1053  WRITE_ERROR("Could not load '" + d.filename + "'.\n" + e.what());
1054  d.skip2D = true;
1055  }
1056  }
1057  glPushMatrix();
1058  glTranslated(d.centerX, d.centerY, d.layer);
1059  glRotated(d.rot, 0, 0, 1);
1060  glColor3d(1, 1, 1);
1061  const SUMOReal halfWidth = d.width / 2.;
1062  const SUMOReal halfHeight = d.height / 2.;
1063  GUITexturesHelper::drawTexturedBox(d.glID, -halfWidth, -halfHeight, halfWidth, halfHeight);
1064  glPopMatrix();
1065  }
1066  myDecalsLock.unlock();
1067  glPopName();
1068 }
1069 
1070 
1071 // ------------ Additional visualisations
1072 bool
1074  if (myAdditionallyDrawn.find(which) == myAdditionallyDrawn.end()) {
1075  myAdditionallyDrawn[which] = 1;
1076  } else {
1077  myAdditionallyDrawn[which] = myAdditionallyDrawn[which] + 1;
1078  }
1079  update();
1080  return true;
1081 }
1082 
1083 
1084 bool
1086  if (getTrackedID() == static_cast<int>(which->getGlID())) {
1087  stopTrack();
1088  }
1089  if (myAdditionallyDrawn.find(which) == myAdditionallyDrawn.end()) {
1090  return false;
1091  }
1092  int cnt = myAdditionallyDrawn[which];
1093  if (cnt == 1) {
1094  myAdditionallyDrawn.erase(which);
1095  } else {
1096  myAdditionallyDrawn[which] = myAdditionallyDrawn[which] - 1;
1097  }
1098  update();
1099  return true;
1100 }
1101 
1102 
1103 void
1105  Boundary bound = myChanger->getViewport(fixRatio);
1106  glMatrixMode(GL_PROJECTION);
1107  glLoadIdentity();
1108  // as a rough rule, each GLObject is drawn at z = -GUIGlObjectType
1109  // thus, objects with a higher value will be closer (drawn on top)
1110  // // @todo last param should be 0 after modifying all glDraw methods
1111  glOrtho(0, getWidth(), 0, getHeight(), -GLO_MAX - 1, GLO_MAX + 1);
1112  glMatrixMode(GL_MODELVIEW);
1113  glLoadIdentity();
1114  SUMOReal scaleX = (SUMOReal)getWidth() / bound.getWidth();
1115  SUMOReal scaleY = (SUMOReal)getHeight() / bound.getHeight();
1116  glScaled(scaleX, scaleY, 1);
1117  glTranslated(-bound.xmin(), -bound.ymin(), 0);
1118 }
1119 
1120 
1121 SUMOReal
1123  return myApp->getDelay();
1124 }
1125 
1126 
1127 void
1129  myApp->setDelay(delay);
1130 }
1131 
1132 /****************************************************************************/
1133 
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:167
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.
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 *)
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:53
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:205
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:214
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.
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.