summaryrefslogtreecommitdiff
path: root/src/pmview/barmod.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/pmview/barmod.cpp')
-rw-r--r--src/pmview/barmod.cpp603
1 files changed, 603 insertions, 0 deletions
diff --git a/src/pmview/barmod.cpp b/src/pmview/barmod.cpp
new file mode 100644
index 0000000..206f32c
--- /dev/null
+++ b/src/pmview/barmod.cpp
@@ -0,0 +1,603 @@
+/*
+ * Copyright (c) 1997 Silicon Graphics, Inc. All Rights Reserved.
+ * Copyright (c) 2009 Aconex. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+#include <Inventor/SoPath.h>
+#include <Inventor/nodes/SoBaseColor.h>
+#include <Inventor/nodes/SoTranslation.h>
+#include <Inventor/nodes/SoScale.h>
+#include <Inventor/nodes/SoSeparator.h>
+#include <Inventor/nodes/SoSelection.h>
+#include "barmod.h"
+#include "modlist.h"
+#include "launch.h"
+
+#include <iostream>
+using namespace std;
+
+//
+// Use debug flag LIBPMDA to trace Bar refreshes
+//
+
+const char BarMod::theBarId = 'b';
+
+BarMod::~BarMod()
+{
+}
+
+BarMod::BarMod(MetricList *metrics,
+ SoNode *obj,
+ BarMod::Direction dir,
+ BarMod::Grouping group,
+ float xScale, float yScale, float zScale,
+ float xSpace, float zSpace)
+: Modulate(metrics),
+ _blocks(),
+ _dir(dir),
+ _mod(BarMod::yScale),
+ _group(group),
+ _colScale(0.0, 0.0, 0.0),
+ _selectCount(0),
+ _infoValue(0),
+ _infoMetric(0),
+ _infoInst(0),
+ _xScale(xScale),
+ _yScale(yScale),
+ _zScale(zScale)
+{
+ generate(obj, xSpace, zSpace);
+}
+
+BarMod::BarMod(MetricList *metrics,
+ const ColorScale &colScale,
+ SoNode *obj,
+ BarMod::Direction dir,
+ BarMod::Modulation mod,
+ BarMod::Grouping group,
+ float xScale, float yScale, float zScale,
+ float xSpace, float zSpace)
+: Modulate(metrics),
+ _blocks(),
+ _dir(dir),
+ _mod(mod),
+ _group(group),
+ _colScale(colScale),
+ _selectCount(0),
+ _infoValue(0),
+ _infoMetric(0),
+ _infoInst(0),
+ _xScale(xScale),
+ _yScale(yScale),
+ _zScale(zScale)
+{
+ generate(obj, xSpace, zSpace);
+}
+
+void
+BarMod::generate(SoNode *obj, float xSpace, float zSpace)
+{
+ int numMetrics = _metrics->numMetrics();
+ int numValues = _metrics->numValues();
+ int maxInst = 0;
+ char buf[32];
+ int m, i, v;
+
+ _root = new SoSeparator;
+
+ if (numValues > 0) {
+
+ for (m = 0; m < numMetrics; m++)
+ if (_metrics->metric(m).numValues() > maxInst)
+ maxInst = _metrics->metric(m).numValues();
+
+ if (_dir == instPerCol) {
+ _cols = maxInst;
+ _rows = numMetrics;
+ }
+ else {
+ _cols = numMetrics;
+ _rows = maxInst;
+ }
+
+ _blocks.resize(numValues);
+
+ for (m = 0, v = 0; m < _metrics->numMetrics(); m++) {
+ const QmcMetric &metric = _metrics->metric(m);
+ for (i = 0; i < metric.numValues(); i++, v++) {
+ BarBlock &block = _blocks[v];
+ sprintf(buf, "%c%d", theBarId, v);
+ block._sep = new SoSeparator;
+ block._sep->setName((SbName)buf);
+ _root->addChild(block._sep);
+
+ block._tran = new SoTranslation;
+ block._sep->addChild(block._tran);
+
+ block._color = new SoBaseColor;
+ block._sep->addChild(block._color);
+
+ block._scale = new SoScale;
+ block._sep->addChild(block._scale);
+
+ block._sep->addChild(obj);
+ }
+ }
+
+ regenerate(_xScale, _zScale, xSpace, zSpace);
+ _infoValue = numValues;
+
+ add();
+#ifdef PCP_DEBUG
+ if (pmDebug & DBG_TRACE_APPL2)
+ cerr << "BarMod::generate: Added " << numValues << " in " << _cols
+ << " cols and " << _rows << " rows." << endl;
+#endif
+
+ }
+
+ // Invalid object
+ else {
+ _sts = -1;
+ }
+}
+
+void
+BarMod::refresh(bool fetchFlag)
+{
+ int m, i, v;
+
+ if (status() < 0)
+ return;
+
+ for (m = 0, v = 0; m < _metrics->numMetrics(); m++) {
+ QmcMetric &metric = _metrics->metric(m);
+
+ if (fetchFlag)
+ metric.update();
+
+ for (i = 0; i < metric.numValues(); i++, v++) {
+
+ BarBlock &block = _blocks[v];
+
+ if (metric.error(i) <= 0) {
+
+ if (block._state != Modulate::error) {
+ block._color->rgb.setValue(_errorColor.getValue());
+ if (_mod != color)
+ block._scale->scaleFactor.setValue(_xScale,
+ theMinScale,
+ _zScale);
+ block._state = Modulate::error;
+ }
+ }
+ else {
+ double unscaled = metric.value(i);
+ double value = unscaled * theScale;
+
+ if (value > theNormError) {
+ if (block._state != Modulate::saturated) {
+ block._color->rgb.setValue(Modulate::_saturatedColor);
+ if (_mod != color)
+ block._scale->scaleFactor.setValue(_xScale,
+ _yScale,
+ _zScale);
+ block._state = Modulate::saturated;
+ }
+ }
+ else {
+ if (block._state != Modulate::normal) {
+ block._state = Modulate::normal;
+ if (_mod == yScale)
+ block._color->rgb.setValue(_metrics->color(m).getValue());
+ }
+ else if (_mod != yScale)
+ block._color->rgb.setValue(_colScale.step(unscaled).color().getValue());
+ if (_mod != color) {
+ if (value < Modulate::theMinScale)
+ value = Modulate::theMinScale;
+ else if (value > 1.0)
+ value = 1.0;
+ block._scale->scaleFactor.setValue(_xScale,
+ _yScale * value,
+ _zScale);
+ }
+
+ }
+ }
+ }
+ }
+}
+
+void
+BarMod::selectAll()
+{
+ int i;
+
+ if (_selectCount == _blocks.size())
+ return;
+
+ theModList->selectAllId(_root, _blocks.size());
+
+#ifdef PCP_DEBUG
+ if (pmDebug & DBG_TRACE_APPL2)
+ cerr << "BarMod::selectAll" << endl;
+#endif
+
+ for (i = 0; i < _blocks.size(); i++) {
+ if (_blocks[i]._selected == false) {
+ _selectCount++;
+ theModList->selectSingle(_blocks[i]._sep);
+ _blocks[i]._selected = true;
+ }
+ }
+}
+
+int
+BarMod::select(SoPath *path)
+{
+ int metric, inst, value;
+
+ findBlock(path, metric, inst, value, false);
+ if (value < _blocks.size() && _blocks[value]._selected == false) {
+ _blocks[value]._selected = true;
+ _selectCount++;
+
+#ifdef PCP_DEBUG
+ if (pmDebug & DBG_TRACE_APPL2)
+ cerr << "BarMod::select: value = " << value
+ << ", count = " << _selectCount << endl;
+#endif
+ }
+ return _selectCount;
+}
+
+int
+BarMod::remove(SoPath *path)
+{
+ int metric, inst, value;
+
+ findBlock(path, metric, inst, value, false);
+ if (value < _blocks.size() && _blocks[value]._selected == true) {
+ _blocks[value]._selected = false;
+ _selectCount--;
+
+#ifdef PCP_DEBUG
+ if (pmDebug & DBG_TRACE_APPL2)
+ cerr << "BarMod::remove: value = " << value
+ << ", count = " << _selectCount << endl;
+#endif
+
+ }
+
+#ifdef PCP_DEBUG
+ else if (pmDebug & DBG_TRACE_APPL2)
+ cerr << "BarMod::remove: did not remove " << value
+ << ", count = " << _selectCount << endl;
+#endif
+
+ return _selectCount;
+}
+
+void BarMod::infoText(QString &str, bool selected) const
+{
+ int m = _infoMetric;
+ int i = _infoInst;
+ int v = _infoValue;
+ bool found = false;
+
+ if (selected && _selectCount == 1) {
+ for (m = 0, v = 0; m < _metrics->numMetrics(); m++) {
+ const QmcMetric &metric = _metrics->metric(m);
+ for (i = 0; i < metric.numValues(); i++, v++)
+ if (_blocks[v]._selected) {
+ found = true;
+ break;
+ }
+ if (found)
+ break;
+ }
+ }
+
+ if (v >= _blocks.size()) {
+#ifdef PCP_DEBUG
+ if (pmDebug & DBG_TRACE_APPL2)
+ cerr << "BarMod::infoText: infoText requested but nothing selected"
+ << endl;
+#endif
+ str = "";
+ }
+ else {
+ const QmcMetric &metric = _metrics->metric(m);
+ str = metric.spec(true, true, i);
+ str.append(QChar('\n'));
+
+ if (_blocks[v]._state == Modulate::error)
+ str.append(theErrorText);
+ else if (_blocks[v]._state == Modulate::start)
+ str.append(theStartText);
+ else {
+ QString value;
+ str.append(value.setNum(metric.realValue(i), 'g', 4));
+ str.append(QChar(' '));
+ if (metric.desc().units().size() > 0)
+ str.append(metric.desc().units());
+ str.append(" [");
+ str.append(value.setNum(metric.value(i) * 100.0, 'g', 4));
+ str.append("% of expected max]");
+ }
+ }
+}
+
+void BarMod::launch(Launch &launch, bool all) const
+{
+ int m, i, v;
+ bool needClose;
+ bool always = all;
+ bool keepGoing = true;
+
+ if (status() < 0)
+ return;
+
+ if (_selectCount == _blocks.size())
+ always = true;
+
+ // Group by metric
+ if (_group == groupByMetric ||
+ (_group == groupByRow && _dir == instPerCol) ||
+ (_group == groupByCol && _dir == instPerRow)) {
+
+ for (m = 0, v = 0; m < _metrics->numMetrics(); m++) {
+ QmcMetric &metric = _metrics->metric(m);
+
+ // Do we have to check that an instance of this metric has
+ // been selected?
+ if (!always) {
+ needClose = false;
+ for (i = 0; i < metric.numValues(); i++, v++) {
+ if (_blocks[v]._selected) {
+ if (needClose == false) {
+ launch.startGroup("point");
+ needClose = true;
+ }
+ if (_mod == yScale)
+ launch.addMetric(metric, _metrics->color(m), i);
+ else
+ launch.addMetric(metric, _colScale, i);
+ }
+ }
+ if (needClose)
+ launch.endGroup();
+ }
+ else {
+ launch.startGroup("point");
+ for (i = 0; i < metric.numValues(); i++, v++) {
+ if (_mod == yScale)
+ launch.addMetric(metric, _metrics->color(m), i);
+ else
+ launch.addMetric(metric, _colScale, i);
+ }
+ launch.endGroup();
+ }
+ }
+ }
+
+ // Group by instance, this gets a little tricky
+ else {
+ for (i = 0; keepGoing ; i++) {
+ needClose = false;
+ keepGoing = false;
+ for (m = 0, v = 0; m < _metrics->numMetrics(); m++) {
+ QmcMetric &metric = _metrics->metric(m);
+ if (metric.numValues() > i) {
+ if (always || _blocks[v+i]._selected) {
+ if (needClose == false) {
+ launch.startGroup("point");
+ needClose = true;
+ }
+ if (_mod == yScale)
+ launch.addMetric(metric, _metrics->color(m), i);
+ else
+ launch.addMetric(metric, _colScale, i);
+ }
+ keepGoing = true;
+ }
+ v += metric.numValues();
+ }
+ if (needClose)
+ launch.endGroup();
+ }
+ }
+}
+
+void
+BarMod::selectInfo(SoPath *path)
+{
+ findBlock(path, _infoMetric, _infoInst, _infoValue);
+}
+
+void
+BarMod::removeInfo(SoPath *)
+{
+ _infoValue = _blocks.size();
+ _infoMetric = _infoInst = 0;
+}
+
+void
+BarMod::dump(QTextStream &os) const
+{
+ int m, i, v;
+
+ os << "BarMod: ";
+
+ if (_dir == instPerCol)
+ os << "inst per col";
+ else
+ os << "inst per row";
+
+ if (_mod == yScale)
+ os << ", Y-Scale: ";
+ else if (_mod == color)
+ os << ", Color Only: ";
+ else
+ os << ", Color & Y-Scale: ";
+
+ if (status() < 0)
+ os << "Invalid metrics: " << pmErrStr(status()) << endl;
+ else {
+ os << endl;
+ for (m = 0, v = 0; m < _metrics->numMetrics(); m++) {
+ QmcMetric &metric = _metrics->metric(m);
+ for (i = 0; i < metric.numValues(); i++, v++) {
+ os << " [" << v << "]: ";
+ if (_blocks[v]._selected == true)
+ os << '*';
+ else
+ os << ' ';
+ dumpState(os, _blocks[v]._state);
+ os << ": ";
+ metric.dump(os, true, i);
+ }
+ }
+ }
+}
+
+void
+BarMod::findBlock(SoPath *path, int &metric, int &inst,
+ int &value, bool idMetric)
+{
+ SoNode *node;
+ char *str;
+ int m, i, v;
+ char c;
+
+ for (i = path->getLength() - 1; i >= 0; --i) {
+ node = path->getNode(i);
+ str = (char *)(node->getName().getString());
+ if (strlen(str) && str[0] == theBarId)
+ break;
+ }
+
+ if (i >= 0) {
+
+#ifdef PCP_DEBUG
+ if (pmDebug & DBG_TRACE_APPL2)
+ cerr << "BarMod::findBlock: Bar id = " << str << endl;
+#endif
+
+ sscanf(str, "%c%d", &c, &value);
+
+ if (value == 0 || idMetric == false) {
+ metric = 0;
+ inst = 0;
+ }
+ else {
+ m = 0;
+ v = value;
+ while (m < _metrics->numMetrics()) {
+ i = _metrics->metric(m).numValues();
+ if (v < i) {
+ metric = m;
+ inst = v;
+ break;
+ }
+ else {
+ v -= i;
+ m++;
+ }
+ }
+ }
+ }
+ else {
+ value = _blocks.size();
+ metric = inst = 0;
+ }
+
+#ifdef PCP_DEBUG
+ if (pmDebug & DBG_TRACE_APPL2) {
+ cerr << "BarMod::findBlock: metric = " << metric
+ << ", inst = " << inst << ", value = " << value << endl;
+ }
+#endif
+
+ return;
+}
+
+void
+BarMod::regenerate(float xScale, float zScale, float xSpace, float zSpace)
+{
+ int m, i, v;
+ float halfX = xScale / 2.0;
+ float halfZ = zScale / 2.0;
+
+ if (status() < 0)
+ return;
+
+ _xScale = xScale;
+ _zScale = zScale;
+
+ _width = (unsigned int)((_cols * (_xScale + xSpace)) - xSpace);
+ _depth = (unsigned int)((_rows * (_zScale + zSpace)) - zSpace);
+
+ for (m = 0, v = 0; m < _metrics->numMetrics(); m++) {
+ const QmcMetric &metric = _metrics->metric(m);
+ for (i = 0; i < metric.numValues(); i++, v++) {
+ BarBlock &block = _blocks[v];
+
+ if (_dir == instPerCol)
+ block._tran->translation.setValue(i * (_xScale+xSpace) + halfX,
+ 0,
+ m * (_zScale+zSpace) + halfZ);
+ else
+ block._tran->translation.setValue(m * (_xScale+xSpace) + halfX,
+ 0,
+ i * (_zScale+zSpace) + halfZ);
+
+ block._color->rgb.setValue(_errorColor.getValue());
+ block._scale->scaleFactor.setValue(_xScale, _yScale, _zScale);
+ block._state = Modulate::start;
+ block._selected = false;
+ }
+ }
+}
+
+const char *
+BarMod::dirStr() const
+{
+ const char *str = NULL;
+
+ if (_dir == instPerCol)
+ str = "instances in columns";
+ else
+ str = "instances in rows";
+
+ return str;
+}
+
+const char *
+BarMod::modStr() const
+{
+ const char *str = NULL;
+
+ switch (_mod) {
+ case yScale:
+ str = "Y-Scale";
+ break;
+ case color:
+ str = "Colored";
+ break;
+ case colYScale:
+ str = "Colored Y-Scale";
+ break;
+ }
+ return str;
+}