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