|
|
|
|
@ -1,4 +1,3 @@
|
|
|
|
|
define(['jquery','jquery.flot'],function(jQuery,jflot){
|
|
|
|
|
/* The MIT License
|
|
|
|
|
|
|
|
|
|
Copyright (c) 2011 by Michael Zinsmaier and nergal.dev
|
|
|
|
|
@ -22,7 +21,7 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
|
|
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
|
|
|
THE SOFTWARE.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
define(['jquery','jquery.flot'],function(jQuery,jflot){
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
|
|
|
|
@ -38,7 +37,7 @@ points. Both modes are achieved through adding of more data points
|
|
|
|
|
=> 1) with large data sets you may get trouble
|
|
|
|
|
=> 2) if you want to display the points too, you have to plot them as 2nd data series over the lines
|
|
|
|
|
|
|
|
|
|
This is version 0.4 of curvedLines so it will probably not work in every case. However
|
|
|
|
|
This is version 0.5 of curvedLines so it will probably not work in every case. However
|
|
|
|
|
the basic form of use descirbed next works (:
|
|
|
|
|
|
|
|
|
|
Feel free to further improve the code
|
|
|
|
|
@ -54,19 +53,17 @@ ____________________________________________________
|
|
|
|
|
var options = { series: { curvedLines: { active: true }}};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
$.plot($("#placeholder"), [{data = d1, curvedLines: { show: true}}], options);
|
|
|
|
|
$.plot($("#placeholder"), [{data = d1, lines: { show: true,curved:true}}], options);
|
|
|
|
|
|
|
|
|
|
_____________________________________________________
|
|
|
|
|
|
|
|
|
|
options:
|
|
|
|
|
_____________________________________________________
|
|
|
|
|
|
|
|
|
|
fill: bool true => lines get filled
|
|
|
|
|
fillColor: null or the color that should be used for filling
|
|
|
|
|
|
|
|
|
|
active: bool true => plugin can be used
|
|
|
|
|
show: bool true => series will be drawn as curved line
|
|
|
|
|
curved: bool true => series will be drawn as curved line
|
|
|
|
|
fit: bool true => forces the max,mins of the curve to be on the datapoints
|
|
|
|
|
lineWidth: int width of the line
|
|
|
|
|
curvePointFactor int defines how many "virtual" points are used per "real" data point to
|
|
|
|
|
emulate the curvedLines
|
|
|
|
|
fitPointDist: int defines the x axis distance of the additional two points that are used
|
|
|
|
|
@ -82,7 +79,7 @@ _____________________________________________________
|
|
|
|
|
* v0.2 added fill option (thanks to monemihir) and multi axis support (thanks to soewono effendi)
|
|
|
|
|
* v0.3 improved saddle handling and added basic handling of Dates
|
|
|
|
|
* v0.4 rewritten fill option (thomas ritou) mostly from original flot code (now fill between points rather than to graph bottom), corrected fill Opacity bug
|
|
|
|
|
*
|
|
|
|
|
* v0.5 completly rewritten to let flot do the hard work. CurvedLines usage changed and will require code change but is more straightforward to use for new users (so all flot lines options (gradient fill, shadow are now supported)
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
(function ($) {
|
|
|
|
|
@ -104,328 +101,93 @@ _____________________________________________________
|
|
|
|
|
|
|
|
|
|
plot.hooks.processOptions.push(processOptions);
|
|
|
|
|
|
|
|
|
|
//if the plugin is active register draw method
|
|
|
|
|
//if the plugin is active register processDatapoints method
|
|
|
|
|
function processOptions(plot,options) {
|
|
|
|
|
if (options.series.curvedLines.active) {
|
|
|
|
|
plot.hooks.draw.push(draw);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//select the data sets that should be drawn with curved lines and draws them
|
|
|
|
|
function draw(plot, ctx) {
|
|
|
|
|
var series;
|
|
|
|
|
var sdata = plot.getData();
|
|
|
|
|
var offset = plot.getPlotOffset();
|
|
|
|
|
|
|
|
|
|
for (var i = 0; i < sdata.length; i++) {
|
|
|
|
|
series = sdata[i];
|
|
|
|
|
if (series.curvedLines.show) {
|
|
|
|
|
|
|
|
|
|
axisx = series.xaxis;
|
|
|
|
|
axisy = series.yaxis;
|
|
|
|
|
|
|
|
|
|
ctx.save();
|
|
|
|
|
ctx.translate(offset.left, offset.top);
|
|
|
|
|
ctx.lineJoin = "round";
|
|
|
|
|
ctx.strokeStyle = series.color;
|
|
|
|
|
|
|
|
|
|
ctx.lineWidth = series.curvedLines.lineWidth;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var points,data;
|
|
|
|
|
if(series.curvedLines.fill || series.curvedLines.lineWidth) {
|
|
|
|
|
|
|
|
|
|
//convenience check for x or y values if they are Dates if so apply .getTime()
|
|
|
|
|
//only check on first value mixing numeric and Date fields in one input array is not allowed
|
|
|
|
|
if ('map' in Array.prototype && (series.data[0][0] instanceof Date || series.data[0][1] instanceof Date)) {
|
|
|
|
|
data = series.data.map(getTimeFromDate);
|
|
|
|
|
} else {
|
|
|
|
|
//default case
|
|
|
|
|
data = series.data;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
points= calculateCurvePoints(data, series.curvedLines,1);
|
|
|
|
|
}
|
|
|
|
|
if(series.curvedLines.fill) {
|
|
|
|
|
var fillColor = series.curvedLines.fillColor == null ? series.color : series.curvedLines.fillColor;
|
|
|
|
|
var c = $.color.parse(fillColor);
|
|
|
|
|
c.a = typeof series.curvedLines.fill == "number" ? series.curvedLines.fill : 0.4;
|
|
|
|
|
c.normalize();
|
|
|
|
|
ctx.fillStyle = c.toString();
|
|
|
|
|
//Make sure we've got a second y point for filling area
|
|
|
|
|
for (var j=0;j<data.length;j++){
|
|
|
|
|
if (data[j].length==2) data[j][2]=0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var pointsFill = calculateCurvePoints(data, series.curvedLines,2);
|
|
|
|
|
|
|
|
|
|
plotLineArea(ctx,points,pointsFill,axisx,axisy);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (series.curvedLines.lineWidth>0)
|
|
|
|
|
plotLine(ctx, points, axisx, axisy,2);
|
|
|
|
|
ctx.restore();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
plot.hooks.processDatapoints.push(processDatapoints);
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//helper method that convertes Dates to a numeric representation
|
|
|
|
|
function getTimeFromDate(timeElement) {
|
|
|
|
|
var xVal = timeElement[0];
|
|
|
|
|
var yVal = timeElement[1];
|
|
|
|
|
var ret = new Array;
|
|
|
|
|
|
|
|
|
|
if (timeElement[0] instanceof Date) {
|
|
|
|
|
ret[0] = xVal.getTime();
|
|
|
|
|
} else {
|
|
|
|
|
ret[0] = xVal;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (timeElement[1] instanceof Date) {
|
|
|
|
|
ret[1] = yVal.getTime();
|
|
|
|
|
} else {
|
|
|
|
|
ret[1] = yVal;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
function processDatapoints(plot, series, datapoints) {
|
|
|
|
|
if (series.lines.curved==true){
|
|
|
|
|
if (series.lines.fill){
|
|
|
|
|
|
|
|
|
|
var pointsTop=calculateCurvePoints2(datapoints, series.curvedLines,1);
|
|
|
|
|
|
|
|
|
|
//Make sure we've got a second y point for filling area
|
|
|
|
|
for (var j=0;j<datapoints.length;j+=3){
|
|
|
|
|
if (data[j]==null) data[j]=series.yaxis.min; //If second y point is null, let it be zero (else no curve !)
|
|
|
|
|
}
|
|
|
|
|
var pointsBottom = calculateCurvePoints2(datapoints, series.curvedLines,2);
|
|
|
|
|
|
|
|
|
|
//Merge top and bottom curve
|
|
|
|
|
datapoints.pointsize=3;
|
|
|
|
|
datapoints.points=[];
|
|
|
|
|
var j=0;
|
|
|
|
|
var k=0;
|
|
|
|
|
var i=0;
|
|
|
|
|
var ps=2;
|
|
|
|
|
while (i<pointsTop.length || j<pointsBottom.length){
|
|
|
|
|
if (pointsTop[i]==pointsBottom[j]){
|
|
|
|
|
datapoints.points[k]=pointsTop[i];
|
|
|
|
|
datapoints.points[k+1]=pointsTop[i+1];
|
|
|
|
|
datapoints.points[k+2]=pointsBottom[j+1];
|
|
|
|
|
j+=ps;
|
|
|
|
|
i+=ps;
|
|
|
|
|
|
|
|
|
|
}else if (pointsTop[i]<pointsBottom[j]){
|
|
|
|
|
datapoints.points[k]=pointsTop[i];
|
|
|
|
|
datapoints.points[k+1]=pointsTop[i+1];
|
|
|
|
|
datapoints.points[k+2]=null;
|
|
|
|
|
i+=ps;
|
|
|
|
|
}else{
|
|
|
|
|
datapoints.points[k]=pointsBottom[j];
|
|
|
|
|
datapoints.points[k+1]=null;
|
|
|
|
|
datapoints.points[k+2]=pointsBottom[j+1];
|
|
|
|
|
j+=ps;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function plotLineArea(ctx,points2,points3, axisx, axisy) {
|
|
|
|
|
var points = points2,
|
|
|
|
|
ps = 2,
|
|
|
|
|
bottom = Math.min(Math.max(0, axisy.min), axisy.max),
|
|
|
|
|
i = 0, top, areaOpen = false,
|
|
|
|
|
ypos = 1, segmentStart = 0, segmentEnd = 0;
|
|
|
|
|
|
|
|
|
|
// we process each segment in two turns, first forward
|
|
|
|
|
// direction to sketch out top, then once we hit the
|
|
|
|
|
// end we go backwards to sketch the bottom
|
|
|
|
|
while (true) {
|
|
|
|
|
if (ps > 0 && i > points.length + ps)
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
i += ps; // ps is negative if going backwards
|
|
|
|
|
|
|
|
|
|
var x1 = points[i - ps],
|
|
|
|
|
y1 = points[i - ps + ypos],
|
|
|
|
|
x2 = points[i], y2 = points[i + ypos];
|
|
|
|
|
|
|
|
|
|
if (areaOpen) {
|
|
|
|
|
if (ps > 0 && x1 != null && x2 == null) {
|
|
|
|
|
// at turning point
|
|
|
|
|
segmentEnd = i;
|
|
|
|
|
ps = -ps;
|
|
|
|
|
ypos = 1;
|
|
|
|
|
points=points3;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (ps < 0 && i == segmentStart + ps) {
|
|
|
|
|
// done with the reverse sweep
|
|
|
|
|
ctx.fill();
|
|
|
|
|
areaOpen = false;
|
|
|
|
|
ps = -ps;
|
|
|
|
|
ypos = 1;
|
|
|
|
|
points=points2;
|
|
|
|
|
i = segmentStart = segmentEnd + ps;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (x1 == null || x2 == null)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
// clip x values
|
|
|
|
|
|
|
|
|
|
// clip with xmin
|
|
|
|
|
if (x1 <= x2 && x1 < axisx.min) {
|
|
|
|
|
if (x2 < axisx.min)
|
|
|
|
|
continue;
|
|
|
|
|
y1 = (axisx.min - x1) / (x2 - x1) * (y2 - y1) + y1;
|
|
|
|
|
x1 = axisx.min;
|
|
|
|
|
}
|
|
|
|
|
else if (x2 <= x1 && x2 < axisx.min) {
|
|
|
|
|
if (x1 < axisx.min)
|
|
|
|
|
continue;
|
|
|
|
|
y2 = (axisx.min - x1) / (x2 - x1) * (y2 - y1) + y1;
|
|
|
|
|
x2 = axisx.min;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// clip with xmax
|
|
|
|
|
if (x1 >= x2 && x1 > axisx.max) {
|
|
|
|
|
if (x2 > axisx.max)
|
|
|
|
|
continue;
|
|
|
|
|
y1 = (axisx.max - x1) / (x2 - x1) * (y2 - y1) + y1;
|
|
|
|
|
x1 = axisx.max;
|
|
|
|
|
}
|
|
|
|
|
else if (x2 >= x1 && x2 > axisx.max) {
|
|
|
|
|
if (x1 > axisx.max)
|
|
|
|
|
continue;
|
|
|
|
|
y2 = (axisx.max - x1) / (x2 - x1) * (y2 - y1) + y1;
|
|
|
|
|
x2 = axisx.max;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!areaOpen) {
|
|
|
|
|
// open area
|
|
|
|
|
ctx.beginPath();
|
|
|
|
|
ctx.moveTo(axisx.p2c(x1), axisy.p2c(bottom));
|
|
|
|
|
areaOpen = true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// now first check the case where both is outside
|
|
|
|
|
if (y1 >= axisy.max && y2 >= axisy.max) {
|
|
|
|
|
ctx.lineTo(axisx.p2c(x1), axisy.p2c(axisy.max));
|
|
|
|
|
ctx.lineTo(axisx.p2c(x2), axisy.p2c(axisy.max));
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
else if (y1 <= axisy.min && y2 <= axisy.min) {
|
|
|
|
|
ctx.lineTo(axisx.p2c(x1), axisy.p2c(axisy.min));
|
|
|
|
|
ctx.lineTo(axisx.p2c(x2), axisy.p2c(axisy.min));
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// else it's a bit more complicated, there might
|
|
|
|
|
// be a flat maxed out rectangle first, then a
|
|
|
|
|
// triangular cutout or reverse; to find these
|
|
|
|
|
// keep track of the current x values
|
|
|
|
|
var x1old = x1, x2old = x2;
|
|
|
|
|
|
|
|
|
|
// clip the y values, without shortcutting, we
|
|
|
|
|
// go through all cases in turn
|
|
|
|
|
|
|
|
|
|
// clip with ymin
|
|
|
|
|
if (y1 <= y2 && y1 < axisy.min && y2 >= axisy.min) {
|
|
|
|
|
x1 = (axisy.min - y1) / (y2 - y1) * (x2 - x1) + x1;
|
|
|
|
|
y1 = axisy.min;
|
|
|
|
|
}
|
|
|
|
|
else if (y2 <= y1 && y2 < axisy.min && y1 >= axisy.min) {
|
|
|
|
|
x2 = (axisy.min - y1) / (y2 - y1) * (x2 - x1) + x1;
|
|
|
|
|
y2 = axisy.min;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// clip with ymax
|
|
|
|
|
if (y1 >= y2 && y1 > axisy.max && y2 <= axisy.max) {
|
|
|
|
|
x1 = (axisy.max - y1) / (y2 - y1) * (x2 - x1) + x1;
|
|
|
|
|
y1 = axisy.max;
|
|
|
|
|
}
|
|
|
|
|
else if (y2 >= y1 && y2 > axisy.max && y1 <= axisy.max) {
|
|
|
|
|
x2 = (axisy.max - y1) / (y2 - y1) * (x2 - x1) + x1;
|
|
|
|
|
y2 = axisy.max;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// if the x value was changed we got a rectangle
|
|
|
|
|
// to fill
|
|
|
|
|
if (x1 != x1old) {
|
|
|
|
|
ctx.lineTo(axisx.p2c(x1old), axisy.p2c(y1));
|
|
|
|
|
// it goes to (x1, y1), but we fill that below
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// fill triangular section, this sometimes result
|
|
|
|
|
// in redundant points if (x1, y1) hasn't changed
|
|
|
|
|
// from previous line to, but we just ignore that
|
|
|
|
|
ctx.lineTo(axisx.p2c(x1), axisy.p2c(y1));
|
|
|
|
|
ctx.lineTo(axisx.p2c(x2), axisy.p2c(y2));
|
|
|
|
|
|
|
|
|
|
// fill the other rectangle if it's there
|
|
|
|
|
if (x2 != x2old) {
|
|
|
|
|
ctx.lineTo(axisx.p2c(x2), axisy.p2c(y2));
|
|
|
|
|
ctx.lineTo(axisx.p2c(x2old), axisy.p2c(y2));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//nearly the same as in the core library
|
|
|
|
|
function plotLine(ctx, points, axisx, axisy,ps) {
|
|
|
|
|
|
|
|
|
|
var prevx = null;
|
|
|
|
|
var prevy = null;
|
|
|
|
|
|
|
|
|
|
ctx.beginPath();
|
|
|
|
|
|
|
|
|
|
for (var i = ps; i < points.length; i += ps) {
|
|
|
|
|
var x1 = points[i - ps], y1 = points[i - ps + 1];
|
|
|
|
|
var x2 = points[i], y2 = points[i + 1];
|
|
|
|
|
|
|
|
|
|
if (x1 == null || x2 == null)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
// clip with ymin
|
|
|
|
|
if (y1 <= y2 && y1 < axisy.min) {
|
|
|
|
|
if (y2 < axisy.min)
|
|
|
|
|
continue; // line segment is outside
|
|
|
|
|
// compute new intersection point
|
|
|
|
|
x1 = (axisy.min - y1) / (y2 - y1) * (x2 - x1) + x1;
|
|
|
|
|
y1 = axisy.min;
|
|
|
|
|
}
|
|
|
|
|
else if (y2 <= y1 && y2 < axisy.min) {
|
|
|
|
|
if (y1 < axisy.min)
|
|
|
|
|
continue;
|
|
|
|
|
x2 = (axisy.min - y1) / (y2 - y1) * (x2 - x1) + x1;
|
|
|
|
|
y2 = axisy.min;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// clip with ymax
|
|
|
|
|
if (y1 >= y2 && y1 > axisy.max) {
|
|
|
|
|
if (y2 > axisy.max)
|
|
|
|
|
continue;
|
|
|
|
|
x1 = (axisy.max - y1) / (y2 - y1) * (x2 - x1) + x1;
|
|
|
|
|
y1 = axisy.max;
|
|
|
|
|
}
|
|
|
|
|
else if (y2 >= y1 && y2 > axisy.max) {
|
|
|
|
|
if (y1 > axisy.max)
|
|
|
|
|
continue;
|
|
|
|
|
x2 = (axisy.max - y1) / (y2 - y1) * (x2 - x1) + x1;
|
|
|
|
|
y2 = axisy.max;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// clip with xmin
|
|
|
|
|
if (x1 <= x2 && x1 < axisx.min) {
|
|
|
|
|
if (x2 < axisx.min)
|
|
|
|
|
continue;
|
|
|
|
|
y1 = (axisx.min - x1) / (x2 - x1) * (y2 - y1) + y1;
|
|
|
|
|
x1 = axisx.min;
|
|
|
|
|
}
|
|
|
|
|
else if (x2 <= x1 && x2 < axisx.min) {
|
|
|
|
|
if (x1 < axisx.min)
|
|
|
|
|
continue;
|
|
|
|
|
y2 = (axisx.min - x1) / (x2 - x1) * (y2 - y1) + y1;
|
|
|
|
|
x2 = axisx.min;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// clip with xmax
|
|
|
|
|
if (x1 >= x2 && x1 > axisx.max) {
|
|
|
|
|
if (x2 > axisx.max)
|
|
|
|
|
continue;
|
|
|
|
|
y1 = (axisx.max - x1) / (x2 - x1) * (y2 - y1) + y1;
|
|
|
|
|
x1 = axisx.max;
|
|
|
|
|
}
|
|
|
|
|
else if (x2 >= x1 && x2 > axisx.max) {
|
|
|
|
|
if (x1 > axisx.max)
|
|
|
|
|
continue;
|
|
|
|
|
y2 = (axisx.max - x1) / (x2 - x1) * (y2 - y1) + y1;
|
|
|
|
|
x2 = axisx.max;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (x1 != prevx || y1 != prevy)
|
|
|
|
|
ctx.lineTo(axisx.p2c(x1), axisy.p2c(y1));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
prevx = x2;
|
|
|
|
|
prevy = y2;
|
|
|
|
|
ctx.lineTo(axisx.p2c(x2), axisy.p2c(y2));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ctx.stroke();
|
|
|
|
|
k+=3;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (series.lines.lineWidth>0){ //Let's draw line in separate series
|
|
|
|
|
var newSerie=$.extend({},series);
|
|
|
|
|
newSerie.lines=$.extend({},series.lines);
|
|
|
|
|
newSerie.lines.fill=undefined;
|
|
|
|
|
newSerie.label=undefined;
|
|
|
|
|
newSerie.lines.curved=false; //Don't redo curve point calculation as datapoint is copied to this new serie
|
|
|
|
|
//We find our series to add the line just after the fill (so other series you wanted above this one will still be)
|
|
|
|
|
var allSeries=plot.getData();
|
|
|
|
|
for (i=0;i<allSeries.length;i++){
|
|
|
|
|
if (allSeries[i]==series){
|
|
|
|
|
plot.getData().splice(i+1,0,newSerie);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
series.lines.lineWidth=0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}else if (series.lines.lineWidth>0){
|
|
|
|
|
datapoints.points=calculateCurvePoints2(datapoints, series.curvedLines,1);
|
|
|
|
|
datapoints.pointsize=2;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//no real idea whats going on here code mainly from https://code.google.com/p/flot/issues/detail?id=226
|
|
|
|
|
//I don't understand what nergal computes here and to be honest I didn't even try
|
|
|
|
|
function calculateCurvePoints2(datapoints, curvedLinesOptions,yPos) {
|
|
|
|
|
|
|
|
|
|
//no real idea whats going on here code mainly from https://code.google.com/p/flot/issues/detail?id=226
|
|
|
|
|
//I don't understand what nergal computes here and to be honest I didn't even try
|
|
|
|
|
function calculateCurvePoints(data, curvedLinesOptions,yPos) {
|
|
|
|
|
|
|
|
|
|
var num = curvedLinesOptions.curvePointFactor * data.length;
|
|
|
|
|
var points = datapoints.points, ps = datapoints.pointsize;
|
|
|
|
|
var num = curvedLinesOptions.curvePointFactor * (points.length/ps);
|
|
|
|
|
|
|
|
|
|
var xdata = new Array;
|
|
|
|
|
var ydata = new Array;
|
|
|
|
|
|
|
|
|
|
@ -439,39 +201,41 @@ _____________________________________________________
|
|
|
|
|
var neigh = curvedLinesOptions.fitPointDist;
|
|
|
|
|
var j = 0;
|
|
|
|
|
|
|
|
|
|
for (var i = 0; i < data.length; i++) {
|
|
|
|
|
for (var i = 0; i < points.length; i+=ps) {
|
|
|
|
|
|
|
|
|
|
var front = new Array;
|
|
|
|
|
var back = new Array;
|
|
|
|
|
var curX=i;
|
|
|
|
|
var curY=i+yPos;
|
|
|
|
|
|
|
|
|
|
//smooth front
|
|
|
|
|
front[X] = data[i][X] - 0.1;
|
|
|
|
|
if (i > 0) {
|
|
|
|
|
front[Y] = data[i-1][Y] * neigh + data[i][Y] * (1 - neigh);
|
|
|
|
|
front[X] = points[curX] - 0.1;
|
|
|
|
|
if (i >= ps) {
|
|
|
|
|
front[Y] = points[curY-ps] * neigh + points[curY] * (1 - neigh);
|
|
|
|
|
} else {
|
|
|
|
|
front[Y] = data[i][Y];
|
|
|
|
|
front[Y] = points[curY];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//smooth back
|
|
|
|
|
back[X] = data[i][X] + 0.1;
|
|
|
|
|
if ((i + 1) < data.length) {
|
|
|
|
|
back[Y] = data[i+1][Y] * neigh + data[i][Y] * (1 - neigh);
|
|
|
|
|
back[X] = points[curX] + 0.1;
|
|
|
|
|
if ((i + ps) < points.length) {
|
|
|
|
|
back[Y] = points[curY+ps] * neigh + points[curY] * (1 - neigh);
|
|
|
|
|
} else {
|
|
|
|
|
back[Y] = data[i][Y];
|
|
|
|
|
back[Y] = points[curY];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//test for a saddle
|
|
|
|
|
if ((front[Y] <= data[i][Y] && back[Y] <= data[i][Y]) || //max or partial horizontal
|
|
|
|
|
(front[Y] >= data[i][Y] && back[Y] >= data[i][Y])) { //min or partial horizontal
|
|
|
|
|
if ((front[Y] <= points[curY] && back[Y] <= points[curY]) || //max or partial horizontal
|
|
|
|
|
(front[Y] >= points[curY] && back[Y] >= points[curY])) { //min or partial horizontal
|
|
|
|
|
|
|
|
|
|
//add curve points
|
|
|
|
|
xdata[j] = front[X];
|
|
|
|
|
ydata[j] = front[Y];
|
|
|
|
|
j++;
|
|
|
|
|
|
|
|
|
|
xdata[j] = data[i][X];
|
|
|
|
|
ydata[j] = data[i][Y];
|
|
|
|
|
xdata[j] = points[curX];
|
|
|
|
|
ydata[j] = points[curY];
|
|
|
|
|
j++;
|
|
|
|
|
|
|
|
|
|
xdata[j] = back[X];
|
|
|
|
|
@ -479,8 +243,8 @@ _____________________________________________________
|
|
|
|
|
j++;
|
|
|
|
|
} else { //saddle
|
|
|
|
|
//use original point only
|
|
|
|
|
xdata[j] = data[i][X];
|
|
|
|
|
ydata[j] = data[i][Y];
|
|
|
|
|
xdata[j] = points[curX];
|
|
|
|
|
ydata[j] = points[curY];
|
|
|
|
|
j++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@ -489,8 +253,8 @@ _____________________________________________________
|
|
|
|
|
} else {
|
|
|
|
|
//just use the datapoints
|
|
|
|
|
for (var i = 0; i < data.length; i++) {
|
|
|
|
|
xdata[i] = data[i][X];
|
|
|
|
|
ydata[i] = data[i][Y];
|
|
|
|
|
xdata[i] = points[curX];
|
|
|
|
|
ydata[i] = points[curY];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@ -575,7 +339,7 @@ _____________________________________________________
|
|
|
|
|
init: init,
|
|
|
|
|
options: options,
|
|
|
|
|
name: 'curvedLines',
|
|
|
|
|
version: '0.4'
|
|
|
|
|
version: '0.5'
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|