Commit e5456a5d authored by Hisham's avatar Hisham
Browse files

Determine graph colors in O(items+graphHeight),

as suggested by @Explorer09. It's not really faster.
parent de432309
...@@ -108,8 +108,8 @@ typedef struct GraphData_ { ...@@ -108,8 +108,8 @@ typedef struct GraphData_ {
struct timeval time; struct timeval time;
double values[METER_BUFFER_LEN]; double values[METER_BUFFER_LEN];
int colors[METER_BUFFER_LEN][GRAPH_HEIGHT]; int colors[METER_BUFFER_LEN][GRAPH_HEIGHT];
double *prevItemSums; double *prevItems;
double *currentItemSums; double *currentItems;
} GraphData; } GraphData;
}*/ }*/
...@@ -120,6 +120,9 @@ typedef struct GraphData_ { ...@@ -120,6 +120,9 @@ typedef struct GraphData_ {
#ifndef MAX #ifndef MAX
#define MAX(a,b) ((a)>(b)?(a):(b)) #define MAX(a,b) ((a)>(b)?(a):(b))
#endif #endif
#ifndef CLAMP
#define CLAMP(x, low, high) (((x) > (high)) ? (high) : (((x) < (low)) ? (low) : (x)))
#endif
MeterClass Meter_class = { MeterClass Meter_class = {
.super = { .super = {
...@@ -373,10 +376,10 @@ static void GraphMeterMode_draw(Meter* this, int x, int y, int w) { ...@@ -373,10 +376,10 @@ static void GraphMeterMode_draw(Meter* this, int x, int y, int w) {
if (!this->drawData) { if (!this->drawData) {
this->drawData = calloc(1, sizeof(GraphData)); this->drawData = calloc(1, sizeof(GraphData));
GraphData* data = (GraphData*) this->drawData; GraphData* data = (GraphData*) this->drawData;
if (!data->prevItemSums) if (!data->prevItems)
data->prevItemSums = calloc(Meter_getMaxItems(this), sizeof(*data->prevItemSums)); data->prevItems = calloc(Meter_getMaxItems(this), sizeof(*data->prevItems));
if (!data->currentItemSums) if (!data->currentItems)
data->currentItemSums = calloc(Meter_getMaxItems(this), sizeof(*data->currentItemSums)); data->currentItems = calloc(Meter_getMaxItems(this), sizeof(*data->currentItems));
for (int i = 0; i < nValues; i++) { for (int i = 0; i < nValues; i++) {
for (int line = 0; line < GRAPH_HEIGHT; line++) { for (int line = 0; line < GRAPH_HEIGHT; line++) {
data->colors[i][line] = BAR_SHADOW; data->colors[i][line] = BAR_SHADOW;
...@@ -418,35 +421,68 @@ static void GraphMeterMode_draw(Meter* this, int x, int y, int w) { ...@@ -418,35 +421,68 @@ static void GraphMeterMode_draw(Meter* this, int x, int y, int w) {
int items = Meter_getItems(this); int items = Meter_getItems(this);
double *prevItemSums = data->prevItemSums; double *prevItems = data->prevItems;
double *currentItemSums = data->currentItemSums; double *currentItems = data->currentItems;
data->values[nValues - 1] = 0.0;
for (int i = 0; i < items; i++) { for (int i = 0; i < items; i++) {
prevItemSums[i] = currentItemSums[i]; prevItems[i] = currentItems[i];
currentItemSums[i] = ((i > 0) ? currentItemSums[i-1] : 0.0) + this->values[i]; currentItems[i] = this->values[i];
data->values[nValues - 1] += this->values[i];
} }
data->values[nValues - 1] = currentItemSums[items - 1] / this->total; data->values[nValues - 1] /= this->total;
// Determine the dominant color of the cell in graph double cellAmount = (this->total * 2) / GRAPH_HEIGHT;
for (int line = 0; line < GRAPH_HEIGHT; line++) { int currCell = GRAPH_HEIGHT - 1;
int dominantColor = BAR_SHADOW; int currCellColor = BAR_SHADOW;
double maxArea = 0.0; double currCellAvailable = cellAmount;
double currCellDominant = 0.0;
for (int i = 0; i < items; i++) { for (int i = 0; i < items; i++) {
double area; int itemColor = Meter_attributes(this)[i];
double upperBound = this->total * (GRAPH_HEIGHT - line) / GRAPH_HEIGHT; double itemAmount = prevItems[i] + currentItems[i];
double lowerBound = this->total * (GRAPH_HEIGHT - 1 - line) / GRAPH_HEIGHT; // How much I can contribute to the current bucket
area = MAX(lowerBound, MIN(currentItemSums[i], upperBound)) + double itemFillCurr = CLAMP(itemAmount, itemAmount, currCellAvailable);
MAX(lowerBound, MIN(prevItemSums[i], upperBound)); // If I'm winning I take over the bucket color...
area -= MAX(lowerBound, MIN(((i > 0) ? currentItemSums[i-1] : 0.0), upperBound)) + if (itemFillCurr > currCellDominant) {
MAX(lowerBound, MIN(((i > 0) ? prevItemSums[i-1] : 0.0), upperBound)); currCellDominant = itemFillCurr;
if (area > maxArea) { currCellColor = itemColor;
maxArea = area; }
dominantColor = Meter_attributes(this)[i]; currCellAvailable -= itemFillCurr;
// If I filled the bucket, time to give it to the winner:
if (currCellAvailable == 0.0) {
data->colors[nValues - 1][currCell] = currCellColor;
// on to the next bucket
currCell--;
currCellColor = BAR_SHADOW;
currCellAvailable = cellAmount;
currCellDominant = 0.0;
// Do I have anything else for more buckets?
itemAmount -= itemFillCurr;
if (itemAmount > 0.0) {
// Anything to fill entire buckets?
int fullCells = itemAmount / cellAmount;
if (fullCells > 0) {
for (int c = 0; c < fullCells; c++) {
data->colors[nValues - 1][currCell - c] = itemColor;
}
currCell -= fullCells;
} }
// If there's anything left, I'm the first in the next open bucket.
double restAmount = itemAmount - (fullCells * cellAmount);
if (restAmount > 0.0) {
currCellColor = itemColor;
currCellAvailable = cellAmount - restAmount;
currCellDominant = restAmount;
} }
data->colors[nValues - 1][line] = dominantColor;
} }
} }
}
for (int c = currCell; c >= 0; c--) {
data->colors[nValues - 1][c] = currCellColor;
currCellColor = BAR_SHADOW;
}
}
for (int i = nValues - (w*2) + 2, k = 0; i < nValues; i+=2, k++) { for (int i = nValues - (w*2) + 2, k = 0; i < nValues; i+=2, k++) {
int pix = GraphMeterMode_pixPerRow * GRAPH_HEIGHT; int pix = GraphMeterMode_pixPerRow * GRAPH_HEIGHT;
......
...@@ -95,8 +95,8 @@ typedef struct GraphData_ { ...@@ -95,8 +95,8 @@ typedef struct GraphData_ {
struct timeval time; struct timeval time;
double values[METER_BUFFER_LEN]; double values[METER_BUFFER_LEN];
int colors[METER_BUFFER_LEN][GRAPH_HEIGHT]; int colors[METER_BUFFER_LEN][GRAPH_HEIGHT];
double *prevItemSums; double *prevItems;
double *currentItemSums; double *currentItems;
} GraphData; } GraphData;
...@@ -106,6 +106,9 @@ typedef struct GraphData_ { ...@@ -106,6 +106,9 @@ typedef struct GraphData_ {
#ifndef MAX #ifndef MAX
#define MAX(a,b) ((a)>(b)?(a):(b)) #define MAX(a,b) ((a)>(b)?(a):(b))
#endif #endif
#ifndef CLAMP
#define CLAMP(x, low, high) (((x) > (high)) ? (high) : (((x) < (low)) ? (low) : (x)))
#endif
extern MeterClass Meter_class; extern MeterClass Meter_class;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment