SUMO - Simulation of Urban MObility
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
GUIParameterTracker.cpp
Go to the documentation of this file.
1 /****************************************************************************/
9 // A window which displays the time line of one (or more) value(s)
10 /****************************************************************************/
11 // SUMO, Simulation of Urban MObility; see http://sumo.sourceforge.net/
12 // Copyright (C) 2001-2012 DLR (http://www.dlr.de/) and contributors
13 /****************************************************************************/
14 //
15 // This file is part of SUMO.
16 // SUMO is free software: you can redistribute it and/or modify
17 // it under the terms of the GNU General Public License as published by
18 // the Free Software Foundation, either version 3 of the License, or
19 // (at your option) any later version.
20 //
21 /****************************************************************************/
22 
23 
24 // ===========================================================================
25 // included modules
26 // ===========================================================================
27 #ifdef _MSC_VER
28 #include <windows_config.h>
29 #else
30 #include <config.h>
31 #endif
32 
33 #include <string>
34 #include <fstream>
38 #include <utils/common/ToString.h>
40 #include <utils/common/SUMOTime.h>
46 #include "GUIParameterTracker.h"
47 
48 #ifdef _WIN32
49 #include <windows.h>
50 #endif
51 
52 #include <GL/gl.h>
53 
54 #ifdef CHECK_MEMORY_LEAKS
55 #include <foreign/nvwa/debug_new.h>
56 #endif // CHECK_MEMORY_LEAKS
57 
58 
59 // ===========================================================================
60 // FOX callback mapping
61 // ===========================================================================
62 FXDEFMAP(GUIParameterTracker) GUIParameterTrackerMap[] = {
63  FXMAPFUNC(SEL_CONFIGURE, 0, GUIParameterTracker::onConfigure),
64  FXMAPFUNC(SEL_PAINT, 0, GUIParameterTracker::onPaint),
65  FXMAPFUNC(SEL_COMMAND, MID_SIMSTEP, GUIParameterTracker::onSimStep),
68 
69 };
70 
71 // Macro for the GLTestApp class hierarchy implementation
72 FXIMPLEMENT(GUIParameterTracker, FXMainWindow, GUIParameterTrackerMap, ARRAYNUMBER(GUIParameterTrackerMap))
73 
74 
75 // ===========================================================================
76 // method definitions
77 // ===========================================================================
79  const std::string& name)
80  : FXMainWindow(app.getApp(), "Tracker", NULL, NULL, DECOR_ALL, 20, 20, 300, 200),
81  myApplication(&app) {
82  buildToolBar();
83  app.addChild(this, true);
84  FXVerticalFrame* glcanvasFrame = new FXVerticalFrame(this, FRAME_SUNKEN | LAYOUT_SIDE_TOP | LAYOUT_FILL_X | LAYOUT_FILL_Y, 0, 0, 0, 0, 0, 0, 0, 0);
85  myPanel = new GUIParameterTrackerPanel(glcanvasFrame, *myApplication, *this);
86  setTitle(name.c_str());
88 }
89 
90 
93  for (std::vector<TrackerValueDesc*>::iterator i1 = myTracked.begin(); i1 != myTracked.end(); i1++) {
94  delete(*i1);
95  }
96  // deleted by GUINet
97  for (std::vector<GLObjectValuePassConnector<SUMOReal>*>::iterator i2 = myValuePassers.begin(); i2 != myValuePassers.end(); i2++) {
98  delete(*i2);
99  }
100  delete myToolBarDrag;
101  delete myToolBar;
102 }
103 
104 
105 void
108  myToolBarDrag->create();
109 }
110 
111 
112 void
114  myToolBarDrag = new FXToolBarShell(this, FRAME_NORMAL);
115  myToolBar = new FXToolBar(this, myToolBarDrag, LAYOUT_SIDE_TOP | LAYOUT_FILL_X | FRAME_RAISED);
116  new FXToolBarGrip(myToolBar, myToolBar, FXToolBar::ID_TOOLBARGRIP, TOOLBARGRIP_DOUBLE);
117  // save button
118  new FXButton(myToolBar, "\t\tSave the data...",
120  ICON_ABOVE_TEXT | BUTTON_TOOLBAR | FRAME_RAISED | LAYOUT_TOP | LAYOUT_LEFT);
121  // aggregation interval combo
123  new FXComboBox(myToolBar, 8, this, MID_AGGREGATIONINTERVAL,
124  FRAME_SUNKEN | LAYOUT_LEFT | LAYOUT_TOP | COMBOBOX_STATIC);
125  myAggregationInterval->appendItem("1s");
126  myAggregationInterval->appendItem("1min");
127  myAggregationInterval->appendItem("5min");
128  myAggregationInterval->appendItem("15min");
129  myAggregationInterval->appendItem("30min");
130  myAggregationInterval->appendItem("60min");
131  myAggregationInterval->setNumVisible(6);
132 }
133 
134 
135 void
137  TrackerValueDesc* newTracked) {
138  myTracked.push_back(newTracked);
139  // build connection (is automatically set into an execution map)
140  myValuePassers.push_back(new GLObjectValuePassConnector<SUMOReal>(o, src, newTracked));
141 }
142 
143 
144 long
145 GUIParameterTracker::onConfigure(FXObject* sender, FXSelector sel, void* data) {
146  myPanel->onConfigure(sender, sel, data);
147  return FXMainWindow::onConfigure(sender, sel, data);
148 }
149 
150 
151 long
152 GUIParameterTracker::onPaint(FXObject* sender, FXSelector sel, void* data) {
153  myPanel->onPaint(sender, sel, data);
154  return FXMainWindow::onPaint(sender, sel, data);
155 }
156 
157 
158 long
160  update();
161  return 1;
162 }
163 
164 
165 long
167  int index = myAggregationInterval->getCurrentItem();
168  size_t aggInt = 0;
169  switch (index) {
170  case 0:
171  aggInt = 1;
172  break;
173  case 1:
174  aggInt = 60;
175  break;
176  case 2:
177  aggInt = 60 * 5;
178  break;
179  case 3:
180  aggInt = 60 * 15;
181  break;
182  case 4:
183  aggInt = 60 * 30;
184  break;
185  case 5:
186  aggInt = 60 * 60;
187  break;
188  default:
189  throw 1;
190  break;
191  }
192  for (std::vector<TrackerValueDesc*>::iterator i1 = myTracked.begin(); i1 != myTracked.end(); i1++) {
193  (*i1)->setAggregationSpan(TIME2STEPS(aggInt));
194  }
195  return 1;
196 }
197 
198 
199 long
201  FXString file = MFXUtils::getFilename2Write(this, "Save Data", ".csv", GUIIconSubSys::getIcon(ICON_EMPTY), gCurrentFolder);
202  if (file == "") {
203  return 1;
204  }
205  try {
206  OutputDevice& dev = OutputDevice::getDevice(file.text());
207  // write header
208  std::vector<TrackerValueDesc*>::iterator i;
209  dev << "# ";
210  for (i = myTracked.begin(); i != myTracked.end(); ++i) {
211  if (i != myTracked.begin()) {
212  dev << ';';
213  }
214  TrackerValueDesc* tvd = *i;
215  dev << tvd->getName();
216  }
217  dev << '\n';
218  // count entries
219  size_t max = 0;
220  for (i = myTracked.begin(); i != myTracked.end(); ++i) {
221  TrackerValueDesc* tvd = *i;
222  size_t sizei = tvd->getAggregatedValues().size();
223  if (max < sizei) {
224  max = sizei;
225  }
226  tvd->unlockValues();
227  }
228  // write entries
229  for (unsigned int j = 0; j < max; j++) {
230  for (i = myTracked.begin(); i != myTracked.end(); ++i) {
231  if (i != myTracked.begin()) {
232  dev << ';';
233  }
234  TrackerValueDesc* tvd = *i;
235  dev << tvd->getAggregatedValues()[j];
236  tvd->unlockValues();
237  }
238  dev << '\n';
239  }
240  dev.close();
241  } catch (IOError& e) {
242  FXMessageBox::error(this, MBOX_OK, "Storing failed!", "%s", e.what());
243  }
244  return 1;
245 }
246 
247 
248 /* -------------------------------------------------------------------------
249  * GUIParameterTracker::GUIParameterTrackerPanel-methods
250  * ----------------------------------------------------------------------- */
251 FXDEFMAP(GUIParameterTracker::GUIParameterTrackerPanel) GUIParameterTrackerPanelMap[] = {
254 
255 };
256 
257 // Macro for the GLTestApp class hierarchy implementation
258 FXIMPLEMENT(GUIParameterTracker::GUIParameterTrackerPanel, FXGLCanvas, GUIParameterTrackerPanelMap, ARRAYNUMBER(GUIParameterTrackerPanelMap))
259 
260 
261 
263  FXComposite* c, GUIMainWindow& app,
264  GUIParameterTracker& parent)
265  : FXGLCanvas(c, app.getGLVisual(), app.getBuildGLCanvas(), (FXObject*) 0, (FXSelector) 0, LAYOUT_SIDE_TOP | LAYOUT_FILL_X | LAYOUT_FILL_Y, 0, 0, 300, 200),
266  myParent(&parent), myApplication(&app) {}
267 
268 
270 
271 
272 void
274  pfSetScale((SUMOReal) 0.1);
275  pfSetScaleXY((SUMOReal)(.1 * 300. / myWidthInPixels), (SUMOReal)(.1 * 300. / (SUMOReal) myHeightInPixels));
276  //
277  glMatrixMode(GL_PROJECTION);
278  glLoadIdentity();
279  glMatrixMode(GL_MODELVIEW);
280  glLoadIdentity();
281  glDisable(GL_TEXTURE_2D);
282  size_t run = 0;
283  for (std::vector<TrackerValueDesc*>::iterator i = myParent->myTracked.begin(); i != myParent->myTracked.end(); i++) {
284  TrackerValueDesc* desc = *i;
285  drawValue(*desc,
286  (SUMOReal) myWidthInPixels / (SUMOReal) myParent->myTracked.size() * (SUMOReal) run);
287  run++;
288  }
289 }
290 
291 
292 void
294  SUMOReal /*namePos*/) {
295  // apply scaling
296  glPushMatrix();
297 
298  // apply the positiopn offset of the display
299  glScaled(0.8, 0.8, 1);
300  // apply value range scaling
301  SUMOReal ys = (SUMOReal) 2.0 / (SUMOReal) desc.getRange();
302  glScaled(1.0, ys, 1.0);
303  glTranslated(-1.0, -desc.getYCenter(), 0);
304 
305  // set color
306  const RGBColor& col = desc.getColor();
307  SUMOReal red = (SUMOReal) col.red();
308  SUMOReal green = (SUMOReal) col.green();
309  SUMOReal blue = (SUMOReal) col.blue();
310  // draw value bounderies
311  // draw minimum boundary
312  glBegin(GL_LINES);
313  glVertex2d(0, desc.getMin());
314  glVertex2d(2.0, desc.getMin());
315  glEnd();
316  glBegin(GL_LINES);
317  glVertex2d(0, desc.getMax());
318  glVertex2d(2.0, desc.getMax());
319  glEnd();
320  glColor4f(red, green, blue, 0.3f);
321  for (int a = 1; a < 6; a++) {
322  SUMOReal ypos = (desc.getRange()) / (SUMOReal) 6.0 * (SUMOReal) a + desc.getMin();
323  glBegin(GL_LINES);
324  glVertex2d(0, ypos);
325  glVertex2d(2.0, ypos);
326  glEnd();
327  }
328  const std::vector<SUMOReal> &values = desc.getAggregatedValues();
329  SUMOReal latest = 0;
330  if (values.size() < 2) {
331  glPopMatrix();
332  desc.unlockValues();
333  return;
334  } else {
335  latest = values.back();
336  // init values
337  SUMOReal xStep = (SUMOReal) 2.0 / (SUMOReal) values.size();
338  std::vector<SUMOReal>::const_iterator i = values.begin();
339  SUMOReal yp = (*i);
340  SUMOReal xp = 0;
341  i++;
342  glColor4f(red, green, blue, 1.0f);
343  for (; i != values.end(); i++) {
344  SUMOReal yn = (*i);
345  SUMOReal xn = xp + xStep;
346  glBegin(GL_LINES);
347  glVertex2d(xp, yp);
348  glVertex2d(xn, yn);
349  glEnd();
350  yp = yn;
351  xp = xn;
352  }
353  desc.unlockValues();
354  glPopMatrix();
355  }
356 
357  // draw value bounderies and descriptions
358  glColor3d(red, green, blue);
359 
360  // draw min time
361  SUMOTime beginStep = desc.getRecordingBegin();
362  std::string begStr = time2string(beginStep);
363  SUMOReal w = pfdkGetStringWidth(begStr.c_str());
364  glRotated(180, 1, 0, 0);
365  pfSetPosition(0, 0);
366  glTranslated(-0.8 - w / 2., 0.88, 0);
367  pfDrawString(begStr.c_str());
368  glTranslated(0.8 + w / 2., -0.88, 0);
369  glRotated(-180, 1, 0, 0);
370 
371  // draw max time
372  glRotated(180, 1, 0, 0);
373  pfSetPosition(0, 0);
374  glTranslated(0.75, 0.88, 0);
375  pfDrawString(time2string(beginStep + static_cast<SUMOTime>(values.size() * desc.getAggregationSpan())).c_str());
376  glTranslated(-0.75, -0.88, 0);
377  glRotated(-180, 1, 0, 0);
378 
379  // draw min value
380  glRotated(180, 1, 0, 0);
381  pfSetPosition(0, 0);
382  glTranslated(-0.98, 0.82, 0);
383  pfDrawString(toString(desc.getMin()).c_str());
384  glTranslated(0.98, -0.82, 0);
385  glRotated(-180, 1, 0, 0);
386 
387  // draw max value
388  glRotated(180, 1, 0, 0);
389  pfSetPosition(0, 0);
390  glTranslated(-0.98, -0.78, 0);
391  pfDrawString(toString(desc.getMax()).c_str());
392  glTranslated(0.98, 0.78, 0);
393  glRotated(-180, 1, 0, 0);
394 
395  // draw current value
396  glRotated(180, 1, 0, 0);
397  pfSetPosition(0, 0);
398  SUMOReal p = (SUMOReal) 0.8 -
399  ((SUMOReal) 1.6 / (desc.getMax() - desc.getMin()) * (latest - desc.getMin()));
400  glTranslated(-0.98, p + .02, 0);
401  pfDrawString(toString(latest).c_str());
402  glTranslated(0.98, -(p + .02), 0);
403  glRotated(-180, 1, 0, 0);
404 
405  // draw name
406  glRotated(180, 1, 0, 0);
407  pfSetPosition(0, 0);
408  glTranslated(-0.98, -.92, 0);
409  pfDrawString(desc.getName().c_str());
410  glTranslated(0.98, .92, 0);
411  glRotated(-180, 1, 0, 0);
412 }
413 
414 
415 long
417  FXSelector, void*) {
418  if (makeCurrent()) {
419  myWidthInPixels = myParent->getWidth();
420  myHeightInPixels = myParent->getHeight();
421  if (myWidthInPixels != 0 && myHeightInPixels != 0) {
422  glViewport(0, 0, myWidthInPixels - 1, myHeightInPixels - 1);
423  glClearColor(1.0, 1.0, 1.0, 1);
424  glDisable(GL_DEPTH_TEST);
425  glDisable(GL_LIGHTING);
426  glDisable(GL_LINE_SMOOTH);
427  glEnable(GL_BLEND);
428  glEnable(GL_ALPHA_TEST);
429  glDisable(GL_COLOR_MATERIAL);
430  glLineWidth(1);
431  glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
432  }
433  makeNonCurrent();
434  }
435  return 1;
436 }
437 
438 
439 long
441  FXSelector, void*) {
442  if (!isEnabled()) {
443  return 1;
444  }
445  if (makeCurrent()) {
446  myWidthInPixels = getWidth();
447  myHeightInPixels = getHeight();
448  if (myWidthInPixels != 0 && myHeightInPixels != 0) {
449  glViewport(0, 0, myWidthInPixels - 1, myHeightInPixels - 1);
450  glClearColor(1.0, 1.0, 1.0, 1);
451  glDisable(GL_DEPTH_TEST);
452  glDisable(GL_LIGHTING);
453  glDisable(GL_LINE_SMOOTH);
454  glEnable(GL_BLEND);
455  glEnable(GL_ALPHA_TEST);
456  glDisable(GL_COLOR_MATERIAL);
457  glLineWidth(1);
458  glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
459  // draw
460  glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
461  drawValues();
462  swapBuffers();
463  }
464  makeNonCurrent();
465  }
466  return 1;
467 }
468 
469 
470 
471 /****************************************************************************/
472