SUMO - Simulation of Urban MObility
GUIParameterTracker.cpp
Go to the documentation of this file.
1 /****************************************************************************/
2 // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
3 // Copyright (C) 2001-2017 German Aerospace Center (DLR) and others.
4 /****************************************************************************/
5 //
6 // This program and the accompanying materials
7 // are made available under the terms of the Eclipse Public License v2.0
8 // which accompanies this distribution, and is available at
9 // http://www.eclipse.org/legal/epl-v20.html
10 //
11 /****************************************************************************/
19 // A window which displays the time line of one (or more) value(s)
20 /****************************************************************************/
21 
22 
23 // ===========================================================================
24 // included modules
25 // ===========================================================================
26 #ifdef _MSC_VER
27 #include <windows_config.h>
28 #else
29 #include <config.h>
30 #endif
31 
32 #include <string>
33 #include <fstream>
36 #include <utils/common/ToString.h>
38 #include <utils/common/SUMOTime.h>
39 #include <utils/gui/div/GLHelper.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  glMatrixMode(GL_PROJECTION);
266  glLoadIdentity();
267  glMatrixMode(GL_MODELVIEW);
268  glLoadIdentity();
269  glDisable(GL_TEXTURE_2D);
270  int run = 0;
271  for (std::vector<TrackerValueDesc*>::iterator i = myParent->myTracked.begin(); i != myParent->myTracked.end(); i++) {
272  TrackerValueDesc* desc = *i;
273  drawValue(*desc,
274  (double) myWidthInPixels / (double) myParent->myTracked.size() * (double) run);
275  run++;
276  }
277 }
278 
279 
280 void
282  double /*namePos*/) {
283  const double fontWidth = 0.1 * 300. / myWidthInPixels;
284  const double fontHeight = 0.1 * 300. / myHeightInPixels;
285  //
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 = 50 / myWidthInPixels;
354  glTranslated(-0.8 - w / 2., -0.88, 0);
355  GLHelper::drawText(begStr, Position(0, 0), 1, fontHeight, RGBColor::BLACK, 0, FONS_ALIGN_LEFT | FONS_ALIGN_MIDDLE, fontWidth);
356  glTranslated(0.8 + w / 2., 0.88, 0);
357 
358  // draw max time
359  glTranslated(0.75, -0.88, 0);
360  GLHelper::drawText(time2string(beginStep + static_cast<SUMOTime>(values.size() * desc.getAggregationSpan())),
361  Position(0, 0), 1, fontHeight, RGBColor::BLACK, 0, FONS_ALIGN_LEFT | FONS_ALIGN_MIDDLE, fontWidth);
362  glTranslated(-0.75, 0.88, 0);
363 
364  // draw min value
365  glTranslated(-0.98, -0.82, 0);
366  GLHelper::drawText(toString(desc.getMin()), Position(0, 0), 1, fontHeight, RGBColor::BLACK, 0, FONS_ALIGN_LEFT | FONS_ALIGN_MIDDLE, fontWidth);
367  glTranslated(0.98, 0.82, 0);
368 
369  // draw max value
370  glTranslated(-0.98, 0.78, 0);
371  GLHelper::drawText(toString(desc.getMax()), Position(0, 0), 1, fontHeight, RGBColor::BLACK, 0, FONS_ALIGN_LEFT | FONS_ALIGN_MIDDLE, fontWidth);
372  glTranslated(0.98, -0.78, 0);
373 
374  // draw current value
375  double p = (double) 0.8 -
376  ((double) 1.6 / (desc.getMax() - desc.getMin()) * (latest - desc.getMin()));
377  glTranslated(-0.98, -(p + .02), 0);
378  GLHelper::drawText(toString(latest), Position(0, 0), 1, fontHeight, RGBColor::BLACK, 0, FONS_ALIGN_LEFT | FONS_ALIGN_MIDDLE, fontWidth);
379  glTranslated(0.98, p + .02, 0);
380 
381  // draw name
382  glTranslated(-0.98, .92, 0);
383  GLHelper::drawText(desc.getName(), Position(0, 0), 1, fontHeight, RGBColor::BLACK, 0, FONS_ALIGN_LEFT | FONS_ALIGN_MIDDLE, fontWidth);
384  glTranslated(0.98, -.92, 0);
385 }
386 
387 
388 long
390  FXSelector, void*) {
391  if (makeCurrent()) {
392  myWidthInPixels = myParent->getWidth();
393  myHeightInPixels = myParent->getHeight();
394  if (myWidthInPixels != 0 && myHeightInPixels != 0) {
395  glViewport(0, 0, myWidthInPixels - 1, myHeightInPixels - 1);
396  glClearColor(1.0, 1.0, 1.0, 1);
397  glDisable(GL_DEPTH_TEST);
398  glDisable(GL_LIGHTING);
399  glDisable(GL_LINE_SMOOTH);
400  glEnable(GL_BLEND);
401  glEnable(GL_ALPHA_TEST);
402  glDisable(GL_COLOR_MATERIAL);
403  glLineWidth(1);
404  glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
405  }
406  makeNonCurrent();
407  }
408  return 1;
409 }
410 
411 
412 long
414  FXSelector, void*) {
415  if (!isEnabled()) {
416  return 1;
417  }
418  if (makeCurrent()) {
419  myWidthInPixels = getWidth();
420  myHeightInPixels = 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  // draw
433  glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
434  drawValues();
435  swapBuffers();
436  }
437  makeNonCurrent();
438  }
439  return 1;
440 }
441 
442 
443 
444 /****************************************************************************/
445 
double getYCenter() const
Returns the center of the value.
void close()
Closes the device and removes it from the dictionary.
Save the current values.
void drawValue(TrackerValueDesc &desc, double namePos)
Draws a single value.
#define GUIDesignButtonToolbar
little button with icon placed in navigation toolbar
Definition: GUIDesigns.h:81
std::string time2string(SUMOTime t)
Definition: SUMOTime.cpp:59
#define GUIDesignToolBarGrip
design for toolbar grip (used to change the position of toolbar with mouse)
Definition: GUIDesigns.h:268
static void drawText(const std::string &text, const Position &pos, const double layer, const double size, const RGBColor &col=RGBColor::BLACK, const double angle=0, int align=0, double width=-1)
Definition: GLHelper.cpp:487
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:82
static const RGBColor BLACK
Definition: RGBColor.h:186
#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:90
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)
FXToolBarShell * myToolBarDrag
for some menu detaching fun
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition: ToString.h:55
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.
A point in 2D or 3D with translation and scaling methods.
Definition: Position.h:45
void buildToolBar()
Builds the tool bar.
#define GUIDesignComboBoxStatic
Combo box static (not editable)
Definition: GUIDesigns.h:192
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.
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.
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:75
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:68
Static storage of an output device and its base (abstract) implementation.
Definition: OutputDevice.h:70
const RGBColor & getColor() const
Returns the color to use to display the value.
A Simulation step was performed.
Definition: GUIAppEnum.h:290
long long int SUMOTime
Definition: TraCIDefs.h:51
double getMin() const
Returns the values minimum.
#define GUIDesignToolBarShell3
Definition: GUIDesigns.h:276
static FXIcon * getIcon(GUIIcon which)
returns a icon previously defined in the enum GUIIcon
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.