// JenScript - 1.3.2 2017-06-10 // http://jenscript.io - Copyright 2017 Sébastien Janaud. All Rights reserved !function(){JenScript.UnivariateRealFunction=function(a){this.init(a)},JenScript.Model.addMethods(JenScript.UnivariateRealFunction,{init:function(){},value:function(){}}),JenScript.DifferentiableUnivariateRealFunction=function(a){this._init(a)},JenScript.Model.inheritPrototype(JenScript.DifferentiableUnivariateRealFunction,JenScript.UnivariateRealFunction),JenScript.Model.addMethods(JenScript.DifferentiableUnivariateRealFunction,{_init:function(a){JenScript.UnivariateRealFunction.call(this,a)},derivative:function(){}}),JenScript.UnivariateRealInterpolator=function(a){this.init(a)},JenScript.Model.addMethods(JenScript.UnivariateRealInterpolator,{init:function(){},interpolate:function(){}}),JenScript.PolynomialFunction=function(a){this.__init(a)},JenScript.Model.inheritPrototype(JenScript.PolynomialFunction,JenScript.DifferentiableUnivariateRealFunction),JenScript.Model.addMethods(JenScript.PolynomialFunction,{__init:function(a){a=a||{};var b=a.coefficients,c=b.length;if(0==c)throw new Error("coefficients should be supplied");for(;c>1&&0==b[c-1];)--c;this.coefficients=[];for(var d=0;c>d;d++)this.coefficients[d]=b[d];JenScript.DifferentiableUnivariateRealFunction.call(this,a)},value:function(a){return this.evaluate(this.coefficients,a)},degree:function(){return this.coefficients.length-1},getCoefficients:function(){return this.coefficients.clone()},evaluate:function(a,b){var c=a.length;if(0==c)throw new Error("coefficients should be supplied");for(var d=a[c-1],e=c-2;e>=0;e--)d=b*d+a[e];return d},add:function(a){for(var b=this.min(this.coefficients.length,a.coefficients.length),c=this.max(this.coefficients.length,a.coefficients.length),d=[],e=0;b>e;++e)d[e]=this.coefficients[e]+a.coefficients[e];if(coefficients.lengthe;e++){var f=a.coefficients[e];d[d.length]=f}else for(var e=b;c-b>e;e++){var f=this.coefficients[e];d[d.length]=f}return new JenScript.PolynomialFunction(d)},subtract:function(a){for(var b=this.min(this.coefficients.length,a.coefficients.length),c=this.max(this.coefficients.length,a.coefficients.length),d=[],e=0;b>e;++e)d[e]=this.coefficients[e]-a.coefficients[e];if(this.coefficients.lengthe;++e)d[e]=-a.coefficients[e];else for(var e=b;c-b>e;e++){var f=this.coefficients[e];d[d.length]=f}return new JenScript.PolynomialFunction(d)},negate:function(){for(var a=[],b=0;b0;d--)c[d-1]=d*this.coefficients[d];return c},polynomialDerivative:function(){return new JenScript.PolynomialFunction({coefficients:this.differentiate(this.coefficients)})},derivative:function(){return this.polynomialDerivative()},min:function(a,b){return b>=a?a:b},max:function(a,b){return b>=a?b:a},abs:function(a){return 0>a?-a:0==a?0:a},toString:function(){return"JenScript.PolynomialFunction"}}),JenScript.PolynomialSplineFunction=function(a){this.__init(a)},JenScript.Model.inheritPrototype(JenScript.PolynomialSplineFunction,JenScript.DifferentiableUnivariateRealFunction),JenScript.Model.addMethods(JenScript.PolynomialSplineFunction,{__init:function(a){if(a=a||{},this.knots=[],this.polynomials=[],this.n,this.knots=a.knots,this.polynomials=a.polynomials,this.knots.length<2)throw new Error("spline partition must have at least 2 points");if(this.knots.length-1!=this.polynomials.length)throw new Error("number of polynomial interpolants must match the number of segments");if(!this.isStrictlyIncreasing(this.knots))throw new Error("knot values must be strictly increasing");this.n=this.knots.length-1},binarySearch:function(a,b){for(var c=0,d=a.length-1;d>=c;){var e=c+d>>>1,f=a[e];if(b>f)c=e+1;else{if(!(f>b))return e;d=e-1}}return-(c+1)},value:function(a){if(athis.knots[this.n])throw new Error("value "+a+" is outside function domain.");var b=this.binarySearch(this.knots,a);return 0>b&&(b=-b-2),b>=this.polynomials.length&&b--,this.polynomials[b].value(a-this.knots[b])},derivative:function(){return this.polynomialSplineDerivative()},polynomialSplineDerivative:function(){for(var a=[],b=0;b=a[b])return!1;return!0}}),JenScript.SplineInterpolator=function(a){this._init(a)},JenScript.Model.inheritPrototype(JenScript.SplineInterpolator,JenScript.UnivariateRealInterpolator),JenScript.Model.addMethods(JenScript.SplineInterpolator,{_init:function(a){a=a||{}},interpolate:function(a,b){if(a.length!=b.length)throw new Error("x and y array values dimensions mismatch");if(a.length<3)throw new Error("the number of points must be greater than 3");var c=a.length-1;this.checkOrder(a,"INCREASING",!0);for(var d=[],e=0;c>e;e++)d[e]=a[e+1]-a[e];var f=[],g=[];f[0]=0,g[0]=0;for(var h=0,e=1;c>e;e++)h=2*(a[e+1]-a[e-1])-d[e-1]*f[e-1],f[e]=d[e]/h,g[e]=(3*(b[e+1]*d[e-1]-b[e]*(a[e+1]-a[e-1])+b[e-1]*d[e])/(d[e-1]*d[e])-d[e-1]*g[e-1])/h;var i=[],j=[],k=[];g[c]=0,j[c]=0;for(var l=c-1;l>=0;l--)j[l]=g[l]-f[l]*j[l+1],i[l]=(b[l+1]-b[l])/d[l]-d[l]*(j[l+1]+2*j[l])/3,k[l]=(j[l+1]-j[l])/(3*d[l]);for(var m=[],n=[],e=0;c>e;e++)n[0]=b[e],n[1]=i[e],n[2]=j[e],n[3]=k[e],m[e]=new JenScript.PolynomialFunction({coefficients:n});return new JenScript.PolynomialSplineFunction({knots:a,polynomials:m})},checkOrder:function(a,b,c){for(var d=a[0],e=!0,f=a.length,g=1;f>g;g++){switch(b){case"INCREASING":c?a[g]<=d&&(e=!1):a[g]=d&&(e=!1):a[g]>d&&(e=!1);break;default:throw new Error("checkOrder error")}if(!e)throw new Error("Spline interpolator can not be used with values which are not order");d=a[g]}}})}(),function(){JenScript.FunctionNature=function(a){this.nature=a,this.isXFunction=function(){return void 0===this.nature?!1:this.nature instanceof JenScript.FunctionNature?this.nature.isXFunction():"xfunction"===this.nature.toLowerCase()||"x"===this.nature.toLowerCase()?!0:!1},this.isYFunction=function(){return void 0===this.nature?!1:this.nature instanceof JenScript.FunctionNature?this.nature.isYFunction():"yfunction"===this.nature.toLowerCase()||"y"===this.nature.toLowerCase()?!0:!1},this.toString=function(){return this.isXFunction()?"x":this.isYFunction()?"y":"undefined nature"}}}(),function(){JenScript.PathSegment=function(a){this.init(a)},JenScript.Model.addMethods(JenScript.PathSegment,{init:function(a){this.segmentUserStart=a.userStart,this.segmentUserEnd=a.userEnd,this.segmentDeviceStart=a.deviceStart,this.segmentDeviceEnd=a.deviceEnd},getSegmentDeviceStart:function(){return this.segmentDeviceStart},setSegmentDeviceStart:function(a){this.segmentDeviceStart=a},getSegmentDeviceEnd:function(){return this.segmentDeviceEnd},setSegmentDeviceEnd:function(a){this.segmentDeviceEnd=a},match:function(a){return this.sourceFunction.getNature().isXFunction()?a>=this.segmentUserStart.getX()&&a<=this.segmentUserEnd.getX():this.sourceFunction.getNature().isYFunction()?a>=this.segmentUserStart.getY()&&a<=this.segmentUserEnd.getY():void 0},getUserPoint:function(a){if(this.sourceFunction.getNature().isXFunction()){var b=this.getCoefficient()*a+this.getConstant();return new JenScript.Point2D(a,b)}if(this.sourceFunction.getNature().isYFunction()){var c=this.getCoefficient()*a+this.getConstant();return new JenScript.Point2D(c,a)}},getSegmentUserStart:function(){return this.segmentUserStart},setSegmentUserStart:function(a){this.segmentUserStart=a},getSegmentUserEnd:function(){return this.segmentUserEnd},setSegmentUserEnd:function(a){this.segmentUserEnd=a},deviceLength:function(){var a=Math.pow(this.segmentDeviceStart.getX()-this.segmentDeviceEnd.getX(),2),b=Math.pow(this.segmentDeviceStart.getY()-this.segmentDeviceEnd.getY(),2);return Math.sqrt(a+b)},getCoefficient:function(){return this.sourceFunction.getNature().isXFunction()?(this.segmentUserEnd.getY()-this.segmentUserStart.getY())/(this.segmentUserEnd.getX()-this.segmentUserStart.getX()):this.sourceFunction.getNature().isYFunction()?(this.segmentUserEnd.getX()-this.segmentUserStart.getX())/(this.segmentUserEnd.getY()-this.segmentUserStart.getY()):void 0},getConstant:function(){return this.sourceFunction.getNature().isXFunction()?this.segmentUserStart.getY()-this.getCoefficient()*this.segmentUserStart.getX():this.sourceFunction.getNature().isYFunction()?this.segmentUserStart.getX()-this.getCoefficient()*this.segmentUserStart.getY():void 0},toString:function(){return"PathSegment [segmentUserStart="+this.segmentUserStart+", segmentUserEnd="+this.segmentUserEnd+"]"},equals:function(a){return void 0===a?!1:!a instanceof JenScript.PathSegment?!1:this.segmentUserStart.equals(a.segmentUserStart)&&this.segmentUserEnd.equals(a.segmentUserEnd)?!0:!1}})}(),function(){JenScript.AbstractSourceFunction=function(a){this.init(a)},JenScript.Model.addMethods(JenScript.AbstractSourceFunction,{init:function(a){a=a||{},this.hostFunction,this.id,this.name,this.nature=new JenScript.FunctionNature(void 0!==a.nature?a.nature:"x"),this.currentFunction=void 0},clearCurrentFunction:function(){this.currentFunction=[]},getCurrentFunction:function(){if(void 0===this.currentFunction||0===this.currentFunction.length){var a=this.getHostFunction().getProjection();this.getNature().isXFunction()?this.currentFunction=this.solveFunction(a.getMinX(),a.getMaxX()):this.getNature().isYFunction()&&(this.currentFunction=this.solveFunction(a.getMinY(),a.getMaxY()))}return this.currentFunction},solveFunction:function(){throw new Error("SourceFunction Error, solveFunction method should be provided.")},evaluate:function(){},getHostFunction:function(){return this.hostFunction},setHostFunction:function(a){this.hostFunction=a},getId:function(){return this.id},setId:function(a){this.id=a},getName:function(){return this.name},setName:function(a){this.name=a},getNature:function(){return this.nature},setNature:function(a){this.nature=a}}),JenScript.UserSourceFunction=function(a){this._init(a)},JenScript.Model.inheritPrototype(JenScript.UserSourceFunction,JenScript.AbstractSourceFunction),JenScript.Model.addMethods(JenScript.UserSourceFunction,{_init:function(a){a=a||{},JenScript.AbstractSourceFunction.call(this,a)}}),JenScript.LineSource=function(a){this.__init(a)},JenScript.Model.inheritPrototype(JenScript.LineSource,JenScript.UserSourceFunction),JenScript.Model.addMethods(JenScript.LineSource,{__init:function(a){a=a||{},this.xValues=a.xValues,this.yValues=a.yValues,this.source=this.createPointsFromArray(this.xValues,this.yValues),JenScript.UserSourceFunction.call(this,a)},createPointsFromArray:function(a,b){if(a.length!==b.length)throw new Error(" x and y array values length does not match");for(var c=[],d=0;d=a&&f.x<=b&&(c[c.length]=f)}else if(this.getNature().isYFunction())for(var e=0;e=a&&f.y<=b&&(c[c.length]=f)}if(c.length>=1){var g=void 0,h=void 0;if(this.getNature().isXFunction()?(g=this.previous(c[0].x),h=this.next(c[c.length-1].x)):this.getNature().isYFunction()&&(g=this.previous(c[0].y),h=this.next(c[c.length-1].y)),void 0!=g&&!g.equals(c[0])){var i=[g].concat(c);c=i}void 0==h||h.equals(c[c.length-1])||(c[c.length]=h)}else{var g=this.previous(a),h=this.next(b);if(void 0!=g){var i=[g].concat(c);c=i}null!=h&&(c[c.length]=h)}return c},next:function(a){for(var b=this.getSource(),c=0;ca)return new JenScript.Point2D(d.x,d.y)}else if(this.getNature().isYFunction()&&d.y>a)return new JenScript.Point2D(d.x,d.y)}return void 0},previous:function(a){for(var b=this.getSource(),c=b.length-1;c>=0;c--){var d=b[c];if(this.getNature().isXFunction()){if(d.xc.x?1:b.xc.y?1:b.y=c.x&&e<=d.x&&(a[a.length]=new JenScript.Point2D(e,this.evaluateFunction.value(e)))}catch(f){return this.getSource()}else if(this.getNature().isYFunction())for(var g=c.y;g<=d.y;g+=this.delta)try{g>=c.y&&g<=d.y&&(a[a.length]=new JenScript.Point2D(this.evaluateFunction.value(g),g))}catch(f){return this.getSource()}return a},createInterpolateFunction:function(){try{for(var a=this.getSource(),b=a.length,c=[],d=[],e=0;b>e;e++){var f=a[e];c[e]=f.x,d[e]=f.y}var g=new JenScript.SplineInterpolator;this.getNature().isXFunction()?this.evaluateFunction=g.interpolate(c,d):this.getNature().isYFunction()&&(this.evaluateFunction=g.interpolate(d,c))}catch(h){console.log(h)}}})}(),function(){JenScript.AbstractPathFunction=function(a){this.init(a)},JenScript.Model.addMethods(JenScript.AbstractPathFunction,{init:function(a){a=a||{},this.name=void 0!==a.name?a.name:"Abstract Path Function",this.themeColor=void 0!==a.themeColor?a.themeColor:"red",this.strokeWidth=void 0!==a.strokeWidth?a.strokeWidth:1,this.source=a.source,this.hostPlugin,this.Id="pathfunction"+JenScript.sequenceId++,this.geometryPath,this.lengthPathDevice,this.metrics=[],this.segments=[],this.pathSegments=[],this.graphicsContext},getProjection:function(){return this.hostPlugin.getProjection()},getHostPlugin:function(){return this.hostPlugin},setHostPlugin:function(a){this.hostPlugin=a},getThemeColor:function(){return this.themeColor},setThemeColor:function(a){this.themeColor=a},getName:function(){return this.name},setName:function(a){this.name=a},setSource:function(a){this.source=a,this.source.hostFunction=this},minFunction:function(){var a=this.source.getCurrentFunction(),b=a[0];if(this.source.getNature().isXFunction())for(var c=0;cb.getY()&&(b=d)}if(this.source.getNature().isYFunction())for(var c=0;cb.getX()&&(b=d)}return b},createPath:function(){return this.svgPathElement=(new JenScript.SVGElement).attr("id",this.Id).name("path").attr("stroke","none").attr("fill","none").attr("d",this.buildPath()).buildHTML(),this.geometryPath=new JenScript.GeometryPath(this.svgPathElement),this.lengthPathDevice=this.geometryPath.lengthOfPath(),this.svgPathElement},addMetric:function(a){this.metrics[this.metrics.length]=a,void 0!==this.hostPlugin&&this.hostPlugin.repaintPlugin()},clearMetric:function(){this.metrics=[]},getMetrics:function(){this.createPath();var a=(new JenScript.SVGElement).attr("id",this.Id+"_path").name("path").attr("stroke","none").attr("fill","none").attr("d",this.buildPath()).buildHTML();if(this.graphicsContext.deleteGraphicsElement(this.Id+"_path"),this.graphicsContext.definesSVG(a),void 0!==this.svgPathElement){if(0===this.geometryPath.lengthOfPath())return[];for(var b=0;bd.getMaxX())return}else if(this.source.getNature().isYFunction()&&(c.getValue()d.getMaxY()))return;var e=c.getValue(),f=this.getPathSegment(e);if(void 0!==f){var g=f.getUserPoint(e),h=function(){return d.userToPixelX(g.x)},i=function(){return d.userToPixelY(g.y)},j=this.getLengthAtSegment(f),k=this.geometryPath.pointAtLength(this.getLengthAtSegment(f)),l=Math.pow(k.x-h(),2),m=Math.pow(k.y-i(),2),n=Math.sqrt(l+m),o=(new JenScript.SVGRect).origin(h(),i()).size(3,3).fill("pink");this.graphicsContext.insertSVG(o.toSVG());var p=j+n,q=p/this.lengthPathDevice*100;c.setLengthOnPath(p),c.setPercentOnPath(q),c.setMetricPointRef(this.geometryPath.pointAtLength(j+n)),c.setMetricAngle(this.geometryPath.angleAtLength(j+n).deg);var r=(new JenScript.SVGText).textAnchor("middle").attr("id",this.Id+"_metrics"+b).attr("transform","rotate("+c.getRotate()+" "+c.getMetricPointRef().x+" "+c.getMetricPointRef().y+")").fill(c.getFillColor()).stroke("white").strokeWidth(.5).fontSize(c.getFontSize()),s=(new JenScript.SVGTextPath).xlinkHref("#"+this.Id+"_path").startOffset(c.getPercentOnPath()+"%"),t=(new JenScript.SVGTSpan).dy(c.getDy()).textContent(c.getMetricsLabel());s.methodStretch(),s.spacingExact(),s.child(t.toSVG());var u=s.toSVG();r.child(u);var v=r.toSVG();this.graphicsContext.insertSVG(v)}}return this.metrics}},getMetricsPoint:function(a){if(this.source.getNature().isXFunction()){if(m.getValue()proj.getMaxX())return}else if(this.source.getNature().isYFunction()&&(m.getValue()proj.getMaxY()))return;var b=this.getPathSegment(a),c=b.getUserPoint(a),d=this.getLengthAtSegment(b),e=this.geometryPath.pointAtLength(this.getLengthAtSegment(b)),f=Math.pow(e.x-proj.userToPixelX(c.x),2),g=Math.pow(e.y-proj.userToPixelY(c.y),2),h=Math.sqrt(f+g);return this.geometryPath.pointAtLength(d+h)},getSegments:function(){return this.segments},getPathSegment:function(a){for(var b=0;b