mirror of
https://github.com/grafana/grafana.git
synced 2024-11-27 19:30:36 -06:00
61749dee23
Parsed all repo with a regexp of common misspelled words and fixed.
289 lines
9.7 KiB
JavaScript
289 lines
9.7 KiB
JavaScript
(function($) {
|
|
"use strict";
|
|
|
|
var options = {
|
|
series: {
|
|
fillBelowTo: null
|
|
}
|
|
};
|
|
|
|
function init(plot) {
|
|
function findBelowSeries( series, allseries ) {
|
|
|
|
var i;
|
|
|
|
for ( i = 0; i < allseries.length; ++i ) {
|
|
if ( allseries[ i ].id === series.fillBelowTo ) {
|
|
return allseries[ i ];
|
|
}
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
/* top and bottom doesn't actually matter for this, we're just using it to help make this easier to think about */
|
|
/* this is a vector cross product operation */
|
|
function segmentIntersection(top_left_x, top_left_y, top_right_x, top_right_y, bottom_left_x, bottom_left_y, bottom_right_x, bottom_right_y) {
|
|
var top_delta_x, top_delta_y, bottom_delta_x, bottom_delta_y,
|
|
s, t;
|
|
|
|
top_delta_x = top_right_x - top_left_x;
|
|
top_delta_y = top_right_y - top_left_y;
|
|
bottom_delta_x = bottom_right_x - bottom_left_x;
|
|
bottom_delta_y = bottom_right_y - bottom_left_y;
|
|
|
|
s = (
|
|
(-top_delta_y * (top_left_x - bottom_left_x)) + (top_delta_x * (top_left_y - bottom_left_y))
|
|
) / (
|
|
-bottom_delta_x * top_delta_y + top_delta_x * bottom_delta_y
|
|
);
|
|
|
|
t = (
|
|
(bottom_delta_x * (top_left_y - bottom_left_y)) - (bottom_delta_y * (top_left_x - bottom_left_x))
|
|
) / (
|
|
-bottom_delta_x * top_delta_y + top_delta_x * bottom_delta_y
|
|
);
|
|
|
|
// Collision detected
|
|
if (s >= 0 && s <= 1 && t >= 0 && t <= 1) {
|
|
return [
|
|
top_left_x + (t * top_delta_x), // X
|
|
top_left_y + (t * top_delta_y) // Y
|
|
];
|
|
}
|
|
|
|
// No collision
|
|
return null;
|
|
}
|
|
|
|
function plotDifferenceArea(plot, ctx, series) {
|
|
if ( series.fillBelowTo === null ) {
|
|
return;
|
|
}
|
|
|
|
var otherseries,
|
|
|
|
ps,
|
|
points,
|
|
|
|
otherps,
|
|
otherpoints,
|
|
|
|
plotOffset,
|
|
fillStyle;
|
|
|
|
function openPolygon(x, y) {
|
|
ctx.beginPath();
|
|
ctx.moveTo(
|
|
series.xaxis.p2c(x) + plotOffset.left,
|
|
series.yaxis.p2c(y) + plotOffset.top
|
|
);
|
|
|
|
}
|
|
|
|
function closePolygon() {
|
|
ctx.closePath();
|
|
ctx.fill();
|
|
}
|
|
|
|
function validateInput() {
|
|
if (points.length/ps !== otherpoints.length/otherps) {
|
|
console.error("Refusing to graph inconsistent number of points");
|
|
return false;
|
|
}
|
|
|
|
var i;
|
|
for (i = 0; i < (points.length / ps); i++) {
|
|
if (
|
|
points[i * ps] !== null &&
|
|
otherpoints[i * otherps] !== null &&
|
|
points[i * ps] !== otherpoints[i * otherps]
|
|
) {
|
|
console.error("Refusing to graph points without matching value");
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
function findNextStart(start_i, end_i) {
|
|
console.assert(end_i > start_i, "expects the end index to be greater than the start index");
|
|
|
|
var start = (
|
|
start_i === 0 ||
|
|
points[start_i - 1] === null ||
|
|
otherpoints[start_i - 1] === null
|
|
),
|
|
equal = false,
|
|
i,
|
|
intersect;
|
|
|
|
for (i = start_i; i < end_i; i++) {
|
|
// Take note of null points
|
|
if (
|
|
points[(i * ps) + 1] === null ||
|
|
otherpoints[(i * ps) + 1] === null
|
|
) {
|
|
equal = false;
|
|
start = true;
|
|
}
|
|
|
|
// Take note of equal points
|
|
else if (points[(i * ps) + 1] === otherpoints[(i * otherps) + 1]) {
|
|
equal = true;
|
|
start = false;
|
|
}
|
|
|
|
|
|
else if (points[(i * ps) + 1] > otherpoints[(i * otherps) + 1]) {
|
|
// If we begin above the desired point
|
|
if (start) {
|
|
openPolygon(points[i * ps], points[(i * ps) + 1]);
|
|
}
|
|
|
|
// If an equal point precedes this, start the polygon at that equal point
|
|
else if (equal) {
|
|
openPolygon(points[(i - 1) * ps], points[((i - 1) * ps) + 1]);
|
|
}
|
|
|
|
// Otherwise, find the intersection point, and start it there
|
|
else {
|
|
intersect = intersectionPoint(i);
|
|
openPolygon(intersect[0], intersect[1]);
|
|
}
|
|
|
|
topTraversal(i, end_i);
|
|
return;
|
|
}
|
|
|
|
// If we go below equal, equal at any preceding point is irrelevant
|
|
else {
|
|
start = false;
|
|
equal = false;
|
|
}
|
|
}
|
|
}
|
|
|
|
function intersectionPoint(right_i) {
|
|
console.assert(right_i > 0, "expects the second point in the series line segment");
|
|
|
|
var i, intersect;
|
|
|
|
for (i = 1; i < (otherpoints.length/otherps); i++) {
|
|
intersect = segmentIntersection(
|
|
points[(right_i - 1) * ps], points[((right_i - 1) * ps) + 1],
|
|
points[right_i * ps], points[(right_i * ps) + 1],
|
|
|
|
otherpoints[(i - 1) * otherps], otherpoints[((i - 1) * otherps) + 1],
|
|
otherpoints[i * otherps], otherpoints[(i * otherps) + 1]
|
|
);
|
|
|
|
if (intersect !== null) {
|
|
return intersect;
|
|
}
|
|
}
|
|
|
|
console.error("intersectionPoint() should only be called when an intersection happens");
|
|
}
|
|
|
|
function bottomTraversal(start_i, end_i) {
|
|
console.assert(start_i >= end_i, "the start should be the rightmost point, and the end should be the leftmost (excluding the equal or intersecting point)");
|
|
|
|
var i;
|
|
|
|
for (i = start_i; i >= end_i; i--) {
|
|
ctx.lineTo(
|
|
otherseries.xaxis.p2c(otherpoints[i * otherps]) + plotOffset.left,
|
|
otherseries.yaxis.p2c(otherpoints[(i * otherps) + 1]) + plotOffset.top
|
|
);
|
|
}
|
|
|
|
closePolygon();
|
|
}
|
|
|
|
function topTraversal(start_i, end_i) {
|
|
console.assert(start_i <= end_i, "the start should be the rightmost point, and the end should be the leftmost (excluding the equal or intersecting point)");
|
|
|
|
var i,
|
|
intersect;
|
|
|
|
for (i = start_i; i < end_i; i++) {
|
|
if (points[(i * ps) + 1] === null && i > start_i) {
|
|
bottomTraversal(i - 1, start_i);
|
|
findNextStart(i, end_i);
|
|
return;
|
|
}
|
|
|
|
else if (points[(i * ps) + 1] === otherpoints[(i * otherps) + 1]) {
|
|
bottomTraversal(i, start_i);
|
|
findNextStart(i, end_i);
|
|
return;
|
|
}
|
|
|
|
else if (points[(i * ps) + 1] < otherpoints[(i * otherps) + 1]) {
|
|
intersect = intersectionPoint(i);
|
|
ctx.lineTo(
|
|
series.xaxis.p2c(intersect[0]) + plotOffset.left,
|
|
series.yaxis.p2c(intersect[1]) + plotOffset.top
|
|
);
|
|
bottomTraversal(i, start_i);
|
|
findNextStart(i, end_i);
|
|
return;
|
|
|
|
}
|
|
|
|
else {
|
|
ctx.lineTo(
|
|
series.xaxis.p2c(points[i * ps]) + plotOffset.left,
|
|
series.yaxis.p2c(points[(i * ps) + 1]) + plotOffset.top
|
|
);
|
|
}
|
|
}
|
|
|
|
bottomTraversal(end_i, start_i);
|
|
}
|
|
|
|
|
|
// Begin processing
|
|
|
|
otherseries = findBelowSeries( series, plot.getData() );
|
|
|
|
if ( !otherseries ) {
|
|
return;
|
|
}
|
|
|
|
ps = series.datapoints.pointsize;
|
|
points = series.datapoints.points;
|
|
otherps = otherseries.datapoints.pointsize;
|
|
otherpoints = otherseries.datapoints.points;
|
|
plotOffset = plot.getPlotOffset();
|
|
|
|
if (!validateInput()) {
|
|
return;
|
|
}
|
|
|
|
|
|
// Flot's getFillStyle() should probably be exposed somewhere
|
|
fillStyle = $.color.parse(series.color);
|
|
fillStyle.a = 0.4;
|
|
fillStyle.normalize();
|
|
ctx.fillStyle = fillStyle.toString();
|
|
|
|
|
|
// Begin recursive bi-directional traversal
|
|
findNextStart(0, points.length/ps);
|
|
}
|
|
|
|
plot.hooks.drawSeries.push(plotDifferenceArea);
|
|
}
|
|
|
|
$.plot.plugins.push({
|
|
init: init,
|
|
options: options,
|
|
name: "fillbelow",
|
|
version: "0.1.0"
|
|
});
|
|
|
|
})(jQuery);
|