SUMO - Simulation of Urban MObility
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.dlr.de/
12 // Copyright (C) 2001-2017 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>
47 #include "GUIParameterTracker.h"
49 
50 
51 // ===========================================================================
52 // FOX callback mapping
53 // ===========================================================================
54 FXDEFMAP(GUIParameterTracker) GUIParameterTrackerMap[] = {
55  FXMAPFUNC(SEL_CONFIGURE, 0, GUIParameterTracker::onConfigure),
56  FXMAPFUNC(SEL_PAINT, 0, GUIParameterTracker::onPaint),
57  FXMAPFUNC(SEL_COMMAND, MID_SIMSTEP, GUIParameterTracker::onSimStep),
60 
61 };
62 
63 // Macro for the GLTestApp class hierarchy implementation
64 FXIMPLEMENT(GUIParameterTracker, FXMainWindow, GUIParameterTrackerMap, ARRAYNUMBER(GUIParameterTrackerMap))
65 
66 
67 // ===========================================================================
68 // method definitions
69 // ===========================================================================
71  const std::string& name)
72  : FXMainWindow(app.getApp(), "Tracker", NULL, NULL, DECOR_ALL, 20, 20, 300, 200),
73  myApplication(&app) {
74  buildToolBar();
75  app.addChild(this, true);
76  FXVerticalFrame* glcanvasFrame = new FXVerticalFrame(this, FRAME_SUNKEN | LAYOUT_SIDE_TOP | LAYOUT_FILL_X | LAYOUT_FILL_Y, 0, 0, 0, 0, 0, 0, 0, 0);
77  myPanel = new GUIParameterTrackerPanel(glcanvasFrame, *myApplication, *this);
78  setTitle(name.c_str());
80 }
81 
82 
85  for (std::vector<TrackerValueDesc*>::iterator i1 = myTracked.begin(); i1 != myTracked.end(); i1++) {
86  delete(*i1);
87  }
88  // deleted by GUINet
89  for (std::vector<GLObjectValuePassConnector<double>*>::iterator i2 = myValuePassers.begin(); i2 != myValuePassers.end(); i2++) {
90  delete(*i2);
91  }
92  delete myToolBarDrag;
93  delete myToolBar;
94 }
95 
96 
97 void
99  FXMainWindow::create();
100  myToolBarDrag->create();
101 }
102 
103 
104 void
106  myToolBarDrag = new FXToolBarShell(this, GUIDesignToolBarShell3);
107  myToolBar = new FXToolBar(this, myToolBarDrag, LAYOUT_SIDE_TOP | LAYOUT_FILL_X | FRAME_RAISED);
108  new FXToolBarGrip(myToolBar, myToolBar, FXToolBar::ID_TOOLBARGRIP, GUIDesignToolBarGrip);
109  // save button
110  new FXButton(myToolBar, "\t\tSave the data...",
112  // aggregation interval combo
114  new FXComboBox(myToolBar, 8, this, MID_AGGREGATIONINTERVAL,
116  myAggregationInterval->appendItem("1s");
117  myAggregationInterval->appendItem("1min");
118  myAggregationInterval->appendItem("5min");
119  myAggregationInterval->appendItem("15min");
120  myAggregationInterval->appendItem("30min");
121  myAggregationInterval->appendItem("60min");
122  myAggregationInterval->setNumVisible(6);
123 }
124 
125 
126 void
128  TrackerValueDesc* newTracked) {
129  myTracked.push_back(newTracked);
130  // build connection (is automatically set into an execution map)
131  myValuePassers.push_back(new GLObjectValuePassConnector<double>(o, src, newTracked));
132 }
133 
134 
135 long
136 GUIParameterTracker::onConfigure(FXObject* sender, FXSelector sel, void* data) {
137  myPanel->onConfigure(sender, sel, data);
138  return FXMainWindow::onConfigure(sender, sel, data);
139 }
140 
141 
142 long
143 GUIParameterTracker::onPaint(FXObject* sender, FXSelector sel, void* data) {
144  myPanel->onPaint(sender, sel, data);
145  return FXMainWindow::onPaint(sender, sel, data);
146 }
147 
148 
149 long
150 GUIParameterTracker::onSimStep(FXObject*, FXSelector, void*) {
151  update();
152  return 1;
153 }
154 
155 
156 long
157 GUIParameterTracker::onCmdChangeAggregation(FXObject*, FXSelector, void*) {
158  int index = myAggregationInterval->getCurrentItem();
159  int aggInt = 0;
160  switch (index) {
161  case 0:
162  aggInt = 1;
163  break;
164  case 1:
165  aggInt = 60;
166  break;
167  case 2:
168  aggInt = 60 * 5;
169  break;
170  case 3:
171  aggInt = 60 * 15;
172  break;
173  case 4:
174  aggInt = 60 * 30;
175  break;
176  case 5:
177  aggInt = 60 * 60;
178  break;
179  default:
180  throw 1;
181  break;
182  }
183  for (std::vector<TrackerValueDesc*>::iterator i1 = myTracked.begin(); i1 != myTracked.end(); i1++) {
184  (*i1)->setAggregationSpan(TIME2STEPS(aggInt));
185  }
186  return 1;
187 }
188 
189 
190 long
191 GUIParameterTracker::onCmdSave(FXObject*, FXSelector, void*) {
192  FXString file = MFXUtils::getFilename2Write(this, "Save Data", ".csv", GUIIconSubSys::getIcon(ICON_EMPTY), gCurrentFolder);
193  if (file == "") {
194  return 1;
195  }
196  try {
197  OutputDevice& dev = OutputDevice::getDevice(file.text());
198  // write header
199  std::vector<TrackerValueDesc*>::iterator i;
200  dev << "# ";
201  for (i = myTracked.begin(); i != myTracked.end(); ++i) {
202  if (i != myTracked.begin()) {
203  dev << ';';
204  }
205  TrackerValueDesc* tvd = *i;
206  dev << tvd->getName();
207  }
208  dev << '\n';
209  // count entries
210  int max = 0;
211  for (i = myTracked.begin(); i != myTracked.end(); ++i) {
212  TrackerValueDesc* tvd = *i;
213  int sizei = (int)tvd->getAggregatedValues().size();
214  if (max < sizei) {
215  max = sizei;
216  }
217  tvd->unlockValues();
218  }
219  // write entries
220  for (int j = 0; j < max; j++) {
221  for (i = myTracked.begin(); i != myTracked.end(); ++i) {
222  if (i != myTracked.begin()) {
223  dev << ';';
224  }
225  TrackerValueDesc* tvd = *i;
226  dev << tvd->getAggregatedValues()[j];
227  tvd->unlockValues();
228  }
229  dev << '\n';
230  }
231  dev.close();
232  } catch (IOError& e) {
233  FXMessageBox::error(this, MBOX_OK, "Storing failed!", "%s", e.what());
234  }
235  return 1;
236 }
237 
238 
239 /* -------------------------------------------------------------------------
240  * GUIParameterTracker::GUIParameterTrackerPanel-methods
241  * ----------------------------------------------------------------------- */
242 FXDEFMAP(GUIParameterTracker::GUIParameterTrackerPanel) GUIParameterTrackerPanelMap[] = {
245 
246 };
247 
248 // Macro for the GLTestApp class hierarchy implementation
249 FXIMPLEMENT(GUIParameterTracker::GUIParameterTrackerPanel, FXGLCanvas, GUIParameterTrackerPanelMap, ARRAYNUMBER(GUIParameterTrackerPanelMap))
250 
251 
252 
254  FXComposite* c, GUIMainWindow& app,
255  GUIParameterTracker& parent)
256  : FXGLCanvas(c, app.getGLVisual(), app.getBuildGLCanvas(), (FXObject*) 0, (FXSelector) 0, LAYOUT_SIDE_TOP | LAYOUT_FILL_X | LAYOUT_FILL_Y, 0, 0, 300, 200),
257  myParent(&parent), myApplication(&app) {}
258 
259 
261 
262 
263 void
265  pfSetScale((double) 0.1);
266  pfSetScaleXY((double)(.1 * 300. / myWidthInPixels), (double)(.1 * 300. / (double) myHeightInPixels));
267  //
268  glMatrixMode(GL_PROJECTION);
269  glLoadIdentity();
270  glMatrixMode(GL_MODELVIEW);
271  glLoadIdentity();
272  glDisable(GL_TEXTURE_2D);
273  int run = 0;
274  for (std::vector<TrackerValueDesc*>::iterator i = myParent->myTracked.begin(); i != myParent->myTracked.end(); i++) {
275  TrackerValueDesc* desc = *i;
276  drawValue(*desc,
277  (double) myWidthInPixels / (double) myParent->myTracked.size() * (double) run);
278  run++;
279  }
280 }
281 
282 
283 void
285  double /*namePos*/) {
286  // apply scaling
287  glPushMatrix();
288 
289  // apply the positiopn offset of the display
290  glScaled(0.8, 0.8, 1);
291  // apply value range scaling
292  double ys = (double) 2.0 / (double) desc.getRange();
293  glScaled(1.0, ys, 1.0);
294  glTranslated(-1.0, -desc.getYCenter(), 0);
295 
296  // set color
297  const unsigned char red = desc.getColor().red();
298  const unsigned char green = desc.getColor().green();
299  const unsigned char blue = desc.getColor().blue();
300  // draw value bounderies
301  // draw minimum boundary
302  glBegin(GL_LINES);
303  glVertex2d(0, desc.getMin());
304  glVertex2d(2.0, desc.getMin());
305  glEnd();
306  glBegin(GL_LINES);
307  glVertex2d(0, desc.getMax());
308  glVertex2d(2.0, desc.getMax());
309  glEnd();
310  glColor4ub(red, green, blue, 77);
311  for (int a = 1; a < 6; a++) {
312  double ypos = (desc.getRange()) / (double) 6.0 * (double) a + desc.getMin();
313  glBegin(GL_LINES);
314  glVertex2d(0, ypos);
315  glVertex2d(2.0, ypos);
316  glEnd();
317  }
318  const std::vector<double>& values = desc.getAggregatedValues();
319  double latest = 0;
320  if (values.size() < 2) {
321  glPopMatrix();
322  desc.unlockValues();
323  return;
324  } else {
325  latest = values.back();
326  // init values
327  double xStep = (double) 2.0 / (double) values.size();
328  std::vector<double>::const_iterator i = values.begin();
329  double yp = (*i);
330  double xp = 0;
331  i++;
332  glColor4ub(red, green, blue, 255);
333  for (; i != values.end(); i++) {
334  double yn = (*i);
335  double xn = xp + xStep;
336  glBegin(GL_LINES);
337  glVertex2d(xp, yp);
338  glVertex2d(xn, yn);
339  glEnd();
340  yp = yn;
341  xp = xn;
342  }
343  desc.unlockValues();
344  glPopMatrix();
345  }
346 
347  // draw value bounderies and descriptions
348  glColor3b(red, green, blue);
349 
350  // draw min time
351  SUMOTime beginStep = desc.getRecordingBegin();
352  std::string begStr = time2string(beginStep);
353  double w = pfdkGetStringWidth(begStr.c_str());
354  glRotated(180, 1, 0, 0);
355  pfSetPosition(0, 0);
356  glTranslated(-0.8 - w / 2., 0.88, 0);
357  pfDrawString(begStr.c_str());
358  glTranslated(0.8 + w / 2., -0.88, 0);
359  glRotated(-180, 1, 0, 0);
360 
361  // draw max time
362  glRotated(180, 1, 0, 0);
363  pfSetPosition(0, 0);
364  glTranslated(0.75, 0.88, 0);
365  pfDrawString(time2string(beginStep + static_cast<SUMOTime>(values.size() * desc.getAggregationSpan())).c_str());
366  glTranslated(-0.75, -0.88, 0);
367  glRotated(-180, 1, 0, 0);
368 
369  // draw min value
370  glRotated(180, 1, 0, 0);
371  pfSetPosition(0, 0);
372  glTranslated(-0.98, 0.82, 0);
373  pfDrawString(toString(desc.getMin()).c_str());
374  glTranslated(0.98, -0.82, 0);
375  glRotated(-180, 1, 0, 0);
376 
377  // draw max value
378  glRotated(180, 1, 0, 0);
379  pfSetPosition(0, 0);
380  glTranslated(-0.98, -0.78, 0);
381  pfDrawString(toString(desc.getMax()).c_str());
382  glTranslated(0.98, 0.78, 0);
383  glRotated(-180, 1, 0, 0);
384 
385  // draw current value
386  glRotated(180, 1, 0, 0);
387  pfSetPosition(0, 0);
388  double p = (double) 0.8 -
389  ((double) 1.6 / (desc.getMax() - desc.getMin()) * (latest - desc.getMin()));
390  glTranslated(-0.98, p + .02, 0);
391  pfDrawString(toString(latest).c_str());
392  glTranslated(0.98, -(p + .02), 0);
393  glRotated(-180, 1, 0, 0);
394 
395  // draw name
396  glRotated(180, 1, 0, 0);
397  pfSetPosition(0, 0);
398  glTranslated(-0.98, -.92, 0);
399  pfDrawString(desc.getName().c_str());
400  glTranslated(0.98, .92, 0);
401  glRotated(-180, 1, 0, 0);
402 }
403 
404 
405 long
407  FXSelector, void*) {
408  if (makeCurrent()) {
409  myWidthInPixels = myParent->getWidth();
410  myHeightInPixels = myParent->getHeight();
411  if (myWidthInPixels != 0 && myHeightInPixels != 0) {
412  glViewport(0, 0, myWidthInPixels - 1, myHeightInPixels - 1);
413  glClearColor(1.0, 1.0, 1.0, 1);
414  glDisable(GL_DEPTH_TEST);
415  glDisable(GL_LIGHTING);
416  glDisable(GL_LINE_SMOOTH);
417  glEnable(GL_BLEND);
418  glEnable(GL_ALPHA_TEST);
419  glDisable(GL_COLOR_MATERIAL);
420  glLineWidth(1);
421  glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
422  }
423  makeNonCurrent();
424  }
425  return 1;
426 }
427 
428 
429 long
431  FXSelector, void*) {
432  if (!isEnabled()) {
433  return 1;
434  }
435  if (makeCurrent()) {
436  myWidthInPixels = getWidth();
437  myHeightInPixels = getHeight();
438  if (myWidthInPixels != 0 && myHeightInPixels != 0) {
439  glViewport(0, 0, myWidthInPixels - 1, myHeightInPixels - 1);
440  glClearColor(1.0, 1.0, 1.0, 1);
441  glDisable(GL_DEPTH_TEST);
442  glDisable(GL_LIGHTING);
443  glDisable(GL_LINE_SMOOTH);
444  glEnable(GL_BLEND);
445  glEnable(GL_ALPHA_TEST);
446  glDisable(GL_COLOR_MATERIAL);
447  glLineWidth(1);
448  glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
449  // draw
450  glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
451  drawValues();
452  swapBuffers();
453  }
454  makeNonCurrent();
455  }
456  return 1;
457 }
458 
459 
460 
461 /****************************************************************************/
462 
double getYCenter() const
Returns the center of the value.
int pfDrawString(const char *c)
Definition: polyfonts.c:1074
void close()
Closes the device and removes it from the dictionary.
void pfSetScale(double s)
Definition: polyfonts.c:465
void drawValue(TrackerValueDesc &desc, double namePos)
Draws a single value.
#define GUIDesignButtonToolbar
little button with icon placed in navigation toolbar
Definition: GUIDesigns.h:82
std::string time2string(SUMOTime t)
Definition: SUMOTime.cpp:60
#define GUIDesignToolBarGrip
design for toolbar grip (used to change the position of toolbar with mouse)
Definition: GUIDesigns.h:266
void unlockValues()
Releases the locking after the values have been drawn.
SUMOTime getRecordingBegin() const
Returns the timestep the recording started.
Representation of a timeline of floats with their names and moments.
FXString gCurrentFolder
The folder used as last.
unsigned char blue() const
Returns the blue-amount of the color.
Definition: RGBColor.h:91
void pfSetPosition(double x, double y)
Definition: polyfonts.c:480
#define TIME2STEPS(x)
Definition: SUMOTime.h:66
long onCmdSave(FXObject *, FXSelector, void *)
Called when the data shall be saved.
GUIMainWindow * myApplication
The main application.
static FXString getFilename2Write(FXWindow *parent, const FXString &header, const FXString &extension, FXIcon *icon, FXString &currentFolder)
Returns the file name to write.
Definition: MFXUtils.cpp:91
long onPaint(FXObject *, FXSelector, void *)
Called if the window shall be repainted.
FXToolBar * myToolBar
The tracker tool bar.
SUMOTime getAggregationSpan() const
get the aggregation amount
A window which displays the time line of one (or more) value(s)
#define max(a, b)
Definition: polyfonts.c:65
FXToolBarShell * myToolBarDrag
for some menu detaching fun
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition: ToString.h:56
void addTracked(GUIGlObject &o, ValueSource< double > *src, TrackerValueDesc *newTracked)
Adds a further time line to display.
FXComboBox * myAggregationInterval
A combo box to select an aggregation interval.
void buildToolBar()
Builds the tool bar.
#define GUIDesignComboBoxStatic
Combo box static (not editable)
Definition: GUIDesigns.h:190
void removeChild(FXMDIChild *child)
removes the given child window from the list
long onPaint(FXObject *, FXSelector, void *)
Called if the window shall be repainted.
const std::vector< double > & getAggregatedValues()
returns the vector of aggregated values The values will be locked - no further addition will be perfo...
long onSimStep(FXObject *, FXSelector, void *)
Called on a simulation step.
void create()
Creates the window.
~GUIParameterTracker()
Destructor.
double pfdkGetStringWidth(const char *c)
Definition: polyfonts.c:1113
const std::string & getName() const
Returns the name of the value.
long onCmdChangeAggregation(FXObject *, FXSelector, void *)
Called when the aggregation interval (combo) has been changed.
Save the current values.
static OutputDevice & getDevice(const std::string &name)
Returns the described OutputDevice.
unsigned char green() const
Returns the green-amount of the color.
Definition: RGBColor.h:83
double getMax() const
Returns the values maximum.
std::vector< TrackerValueDesc * > myTracked
The list of tracked values.
GUIParameterTrackerPanel * myPanel
The panel to display the values in.
unsigned char red() const
Returns the red-amount of the color.
Definition: RGBColor.h:75
Static storage of an output device and its base (abstract) implementation.
Definition: OutputDevice.h:71
const RGBColor & getColor() const
Returns the color to use to display the value.
long long int SUMOTime
Definition: TraCIDefs.h:52
double getMin() const
Returns the values minimum.
#define GUIDesignToolBarShell3
Definition: GUIDesigns.h:274
A Simulation step was performed.
Definition: GUIAppEnum.h:293
static FXIcon * getIcon(GUIIcon which)
returns a icon previously defined in the enum GUIIcon
void pfSetScaleXY(double sx, double sy)
Definition: polyfonts.c:472
std::vector< GLObjectValuePassConnector< double > * > myValuePassers
The value sources.
long onConfigure(FXObject *, FXSelector, void *)
Called on window resizing.
double getRange() const
returns the maximum value range
FXDEFMAP(GUIParameterTracker) GUIParameterTrackerMap[]
Class passing values from a GUIGlObject to another object.
long onConfigure(FXObject *, FXSelector, void *)
Called on window resizing.