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