/* * histogram-based routines * * when dayLen = 1 day and hx1 = nameBorder+1, hx2 = width-1 * then the width of a bin is 85 seconds. */ static final int histBgColor = #99cc99; static final int histFgColor = #999966; // static final int histBgColor = #66cc66; // static final int histFgColor = #999933; static final int histHiColor = #cc3333; static final int histTimeColor = #666666; // X axis coordinates of the left and right of the histogram display area static int hx1, hx2; static int dhx; // hx2 - hx1 // The time coordinates corresponding to the current Histogram display static int ht1, ht2; // final int dht = dayLen; final int dht = (int) (dayLen * 1.5); // ht2 - ht1 // store histogram info int[] histT; int[] histY; /* * Given a time value (relative to time0), calculate the * corresponding X value, given the current time range displayed * by the histogram. */ int timeToHistX(int time) { return hx1 + (int) (dhx * (time - ht1) * 1.0 / dht); } /* * Convert an X axis value to the time, given the current range * displayed by the histogram. */ int histXToTime(int hx) { return ht1 + (int) (dht * (hx - hx1) * 1.0 / dhx); } /* * update the limits so that the given time is * the center of the histogram (or as close to it * as you can get). * * TODO: we may only shift if the difference is * large enough, to try and avoid too much animation */ void recenterHistogram(int time) { ht1 = time - (dht / 2); if (ht1 < timeStart) { ht1 = timeStart; } ht2 = ht1 + dht; if (ht2 > timeEnd) { ht2 = timeEnd; ht1 = ht2 - dht; } } void displayHistogram() { noStroke(); fill(histBgColor); rectMode(CORNERS); rect(0, height, width, height - histogramBorder); // see about drawing on bands of color over the background, every // three hours // fill(0, 0.1); // stroke(0, 0.1); int tlo = timeStart; while (tlo < timeEnd) { int thi = constrain(tlo + 3600 * 3, timeStart, timeEnd); drawHistRect(tlo, thi); tlo += 3600 * 6; } // display marks indicating the time stroke(histTimeColor); fill(histTimeColor); textAlign(LEFT); textFont(timeFont, timeFontSize / 2); for (int i = 0; i < 5; i++) { int t = i * dayLen; int hx = timeToHistX(t); if (hx >= hx1 && hx <= hx2) { line(hx, height, hx, height - histogramBorder); text(dayName[i], hx + 5, height - 35); } } // noStroke(); stroke(histFgColor); fill(histFgColor); // could make partially transparent? beginShape(); vertex(hx1 - 1, height); for(int i = 0; i < histY.length; i++) { int hx = timeToHistX(histT[i]); if (hx >= hx1 && hx <= hx2) { vertex(hx, histY[i]); } } vertex(hx2 + 1, height); endShape(); highlightScreen(); } // highlight the screen area on the histogram void highlightScreen() { stroke(histHiColor); fill(histHiColor, 0.4); rectMode(CORNERS); drawHistRect(pixelToTime(timeY1), currentTime); } /* * draw a rectangle within the histogram area, covering the full * height. t1 and t2 are the times for the two edges and t1 must * be <= t2 (not checked for). */ void drawHistRect(int t1, int t2) { int x1 = timeToHistX(t1); int x2 = timeToHistX(t2); if (x1 <= hx2 || x2 >= hx1) { rect(constrain(x1, hx1, hx2), height, constrain(x2, hx1, hx2), height - histogramBorder); } } /* * Setup the histogram after reading in the tweets. */ void setupHistogram() { hx1 = nameBorder + 1; hx2 = width - 1; dhx = hx2 - hx1; int hwid = 90; // (int) (dht * 1.0 / dhx + 0.5); if (hwid < 1) { println("Errr, width of each histogram bin is < 1 second!"); return; } int nh = 1 + (timeEnd - timeStart) / hwid; histT = new int[nh]; histY = new int[nh]; // we store the left edge of each histogram bin (in units of time) // rather than the center; this should make no difference given the // resolution we have // for(int i = 0; i < nh; i++) { histT[i] = timeStart + i * hwid; histY[i] = 0; } for (int i = 0; i < tweets.length; i++) { if (tweets[i].type == 0) { int j = (int) ((tweets[i].time - timeStart) / hwid); // println(" t = " + tweets[i].time + " -> j = " + j); histY[j] ++; } } int maxHist = 0; for (int i = 0; i < nh; i++) { if (histY[i] > maxHist) { maxHist = histY[i]; } } // println("max counts = " + maxHist); for (int i = 0; i < nh; i++) { int y = (int) (0.5 + histY[i] * histogramBorder * 1.0 / maxHist); // I assume here int() rounds down if (histY[i] > 0 && y == 0) { histY[i] = height - 1; } else { histY[i] = height - y; } } }