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  myVisualizationChanger(0) {
128  setTarget(this);
129  enable();
130  flags |= FLAG_ENABLED;
131  myInEditMode = false;
132  // show the middle at the beginning
133  myChanger = new GUIDanielPerspectiveChanger(*this, *myGrid);
134  myVisualizationSettings = &gSchemeStorage.getDefault();
135  myVisualizationSettings->gaming = myApp->isGaming();
137 }
138 
139 
143  delete myPopup;
144  delete myChanger;
145  delete myViewportChooser;
146  delete myVisualizationChanger;
147  // cleanup decals
148  for (std::vector<GUISUMOAbstractView::Decal>::iterator it = myDecals.begin(); it != myDecals.end(); ++it) {
149  delete it->image;
150  }
151 }
152 
153 
154 bool
156  return myInEditMode;
157 }
158 
159 
160 void
162  if (!myUseToolTips) {
163  return;
164  }
165  update();
166 }
167 
168 
169 Position
171  Boundary bound = myChanger->getViewport();
172  SUMOReal x = bound.xmin() + bound.getWidth() * myWindowCursorPositionX / getWidth();
173  // cursor origin is in the top-left corner
174  SUMOReal y = bound.ymin() + bound.getHeight() * (getHeight() - myWindowCursorPositionY) / getHeight();
175  return Position(x, y);
176 }
177 
178 
179 void
182  std::string text = "x:" + toString(pos.x()) + ", y:" + toString(pos.y());
183  myApp->getCartesianLabel().setText(text.c_str());
185  if (GeoConvHelper::getFinal().usingGeoProjection()) {
186  text = "lat:" + toString(pos.y(), GEO_OUTPUT_ACCURACY) + ", lon:" + toString(pos.x(), GEO_OUTPUT_ACCURACY);
187  } else {
188  text = "x:" + toString(pos.x()) + ", y:" + toString(pos.y());
189  }
190  myApp->getGeoLabel().setText(text.c_str());
191 }
192 
193 
194 Boundary
196  return myChanger->getViewport();
197 }
198 
199 void
201  if (getWidth() == 0 || getHeight() == 0) {
202  return;
203  }
204 
205  if (getTrackedID() > 0) {
206  centerTo(getTrackedID(), false);
207  }
208 
209  unsigned int id = 0;
210  if (myUseToolTips) {
211  id = getObjectUnderCursor();
212  }
213 
214  // draw
215  glClearColor(
220  glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
221  glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
222 
224  glEnable(GL_DITHER);
225  } else {
226  glDisable(GL_DITHER);
227  }
229  glEnable(GL_BLEND);
230  glEnable(GL_POLYGON_SMOOTH);
231  glEnable(GL_LINE_SMOOTH);
232  } else {
233  glDisable(GL_BLEND);
234  glDisable(GL_POLYGON_SMOOTH);
235  glDisable(GL_LINE_SMOOTH);
236  }
237 
239  doPaintGL(GL_RENDER, myChanger->getViewport());
241  displayLegend();
242  }
243  // check whether the select mode /tooltips)
244  // shall be computed, too
245  if (myUseToolTips && id != 0) {
246  showToolTipFor(id);
247  }
248  swapBuffers();
249 }
250 
251 
252 GUIGlID
255 }
256 
257 
258 GUIGlID
260  const SUMOReal SENSITIVITY = 0.1; // meters
261  Boundary selection;
262  selection.add(pos);
263  selection.grow(SENSITIVITY);
264  const std::vector<GUIGlID> ids = getObjectsInBoundary(selection);
265  // Interpret results
266  unsigned int idMax = 0;
268  for (std::vector<GUIGlID>::const_iterator it = ids.begin(); it != ids.end(); it++) {
269  GUIGlID id = *it;
271  if (o == 0) {
272  continue;
273  }
274  if (o->getGlID() == 0) {
275  continue;
276  }
277  //std::cout << "point selection hit " << o->getMicrosimID() << "\n";
278  GUIGlObjectType type = o->getType();
279  if (type != 0) {
280  SUMOReal layer = (SUMOReal)type;
281  // determine an "abstract" layer for shapes
282  // this "layer" resembles the layer of the shape
283  // taking into account the stac of other objects
284  if (type == GLO_POI || type == GLO_POLYGON) {
285  layer = dynamic_cast<Shape*>(o)->getLayer();
286  }
287 #ifdef HAVE_INTERNAL
288  if (type == GLO_LANE && GUIVisualizationSettings::UseMesoSim) {
289  // do not select lanes in meso mode
290  continue;
291  }
292 #endif
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);
515  }
516  }
518 }
519 
520 
521 void
523  myChanger->setViewport(bound);
524  update();
525 }
526 
527 /*
528 bool
529 GUISUMOAbstractView::allowRotation() const
530 {
531  return myParent->allowRotation();
532 }
533 */
534 
535 void
539 }
540 
541 
542 FXbool
544  FXbool ret = FXGLCanvas::makeCurrent();
545  return ret;
546 }
547 
548 
549 long
551  if (makeCurrent()) {
552  glViewport(0, 0, getWidth() - 1, getHeight() - 1);
553  glClearColor(
558  doInit();
559  myAmInitialised = true;
560  makeNonCurrent();
561  checkSnapshots();
562  }
563  return 1;
564 }
565 
566 
567 long
569  if (!isEnabled() || !myAmInitialised) {
570  return 1;
571  }
572  if (makeCurrent()) {
573  paintGL();
574  makeNonCurrent();
575  }
576  return 1;
577 }
578 
579 
580 void
582  delete myPopup;
583  myPopup = 0;
584 }
585 
586 
587 long
588 GUISUMOAbstractView::onLeftBtnPress(FXObject*, FXSelector , void* data) {
589  destroyPopup();
590  FXEvent* e = (FXEvent*) data;
591  // check whether the selection-mode is activated
592  if (e->state & CONTROLMASK) {
593  // try to get the object-id if so
594  if (makeCurrent()) {
595  unsigned int id = getObjectUnderCursor();
596  if (id != 0) {
598  }
599  makeNonCurrent();
600  if (id != 0) {
601  // possibly, the selection-colouring is used,
602  // so we should update the screen again...
603  update();
604  }
605  }
606  }
607  myChanger->onLeftBtnPress(data);
608  grab();
609  return 1;
610 }
611 
612 
613 long
615  destroyPopup();
617  if (myApp->isGaming()) {
619  }
620  ungrab();
621  return 1;
622 }
623 
624 
625 long
626 GUISUMOAbstractView::onRightBtnPress(FXObject*, FXSelector , void* data) {
627  destroyPopup();
628  myChanger->onRightBtnPress(data);
629  grab();
630  return 1;
631 }
632 
633 
634 long
635 GUISUMOAbstractView::onRightBtnRelease(FXObject* o, FXSelector sel, void* data) {
636  destroyPopup();
637  onMouseMove(o, sel, data);
638  if (!myChanger->onRightBtnRelease(data) && !myApp->isGaming()) {
640  }
641  ungrab();
642  return 1;
643 }
644 
645 
646 long
647 GUISUMOAbstractView::onMouseWheel(FXObject*, FXSelector , void* data) {
648  if (!myApp->isGaming()) {
649  myChanger->onMouseWheel(data);
650  }
651  return 1;
652 }
653 
654 
655 long
656 GUISUMOAbstractView::onMouseMove(FXObject*, FXSelector , void* data) {
658  myChanger->onMouseMove(data);
659  }
660  if (myViewportChooser != 0) {
662  }
664  return 1;
665 }
666 
667 
668 long
669 GUISUMOAbstractView::onMouseLeft(FXObject*, FXSelector , void* /*data*/) {
670  return 1;
671 }
672 
673 
674 void
676  ungrab();
677  if (!isEnabled() || !myAmInitialised) {
678  return;
679  }
680  if (makeCurrent()) {
681  // initialise the select mode
682  unsigned int id = getObjectUnderCursor();
683  GUIGlObject* o = 0;
684  if (id != 0) {
686  } else {
688  }
689  if (o != 0) {
690  myPopup = o->getPopUpMenu(*myApp, *this);
691  int x, y;
692  FXuint b;
693  myApp->getCursorPosition(x, y, b);
694  myPopup->setX(x + myApp->getX());
695  myPopup->setY(y + myApp->getY());
696  myPopup->create();
697  myPopup->show();
700  }
701  makeNonCurrent();
702  }
703 }
704 
705 
706 long
707 GUISUMOAbstractView::onKeyPress(FXObject* o, FXSelector sel, void* data) {
708  FXEvent* e = (FXEvent*) data;
709  if ((e->state & ALTMASK) != 0) {
710  setDefaultCursor(getApp()->getDefaultCursor(DEF_CROSSHAIR_CURSOR));
711  grabKeyboard();
712  }
713  /*
714  switch(e->code) {
715  case KEY_Left:
716  myChanger->move((SUMOReal) -p2m((SUMOReal) getWidth()/10), 0);
717  break;
718  case KEY_Right:
719  myChanger->move((SUMOReal) p2m((SUMOReal) getWidth()/10), 0);
720  break;
721  case KEY_Up:
722  myChanger->move(0, (SUMOReal) -p2m((SUMOReal) getHeight()/10));
723  break;
724  case KEY_Down:
725  myChanger->move(0, (SUMOReal) p2m((SUMOReal) getHeight()/10));
726  break;
727  default:
728  break;
729  }
730  */
731  return FXGLCanvas::onKeyPress(o, sel, data);
732 }
733 
734 
735 long
736 GUISUMOAbstractView::onKeyRelease(FXObject* o, FXSelector sel, void* data) {
737  FXEvent* e = (FXEvent*) data;
738  if ((e->state & ALTMASK) == 0) {
739  ungrabKeyboard();
740  setDefaultCursor(getApp()->getDefaultCursor(DEF_ARROW_CURSOR));
741  }
742  return FXGLCanvas::onKeyRelease(o, sel, data);
743 }
744 
745 
746 // ------------ Dealing with snapshots
747 void
748 GUISUMOAbstractView::setSnapshots(std::map<SUMOTime, std::string> snaps) {
749  mySnapshots.insert(snaps.begin(), snaps.end());
750 }
751 
752 
753 std::string
754 GUISUMOAbstractView::makeSnapshot(const std::string& destFile) {
755  std::string errorMessage;
756  FXString ext = FXPath::extension(destFile.c_str());
757  bool useGL2PS = ext == "ps" || ext == "eps" || ext == "pdf" || ext == "svg" || ext == "tex" || ext == "pgf";
758 
759  for (int i = 0; i < 10 && !makeCurrent(); ++i) {
761  }
762  // draw
763  glClearColor(
768  glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
769  glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
770 
772  glEnable(GL_DITHER);
773  } else {
774  glDisable(GL_DITHER);
775  }
777  glEnable(GL_BLEND);
778  glEnable(GL_POLYGON_SMOOTH);
779  glEnable(GL_LINE_SMOOTH);
780  } else {
781  glDisable(GL_BLEND);
782  glDisable(GL_POLYGON_SMOOTH);
783  glDisable(GL_LINE_SMOOTH);
784  }
785 
787 
788  if (useGL2PS) {
789  GLint format = GL2PS_PS;
790  if (ext == "ps") {
791  format = GL2PS_PS;
792  } else if (ext == "eps") {
793  format = GL2PS_EPS;
794  } else if (ext == "pdf") {
795  format = GL2PS_PDF;
796  } else if (ext == "tex") {
797  format = GL2PS_TEX;
798  } else if (ext == "svg") {
799  format = GL2PS_SVG;
800  } else if (ext == "pgf") {
801  format = GL2PS_PGF;
802  } else {
803  return "Could not save '" + destFile + "'.\n Unrecognized format '" + std::string(ext.text()) + "'.";
804  }
805  FILE* fp = fopen(destFile.c_str(), "wb");
806  if (fp == 0) {
807  return "Could not save '" + destFile + "'.\n Could not open file for writing";
808  }
809  GLint buffsize = 0, state = GL2PS_OVERFLOW;
810  GLint viewport[4];
811  glGetIntegerv(GL_VIEWPORT, viewport);
812  while (state == GL2PS_OVERFLOW) {
813  buffsize += 1024 * 1024;
814  gl2psBeginPage(destFile.c_str(), "sumo-gui; http://sumo.dlr.de", viewport, format, GL2PS_SIMPLE_SORT,
815  GL2PS_DRAW_BACKGROUND | GL2PS_USE_CURRENT_VIEWPORT,
816  GL_RGBA, 0, NULL, 0, 0, 0, buffsize, fp, "out.eps");
817  glMatrixMode(GL_MODELVIEW);
818  glPushMatrix();
819  glDisable(GL_TEXTURE_2D);
820  glDisable(GL_ALPHA_TEST);
821  glDisable(GL_BLEND);
822  glEnable(GL_DEPTH_TEST);
823  // compute lane width
824  // draw decals (if not in grabbing mode)
825  if (!myUseToolTips) {
826  drawDecals();
828  paintGLGrid();
829  }
830  }
831  glLineWidth(1);
832  glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
833  Boundary viewPort = myChanger->getViewport();
834  float minB[2];
835  float maxB[2];
836  minB[0] = viewPort.xmin();
837  minB[1] = viewPort.ymin();
838  maxB[0] = viewPort.xmax();
839  maxB[1] = viewPort.ymax();
841  glEnable(GL_POLYGON_OFFSET_FILL);
842  glEnable(GL_POLYGON_OFFSET_LINE);
843  myGrid->Search(minB, maxB, *myVisualizationSettings);
844 
846  displayLegend();
847  }
848  state = gl2psEndPage();
849  glFinish();
850  }
851  fclose(fp);
852  } else {
853  doPaintGL(GL_RENDER, myChanger->getViewport());
855  displayLegend();
856  }
857  swapBuffers();
858  glFinish();
859  FXColor* buf;
860  FXMALLOC(&buf, FXColor, getWidth()*getHeight());
861  // read from the back buffer
862  glReadBuffer(GL_BACK);
863  // Read the pixels
864  glReadPixels(0, 0, getWidth(), getHeight(), GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid*)buf);
865  makeNonCurrent();
866  update();
867  // mirror
868  size_t mwidth = getWidth();
869  size_t mheight = getHeight();
870  FXColor* paa = buf;
871  FXColor* pbb = buf + mwidth * (mheight - 1);
872  do {
873  FXColor* pa = paa;
874  paa += mwidth;
875  FXColor* pb = pbb;
876  pbb -= mwidth;
877  do {
878  FXColor t = *pa;
879  *pa++ = *pb;
880  *pb++ = t;
881  } while (pa < paa);
882  } while (paa < pbb);
883  try {
884  if (!MFXImageHelper::saveImage(destFile, getWidth(), getHeight(), buf)) {
885  errorMessage = "Could not save '" + destFile + "'.";
886  }
887  } catch (InvalidArgument& e) {
888  errorMessage = "Could not save '" + destFile + "'.\n" + e.what();
889  }
890  FXFREE(&buf);
891  }
892  return errorMessage;
893 }
894 
895 
896 void
898  std::map<SUMOTime, std::string>::iterator snapIt = mySnapshots.find(getCurrentTimeStep());
899  if (snapIt != mySnapshots.end()) {
900  std::string error = makeSnapshot(snapIt->second);
901  if (error != "") {
902  WRITE_WARNING(error);
903  }
904  }
905 }
906 
907 
908 void
910  if (myVisualizationChanger == 0) {
915  myVisualizationChanger->create();
916  } else {
918  }
919  myVisualizationChanger->show();
920 }
921 
924  if (myViewportChooser == 0) {
926  new GUIDialog_EditViewport(this, "Edit Viewport...", 0, 0);
927  myViewportChooser->create();
928  }
930  return myViewportChooser;
931 }
932 
933 
934 void
936  getViewportEditor(); // make sure it exists;
939  myViewportChooser->show();
940 }
941 
942 
943 void
944 GUISUMOAbstractView::setViewport(const Position& lookFrom, const Position& /* lookAt */) {
945  myChanger->setViewport(lookFrom.z(), lookFrom.x(), lookFrom.y());
946  update();
947 }
948 
949 
950 void
952  myUseToolTips = val;
953 }
954 
955 
956 
957 SUMOReal
959  return myGrid->getWidth();
960 }
961 
962 
963 SUMOReal
965  return myGrid->getHeight();
966 }
967 
968 
969 FXComboBox&
972 }
973 
974 
975 FXImage*
977 #ifdef HAVE_GDAL
978  GDALAllRegister();
979  GDALDataset* poDataset = (GDALDataset*)GDALOpen(d.filename.c_str(), GA_ReadOnly);
980  if (poDataset == 0) {
981  return 0;
982  }
983  const int xSize = poDataset->GetRasterXSize();
984  const int ySize = poDataset->GetRasterYSize();
985  // checking for geodata in the picture and try to adapt position and scale
986  if (d.width <= 0.) {
987  double adfGeoTransform[6];
988  if (poDataset->GetGeoTransform(adfGeoTransform) == CE_None) {
989  Position topLeft(adfGeoTransform[0], adfGeoTransform[3]);
990  const double horizontalSize = xSize * adfGeoTransform[1];
991  const double verticalSize = ySize * adfGeoTransform[5];
992  Position bottomRight(topLeft.x() + horizontalSize, topLeft.y() + verticalSize);
994  d.width = bottomRight.x() - topLeft.x();
995  d.height = topLeft.y() - bottomRight.y();
996  d.centerX = (topLeft.x() + bottomRight.x()) / 2;
997  d.centerY = (topLeft.y() + bottomRight.y()) / 2;
998  //WRITE_MESSAGE("proj: " + toString(poDataset->GetProjectionRef()) + " dim: " + toString(d.width) + "," + toString(d.height) + " center: " + toString(d.centerX) + "," + toString(d.centerY));
999  } else {
1000  WRITE_WARNING("Could not convert coordinates in " + d.filename + ".");
1001  }
1002  }
1003  }
1004 #endif
1005  if (d.width <= 0.) {
1006  d.width = getGridWidth();
1007  d.height = getGridHeight();
1008  }
1009 
1010  // trying to read the picture
1011 #ifdef HAVE_GDAL
1012  const int picSize = xSize * ySize;
1013  FXColor* result;
1014  if (!FXMALLOC(&result, FXColor, picSize)) {
1015  WRITE_WARNING("Could not allocate memory for " + d.filename + ".");
1016  return 0;
1017  }
1018  for (int j = 0; j < picSize; j++) {
1019  result[j] = FXRGB(0, 0, 0);
1020  }
1021  bool valid = true;
1022  for (int i = 1; i <= poDataset->GetRasterCount(); i++) {
1023  GDALRasterBand* poBand = poDataset->GetRasterBand(i);
1024  int shift = -1;
1025  if (poBand->GetColorInterpretation() == GCI_RedBand) {
1026  shift = 0;
1027  } else if (poBand->GetColorInterpretation() == GCI_GreenBand) {
1028  shift = 1;
1029  } else if (poBand->GetColorInterpretation() == GCI_BlueBand) {
1030  shift = 2;
1031  } else if (poBand->GetColorInterpretation() == GCI_AlphaBand) {
1032  shift = 3;
1033  } else {
1034  WRITE_MESSAGE("Unknown color band in " + d.filename + ", maybe fox can parse it.");
1035  valid = false;
1036  break;
1037  }
1038  assert(xSize == poBand->GetXSize() && ySize == poBand->GetYSize());
1039  if (poBand->RasterIO(GF_Read, 0, 0, xSize, ySize, ((unsigned char*)result) + shift, xSize, ySize, GDT_Byte, 4, 4 * xSize) == CE_Failure) {
1040  valid = false;
1041  break;
1042  }
1043  }
1044  GDALClose(poDataset);
1045  if (valid) {
1046  return new FXImage(getApp(), result, IMAGE_OWNED | IMAGE_KEEP | IMAGE_SHMI | IMAGE_SHMP, xSize, ySize);
1047  }
1048  FXFREE(&result);
1049 #endif
1050  return 0;
1051 }
1052 
1053 
1054 void
1056  glPushName(0);
1057  myDecalsLock.lock();
1058  for (std::vector<GUISUMOAbstractView::Decal>::iterator l = myDecals.begin(); l != myDecals.end(); ++l) {
1060  if (d.skip2D) {
1061  continue;
1062  }
1063  if (!d.initialised) {
1064  try {
1065  FXImage* img = checkGDALImage(d);
1066  if (img == 0) {
1067  img = MFXImageHelper::loadImage(getApp(), d.filename);
1068  }
1070  WRITE_WARNING("Scaling '" + d.filename + "'.");
1071  }
1072  d.glID = GUITexturesHelper::add(img);
1073  d.initialised = true;
1074  d.image = img;
1075  } catch (InvalidArgument& e) {
1076  WRITE_ERROR("Could not load '" + d.filename + "'.\n" + e.what());
1077  d.skip2D = true;
1078  }
1079  }
1080  glPushMatrix();
1081  glTranslated(d.centerX, d.centerY, d.layer);
1082  glRotated(d.rot, 0, 0, 1);
1083  glColor3d(1, 1, 1);
1084  const SUMOReal halfWidth = d.width / 2.;
1085  const SUMOReal halfHeight = d.height / 2.;
1086  GUITexturesHelper::drawTexturedBox(d.glID, -halfWidth, -halfHeight, halfWidth, halfHeight);
1087  glPopMatrix();
1088  }
1089  myDecalsLock.unlock();
1090  glPopName();
1091 }
1092 
1093 
1094 // ------------ Additional visualisations
1095 bool
1097  if (myAdditionallyDrawn.find(which) == myAdditionallyDrawn.end()) {
1098  myAdditionallyDrawn[which] = 1;
1099  } else {
1100  myAdditionallyDrawn[which] = myAdditionallyDrawn[which] + 1;
1101  }
1102  update();
1103  return true;
1104 }
1105 
1106 
1107 bool
1109  if (getTrackedID() == static_cast<int>(which->getGlID())) {
1110  stopTrack();
1111  }
1112  if (myAdditionallyDrawn.find(which) == myAdditionallyDrawn.end()) {
1113  return false;
1114  }
1115  int cnt = myAdditionallyDrawn[which];
1116  if (cnt == 1) {
1117  myAdditionallyDrawn.erase(which);
1118  } else {
1119  myAdditionallyDrawn[which] = myAdditionallyDrawn[which] - 1;
1120  }
1121  update();
1122  return true;
1123 }
1124 
1125 
1126 void
1128  Boundary bound = myChanger->getViewport(fixRatio);
1129  glMatrixMode(GL_PROJECTION);
1130  glLoadIdentity();
1131  // as a rough rule, each GLObject is drawn at z = -GUIGlObjectType
1132  // thus, objects with a higher value will be closer (drawn on top)
1133  // // @todo last param should be 0 after modifying all glDraw methods
1134  glOrtho(0, getWidth(), 0, getHeight(), -GLO_MAX - 1, GLO_MAX + 1);
1135  glMatrixMode(GL_MODELVIEW);
1136  glLoadIdentity();
1137  SUMOReal scaleX = (SUMOReal)getWidth() / bound.getWidth();
1138  SUMOReal scaleY = (SUMOReal)getHeight() / bound.getHeight();
1139  glScaled(scaleX, scaleY, 1);
1140  glTranslated(-bound.xmin(), -bound.ymin(), 0);
1141 }
1142 
1143 
1144 SUMOReal
1146  return myApp->getDelay();
1147 }
1148 
1149 /****************************************************************************/
1150 
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:46
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:91
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:77
GUIDialog_EditViewport * myViewportChooser
A RT-tree for efficient storing of SUMO'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:115
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'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()
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:159
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:71
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:477
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:48
#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:200
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
GLCanvas - ID.
Definition: GUIAppEnum.h:197
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.
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:218
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'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.
const std::string & getFullName() const
Returns the full name appearing in the tool tip.
Definition: GUIGlObject.h:107
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:262
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.