1 |
- (function($){var options={series:{curvedLines:{active:false,apply:false,monotonicFit:false,tension:0.5,nrSplinePoints:20,legacyOverride:undefined}}};function init(plot){plot.hooks.processOptions.push(processOptions);function processOptions(plot,options){if(options.series.curvedLines.active){plot.hooks.processDatapoints.unshift(processDatapoints)}}function processDatapoints(plot,series,datapoints){var nrPoints=datapoints.points.length/datapoints.pointsize;var EPSILON=0.005;var invalidLegacyOptions=hasInvalidParameters(series.curvedLines);if(!invalidLegacyOptions&&series.curvedLines.apply==true&&series.originSeries===undefined&&nrPoints>(1+EPSILON)){if(series.lines.fill){var pointsTop=calculateCurvePoints(datapoints,series.curvedLines,1);var pointsBottom=calculateCurvePoints(datapoints,series.curvedLines,2);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]=k>0?datapoints.points[k-1]:null;i+=ps}else{datapoints.points[k]=pointsBottom[j];datapoints.points[k+1]=k>1?datapoints.points[k-2]:null;datapoints.points[k+2]=pointsBottom[j+1];j+=ps}k+=3}}else if(series.lines.lineWidth>0){datapoints.points=calculateCurvePoints(datapoints,series.curvedLines,1);datapoints.pointsize=2}}}function calculateCurvePoints(datapoints,curvedLinesOptions,yPos){if(typeof curvedLinesOptions.legacyOverride!='undefined'&&curvedLinesOptions.legacyOverride!=false){var defaultOptions={fit:false,curvePointFactor:20,fitPointDist:undefined};var legacyOptions=jQuery.extend(defaultOptions,curvedLinesOptions.legacyOverride);return calculateLegacyCurvePoints(datapoints,legacyOptions,yPos)}return calculateSplineCurvePoints(datapoints,curvedLinesOptions,yPos)}function calculateSplineCurvePoints(datapoints,curvedLinesOptions,yPos){var points=datapoints.points;var ps=datapoints.pointsize;var splines=createHermiteSplines(datapoints,curvedLinesOptions,yPos);var result=[];var j=0;for(var i=0;i<points.length-ps;i+=ps){var curX=i;var curY=i+yPos;var xStart=points[curX];var xEnd=points[curX+ps];var xStep=(xEnd-xStart)/Number(curvedLinesOptions.nrSplinePoints);result.push(points[curX]);result.push(points[curY]);for(var x=(xStart+=xStep);x<xEnd;x+=xStep){result.push(x);result.push(splines[j](x))}j+=1}result.push(points[points.length-ps]);result.push(points[points.length-ps+yPos]);return result}function createHermiteSplines(datapoints,curvedLinesOptions,yPos){var points=datapoints.points;var ps=datapoints.pointsize;var segmentLengths=[];var segmentSlopes=[];for(var i=0;i<points.length-ps;i+=ps){var curX=i;var curY=i+yPos;var dx=points[curX+ps]-points[curX];var dy=points[curY+ps]-points[curY];segmentLengths.push(dx);segmentSlopes.push(dy/dx)}var gradients=[segmentSlopes[0]];if(curvedLinesOptions.monotonicFit){for(var i=1;i<segmentLengths.length;i+=1){var slope=segmentSlopes[i];var prev_slope=segmentSlopes[i-1];if(slope*prev_slope<=0){gradients.push(0)}else{var length=segmentLengths[i];var prev_length=segmentLengths[i-1];var common=length+prev_length;gradients.push(3*common/((common+length)/prev_slope+(common+prev_length)/slope))}}}else{for(var i=ps;i<points.length-ps;i+=ps){var curX=i;var curY=i+yPos;gradients.push(Number(curvedLinesOptions.tension)*(points[curY+ps]-points[curY-ps])/(points[curX+ps]-points[curX-ps]))}}gradients.push(segmentSlopes[segmentSlopes.length-1]);var coefs1=[];var coefs2=[];for(i=0;i<segmentLengths.length;i+=1){var m_k=gradients[i];var m_k_plus=gradients[i+1];var slope=segmentSlopes[i];var invLength=1/segmentLengths[i];var common=m_k+m_k_plus-slope-slope;coefs1.push(common*invLength*invLength);coefs2.push((slope-common-m_k)*invLength)}var ret=[];for(var i=0;i<segmentLengths.length;i+=1){var spline=function(x_k,coef1,coef2,coef3,coef4){return function(x){var diff=x-x_k;var diffSq=diff*diff;return coef1*diff*diffSq+coef2*diffSq+coef3*diff+coef4}};ret.push(spline(points[i*ps],coefs1[i],coefs2[i],gradients[i],points[i*ps+yPos]))}return ret};function calculateLegacyCurvePoints(datapoints,curvedLinesOptions,yPos){var points=datapoints.points;var ps=datapoints.pointsize;var num=Number(curvedLinesOptions.curvePointFactor)*(points.length/ps);var xdata=new Array;var ydata=new Array;var curX=-1;var curY=-1;var j=0;if(curvedLinesOptions.fit){var fpDist;if(typeof curvedLinesOptions.fitPointDist=='undefined'){var minX=points[0];var maxX=points[points.length-ps];fpDist=(maxX-minX)/(500*100);}else{fpDist=Number(curvedLinesOptions.fitPointDist)}for(var i=0;i<points.length;i+=ps){var frontX;var backX;curX=i;curY=i+yPos;frontX=points[curX]-fpDist;backX=points[curX]+fpDist;var factor=2;while(frontX==points[curX]||backX==points[curX]){frontX=points[curX]-(fpDist*factor);backX=points[curX]+(fpDist*factor);factor+=1}xdata[j]=frontX;ydata[j]=points[curY];j+=1;xdata[j]=points[curX];ydata[j]=points[curY];j+=1;xdata[j]=backX;ydata[j]=points[curY];j+=1}}else{for(var i=0;i<points.length;i+=ps){curX=i;curY=i+yPos;xdata[j]=points[curX];ydata[j]=points[curY];j+=1}}var n=xdata.length;var y2=[];var delta=[];y2[0]=0;y2[n-1]=0;delta[0]=0;for(var i=1;i<n-1;i+=1){var d=(xdata[i+1]-xdata[i-1]);if(d==0){return[]}var s=(xdata[i]-xdata[i-1])/d;var p=s*y2[i-1]+2;y2[i]=(s-1)/p;delta[i]=(ydata[i+1]-ydata[i])/(xdata[i+1]-xdata[i])-(ydata[i]-ydata[i-1])/(xdata[i]-xdata[i-1]);delta[i]=(6*delta[i]/(xdata[i+1]-xdata[i-1])-s*delta[i-1])/p}for(var j=n-2;j>=0;j-=1){y2[j]=y2[j]*y2[j+1]+delta[j]}var step=(xdata[n-1]-xdata[0])/(num-1);var xnew=new Array;var ynew=new Array;var result=new Array;xnew[0]=xdata[0];ynew[0]=ydata[0];result.push(xnew[0]);result.push(ynew[0]);for(j=1;j<num;j+=1){xnew[j]=xnew[0]+j*step;var max=n-1;var min=0;while(max-min>1){var k=Math.round((max+min)/2);if(xdata[k]>xnew[j]){max=k}else{min=k}}var h=(xdata[max]-xdata[min]);if(h==0){return[]}var a=(xdata[max]-xnew[j])/h;var b=(xnew[j]-xdata[min])/h;ynew[j]=a*ydata[min]+b*ydata[max]+((a*a*a-a)*y2[min]+(b*b*b-b)*y2[max])*(h*h)/6;result.push(xnew[j]);result.push(ynew[j])}return result}function hasInvalidParameters(curvedLinesOptions){if(typeof curvedLinesOptions.fit!='undefined'||typeof curvedLinesOptions.curvePointFactor!='undefined'||typeof curvedLinesOptions.fitPointDist!='undefined'){throw new Error("CurvedLines detected illegal parameters. The CurvedLines API changed with version 1.0.0 please check the options object.");return true}return false}}$.plot.plugins.push({init:init,options:options,name:'curvedLines',version:'1.1.1'})})(jQuery);
|