import{Point,Drawable}from"./geometry.mjs";import{isEmpty,roundTo,shiftingFrameIterator}from"../base/helpers.mjs";class SplinePoint{static TYPE_LINEAR=0;static TYPE_BEZIER=1;constructor(t,o,i,n){this.anchorPoint=t,this.pointType=o,this.controlPoint1=i,this.controlPoint2=n}add(t){for(let o of[this.anchorPoint,this.controlPoint1,this.controlPoint2])isEmpty(o)||(o.x+=t.x,o.y+=t.y);return this}subtract(t){for(let o of[this.anchorPoint,this.controlPoint1,this.controlPoint2])isEmpty(o)||(o.x-=t.x,o.y-=t.y);return this}rotate(t){for(let o of[this.anchorPoint,this.controlPoint1,this.controlPoint2])if(!isEmpty(o)){let i=o.x,n=o.y;o.x=i*Math.cos(t)-n*Math.sin(t),o.y=n*Math.cos(t)+i*Math.sin(t)}return this}clone(){return new this.constructor(this.anchorPoint.clone(),this.pointType,void 0===this.controlPoint1?void 0:this.controlPoint1.clone(),void 0===this.controlPoint2?void 0:this.controlPoint2.clone())}copy(t){if(t instanceof SplinePoint)this.anchorPoint.x=t.x,this.anchorPoint.y=t.y,this.pointType=t.pointType,void 0===t.controlPoint1?this.controlPoint1=void 0:void 0===this.controlPoint1?this.controlPoint1=t.controlPoint1.clone():this.controlPoint1.copy(t.controlPoint1),void 0===t.controlPoint2?this.controlPoint2=void 0:void 0===this.controlPoint2?this.controlPoint2=t.controlPoint2.clone():this.controlPoint2.copy(t.controlPoint2);else{if(!(t instanceof Point))throw"Cannot copy point of type "+typeof t;this.anchorPoint.x=t.x,this.anchorPoint.y=t.y}}set x(t){this.anchorPoint.x=t}get x(){return this.anchorPoint.x}set y(t){this.anchorPoint.y=t}get y(){return this.anchorPoint.y}get cp1x(){return this.controlPoint1.x}set cp1x(t){this.controlPoint1.x=t}get cp1y(){return this.controlPoint1.y}set cp1y(t){this.controlPoint1.y=t}get cp2x(){return this.controlPoint2.x}set cp2x(t){this.controlPoint2.x=t}get cp2y(){return this.controlPoint2.y}set cp2y(t){this.controlPoint2.y=t}}class Spline extends Drawable{pointAlongSpline(t,o){let i=0;for(let[n,r]of shiftingFrameIterator(this.points,2)){if(n.pointType===SplinePoint.TYPE_LINEAR&&r.pointType===SplinePoint.TYPE_LINEAR){let e=Math.min(n.x,r.x),p=Math.min(n.y,r.y),c=Math.max(n.x,r.x),h=Math.max(n.y,r.y);if(e<=t.x+o&&t.x<=c+o&&p<=t.y+o&&t.y<=h+o){let e,p;if(n.y===r.y)return i;if(n.x==r.x)return i;if(e=(r.y-n.y)/(r.x-n.x),e>5)return i;if(p=e*(t.x-n.x)+n.y,p-o<=t.y&&p+o>=t.y)return i}}else if(n.pointType===SplinePoint.TYPE_BEZIER&&r.pointType===SplinePoint.TYPE_BEZIER)for(let e=1;e<=3*o;e++){let p=e/(3*o),c=n,h=n.controlPoint2,s=r.controlPoint1,l=r,P=Math.pow(1-p,3)*c.x+3*Math.pow(1-p,2)*p*h.x+3*(1-p)*Math.pow(p,2)*s.x+Math.pow(p,3)*l.x,y=Math.pow(1-p,3)*c.y+3*Math.pow(1-p,2)*p*h.y+3*(1-p)*Math.pow(p,2)*s.y+Math.pow(p,3)*l.y;if(P-o<=t.x&&P+o>=t.x&&y-o<=t.y&&y+o>=t.y)return i}else for(let e=1;e<=2*o;e++){let p=e/(2*o),c=n,h=n.pointType===SplinePoint.TYPE_BEZIER?n.controlPoint2:r.controlPoint1,s=r,l=Math.pow(1-p,2)*c.x+2*(1-p)*p*h.x+Math.pow(p,2)*s.x,P=Math.pow(1-p,2)*c.y+2*(1-p)*p*h.y+Math.pow(p,2)*s.y;if(l-o<=t.x&&l+o>=t.x&&P-o<=t.y&&P+o>=t.y)return i}i++}}drawPath(t){t.beginPath(),t.moveTo(this.points[0].x,this.points[0].y);for(let[o,i]of shiftingFrameIterator(this.points,2))o.pointType===SplinePoint.TYPE_LINEAR&&i.pointType===SplinePoint.TYPE_LINEAR?t.lineTo(i.x,i.y):o.pointType===SplinePoint.TYPE_LINEAR&&i.pointType===SplinePoint.TYPE_BEZIER?t.quadraticCurveTo(i.cp1x,i.cp1y,i.x,i.y):o.pointType===SplinePoint.TYPE_BEZIER&&i.pointType===SplinePoint.TYPE_LINEAR?t.quadraticCurveTo(o.cp2x,o.cp2y,i.x,i.y):t.bezierCurveTo(o.cp2x,o.cp2y,i.cp1x,i.cp1y,i.x,i.y)}}export{SplinePoint,Spline};
