|
|
@@ -1,8 +1,10 @@
|
|
|
//
|
|
|
-// ofxPlotter.h
|
|
|
-// Plotter example
|
|
|
+// ofxPlotter.cpp
|
|
|
//
|
|
|
-// Created by zebra on 06/05/16.
|
|
|
+// Created by Juan Carlos Carvajal B.
|
|
|
+// juan-carlos.info
|
|
|
+//
|
|
|
+// Based on the plugin by zebra on 06/05/16.
|
|
|
//
|
|
|
//
|
|
|
|
|
|
@@ -15,16 +17,18 @@
|
|
|
|
|
|
#include "ofMain.h"
|
|
|
|
|
|
+using namespace std;
|
|
|
+
|
|
|
|
|
|
class ofxPlotter {
|
|
|
|
|
|
- class Value {
|
|
|
public:
|
|
|
- float inner_value;
|
|
|
- float inner_value_filtered;
|
|
|
-
|
|
|
- Value() { }
|
|
|
-
|
|
|
+
|
|
|
+ struct singleValue {
|
|
|
+ public:
|
|
|
+
|
|
|
+ singleValue() : inner_value (0) { }
|
|
|
+
|
|
|
// Float righthand
|
|
|
void operator<<(float righthand) {
|
|
|
inner_value = righthand;
|
|
|
@@ -34,242 +38,76 @@ class ofxPlotter {
|
|
|
void operator<<(int righthand) {
|
|
|
inner_value = righthand;
|
|
|
}
|
|
|
-
|
|
|
-
|
|
|
- int getI() {
|
|
|
- return inner_value;
|
|
|
- }
|
|
|
|
|
|
- float getF() {
|
|
|
- return (float)inner_value;
|
|
|
+ void setCurrentValue(float righthand) {
|
|
|
+ inner_value = righthand;
|
|
|
}
|
|
|
-
|
|
|
- float getFiltered(float filter_amount = 0.2) {
|
|
|
- inner_value_filtered = inner_value_filtered * filter_amount + inner_value * filter_amount;
|
|
|
- return inner_value_filtered;
|
|
|
+
|
|
|
+ void setCurrentValue(int righthand) {
|
|
|
+ inner_value = float(righthand);
|
|
|
}
|
|
|
-
|
|
|
- };
|
|
|
|
|
|
-
|
|
|
- static int windowSize;
|
|
|
- static float windowLength;
|
|
|
-
|
|
|
-public:
|
|
|
- ofxPlotter() {
|
|
|
- windowSize = 300;
|
|
|
- ofAddListener(ofEvents().update, this, &::ofxPlotter::update);
|
|
|
- }
|
|
|
-
|
|
|
- void updateHistory() {
|
|
|
- for (std::map<std::string, ofxPlotter::Value>::iterator i = values.begin(); i != values.end(); i++) {
|
|
|
- history[i->first].push_back(i->second);
|
|
|
- if (history[i->first].size() > windowSize) {
|
|
|
- history[i->first].erase(history[i->first].begin());
|
|
|
- }
|
|
|
- if (accents[i->first].size() > windowSize) {
|
|
|
- accents[i->first].erase(accents[i->first].begin());
|
|
|
- }
|
|
|
- accents[i->first].push_back(0);
|
|
|
+ // void setNullValue() { inner_value = NAN; }
|
|
|
+
|
|
|
+ float getF() {
|
|
|
+ return inner_value;
|
|
|
}
|
|
|
- }
|
|
|
-
|
|
|
- void addAccent(std::string index) {
|
|
|
- accents[index][accents[index].size() - 1] = 5;
|
|
|
- }
|
|
|
-
|
|
|
- void addGuideline(std::string index, float guideline) {
|
|
|
- guidelines[index] = guideline;
|
|
|
- }
|
|
|
-
|
|
|
- void update(ofEventArgs & args) {
|
|
|
- updateHistory();
|
|
|
- }
|
|
|
-
|
|
|
- Value& operator[](std::string righthand) {
|
|
|
- return (Value&)values[righthand];
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- float getHistoryFor(std::string index, int step) {
|
|
|
- return history[index][history[index].size() - 1 - step].getF();
|
|
|
- }
|
|
|
-
|
|
|
- void drawOverlay(float x, float y, float width, float height) {
|
|
|
- int graphCount = values.size();
|
|
|
- if (!ofRectangle(x, y, width, height).inside(ofGetMouseX(), ofGetMouseY())) return;
|
|
|
- float mx = (ofGetMouseX() - x) / width;
|
|
|
- float my = (ofGetMouseY() - y) / height;
|
|
|
- int yspace = (float)height / graphCount;
|
|
|
-
|
|
|
- int index = (my / (1 / (float)graphCount));
|
|
|
-
|
|
|
- ofSetColor(255);
|
|
|
+
|
|
|
+ float inner_value;
|
|
|
|
|
|
- int counter = 0;
|
|
|
- for (std::map<std::string, ofxPlotter::Value>::iterator i = values.begin(); i != values.end(); i++) {
|
|
|
- if (index == counter) {
|
|
|
- float position = (mx * history[i->first].size());
|
|
|
- ofDrawBitmapStringHighlight(ofToString(history[i->first][position].getF()), x + mx * width, y + my * height);
|
|
|
- }
|
|
|
- counter++;
|
|
|
- }
|
|
|
- }
|
|
|
+ };
|
|
|
|
|
|
- void drawCustomPlot(string plot, int x, int y,
|
|
|
- int width, int height) {
|
|
|
- std::vector<ofxPlotter::Value>* historyValues = &history[plot];
|
|
|
+ struct dataCollection{
|
|
|
+
|
|
|
+ dataCollection(); // : plotColor ( ofColor(0) ) , autoRange ( True ), drawOverlay ( False ), plotLength ( 300 ) { }
|
|
|
+ ofColor plotColor;
|
|
|
+ singleValue currentValue;
|
|
|
+ vector<singleValue> records;
|
|
|
+ vector<float> guidelines;
|
|
|
+ int plotLength;
|
|
|
+ float maxValue;
|
|
|
+ float minValue;
|
|
|
+ bool autoRange;
|
|
|
+ bool drawOverlay;
|
|
|
+ bool drawInfo;
|
|
|
+ bool drawGuidelines;
|
|
|
+
|
|
|
+ void setCurrentValue (int currentValue) { this->currentValue.setCurrentValue(currentValue); }
|
|
|
+ void setCurrentValue (float currentValue) { this->currentValue.setCurrentValue(currentValue); }
|
|
|
+ void setMinMaxValue (float maxValue, float minValue ) { this->maxValue = maxValue; this->minValue = minValue; autoRange = false; }
|
|
|
+ void setPlotLength (int plotLength); // { this->plotLength = plotLength; }
|
|
|
+ int getplotLength() { return plotLength; }
|
|
|
+ void setColor(ofColor plotColor) { this->plotColor = plotColor; }
|
|
|
+ void addGuideline(float guideline) { guidelines.push_back(guideline); }
|
|
|
|
|
|
- // Measuring the function scale
|
|
|
- float sum = 0;
|
|
|
- float max = -999999999;
|
|
|
- float min = 999999999;
|
|
|
- for (int i = 0; i < historyValues->size(); i++) {
|
|
|
- float value = (*historyValues).operator[](i).getF();
|
|
|
- sum += value;
|
|
|
- if (value > max) max = value;
|
|
|
- if (value < min) min = value;
|
|
|
- }
|
|
|
- float median = sum / historyValues->size();
|
|
|
+ };
|
|
|
|
|
|
- float multiplier = 1 / (max - min);
|
|
|
+ ofxPlotter();
|
|
|
+ ofxPlotter( int plotLength );
|
|
|
|
|
|
- float stepWidth = width / historyValues->size();
|
|
|
- ofPushMatrix();
|
|
|
- ofTranslate(x, y);
|
|
|
+ void update(ofEventArgs & args) { updateHistory(); }
|
|
|
+ void updateHistory();
|
|
|
|
|
|
- ofPoint p, p2;
|
|
|
- for (int j = 0; j < (*historyValues).size(); j++) {
|
|
|
+ void drawAllVertical();
|
|
|
+ void drawAllVertical(float x, float y, float width, float height);
|
|
|
|
|
|
- float mappedPoint = 1 - ofMap((*historyValues)[j].getF(), min, max, 0, 1);
|
|
|
+ void drawAllHorizontal();
|
|
|
+ void drawAllHorizontal(float x, float y, float width, float height);
|
|
|
|
|
|
- p = ofPoint(j * stepWidth,
|
|
|
- mappedPoint * (float)height);
|
|
|
- ofSetLineWidth(2);
|
|
|
- if (j != 0) ofLine(p2, p);
|
|
|
- p2 = p;
|
|
|
+ void drawPlot(string plot);
|
|
|
+ void drawPlot(string plot, int x, int y, int width, int height);
|
|
|
|
|
|
- }
|
|
|
- ofPopMatrix();
|
|
|
- }
|
|
|
-
|
|
|
- void draw(float x, float y, float width, float height, int verticalLines = 16) {
|
|
|
- int graphCount = values.size();
|
|
|
- int yspace = (float)height / graphCount;
|
|
|
- int index = 0;
|
|
|
- float colorspaceWidth = 255. / (float)graphCount;
|
|
|
- for (std::map<std::string, ofxPlotter::Value>::iterator i = values.begin(); i != values.end(); i++) {
|
|
|
- std::vector<ofxPlotter::Value>* historyValues = &history[i->first];
|
|
|
-
|
|
|
- ofColor plotColor = ofColor::fromHsb((index * colorspaceWidth), 255, 150, 255);
|
|
|
-
|
|
|
- // Measuring the function scale
|
|
|
- float sum = 0;
|
|
|
- float max = -999999999;
|
|
|
- float min = 999999999;
|
|
|
- for (int i = 0; i < historyValues->size(); i++) {
|
|
|
- float value = (*historyValues).operator[](i).getF();
|
|
|
- sum += value;
|
|
|
- if (value > max) max = value;
|
|
|
- if (value < min) min = value;
|
|
|
- }
|
|
|
- float median = sum / historyValues->size();
|
|
|
-
|
|
|
- float multiplier = 1 / (max - min);
|
|
|
-
|
|
|
- float stepWidth = width / historyValues->size();
|
|
|
- ofPushMatrix();
|
|
|
- ofTranslate(x, y + yspace * index);
|
|
|
-
|
|
|
- ofPoint p, p2;
|
|
|
- for (int j = 0; j < (*historyValues).size(); j++) {
|
|
|
-
|
|
|
- float mappedPoint = 1 - ofMap((*historyValues)[j].getF(), min, max, 0, 1);
|
|
|
-
|
|
|
- p = ofPoint(j * stepWidth,
|
|
|
- mappedPoint * yspace);
|
|
|
- ofSetLineWidth(2);
|
|
|
- ofSetColor(plotColor);
|
|
|
- if (j != 0) ofLine(p2, p);
|
|
|
- p2 = p;
|
|
|
-
|
|
|
- }
|
|
|
+ void drawOverlay(string plot, float x, float y, float width, float height);
|
|
|
+ void drawInfo(string plot, float x, float y, float width, float height);
|
|
|
+ void drawGuidelines(string plot, float x, float y, float width, float height);
|
|
|
|
|
|
- auto guidelineIter = guidelines.find(i->first);
|
|
|
- if (guidelineIter != guidelines.end()) {
|
|
|
- float mappedPoint = 1 - ofMap(guidelines[i->first], min, max, 0, 1);
|
|
|
- ofLine(x, y + yspace * mappedPoint, x + width, y + yspace * mappedPoint);
|
|
|
- }
|
|
|
+ dataCollection& operator[](string name) {
|
|
|
+ return (dataCollection&)plotData[name];
|
|
|
|
|
|
- int lastx = -200;
|
|
|
- for (int j = 0; j < (*historyValues).size(); j++) {
|
|
|
- if (accents[i->first][j] != 0) {
|
|
|
- ofSetColor(255);
|
|
|
- ofSetLineWidth(2);
|
|
|
- ofLine(j * stepWidth, index * yspace,
|
|
|
- j * stepWidth, (index - 1) * yspace);
|
|
|
- ofCircle(j * stepWidth, index * yspace, 3);
|
|
|
- float mid = 0;
|
|
|
- if (j > 5) {
|
|
|
- for (int k = j - 5; k < j + 5; k++) {
|
|
|
- mid += (*historyValues)[k].getF();
|
|
|
- }
|
|
|
- mid /= 10;
|
|
|
- }
|
|
|
- if ((j * stepWidth - lastx) > 200) {
|
|
|
- ofDrawBitmapStringHighlight(ofToString(mid), j * stepWidth, index * yspace - 15);
|
|
|
- lastx = j * stepWidth;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- std::string overlayName = i->first;
|
|
|
- std::string minValueStr = ofToString(min, 4);
|
|
|
- std::string maxValueStr = ofToString(max, 4);
|
|
|
-
|
|
|
- // Plot name
|
|
|
- ofSetColor(255, 240);
|
|
|
- ofDrawRectangle(width - overlayName.length() * 8, yspace / 2 - 12, overlayName.length() * 8, 15);
|
|
|
- ofSetColor(plotColor);
|
|
|
- ofDrawBitmapString(overlayName, width - overlayName.length() * 8, yspace / 2);
|
|
|
-
|
|
|
- // Max value
|
|
|
- ofSetColor(255, 240);
|
|
|
- ofDrawRectangle(0, 0, maxValueStr.length() * 8, 15);
|
|
|
- ofSetColor(plotColor);
|
|
|
- ofDrawBitmapString(maxValueStr, 0, 12);
|
|
|
-
|
|
|
- // Min value
|
|
|
- ofSetColor(255, 240);
|
|
|
- ofDrawRectangle(0, yspace - 12, minValueStr.length() * 8, 15);
|
|
|
- ofSetColor(plotColor);
|
|
|
- ofDrawBitmapString(minValueStr, 0, yspace);
|
|
|
-
|
|
|
- ofPopMatrix();
|
|
|
-
|
|
|
- index++;
|
|
|
- }
|
|
|
-
|
|
|
- if (drawMouseOverlay) drawOverlay(x, y, width, height);
|
|
|
}
|
|
|
-
|
|
|
- std::map<std::string, ofxPlotter::Value> values;
|
|
|
- std::map<std::string, std::vector<ofxPlotter::Value>> history;
|
|
|
- std::map<std::string, std::vector<int>> accents;
|
|
|
- std::map<std::string, float> guidelines;
|
|
|
-
|
|
|
-
|
|
|
- // Parameters
|
|
|
-
|
|
|
- void setWindowSize(int size) {
|
|
|
- windowSize = size;
|
|
|
- }
|
|
|
-
|
|
|
- int getWindowSize() {
|
|
|
- return windowSize;
|
|
|
- }
|
|
|
-
|
|
|
- bool drawMouseOverlay = true;
|
|
|
+
|
|
|
+ map<string, dataCollection> plotData;
|
|
|
+
|
|
|
};
|
|
|
|
|
|
#endif /* ofxPlotter_h */
|