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
592  destroyPopup();
593  if (!myChanger->onRightBtnRelease(data) && !myApp->isGaming()) {
595  }
596  ungrab();
597  return 1;
598 }
599 
600 
601 long
602 GUISUMOAbstractView::onMouseWheel(FXObject*, FXSelector , void* data) {
603  myChanger->onMouseWheel(data);
604  return 1;
605 }
606 
607 
608 long
609 GUISUMOAbstractView::onMouseMove(FXObject*, FXSelector , void* data) {
610  SUMOReal xpos = myChanger->getXPos();
611  SUMOReal ypos = myChanger->getYPos();
612  SUMOReal zoom = myChanger->getZoom();
614  myChanger->onMouseMove(data);
615  }
616  if (myViewportChooser != 0 &&
617  (xpos != myChanger->getXPos() || ypos != myChanger->getYPos() || zoom != myChanger->getZoom())) {
619  }
621  return 1;
622 }
623 
624 
625 long
626 GUISUMOAbstractView::onMouseLeft(FXObject*, FXSelector , void* /*data*/) {
627  return 1;
628 }
629 
630 
631 void
633  ungrab();
634  if (!isEnabled() || !myAmInitialised) {
635  return;
636  }
637  if (makeCurrent()) {
638  // initialise the select mode
639  unsigned int id = getObjectUnderCursor();
640  GUIGlObject* o = 0;
641  if (id != 0) {
643  } else {
645  }
646  if (o != 0) {
647  myPopup = o->getPopUpMenu(*myApp, *this);
648  int x, y;
649  FXuint b;
650  myApp->getCursorPosition(x, y, b);
651  myPopup->setX(x + myApp->getX());
652  myPopup->setY(y + myApp->getY());
653  myPopup->create();
654  myPopup->show();
657  }
658  makeNonCurrent();
659  }
660 }
661 
662 
663 long
664 GUISUMOAbstractView::onKeyPress(FXObject* o, FXSelector sel, void* data) {
665  FXEvent* e = (FXEvent*) data;
666  if ((e->state & ALTMASK) != 0) {
667  setDefaultCursor(getApp()->getDefaultCursor(DEF_CROSSHAIR_CURSOR));
668  grabKeyboard();
669  }
670  /*
671  switch(e->code) {
672  case KEY_Left:
673  myChanger->move((SUMOReal) -p2m((SUMOReal) getWidth()/10), 0);
674  break;
675  case KEY_Right:
676  myChanger->move((SUMOReal) p2m((SUMOReal) getWidth()/10), 0);
677  break;
678  case KEY_Up:
679  myChanger->move(0, (SUMOReal) -p2m((SUMOReal) getHeight()/10));
680  break;
681  case KEY_Down:
682  myChanger->move(0, (SUMOReal) p2m((SUMOReal) getHeight()/10));
683  break;
684  default:
685  break;
686  }
687  */
688  return FXGLCanvas::onKeyPress(o, sel, data);
689 }
690 
691 
692 long
693 GUISUMOAbstractView::onKeyRelease(FXObject* o, FXSelector sel, void* data) {
694  FXEvent* e = (FXEvent*) data;
695  if ((e->state & ALTMASK) == 0) {
696  ungrabKeyboard();
697  setDefaultCursor(getApp()->getDefaultCursor(DEF_ARROW_CURSOR));
698  }
699  return FXGLCanvas::onKeyRelease(o, sel, data);
700 }
701 
702 
703 // ------------ Dealing with snapshots
704 void
705 GUISUMOAbstractView::setSnapshots(std::map<SUMOTime, std::string> snaps) {
706  mySnapshots.insert(snaps.begin(), snaps.end());
707 }
708 
709 
710 std::string
711 GUISUMOAbstractView::makeSnapshot(const std::string& destFile) {
712  std::string errorMessage;
713  FXString ext = FXPath::extension(destFile.c_str());
714  bool useGL2PS = ext == "ps" || ext == "eps" || ext == "pdf" || ext == "svg" || ext == "tex" || ext == "pgf";
715 
716  for (int i = 0; i < 10 && !makeCurrent(); ++i) {
718  }
719  // draw
720  glClearColor(
725  glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
726  glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
727 
729  glEnable(GL_DITHER);
730  } else {
731  glDisable(GL_DITHER);
732  }
734  glEnable(GL_BLEND);
735  glEnable(GL_POLYGON_SMOOTH);
736  glEnable(GL_LINE_SMOOTH);
737  } else {
738  glDisable(GL_BLEND);
739  glDisable(GL_POLYGON_SMOOTH);
740  glDisable(GL_LINE_SMOOTH);
741  }
742 
744 
745  if (useGL2PS) {
746  GLint format = GL2PS_PS;
747  if (ext == "ps") {
748  format = GL2PS_PS;
749  } else if (ext == "eps") {
750  format = GL2PS_EPS;
751  } else if (ext == "pdf") {
752  format = GL2PS_PDF;
753  } else if (ext == "tex") {
754  format = GL2PS_TEX;
755  } else if (ext == "svg") {
756  format = GL2PS_SVG;
757  } else if (ext == "pgf") {
758  format = GL2PS_PGF;
759  } else {
760  return "Could not save '" + destFile + "'.\n Unrecognized format '" + std::string(ext.text()) + "'.";
761  }
762  FILE* fp = fopen(destFile.c_str(), "wb");
763  if (fp == 0) {
764  return "Could not save '" + destFile + "'.\n Could not open file for writing";
765  }
766  GLint buffsize = 0, state = GL2PS_OVERFLOW;
767  GLint viewport[4];
768  glGetIntegerv(GL_VIEWPORT, viewport);
769  while (state == GL2PS_OVERFLOW) {
770  buffsize += 1024 * 1024;
771  gl2psBeginPage(destFile.c_str(), "sumo-gui; http://sumo.sf.net", viewport, format, GL2PS_SIMPLE_SORT,
773  GL_RGBA, 0, NULL, 0, 0, 0, buffsize, fp, "out.eps");
774  glMatrixMode(GL_MODELVIEW);
775  glPushMatrix();
776  glDisable(GL_TEXTURE_2D);
777  glDisable(GL_ALPHA_TEST);
778  glDisable(GL_BLEND);
779  glEnable(GL_DEPTH_TEST);
780  // compute lane width
781  // draw decals (if not in grabbing mode)
782  if (!myUseToolTips) {
783  drawDecals();
785  paintGLGrid();
786  }
787  }
788  glLineWidth(1);
789  glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
790  Boundary viewPort = myChanger->getViewport();
791  float minB[2];
792  float maxB[2];
793  minB[0] = viewPort.xmin();
794  minB[1] = viewPort.ymin();
795  maxB[0] = viewPort.xmax();
796  maxB[1] = viewPort.ymax();
798  glEnable(GL_POLYGON_OFFSET_FILL);
799  glEnable(GL_POLYGON_OFFSET_LINE);
800  myGrid->Search(minB, maxB, *myVisualizationSettings);
801 
803  displayLegend();
804  }
805  state = gl2psEndPage();
806  glFinish();
807  }
808  fclose(fp);
809  } else {
810  doPaintGL(GL_RENDER, myChanger->getViewport());
812  displayLegend();
813  }
814  swapBuffers();
815  glFinish();
816  FXColor* buf;
817  FXMALLOC(&buf, FXColor, getWidth()*getHeight());
818  // read from the back buffer
819  glReadBuffer(GL_BACK);
820  // Read the pixels
821  glReadPixels(0, 0, getWidth(), getHeight(), GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid*)buf);
822  makeNonCurrent();
823  update();
824  // mirror
825  size_t mwidth = getWidth();
826  size_t mheight = getHeight();
827  FXColor* paa = buf;
828  FXColor* pbb = buf + mwidth * (mheight - 1);
829  do {
830  FXColor* pa = paa;
831  paa += mwidth;
832  FXColor* pb = pbb;
833  pbb -= mwidth;
834  do {
835  FXColor t = *pa;
836  *pa++ = *pb;
837  *pb++ = t;
838  } while (pa < paa);
839  } while (paa < pbb);
840  try {
841  if (!MFXImageHelper::saveImage(destFile, getWidth(), getHeight(), buf)) {
842  errorMessage = "Could not save '" + destFile + "'.";
843  }
844  } catch (InvalidArgument& e) {
845  errorMessage = "Could not save '" + destFile + "'.\n" + e.what();
846  }
847  FXFREE(&buf);
848  }
849  return errorMessage;
850 }
851 
852 
853 void
855  std::map<SUMOTime, std::string>::iterator snapIt = mySnapshots.find(getCurrentTimeStep());
856  if (snapIt != mySnapshots.end()) {
857  std::string error = makeSnapshot(snapIt->second);
858  if (error != "") {
859  WRITE_WARNING(error);
860  }
861  }
862 }
863 
864 
865 void
867  if (myVisualizationChanger == 0) {
872  myVisualizationChanger->create();
873  } else {
875  }
876  myVisualizationChanger->show();
877 }
878 
879 
880 void
882  if (myViewportChooser == 0) {
884  new GUIDialog_EditViewport(this, "Edit Viewport...", 0, 0);
885  myViewportChooser->create();
886  }
889  myViewportChooser->show();
890 }
891 
892 
893 void
894 GUISUMOAbstractView::setViewport(const Position& lookFrom, const Position& /* lookAt */) {
895  myChanger->setViewport(lookFrom.z(), lookFrom.x(), lookFrom.y());
896  update();
897 }
898 
899 
900 void
902  myUseToolTips = val;
903 }
904 
905 
906 
907 SUMOReal
909  return myGrid->getWidth();
910 }
911 
912 
913 SUMOReal
915  return myGrid->getHeight();
916 }
917 
918 
919 FXComboBox&
922 }
923 
924 
925 FXImage*
927 #ifdef HAVE_GDAL
928  GDALAllRegister();
929  GDALDataset* poDataset = (GDALDataset*)GDALOpen(d.filename.c_str(), GA_ReadOnly);
930  if (poDataset == 0) {
931  return 0;
932  }
933  const int xSize = poDataset->GetRasterXSize();
934  const int ySize = poDataset->GetRasterYSize();
935  // checking for geodata in the picture and try to adapt position and scale
936  if (d.width <= 0.) {
937  double adfGeoTransform[6];
938  if (poDataset->GetGeoTransform(adfGeoTransform) == CE_None) {
939  Position topLeft(adfGeoTransform[0], adfGeoTransform[3]);
940  const double horizontalSize = xSize * adfGeoTransform[1];
941  const double verticalSize = ySize * adfGeoTransform[5];
942  Position bottomRight(topLeft.x() + horizontalSize, topLeft.y() + verticalSize);
944  d.width = bottomRight.x() - topLeft.x();
945  d.height = topLeft.y() - bottomRight.y();
946  d.centerX = (topLeft.x() + bottomRight.x()) / 2;
947  d.centerY = (topLeft.y() + bottomRight.y()) / 2;
948  //WRITE_MESSAGE("proj: " + toString(poDataset->GetProjectionRef()) + " dim: " + toString(d.width) + "," + toString(d.height) + " center: " + toString(d.centerX) + "," + toString(d.centerY));
949  } else {
950  WRITE_WARNING("Could not convert coordinates in " + d.filename + ".");
951  }
952  }
953  }
954 #endif
955  if (d.width <= 0.) {
956  d.width = getGridWidth();
957  d.height = getGridHeight();
958  }
959 
960  // trying to read the picture
961 #ifdef HAVE_GDAL
962  const int picSize = xSize * ySize;
963  FXColor* result;
964  if (!FXMALLOC(&result, FXColor, picSize)) {
965  WRITE_WARNING("Could not allocate memory for " + d.filename + ".");
966  return 0;
967  }
968  for (int j = 0; j < picSize; j++) {
969  result[j] = FXRGB(0, 0, 0);
970  }
971  bool valid = true;
972  for (int i = 1; i <= poDataset->GetRasterCount(); i++) {
973  GDALRasterBand* poBand = poDataset->GetRasterBand(i);
974  int shift = -1;
975  if (poBand->GetColorInterpretation() == GCI_RedBand) {
976  shift = 0;
977  } else if (poBand->GetColorInterpretation() == GCI_GreenBand) {
978  shift = 1;
979  } else if (poBand->GetColorInterpretation() == GCI_BlueBand) {
980  shift = 2;
981  } else if (poBand->GetColorInterpretation() == GCI_AlphaBand) {
982  shift = 3;
983  } else {
984  WRITE_MESSAGE("Unknown color band in " + d.filename + ", maybe fox can parse it.");
985  valid = false;
986  break;
987  }
988  assert(xSize == poBand->GetXSize() && ySize == poBand->GetYSize());
989  if (poBand->RasterIO(GF_Read, 0, 0, xSize, ySize, ((unsigned char*)result) + shift, xSize, ySize, GDT_Byte, 4, 4 * xSize) == CE_Failure) {
990  valid = false;
991  break;
992  }
993  }
994  GDALClose(poDataset);
995  if (valid) {
996  return new FXImage(getApp(), result, IMAGE_OWNED | IMAGE_KEEP | IMAGE_SHMI | IMAGE_SHMP, xSize, ySize);
997  }
998  FXFREE(&result);
999 #endif
1000  return 0;
1001 }
1002 
1003 
1004 void
1006  glPushName(0);
1007  myDecalsLock.lock();
1008  for (std::vector<GUISUMOAbstractView::Decal>::iterator l = myDecals.begin(); l != myDecals.end(); ++l) {
1010  if (d.skip2D) {
1011  continue;
1012  }
1013  if (!d.initialised) {
1014  try {
1015  FXImage* img = checkGDALImage(d);
1016  if (img == 0) {
1017  img = MFXImageHelper::loadImage(getApp(), d.filename);
1018  }
1020  WRITE_WARNING("Scaling '" + d.filename + "'.");
1021  }
1022  d.glID = GUITexturesHelper::add(img);
1023  d.initialised = true;
1024  d.image = img;
1025  } catch (InvalidArgument& e) {
1026  WRITE_ERROR("Could not load '" + d.filename + "'.\n" + e.what());
1027  d.skip2D = true;
1028  }
1029  }
1030  glPushMatrix();
1031  glTranslated(d.centerX, d.centerY, d.layer);
1032  glRotated(d.rot, 0, 0, 1);
1033  glColor3d(1, 1, 1);
1034  const SUMOReal halfWidth = d.width / 2.;
1035  const SUMOReal halfHeight = d.height / 2.;
1036  GUITexturesHelper::drawTexturedBox(d.glID, -halfWidth, -halfHeight, halfWidth, halfHeight);
1037  glPopMatrix();
1038  }
1039  myDecalsLock.unlock();
1040  glPopName();
1041 }
1042 
1043 
1044 // ------------ Additional visualisations
1045 bool
1047  if (myAdditionallyDrawn.find(which) == myAdditionallyDrawn.end()) {
1048  myAdditionallyDrawn[which] = 1;
1049  } else {
1050  myAdditionallyDrawn[which] = myAdditionallyDrawn[which] + 1;
1051  }
1052  update();
1053  return true;
1054 }
1055 
1056 
1057 bool
1059  if (getTrackedID() == static_cast<int>(which->getGlID())) {
1060  stopTrack();
1061  }
1062  if (myAdditionallyDrawn.find(which) == myAdditionallyDrawn.end()) {
1063  return false;
1064  }
1065  int cnt = myAdditionallyDrawn[which];
1066  if (cnt == 1) {
1067  myAdditionallyDrawn.erase(which);
1068  } else {
1069  myAdditionallyDrawn[which] = myAdditionallyDrawn[which] - 1;
1070  }
1071  update();
1072  return true;
1073 }
1074 
1075 
1076 void
1078  Boundary bound = myChanger->getViewport(fixRatio);
1079  glMatrixMode(GL_PROJECTION);
1080  glLoadIdentity();
1081  // as a rough rule, each GLObject is drawn at z = -GUIGlObjectType
1082  // thus, objects with a higher value will be closer (drawn on top)
1083  // // @todo last param should be 0 after modifying all glDraw methods
1084  glOrtho(0, getWidth(), 0, getHeight(), -GLO_MAX - 1, GLO_MAX + 1);
1085  glMatrixMode(GL_MODELVIEW);
1086  glLoadIdentity();
1087  SUMOReal scaleX = (SUMOReal)getWidth() / bound.getWidth();
1088  SUMOReal scaleY = (SUMOReal)getHeight() / bound.getHeight();
1089  glScaled(scaleX, scaleY, 1);
1090  glTranslated(-bound.xmin(), -bound.ymin(), 0);
1091 }
1092 
1093 /****************************************************************************/
1094 
#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.
virtual int Search(const float a_min[2], const float a_max[2], const GUIVisualizationSettings &c)
Find all within search rectangle.
Definition: SUMORTree.h:108
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 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:221
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