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-sim.org/
14 // Copyright (C) 2001-2014 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  // check whether the current object is above a previous one
288  if (layer > maxLayer) {
289  idMax = id;
290  maxLayer = layer;
291  }
292  }
294  }
295  return idMax;
296 }
297 
298 
299 std::vector<GUIGlID>
301  Boundary selection;
302  selection.add(pos);
303  selection.grow(radius);
304  const std::vector<GUIGlID> ids = getObjectsInBoundary(selection);
305  std::vector<GUIGlID> result;
306  // Interpret results
307  for (std::vector<GUIGlID>::const_iterator it = ids.begin(); it != ids.end(); it++) {
308  GUIGlID id = *it;
310  if (o == 0) {
311  continue;
312  }
313  if (o->getGlID() == 0) {
314  continue;
315  }
316  //std::cout << "point selection hit " << o->getMicrosimID() << "\n";
317  GUIGlObjectType type = o->getType();
318  if (type != 0) {
319  result.push_back(id);
320  }
322  }
323  return result;
324 }
325 
326 
327 std::vector<GUIGlID>
329  const int NB_HITS_MAX = 1024 * 1024;
330  // Prepare the selection mode
331  static GUIGlID hits[NB_HITS_MAX];
332  static GLint nb_hits = 0;
333  glSelectBuffer(NB_HITS_MAX, hits);
334  glInitNames();
335 
336  Boundary oldViewPort = myChanger->getViewport(false); // backup the actual viewPort
337  myChanger->setViewport(bound);
338  applyGLTransform(false);
339 
340  // paint in select mode
341  int hits2 = doPaintGL(GL_SELECT, bound);
342  // Get the results
343  nb_hits = glRenderMode(GL_RENDER);
344  if (nb_hits == -1) {
345  myApp->setStatusBarText("Selection in boundary failed. Try to select fewer than " + toString(hits2) + " items");
346  }
347  std::vector<GUIGlID> result;
348  for (int i = 0; i < nb_hits; ++i) {
349  assert(i * 4 + 3 < NB_HITS_MAX);
350  result.push_back(hits[i * 4 + 3]);
351  }
352  // switch viewport back to normal
353  myChanger->setViewport(oldViewPort);
354  return result;
355 }
356 
357 
358 void
360  if (id != 0) {
362  if (object != 0) {
364  pos.add(0, p2m(15));
365  GLHelper::drawTextBox(object->getFullName(), pos, GLO_MAX - 1, p2m(20), RGBColor::BLACK, RGBColor(255, 179, 0, 255));
367  }
368  }
369 }
370 
371 
372 void
374  glEnable(GL_DEPTH_TEST);
375  glLineWidth(1);
376 
377  SUMOReal xmin = myGrid->xmin();
378  SUMOReal ymin = myGrid->ymin();
379  SUMOReal ypos = ymin;
380  SUMOReal xpos = xmin;
381  SUMOReal xend = myGrid->xmax();
382  SUMOReal yend = myGrid->ymax();
383 
384  glTranslated(0, 0, .55);
385  glColor3d(0.5, 0.5, 0.5);
386  // draw horizontal lines
387  glBegin(GL_LINES);
388  for (; ypos < yend;) {
389  glVertex2d(xmin, ypos);
390  glVertex2d(xend, ypos);
392  }
393  // draw vertical lines
394  for (; xpos < xend;) {
395  glVertex2d(xpos, ymin);
396  glVertex2d(xpos, yend);
398  }
399  glEnd();
400  glTranslated(0, 0, -.55);
401 }
402 
403 
404 void
406  // compute the scale bar length
407  size_t length = 1;
408  const std::string text("10000000000");
409  size_t noDigits = 1;
410  size_t pixelSize = (size_t) m2p((SUMOReal) length);
411  while (pixelSize <= 20) {
412  length *= 10;
413  noDigits++;
414  if (noDigits > text.length()) {
415  return;
416  }
417  pixelSize = (size_t) m2p((SUMOReal) length);
418  }
419  SUMOReal lineWidth = 1.0;
420  glLineWidth((SUMOReal) lineWidth);
421 
422  glMatrixMode(GL_PROJECTION);
423  glPushMatrix();
424  glLoadIdentity();
425  glMatrixMode(GL_MODELVIEW);
426  glPushMatrix();
427  glLoadIdentity();
428 
429  // draw the scale bar
430  glDisable(GL_TEXTURE_2D);
431  glDisable(GL_ALPHA_TEST);
432  glDisable(GL_BLEND);
433  glEnable(GL_DEPTH_TEST);
434 
435  SUMOReal len = (SUMOReal) pixelSize / (SUMOReal)(getWidth() - 1) * (SUMOReal) 2.0;
436  glColor3d(0, 0, 0);
437  double o = double(15) / double(getHeight());
438  double o2 = o + o;
439  double oo = double(5) / double(getHeight());
440  glBegin(GL_LINES);
441  // vertical
442  glVertex2d(-.98, -1. + o);
443  glVertex2d(-.98 + len, -1. + o);
444  // tick at begin
445  glVertex2d(-.98, -1. + o);
446  glVertex2d(-.98, -1. + o2);
447  // tick at end
448  glVertex2d(-.98 + len, -1. + o);
449  glVertex2d(-.98 + len, -1. + o2);
450  glEnd();
451 
452  SUMOReal w = SUMOReal(35) / SUMOReal(getWidth());
453  SUMOReal h = SUMOReal(35) / SUMOReal(getHeight());
454  pfSetPosition(SUMOReal(-0.99), SUMOReal(1. - o2 - oo));
455  pfSetScaleXY(w, h);
456  glRotated(180, 1, 0, 0);
457  pfDrawString("0m");
458  glRotated(-180, 1, 0, 0);
459 
460  pfSetPosition(SUMOReal(-.99 + len), SUMOReal(1. - o2 - oo));
461  glRotated(180, 1, 0, 0);
462  pfDrawString((text.substr(0, noDigits) + "m").c_str());
463  glRotated(-180, 1, 0, 0);
464 
465  // restore matrices
466  glMatrixMode(GL_PROJECTION);
467  glPopMatrix();
468  glMatrixMode(GL_MODELVIEW);
469  glPopMatrix();
470 }
471 
472 
473 SUMOReal
475  return meter * getWidth() / myChanger->getViewport().getWidth();
476 }
477 
478 
479 SUMOReal
481  return pixel * myChanger->getViewport().getWidth() / getWidth();
482 }
483 
484 
485 void
488 }
489 
490 
491 void
492 GUISUMOAbstractView::centerTo(GUIGlID id, bool applyZoom, SUMOReal zoomDist) {
494  if (o != 0 && dynamic_cast<GUIGlObject*>(o) != 0) {
495  if (applyZoom && zoomDist < 0) {
497  } else {
498  myChanger->centerTo(o->getCenteringBoundary().getCenter(), zoomDist, applyZoom);
499  }
500  }
502 }
503 
504 
505 void
507  myChanger->setViewport(bound);
508  update();
509 }
510 
511 /*
512 bool
513 GUISUMOAbstractView::allowRotation() const
514 {
515  return myParent->allowRotation();
516 }
517 */
518 
519 void
523 }
524 
525 
526 FXbool
528  FXbool ret = FXGLCanvas::makeCurrent();
529  return ret;
530 }
531 
532 
533 long
535  if (makeCurrent()) {
536  glViewport(0, 0, getWidth() - 1, getHeight() - 1);
537  glClearColor(
542  doInit();
543  myAmInitialised = true;
544  makeNonCurrent();
545  checkSnapshots();
546  }
547  return 1;
548 }
549 
550 
551 long
553  if (!isEnabled() || !myAmInitialised) {
554  return 1;
555  }
556  if (makeCurrent()) {
557  paintGL();
558  makeNonCurrent();
559  }
560  return 1;
561 }
562 
563 
564 void
566  delete myPopup;
567  myPopup = 0;
568 }
569 
570 
571 long
572 GUISUMOAbstractView::onLeftBtnPress(FXObject*, FXSelector , void* data) {
573  destroyPopup();
574  FXEvent* e = (FXEvent*) data;
575  // check whether the selection-mode is activated
576  if (e->state & CONTROLMASK) {
577  // try to get the object-id if so
578  if (makeCurrent()) {
579  unsigned int id = getObjectUnderCursor();
580  if (id != 0) {
582  }
583  makeNonCurrent();
584  if (id != 0) {
585  // possibly, the selection-colouring is used,
586  // so we should update the screen again...
587  update();
588  }
589  }
590  }
591  myChanger->onLeftBtnPress(data);
592  grab();
593  return 1;
594 }
595 
596 
597 long
599  destroyPopup();
601  if (myApp->isGaming()) {
603  }
604  ungrab();
605  return 1;
606 }
607 
608 
609 long
610 GUISUMOAbstractView::onRightBtnPress(FXObject*, FXSelector , void* data) {
611  destroyPopup();
612  myChanger->onRightBtnPress(data);
613  grab();
614  return 1;
615 }
616 
617 
618 long
619 GUISUMOAbstractView::onRightBtnRelease(FXObject* o, FXSelector sel, void* data) {
620  destroyPopup();
621  onMouseMove(o, sel, data);
622  if (!myChanger->onRightBtnRelease(data) && !myApp->isGaming()) {
624  }
625  ungrab();
626  return 1;
627 }
628 
629 
630 long
631 GUISUMOAbstractView::onMouseWheel(FXObject*, FXSelector , void* data) {
632  if (!myApp->isGaming()) {
633  myChanger->onMouseWheel(data);
634  }
635  return 1;
636 }
637 
638 
639 long
640 GUISUMOAbstractView::onMouseMove(FXObject*, FXSelector , void* data) {
642  myChanger->onMouseMove(data);
643  }
644  const SUMOReal xpos = myChanger->getXPos();
645  const SUMOReal ypos = myChanger->getYPos();
646  const SUMOReal zoom = myChanger->getZoom();
647  if (myViewportChooser != 0 &&
648  (xpos != myChanger->getXPos() || ypos != myChanger->getYPos() || zoom != myChanger->getZoom())) {
650  }
652  return 1;
653 }
654 
655 
656 long
657 GUISUMOAbstractView::onMouseLeft(FXObject*, FXSelector , void* /*data*/) {
658  return 1;
659 }
660 
661 
662 void
664  ungrab();
665  if (!isEnabled() || !myAmInitialised) {
666  return;
667  }
668  if (makeCurrent()) {
669  // initialise the select mode
670  unsigned int id = getObjectUnderCursor();
671  GUIGlObject* o = 0;
672  if (id != 0) {
674  } else {
676  }
677  if (o != 0) {
678  myPopup = o->getPopUpMenu(*myApp, *this);
679  int x, y;
680  FXuint b;
681  myApp->getCursorPosition(x, y, b);
682  myPopup->setX(x + myApp->getX());
683  myPopup->setY(y + myApp->getY());
684  myPopup->create();
685  myPopup->show();
688  }
689  makeNonCurrent();
690  }
691 }
692 
693 
694 long
695 GUISUMOAbstractView::onKeyPress(FXObject* o, FXSelector sel, void* data) {
696  FXEvent* e = (FXEvent*) data;
697  if ((e->state & ALTMASK) != 0) {
698  setDefaultCursor(getApp()->getDefaultCursor(DEF_CROSSHAIR_CURSOR));
699  grabKeyboard();
700  }
701  /*
702  switch(e->code) {
703  case KEY_Left:
704  myChanger->move((SUMOReal) -p2m((SUMOReal) getWidth()/10), 0);
705  break;
706  case KEY_Right:
707  myChanger->move((SUMOReal) p2m((SUMOReal) getWidth()/10), 0);
708  break;
709  case KEY_Up:
710  myChanger->move(0, (SUMOReal) -p2m((SUMOReal) getHeight()/10));
711  break;
712  case KEY_Down:
713  myChanger->move(0, (SUMOReal) p2m((SUMOReal) getHeight()/10));
714  break;
715  default:
716  break;
717  }
718  */
719  return FXGLCanvas::onKeyPress(o, sel, data);
720 }
721 
722 
723 long
724 GUISUMOAbstractView::onKeyRelease(FXObject* o, FXSelector sel, void* data) {
725  FXEvent* e = (FXEvent*) data;
726  if ((e->state & ALTMASK) == 0) {
727  ungrabKeyboard();
728  setDefaultCursor(getApp()->getDefaultCursor(DEF_ARROW_CURSOR));
729  }
730  return FXGLCanvas::onKeyRelease(o, sel, data);
731 }
732 
733 
734 // ------------ Dealing with snapshots
735 void
736 GUISUMOAbstractView::setSnapshots(std::map<SUMOTime, std::string> snaps) {
737  mySnapshots.insert(snaps.begin(), snaps.end());
738 }
739 
740 
741 std::string
742 GUISUMOAbstractView::makeSnapshot(const std::string& destFile) {
743  std::string errorMessage;
744  FXString ext = FXPath::extension(destFile.c_str());
745  bool useGL2PS = ext == "ps" || ext == "eps" || ext == "pdf" || ext == "svg" || ext == "tex" || ext == "pgf";
746 
747  for (int i = 0; i < 10 && !makeCurrent(); ++i) {
749  }
750  // draw
751  glClearColor(
756  glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
757  glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
758 
760  glEnable(GL_DITHER);
761  } else {
762  glDisable(GL_DITHER);
763  }
765  glEnable(GL_BLEND);
766  glEnable(GL_POLYGON_SMOOTH);
767  glEnable(GL_LINE_SMOOTH);
768  } else {
769  glDisable(GL_BLEND);
770  glDisable(GL_POLYGON_SMOOTH);
771  glDisable(GL_LINE_SMOOTH);
772  }
773 
775 
776  if (useGL2PS) {
777  GLint format = GL2PS_PS;
778  if (ext == "ps") {
779  format = GL2PS_PS;
780  } else if (ext == "eps") {
781  format = GL2PS_EPS;
782  } else if (ext == "pdf") {
783  format = GL2PS_PDF;
784  } else if (ext == "tex") {
785  format = GL2PS_TEX;
786  } else if (ext == "svg") {
787  format = GL2PS_SVG;
788  } else if (ext == "pgf") {
789  format = GL2PS_PGF;
790  } else {
791  return "Could not save '" + destFile + "'.\n Unrecognized format '" + std::string(ext.text()) + "'.";
792  }
793  FILE* fp = fopen(destFile.c_str(), "wb");
794  if (fp == 0) {
795  return "Could not save '" + destFile + "'.\n Could not open file for writing";
796  }
797  GLint buffsize = 0, state = GL2PS_OVERFLOW;
798  GLint viewport[4];
799  glGetIntegerv(GL_VIEWPORT, viewport);
800  while (state == GL2PS_OVERFLOW) {
801  buffsize += 1024 * 1024;
802  gl2psBeginPage(destFile.c_str(), "sumo-gui; http://sumo-sim.org", viewport, format, GL2PS_SIMPLE_SORT,
804  GL_RGBA, 0, NULL, 0, 0, 0, buffsize, fp, "out.eps");
805  glMatrixMode(GL_MODELVIEW);
806  glPushMatrix();
807  glDisable(GL_TEXTURE_2D);
808  glDisable(GL_ALPHA_TEST);
809  glDisable(GL_BLEND);
810  glEnable(GL_DEPTH_TEST);
811  // compute lane width
812  // draw decals (if not in grabbing mode)
813  if (!myUseToolTips) {
814  drawDecals();
816  paintGLGrid();
817  }
818  }
819  glLineWidth(1);
820  glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
821  Boundary viewPort = myChanger->getViewport();
822  float minB[2];
823  float maxB[2];
824  minB[0] = viewPort.xmin();
825  minB[1] = viewPort.ymin();
826  maxB[0] = viewPort.xmax();
827  maxB[1] = viewPort.ymax();
829  glEnable(GL_POLYGON_OFFSET_FILL);
830  glEnable(GL_POLYGON_OFFSET_LINE);
831  myGrid->Search(minB, maxB, *myVisualizationSettings);
832 
834  displayLegend();
835  }
836  state = gl2psEndPage();
837  glFinish();
838  }
839  fclose(fp);
840  } else {
841  doPaintGL(GL_RENDER, myChanger->getViewport());
843  displayLegend();
844  }
845  swapBuffers();
846  glFinish();
847  FXColor* buf;
848  FXMALLOC(&buf, FXColor, getWidth()*getHeight());
849  // read from the back buffer
850  glReadBuffer(GL_BACK);
851  // Read the pixels
852  glReadPixels(0, 0, getWidth(), getHeight(), GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid*)buf);
853  makeNonCurrent();
854  update();
855  // mirror
856  size_t mwidth = getWidth();
857  size_t mheight = getHeight();
858  FXColor* paa = buf;
859  FXColor* pbb = buf + mwidth * (mheight - 1);
860  do {
861  FXColor* pa = paa;
862  paa += mwidth;
863  FXColor* pb = pbb;
864  pbb -= mwidth;
865  do {
866  FXColor t = *pa;
867  *pa++ = *pb;
868  *pb++ = t;
869  } while (pa < paa);
870  } while (paa < pbb);
871  try {
872  if (!MFXImageHelper::saveImage(destFile, getWidth(), getHeight(), buf)) {
873  errorMessage = "Could not save '" + destFile + "'.";
874  }
875  } catch (InvalidArgument& e) {
876  errorMessage = "Could not save '" + destFile + "'.\n" + e.what();
877  }
878  FXFREE(&buf);
879  }
880  return errorMessage;
881 }
882 
883 
884 void
886  std::map<SUMOTime, std::string>::iterator snapIt = mySnapshots.find(getCurrentTimeStep());
887  if (snapIt != mySnapshots.end()) {
888  std::string error = makeSnapshot(snapIt->second);
889  if (error != "") {
890  WRITE_WARNING(error);
891  }
892  }
893 }
894 
895 
896 void
898  if (myVisualizationChanger == 0) {
903  myVisualizationChanger->create();
904  } else {
906  }
907  myVisualizationChanger->show();
908 }
909 
910 
911 void
913  if (myViewportChooser == 0) {
915  new GUIDialog_EditViewport(this, "Edit Viewport...", 0, 0);
916  myViewportChooser->create();
917  }
920  myViewportChooser->show();
921 }
922 
923 
924 void
925 GUISUMOAbstractView::setViewport(const Position& lookFrom, const Position& /* lookAt */) {
926  myChanger->setViewport(lookFrom.z(), lookFrom.x(), lookFrom.y());
927  update();
928 }
929 
930 
931 void
933  myUseToolTips = val;
934 }
935 
936 
937 
938 SUMOReal
940  return myGrid->getWidth();
941 }
942 
943 
944 SUMOReal
946  return myGrid->getHeight();
947 }
948 
949 
950 FXComboBox&
953 }
954 
955 
956 FXImage*
958 #ifdef HAVE_GDAL
959  GDALAllRegister();
960  GDALDataset* poDataset = (GDALDataset*)GDALOpen(d.filename.c_str(), GA_ReadOnly);
961  if (poDataset == 0) {
962  return 0;
963  }
964  const int xSize = poDataset->GetRasterXSize();
965  const int ySize = poDataset->GetRasterYSize();
966  // checking for geodata in the picture and try to adapt position and scale
967  if (d.width <= 0.) {
968  double adfGeoTransform[6];
969  if (poDataset->GetGeoTransform(adfGeoTransform) == CE_None) {
970  Position topLeft(adfGeoTransform[0], adfGeoTransform[3]);
971  const double horizontalSize = xSize * adfGeoTransform[1];
972  const double verticalSize = ySize * adfGeoTransform[5];
973  Position bottomRight(topLeft.x() + horizontalSize, topLeft.y() + verticalSize);
975  d.width = bottomRight.x() - topLeft.x();
976  d.height = topLeft.y() - bottomRight.y();
977  d.centerX = (topLeft.x() + bottomRight.x()) / 2;
978  d.centerY = (topLeft.y() + bottomRight.y()) / 2;
979  //WRITE_MESSAGE("proj: " + toString(poDataset->GetProjectionRef()) + " dim: " + toString(d.width) + "," + toString(d.height) + " center: " + toString(d.centerX) + "," + toString(d.centerY));
980  } else {
981  WRITE_WARNING("Could not convert coordinates in " + d.filename + ".");
982  }
983  }
984  }
985 #endif
986  if (d.width <= 0.) {
987  d.width = getGridWidth();
988  d.height = getGridHeight();
989  }
990 
991  // trying to read the picture
992 #ifdef HAVE_GDAL
993  const int picSize = xSize * ySize;
994  FXColor* result;
995  if (!FXMALLOC(&result, FXColor, picSize)) {
996  WRITE_WARNING("Could not allocate memory for " + d.filename + ".");
997  return 0;
998  }
999  for (int j = 0; j < picSize; j++) {
1000  result[j] = FXRGB(0, 0, 0);
1001  }
1002  bool valid = true;
1003  for (int i = 1; i <= poDataset->GetRasterCount(); i++) {
1004  GDALRasterBand* poBand = poDataset->GetRasterBand(i);
1005  int shift = -1;
1006  if (poBand->GetColorInterpretation() == GCI_RedBand) {
1007  shift = 0;
1008  } else if (poBand->GetColorInterpretation() == GCI_GreenBand) {
1009  shift = 1;
1010  } else if (poBand->GetColorInterpretation() == GCI_BlueBand) {
1011  shift = 2;
1012  } else if (poBand->GetColorInterpretation() == GCI_AlphaBand) {
1013  shift = 3;
1014  } else {
1015  WRITE_MESSAGE("Unknown color band in " + d.filename + ", maybe fox can parse it.");
1016  valid = false;
1017  break;
1018  }
1019  assert(xSize == poBand->GetXSize() && ySize == poBand->GetYSize());
1020  if (poBand->RasterIO(GF_Read, 0, 0, xSize, ySize, ((unsigned char*)result) + shift, xSize, ySize, GDT_Byte, 4, 4 * xSize) == CE_Failure) {
1021  valid = false;
1022  break;
1023  }
1024  }
1025  GDALClose(poDataset);
1026  if (valid) {
1027  return new FXImage(getApp(), result, IMAGE_OWNED | IMAGE_KEEP | IMAGE_SHMI | IMAGE_SHMP, xSize, ySize);
1028  }
1029  FXFREE(&result);
1030 #endif
1031  return 0;
1032 }
1033 
1034 
1035 void
1037  glPushName(0);
1038  myDecalsLock.lock();
1039  for (std::vector<GUISUMOAbstractView::Decal>::iterator l = myDecals.begin(); l != myDecals.end(); ++l) {
1041  if (d.skip2D) {
1042  continue;
1043  }
1044  if (!d.initialised) {
1045  try {
1046  FXImage* img = checkGDALImage(d);
1047  if (img == 0) {
1048  img = MFXImageHelper::loadImage(getApp(), d.filename);
1049  }
1051  WRITE_WARNING("Scaling '" + d.filename + "'.");
1052  }
1053  d.glID = GUITexturesHelper::add(img);
1054  d.initialised = true;
1055  d.image = img;
1056  } catch (InvalidArgument& e) {
1057  WRITE_ERROR("Could not load '" + d.filename + "'.\n" + e.what());
1058  d.skip2D = true;
1059  }
1060  }
1061  glPushMatrix();
1062  glTranslated(d.centerX, d.centerY, d.layer);
1063  glRotated(d.rot, 0, 0, 1);
1064  glColor3d(1, 1, 1);
1065  const SUMOReal halfWidth = d.width / 2.;
1066  const SUMOReal halfHeight = d.height / 2.;
1067  GUITexturesHelper::drawTexturedBox(d.glID, -halfWidth, -halfHeight, halfWidth, halfHeight);
1068  glPopMatrix();
1069  }
1070  myDecalsLock.unlock();
1071  glPopName();
1072 }
1073 
1074 
1075 // ------------ Additional visualisations
1076 bool
1078  if (myAdditionallyDrawn.find(which) == myAdditionallyDrawn.end()) {
1079  myAdditionallyDrawn[which] = 1;
1080  } else {
1081  myAdditionallyDrawn[which] = myAdditionallyDrawn[which] + 1;
1082  }
1083  update();
1084  return true;
1085 }
1086 
1087 
1088 bool
1090  if (getTrackedID() == static_cast<int>(which->getGlID())) {
1091  stopTrack();
1092  }
1093  if (myAdditionallyDrawn.find(which) == myAdditionallyDrawn.end()) {
1094  return false;
1095  }
1096  int cnt = myAdditionallyDrawn[which];
1097  if (cnt == 1) {
1098  myAdditionallyDrawn.erase(which);
1099  } else {
1100  myAdditionallyDrawn[which] = myAdditionallyDrawn[which] - 1;
1101  }
1102  update();
1103  return true;
1104 }
1105 
1106 
1107 void
1109  Boundary bound = myChanger->getViewport(fixRatio);
1110  glMatrixMode(GL_PROJECTION);
1111  glLoadIdentity();
1112  // as a rough rule, each GLObject is drawn at z = -GUIGlObjectType
1113  // thus, objects with a higher value will be closer (drawn on top)
1114  // // @todo last param should be 0 after modifying all glDraw methods
1115  glOrtho(0, getWidth(), 0, getHeight(), -GLO_MAX - 1, GLO_MAX + 1);
1116  glMatrixMode(GL_MODELVIEW);
1117  glLoadIdentity();
1118  SUMOReal scaleX = (SUMOReal)getWidth() / bound.getWidth();
1119  SUMOReal scaleY = (SUMOReal)getHeight() / bound.getHeight();
1120  glScaled(scaleX, scaleY, 1);
1121  glTranslated(-bound.xmin(), -bound.ymin(), 0);
1122 }
1123 
1124 /****************************************************************************/
1125 
#define GL2PS_PS
Definition: gl2ps.h:100
void paintGLGrid()
paints a grid
A decal (an image) that can be shown.
GL2PSDLL_API GLint gl2psBeginPage(const char *title, const char *producer, GLint viewport[4], GLint format, GLint sort, GLint options, GLint colormode, GLint colorsize, GL2PSrgba *colormap, GLint nr, GLint ng, GLint nb, GLint buffersize, FILE *stream, const char *filename)
Definition: gl2ps.c:5650
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 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.
GLCanvas - ID.
Definition: GUIAppEnum.h:191
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:97
#define GEO_OUTPUT_ACCURACY
Definition: config.h:16
bool x2cartesian(Position &from, bool includeInBoundary=true)
GUIMainWindow * myApp
The application.
#define GL2PS_DRAW_BACKGROUND
Definition: gl2ps.h:126
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:196
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)
#define GL2PS_PGF
Definition: gl2ps.h:105
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)
#define GL2PS_USE_CURRENT_VIEWPORT
Definition: gl2ps.h:135
virtual GUIGLObjectPopupMenu * getPopUpMenu(GUIMainWindow &app, GUISUMOAbstractView &parent)=0
Returns an own popup-menu.
FXComboBox & getColoringSchemesCombo()
GL2PSDLL_API GLint gl2psEndPage(void)
Definition: gl2ps.c:5817
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.
#define GL2PS_TEX
Definition: gl2ps.h:102
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
#define GL2PS_SIMPLE_SORT
Definition: gl2ps.h:110
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:396
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)
#define GL2PS_PDF
Definition: gl2ps.h:103
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
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)
#define GL2PS_SVG
Definition: gl2ps.h:104
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:215
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
#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.
#define GL2PS_OVERFLOW
Definition: gl2ps.h:120
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.
#define GL2PS_EPS
Definition: gl2ps.h:101