Skip to content

Instantly share code, notes, and snippets.

@spudtrooper
Created September 3, 2011 17:31
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save spudtrooper/1191495 to your computer and use it in GitHub Desktop.
Save spudtrooper/1191495 to your computer and use it in GitHub Desktop.
Plots functions over a domain of 2*PI on * http://www.google.com/trends/correlate/draw.
/**
* Plots functions over a domain of 2*PI on
* http://www.google.com/trends/correlate/draw.
*
* More here:
*
* http://www.jeffpalm.com/blog/archives/002216.html
*/
(function() {
/*
* Translation coordinates for the canvas used for the graph --
* found by inspection. They work for me, god knows if they'll work
* for anyone else?
*
* (MIN_X,MAX_VALUE) (MAX_X,MAX_VALUE)
* ^
* |
* (MIN_X,MIN_VALUE) ----------> (MAX_X,MIN_VALUE)
*
*/
const MIN_VALUE = 0, MAX_VALUE = 250, MIN_X = 34, MAX_X = 600;
function plot(f) {
var period = 2*Math.PI;
var steps = 30;
for (var step=0; step<=steps; step++) {
var x = step/period;
var value = eval(f.replace(/y/g,x));
//
// Translate to the canvas coords:
// - tranlate x and scale
// - invert and reflect the y value with the origin down the middle
//
var canvasx = MIN_X + (MAX_X-MIN_X)*(1.0*step/steps);
var canvasy = -(value*((MAX_VALUE-MIN_VALUE)/2) -
((MAX_VALUE-MIN_VALUE)/2));
setPoint2(canvasx,canvasy,g);
}
}
/**
* Just like the setPoint(event,g,context) function in original
* draw.js, except we don't use the context, which is ignored, and
* just pass in canvasx and canvasy, which are easier to manage than
* creating an event, etc. Seems to work?
*/
function setPoint2(canvasx, canvasy, g) {
var xy = g.toDataCoords(canvasx, canvasy);
var x = xy[0], value = xy[1];
var rows = g.numRows();
var closest_row = -1;
var smallest_diff = -1;
for (var row = 0; row < rows; row++) {
var date = g.getValue(row, 0); // millis
var diff = Math.abs(date - x);
if (smallest_diff < 0 || diff < smallest_diff) {
smallest_diff = diff;
closest_row = row;
}
}
if (closest_row != -1) {
if (lastDrawRow === null) {
lastDrawRow = closest_row;
lastDrawValue = value;
}
// If the mouse moves quickly from point A to point B, we won't get events
// for the intervening x-values. We use a linear interpolation to create
// the impression of smooth drawing.
var coeff = (value - lastDrawValue) / (closest_row - lastDrawRow);
if (closest_row == lastDrawRow) coeff = 0.0;
var minRow = Math.min(lastDrawRow, closest_row);
var maxRow = Math.max(lastDrawRow, closest_row);
for (var row = minRow; row <= maxRow; row++) {
var val = lastDrawValue + coeff * (row - lastDrawRow);
val = Math.max(valueRange[0], Math.min(val, valueRange[1]));
if (val != null && !isNaN(val)) {
data[row][1] = val;
}
}
lastDrawRow = closest_row;
lastDrawValue = value;
g.updateOptions({ file: data }); // this redraws the chart
g.setSelection(closest_row); // prevents the dot from being finnicky.
}
}
function main() {
var f = prompt('Enter a function f(y) -- e.g. Math.sin(y):');
plot(f);
}
main();
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment