From 83c00fa87d1b17284175f7d5fd2a0350153ddc43 Mon Sep 17 00:00:00 2001 From: xigua Date: Sun, 4 Aug 2024 15:50:15 +0800 Subject: [PATCH] optimize utils.droots --- dist/bezier.cjs | 6 +++++- dist/bezier.js | 2 +- package-lock.json | 26 +++++++++++++++++++------- src/utils.js | 6 +++++- 4 files changed, 30 insertions(+), 10 deletions(-) diff --git a/dist/bezier.cjs b/dist/bezier.cjs index efc021d..9db9e2d 100644 --- a/dist/bezier.cjs +++ b/dist/bezier.cjs @@ -478,7 +478,11 @@ var utils = { if (p.length === 3) { const a = p[0], b = p[1], c = p[2], d = a - 2 * b + c; if (d !== 0) { - const m1 = -sqrt(b * b - a * c), m2 = -a + b, v1 = -(m1 + m2) / d, v2 = -(-m1 + m2) / d; + const m1Pow2 = b * b - a * c; + if (m1Pow2 < 0) { + return []; + } + const m1 = -sqrt(m1Pow2), m2 = -a + b, v1 = -(m1 + m2) / d, v2 = -(-m1 + m2) / d; return [v1, v2]; } else if (b !== c && d === 0) { return [(2 * b - c) / (2 * (b - c))]; diff --git a/dist/bezier.js b/dist/bezier.js index dea91ec..5312d06 100644 --- a/dist/bezier.js +++ b/dist/bezier.js @@ -1 +1 @@ -(()=>{var{abs:J,cos:N,sin:P,acos:$,atan2:L,sqrt:F,pow:T}=Math;function D(c){return c<0?-T(-c,1/3):T(c,1/3)}var Q=Math.PI,W=2*Q,U=Q/2,B=1e-6,Y=Number.MAX_SAFE_INTEGER||9007199254740991,Z=Number.MIN_SAFE_INTEGER||-9007199254740991,tt={x:0,y:0,z:0},h={Tvalues:[-.06405689286260563,.06405689286260563,-.1911188674736163,.1911188674736163,-.3150426796961634,.3150426796961634,-.4337935076260451,.4337935076260451,-.5454214713888396,.5454214713888396,-.6480936519369755,.6480936519369755,-.7401241915785544,.7401241915785544,-.820001985973903,.820001985973903,-.8864155270044011,.8864155270044011,-.9382745520027328,.9382745520027328,-.9747285559713095,.9747285559713095,-.9951872199970213,.9951872199970213],Cvalues:[.12793819534675216,.12793819534675216,.1258374563468283,.1258374563468283,.12167047292780339,.12167047292780339,.1155056680537256,.1155056680537256,.10744427011596563,.10744427011596563,.09761865210411388,.09761865210411388,.08619016153195327,.08619016153195327,.0733464814110803,.0733464814110803,.05929858491543678,.05929858491543678,.04427743881741981,.04427743881741981,.028531388628933663,.028531388628933663,.0123412297999872,.0123412297999872],arcfn:function(c,n){let e=n(c),i=e.x*e.x+e.y*e.y;return typeof e.z!="undefined"&&(i+=e.z*e.z),F(i)},compute:function(c,n,e){if(c===0)return n[0].t=0,n[0];let i=n.length-1;if(c===1)return n[i].t=1,n[i];let s=1-c,o=n;if(i===0)return n[0].t=c,n[0];if(i===1){let u={x:s*o[0].x+c*o[1].x,y:s*o[0].y+c*o[1].y,t:c};return e&&(u.z=s*o[0].z+c*o[1].z),u}if(i<4){let u=s*s,f=c*c,l,y,a,x=0;i===2?(o=[o[0],o[1],o[2],tt],l=u,y=s*c*2,a=f):i===3&&(l=u*s,y=u*c*3,a=s*f*3,x=c*f);let p={x:l*o[0].x+y*o[1].x+a*o[2].x+x*o[3].x,y:l*o[0].y+y*o[1].y+a*o[2].y+x*o[3].y,t:c};return e&&(p.z=l*o[0].z+y*o[1].z+a*o[2].z+x*o[3].z),p}let r=JSON.parse(JSON.stringify(n));for(;r.length>1;){for(let u=0;u1;s--,o--){let r=[];for(let u=0,f;ur.x.min&&(n=r.x.min),e>r.y.min&&(e=r.y.min),i0&&(y.c1=f,y.c2=l,y.s1=c,y.s2=e,o.push(y))})}),o},makeshape:function(c,n,e){let i=n.points.length,s=c.points.length,o=h.makeline(n.points[i-1],c.points[0]),r=h.makeline(c.points[s-1],n.points[0]),u={startcap:o,forward:c,back:n,endcap:r,bbox:h.findbbox([o,c,n,r])};return u.intersections=function(f){return h.shapeintersections(u,u.bbox,f,f.bbox,e)},u},getminmax:function(c,n,e){if(!e)return{min:0,max:0};let i=Y,s=Z,o,r;e.indexOf(0)===-1&&(e=[0].concat(e)),e.indexOf(1)===-1&&e.push(1);for(let u=0,f=e.length;us&&(s=r[n]);return{min:i,mid:(i+s)/2,max:s,size:s-i}},align:function(c,n){let e=n.p1.x,i=n.p1.y,s=-L(n.p2.y-i,n.p2.x-e),o=function(r){return{x:(r.x-e)*N(s)-(r.y-i)*P(s),y:(r.x-e)*P(s)+(r.y-i)*N(s)}};return c.map(o)},roots:function(c,n){n=n||{p1:{x:0,y:0},p2:{x:1,y:0}};let e=c.length-1,i=h.align(c,n),s=function(d){return 0<=d&&d<=1};if(e===2){let d=i[0].y,z=i[1].y,A=i[2].y,k=d-2*z+A;if(k!==0){let j=-F(z*z-d*A),C=-d+z,R=-(j+C)/k,I=-(-j+C)/k;return[R,I].filter(s)}else if(z!==A&&k===0)return[(2*z-A)/(2*z-2*A)].filter(s);return[]}let o=i[0].y,r=i[1].y,u=i[2].y,f=i[3].y,l=-o+3*r-3*u+f,y=3*o-6*r+3*u,a=-3*o+3*r,x=o;if(h.approximately(l,0)){if(h.approximately(y,0))return h.approximately(a,0)?[]:[-x/a].filter(s);let d=F(a*a-4*y*x),z=2*y;return[(d-a)/z,(-a-d)/z].filter(s)}y/=l,a/=l,x/=l;let p=(3*a-y*y)/3,g=p/3,_=(2*y*y*y-9*y*a+27*x)/27,q=_/2,O=q*q+g*g*g,M,w,S,m,E;if(O<0){let d=-p/3,z=d*d*d,A=F(z),k=-_/(2*A),j=k<-1?-1:k>1?1:k,C=$(j),R=D(A),I=2*R;return S=I*N(C/3)-y/3,m=I*N((C+W)/3)-y/3,E=I*N((C+2*W)/3)-y/3,[S,m,E].filter(s)}else{if(O===0)return M=q<0?D(-q):-D(q),S=2*M-y/3,m=-M-y/3,[S,m].filter(s);{let d=F(O);return M=D(-q+d),w=D(q+d),[M-w-y/3].filter(s)}}},droots:function(c){if(c.length===3){let n=c[0],e=c[1],i=c[2],s=n-2*e+i;if(s!==0){let o=-F(e*e-n*i),r=-n+e,u=-(o+r)/s,f=-(-o+r)/s;return[u,f]}else if(e!==i&&s===0)return[(2*e-i)/(2*(e-i))];return[]}if(c.length===2){let n=c[0],e=c[1];return n!==e?[n/(n-e)]:[]}return[]},curvature:function(c,n,e,i,s){let o,r,u,f,l=0,y=0,a=h.compute(c,n),x=h.compute(c,e),p=a.x*a.x+a.y*a.y;if(i?(o=F(T(a.y*x.z-x.y*a.z,2)+T(a.z*x.x-x.z*a.x,2)+T(a.x*x.y-x.x*a.y,2)),r=T(p+a.z*a.z,3/2)):(o=a.x*x.y-a.y*x.x,r=T(p,3/2)),o===0||r===0)return{k:0,r:0};if(l=o/r,y=r/o,!s){let g=h.curvature(c-.001,n,e,i,!0).k,_=h.curvature(c+.001,n,e,i,!0).k;f=(_-l+(l-g))/2,u=(J(_-l)+J(l-g))/2}return{k:l,r:y,dk:f,adk:u}},inflections:function(c){if(c.length<4)return[];let n=h.align(c,{p1:c[0],p2:c.slice(-1)[0]}),e=n[2].x*n[1].y,i=n[3].x*n[1].y,s=n[1].x*n[2].y,o=n[3].x*n[2].y,r=18*(-3*e+2*i+3*s-o),u=18*(3*e-i-3*s),f=18*(s-e);if(h.approximately(r,0)){if(!h.approximately(u,0)){let x=-f/u;if(0<=x&&x<=1)return[x]}return[]}let l=2*r;if(h.approximately(l,0))return[];let y=u*u-4*r*f;if(y<0)return[];let a=Math.sqrt(y);return[(a-u)/l,-(u+a)/l].filter(function(x){return 0<=x&&x<=1})},bboxoverlap:function(c,n){let e=["x","y"],i=e.length;for(let s=0,o,r,u,f;s=f)return!1;return!0},expandbox:function(c,n){n.x.minc.x.max&&(c.x.max=n.x.max),n.y.max>c.y.max&&(c.y.max=n.y.max),n.z&&n.z.max>c.z.max&&(c.z.max=n.z.max),c.x.mid=(c.x.min+c.x.max)/2,c.y.mid=(c.y.min+c.y.max)/2,c.z&&(c.z.mid=(c.z.min+c.z.max)/2),c.x.size=c.x.max-c.x.min,c.y.size=c.y.max-c.y.min,c.z&&(c.z.size=c.z.max-c.z.min)},pairiteration:function(c,n,e){let i=c.bbox(),s=n.bbox(),o=1e5,r=e||.5;if(i.x.size+i.y.sizeE||E>d)&&(m+=W),m>d&&(z=d,d=m,m=z)):d4){if(arguments.length!==1)throw new Error("Only new Bezier(point[]) is accepted for 4th and higher order curves");s=!0}}else if(o!==6&&o!==8&&o!==9&&o!==12&&arguments.length!==1)throw new Error("Only new Bezier(point[]) is accepted for 4th and higher order curves");let r=this._3d=!s&&(o===9||o===12)||n&&n[0]&&typeof n[0].z!="undefined",u=this.points=[];for(let p=0,g=r?3:2;pp+G(g.y),0)0}length(){return h.length(this.derivative.bind(this))}static getABC(n=2,e,i,s,o=.5){let r=h.projectionratio(o,n),u=1-r,f={x:r*e.x+u*s.x,y:r*e.y+u*s.y},l=h.abcratio(o,n);return{A:{x:i.x+(i.x-f.x)/l,y:i.y+(i.y-f.y)/l},B:i,C:f,S:e,E:s}}getABC(n,e){e=e||this.get(n);let i=this.points[0],s=this.points[this.order];return v.getABC(this.order,i,e,s,n)}getLUT(n){if(this.verify(),n=n||100,this._lut.length===n+1)return this._lut;this._lut=[],n++,this._lut=[];for(let e=0,i,s;e1?1:a,x=this.compute(a),x.t=a,x.d=l,x}get(n){return this.compute(n)}point(n){return this.points[n]}compute(n){return this.ratios?h.computeWithRatios(n,this.points,this.ratios,this._3d):h.compute(n,this.points,this._3d,this.ratios)}raise(){let n=this.points,e=[n[0]],i=n.length;for(let s=1,o,r;s1;){i=[];for(let r=0,u,f=e.length-1;r=0&&r<=1}),e=e.concat(n[i].sort(h.numberSort))}.bind(this)),n.values=e.sort(h.numberSort).filter(function(i,s){return e.indexOf(i)===s}),n}bbox(){let n=this.extrema(),e={};return this.dims.forEach(function(i){e[i]=h.getminmax(this,i,n[i])}.bind(this)),e}overlaps(n){let e=this.bbox(),i=n.bbox();return h.bboxoverlap(e,i)}offset(n,e){if(typeof e!="undefined"){let i=this.get(n),s=this.normal(n),o={c:i,n:s,x:i.x+s.x*e,y:i.y+s.y*e};return this._3d&&(o.z=i.z+s.z*e),o}if(this._linear){let i=this.normal(0),s=this.points.map(function(o){let r={x:o.x+n*i.x,y:o.y+n*i.y};return o.z&&i.z&&(r.z=o.z+n*i.z),r});return[new v(s)]}return this.reduce().map(function(i){return i._linear?i.offset(n)[0]:i.scale(n)})}simple(){if(this.order===3){let s=h.angle(this.points[0],this.points[3],this.points[1]),o=h.angle(this.points[0],this.points[3],this.points[2]);if(s>0&&o<0||s<0&&o>0)return!1}let n=this.normal(0),e=this.normal(1),i=n.x*e.x+n.y*e.y;return this._3d&&(i+=n.z*e.z),G(it(i))(1-u/s)*e+u/s*i);return new v(this.points.map((r,u)=>({x:r.x+n.x*o[u],y:r.y+n.y*o[u]})))}scale(n){let e=this.order,i=!1;if(typeof n=="function"&&(i=n),i&&e===2)return this.raise().scale(i);let s=this.clockwise,o=this.points;if(this._linear)return this.translate(this.normal(0),i?i(0):n,i?i(1):n);let r=i?i(0):n,u=i?i(1):n,f=[this.offset(0,10),this.offset(1,10)],l=[],y=h.lli4(f[0],f[0].c,f[1],f[1].c);if(!y)throw new Error("cannot scale this curve. Try reducing it first.");return[0,1].forEach(function(a){let x=l[a*e]=h.copy(o[a*e]);x.x+=(a?u:r)*f[a].n.x,x.y+=(a?u:r)*f[a].n.y}),i?([0,1].forEach(function(a){if(!(e===2&&!!a)){var x=o[a+1],p={x:x.x-y.x,y:x.y-y.y},g=i?i((a+1)/e):n;i&&!s&&(g=-g);var _=X(p.x*p.x+p.y*p.y);p.x/=_,p.y/=_,l[a+1]={x:x.x+g*p.x,y:x.y+g*p.y}}}),new v(l)):([0,1].forEach(a=>{if(e===2&&!!a)return;let x=l[a*e],p=this.derivative(a),g={x:x.x+p.x,y:x.y+p.y};l[a+1]=h.lli4(x,g,y,o[a+1])}),new v(l))}outline(n,e,i,s){if(e=e===void 0?n:e,this._linear){let m=this.normal(0),E=this.points[0],d=this.points[this.points.length-1],z,A,k;i===void 0&&(i=n,s=e),z={x:E.x+m.x*n,y:E.y+m.y*n},k={x:d.x+m.x*i,y:d.y+m.y*i},A={x:(z.x+k.x)/2,y:(z.y+k.y)/2};let j=[z,A,k];z={x:E.x-m.x*e,y:E.y-m.y*e},k={x:d.x-m.x*s,y:d.y-m.y*s},A={x:(z.x+k.x)/2,y:(z.y+k.y)/2};let C=[k,A,z],R=h.makeline(C[2],j[0]),I=h.makeline(j[2],C[0]),K=[R,new v(j),I,new v(C)];return new b(K)}let o=this.reduce(),r=o.length,u=[],f=[],l,y=0,a=this.length(),x=typeof i!="undefined"&&typeof s!="undefined";function p(m,E,d,z,A){return function(k){let j=z/d,C=(z+A)/d,R=E-m;return h.map(k,0,1,m+j*R,m+C*R)}}o.forEach(function(m){let E=m.length();x?(u.push(m.scale(p(n,i,a,y,E))),f.push(m.scale(p(-e,-s,a,y,E)))):(u.push(m.scale(n)),f.push(m.scale(-e))),y+=E}),f=f.map(function(m){return l=m.points,l[3]?m.points=[l[3],l[2],l[1],l[0]]:m.points=[l[2],l[1],l[0]],m}).reverse();let g=u[0].points[0],_=u[r-1].points[u[r-1].points.length-1],q=f[r-1].points[f[r-1].points.length-1],O=f[0].points[0],M=h.makeline(q,g),w=h.makeline(_,O),S=[M].concat(u).concat([w]).concat(f);return new b(S)}outlineshapes(n,e,i){e=e||n;let s=this.outline(n,e).curves,o=[];for(let r=1,u=s.length;r1,f.endcap.virtual=r{var u=this.get(r);return h.between(u.x,e,s)&&h.between(u.y,i,o)})}selfintersects(n){let e=this.reduce(),i=e.length-2,s=[];for(let o=0,r,u,f;o0&&(o=o.concat(u))}),o}arcs(n){return n=n||.5,this._iterate(n,[])}_error(n,e,i,s){let o=(s-i)/4,r=this.get(i+o),u=this.get(s-o),f=h.dist(n,e),l=h.dist(n,r),y=h.dist(n,u);return G(l-f)+G(y-f)}_iterate(n,e){let i=0,s=1,o;do{o=0,s=1;let r=this.get(i),u,f,l,y,a=!1,x=!1,p,g=s,_=1,q=0;do if(x=a,y=l,g=(i+s)/2,q++,u=this.get(g),f=this.get(s),l=h.getccenter(r,u,f),l.interval={start:i,end:s},a=this._error(l,r,i,s)<=n,p=x&&!a,p||(_=s),a){if(s>=1){if(l.interval.end=_=1,y=l,s>1){let M={x:l.x+l.r*nt(l.e),y:l.y+l.r*et(l.e)};l.e+=h.angle({x:l.x,y:l.y},M,this.get(1))}break}s=s+(s-i)/2}else s=g;while(!p&&o++<100);if(o>=100)break;y=y||l,e.push(y),i=_}while(s<1);return e}};})(); +(()=>{var{abs:J,cos:N,sin:b,acos:$,atan2:L,sqrt:F,pow:T}=Math;function D(c){return c<0?-T(-c,1/3):T(c,1/3)}var Q=Math.PI,W=2*Q,U=Q/2,B=1e-6,Y=Number.MAX_SAFE_INTEGER||9007199254740991,Z=Number.MIN_SAFE_INTEGER||-9007199254740991,tt={x:0,y:0,z:0},h={Tvalues:[-.06405689286260563,.06405689286260563,-.1911188674736163,.1911188674736163,-.3150426796961634,.3150426796961634,-.4337935076260451,.4337935076260451,-.5454214713888396,.5454214713888396,-.6480936519369755,.6480936519369755,-.7401241915785544,.7401241915785544,-.820001985973903,.820001985973903,-.8864155270044011,.8864155270044011,-.9382745520027328,.9382745520027328,-.9747285559713095,.9747285559713095,-.9951872199970213,.9951872199970213],Cvalues:[.12793819534675216,.12793819534675216,.1258374563468283,.1258374563468283,.12167047292780339,.12167047292780339,.1155056680537256,.1155056680537256,.10744427011596563,.10744427011596563,.09761865210411388,.09761865210411388,.08619016153195327,.08619016153195327,.0733464814110803,.0733464814110803,.05929858491543678,.05929858491543678,.04427743881741981,.04427743881741981,.028531388628933663,.028531388628933663,.0123412297999872,.0123412297999872],arcfn:function(c,n){let e=n(c),i=e.x*e.x+e.y*e.y;return typeof e.z!="undefined"&&(i+=e.z*e.z),F(i)},compute:function(c,n,e){if(c===0)return n[0].t=0,n[0];let i=n.length-1;if(c===1)return n[i].t=1,n[i];let s=1-c,o=n;if(i===0)return n[0].t=c,n[0];if(i===1){let u={x:s*o[0].x+c*o[1].x,y:s*o[0].y+c*o[1].y,t:c};return e&&(u.z=s*o[0].z+c*o[1].z),u}if(i<4){let u=s*s,f=c*c,l,y,a,x=0;i===2?(o=[o[0],o[1],o[2],tt],l=u,y=s*c*2,a=f):i===3&&(l=u*s,y=u*c*3,a=s*f*3,x=c*f);let p={x:l*o[0].x+y*o[1].x+a*o[2].x+x*o[3].x,y:l*o[0].y+y*o[1].y+a*o[2].y+x*o[3].y,t:c};return e&&(p.z=l*o[0].z+y*o[1].z+a*o[2].z+x*o[3].z),p}let r=JSON.parse(JSON.stringify(n));for(;r.length>1;){for(let u=0;u1;s--,o--){let r=[];for(let u=0,f;ur.x.min&&(n=r.x.min),e>r.y.min&&(e=r.y.min),i0&&(y.c1=f,y.c2=l,y.s1=c,y.s2=e,o.push(y))})}),o},makeshape:function(c,n,e){let i=n.points.length,s=c.points.length,o=h.makeline(n.points[i-1],c.points[0]),r=h.makeline(c.points[s-1],n.points[0]),u={startcap:o,forward:c,back:n,endcap:r,bbox:h.findbbox([o,c,n,r])};return u.intersections=function(f){return h.shapeintersections(u,u.bbox,f,f.bbox,e)},u},getminmax:function(c,n,e){if(!e)return{min:0,max:0};let i=Y,s=Z,o,r;e.indexOf(0)===-1&&(e=[0].concat(e)),e.indexOf(1)===-1&&e.push(1);for(let u=0,f=e.length;us&&(s=r[n]);return{min:i,mid:(i+s)/2,max:s,size:s-i}},align:function(c,n){let e=n.p1.x,i=n.p1.y,s=-L(n.p2.y-i,n.p2.x-e),o=function(r){return{x:(r.x-e)*N(s)-(r.y-i)*b(s),y:(r.x-e)*b(s)+(r.y-i)*N(s)}};return c.map(o)},roots:function(c,n){n=n||{p1:{x:0,y:0},p2:{x:1,y:0}};let e=c.length-1,i=h.align(c,n),s=function(d){return 0<=d&&d<=1};if(e===2){let d=i[0].y,z=i[1].y,A=i[2].y,k=d-2*z+A;if(k!==0){let j=-F(z*z-d*A),C=-d+z,R=-(j+C)/k,I=-(-j+C)/k;return[R,I].filter(s)}else if(z!==A&&k===0)return[(2*z-A)/(2*z-2*A)].filter(s);return[]}let o=i[0].y,r=i[1].y,u=i[2].y,f=i[3].y,l=-o+3*r-3*u+f,y=3*o-6*r+3*u,a=-3*o+3*r,x=o;if(h.approximately(l,0)){if(h.approximately(y,0))return h.approximately(a,0)?[]:[-x/a].filter(s);let d=F(a*a-4*y*x),z=2*y;return[(d-a)/z,(-a-d)/z].filter(s)}y/=l,a/=l,x/=l;let p=(3*a-y*y)/3,g=p/3,_=(2*y*y*y-9*y*a+27*x)/27,q=_/2,O=q*q+g*g*g,M,w,S,m,E;if(O<0){let d=-p/3,z=d*d*d,A=F(z),k=-_/(2*A),j=k<-1?-1:k>1?1:k,C=$(j),R=D(A),I=2*R;return S=I*N(C/3)-y/3,m=I*N((C+W)/3)-y/3,E=I*N((C+2*W)/3)-y/3,[S,m,E].filter(s)}else{if(O===0)return M=q<0?D(-q):-D(q),S=2*M-y/3,m=-M-y/3,[S,m].filter(s);{let d=F(O);return M=D(-q+d),w=D(q+d),[M-w-y/3].filter(s)}}},droots:function(c){if(c.length===3){let n=c[0],e=c[1],i=c[2],s=n-2*e+i;if(s!==0){let o=e*e-n*i;if(o<0)return[];let r=-F(o),u=-n+e,f=-(r+u)/s,l=-(-r+u)/s;return[f,l]}else if(e!==i&&s===0)return[(2*e-i)/(2*(e-i))];return[]}if(c.length===2){let n=c[0],e=c[1];return n!==e?[n/(n-e)]:[]}return[]},curvature:function(c,n,e,i,s){let o,r,u,f,l=0,y=0,a=h.compute(c,n),x=h.compute(c,e),p=a.x*a.x+a.y*a.y;if(i?(o=F(T(a.y*x.z-x.y*a.z,2)+T(a.z*x.x-x.z*a.x,2)+T(a.x*x.y-x.x*a.y,2)),r=T(p+a.z*a.z,3/2)):(o=a.x*x.y-a.y*x.x,r=T(p,3/2)),o===0||r===0)return{k:0,r:0};if(l=o/r,y=r/o,!s){let g=h.curvature(c-.001,n,e,i,!0).k,_=h.curvature(c+.001,n,e,i,!0).k;f=(_-l+(l-g))/2,u=(J(_-l)+J(l-g))/2}return{k:l,r:y,dk:f,adk:u}},inflections:function(c){if(c.length<4)return[];let n=h.align(c,{p1:c[0],p2:c.slice(-1)[0]}),e=n[2].x*n[1].y,i=n[3].x*n[1].y,s=n[1].x*n[2].y,o=n[3].x*n[2].y,r=18*(-3*e+2*i+3*s-o),u=18*(3*e-i-3*s),f=18*(s-e);if(h.approximately(r,0)){if(!h.approximately(u,0)){let x=-f/u;if(0<=x&&x<=1)return[x]}return[]}let l=2*r;if(h.approximately(l,0))return[];let y=u*u-4*r*f;if(y<0)return[];let a=Math.sqrt(y);return[(a-u)/l,-(u+a)/l].filter(function(x){return 0<=x&&x<=1})},bboxoverlap:function(c,n){let e=["x","y"],i=e.length;for(let s=0,o,r,u,f;s=f)return!1;return!0},expandbox:function(c,n){n.x.minc.x.max&&(c.x.max=n.x.max),n.y.max>c.y.max&&(c.y.max=n.y.max),n.z&&n.z.max>c.z.max&&(c.z.max=n.z.max),c.x.mid=(c.x.min+c.x.max)/2,c.y.mid=(c.y.min+c.y.max)/2,c.z&&(c.z.mid=(c.z.min+c.z.max)/2),c.x.size=c.x.max-c.x.min,c.y.size=c.y.max-c.y.min,c.z&&(c.z.size=c.z.max-c.z.min)},pairiteration:function(c,n,e){let i=c.bbox(),s=n.bbox(),o=1e5,r=e||.5;if(i.x.size+i.y.sizeE||E>d)&&(m+=W),m>d&&(z=d,d=m,m=z)):d4){if(arguments.length!==1)throw new Error("Only new Bezier(point[]) is accepted for 4th and higher order curves");s=!0}}else if(o!==6&&o!==8&&o!==9&&o!==12&&arguments.length!==1)throw new Error("Only new Bezier(point[]) is accepted for 4th and higher order curves");let r=this._3d=!s&&(o===9||o===12)||n&&n[0]&&typeof n[0].z!="undefined",u=this.points=[];for(let p=0,g=r?3:2;pp+G(g.y),0)0}length(){return h.length(this.derivative.bind(this))}static getABC(n=2,e,i,s,o=.5){let r=h.projectionratio(o,n),u=1-r,f={x:r*e.x+u*s.x,y:r*e.y+u*s.y},l=h.abcratio(o,n);return{A:{x:i.x+(i.x-f.x)/l,y:i.y+(i.y-f.y)/l},B:i,C:f,S:e,E:s}}getABC(n,e){e=e||this.get(n);let i=this.points[0],s=this.points[this.order];return v.getABC(this.order,i,e,s,n)}getLUT(n){if(this.verify(),n=n||100,this._lut.length===n+1)return this._lut;this._lut=[],n++,this._lut=[];for(let e=0,i,s;e1?1:a,x=this.compute(a),x.t=a,x.d=l,x}get(n){return this.compute(n)}point(n){return this.points[n]}compute(n){return this.ratios?h.computeWithRatios(n,this.points,this.ratios,this._3d):h.compute(n,this.points,this._3d,this.ratios)}raise(){let n=this.points,e=[n[0]],i=n.length;for(let s=1,o,r;s1;){i=[];for(let r=0,u,f=e.length-1;r=0&&r<=1}),e=e.concat(n[i].sort(h.numberSort))}.bind(this)),n.values=e.sort(h.numberSort).filter(function(i,s){return e.indexOf(i)===s}),n}bbox(){let n=this.extrema(),e={};return this.dims.forEach(function(i){e[i]=h.getminmax(this,i,n[i])}.bind(this)),e}overlaps(n){let e=this.bbox(),i=n.bbox();return h.bboxoverlap(e,i)}offset(n,e){if(typeof e!="undefined"){let i=this.get(n),s=this.normal(n),o={c:i,n:s,x:i.x+s.x*e,y:i.y+s.y*e};return this._3d&&(o.z=i.z+s.z*e),o}if(this._linear){let i=this.normal(0),s=this.points.map(function(o){let r={x:o.x+n*i.x,y:o.y+n*i.y};return o.z&&i.z&&(r.z=o.z+n*i.z),r});return[new v(s)]}return this.reduce().map(function(i){return i._linear?i.offset(n)[0]:i.scale(n)})}simple(){if(this.order===3){let s=h.angle(this.points[0],this.points[3],this.points[1]),o=h.angle(this.points[0],this.points[3],this.points[2]);if(s>0&&o<0||s<0&&o>0)return!1}let n=this.normal(0),e=this.normal(1),i=n.x*e.x+n.y*e.y;return this._3d&&(i+=n.z*e.z),G(it(i))(1-u/s)*e+u/s*i);return new v(this.points.map((r,u)=>({x:r.x+n.x*o[u],y:r.y+n.y*o[u]})))}scale(n){let e=this.order,i=!1;if(typeof n=="function"&&(i=n),i&&e===2)return this.raise().scale(i);let s=this.clockwise,o=this.points;if(this._linear)return this.translate(this.normal(0),i?i(0):n,i?i(1):n);let r=i?i(0):n,u=i?i(1):n,f=[this.offset(0,10),this.offset(1,10)],l=[],y=h.lli4(f[0],f[0].c,f[1],f[1].c);if(!y)throw new Error("cannot scale this curve. Try reducing it first.");return[0,1].forEach(function(a){let x=l[a*e]=h.copy(o[a*e]);x.x+=(a?u:r)*f[a].n.x,x.y+=(a?u:r)*f[a].n.y}),i?([0,1].forEach(function(a){if(!(e===2&&!!a)){var x=o[a+1],p={x:x.x-y.x,y:x.y-y.y},g=i?i((a+1)/e):n;i&&!s&&(g=-g);var _=X(p.x*p.x+p.y*p.y);p.x/=_,p.y/=_,l[a+1]={x:x.x+g*p.x,y:x.y+g*p.y}}}),new v(l)):([0,1].forEach(a=>{if(e===2&&!!a)return;let x=l[a*e],p=this.derivative(a),g={x:x.x+p.x,y:x.y+p.y};l[a+1]=h.lli4(x,g,y,o[a+1])}),new v(l))}outline(n,e,i,s){if(e=e===void 0?n:e,this._linear){let m=this.normal(0),E=this.points[0],d=this.points[this.points.length-1],z,A,k;i===void 0&&(i=n,s=e),z={x:E.x+m.x*n,y:E.y+m.y*n},k={x:d.x+m.x*i,y:d.y+m.y*i},A={x:(z.x+k.x)/2,y:(z.y+k.y)/2};let j=[z,A,k];z={x:E.x-m.x*e,y:E.y-m.y*e},k={x:d.x-m.x*s,y:d.y-m.y*s},A={x:(z.x+k.x)/2,y:(z.y+k.y)/2};let C=[k,A,z],R=h.makeline(C[2],j[0]),I=h.makeline(j[2],C[0]),K=[R,new v(j),I,new v(C)];return new P(K)}let o=this.reduce(),r=o.length,u=[],f=[],l,y=0,a=this.length(),x=typeof i!="undefined"&&typeof s!="undefined";function p(m,E,d,z,A){return function(k){let j=z/d,C=(z+A)/d,R=E-m;return h.map(k,0,1,m+j*R,m+C*R)}}o.forEach(function(m){let E=m.length();x?(u.push(m.scale(p(n,i,a,y,E))),f.push(m.scale(p(-e,-s,a,y,E)))):(u.push(m.scale(n)),f.push(m.scale(-e))),y+=E}),f=f.map(function(m){return l=m.points,l[3]?m.points=[l[3],l[2],l[1],l[0]]:m.points=[l[2],l[1],l[0]],m}).reverse();let g=u[0].points[0],_=u[r-1].points[u[r-1].points.length-1],q=f[r-1].points[f[r-1].points.length-1],O=f[0].points[0],M=h.makeline(q,g),w=h.makeline(_,O),S=[M].concat(u).concat([w]).concat(f);return new P(S)}outlineshapes(n,e,i){e=e||n;let s=this.outline(n,e).curves,o=[];for(let r=1,u=s.length;r1,f.endcap.virtual=r{var u=this.get(r);return h.between(u.x,e,s)&&h.between(u.y,i,o)})}selfintersects(n){let e=this.reduce(),i=e.length-2,s=[];for(let o=0,r,u,f;o0&&(o=o.concat(u))}),o}arcs(n){return n=n||.5,this._iterate(n,[])}_error(n,e,i,s){let o=(s-i)/4,r=this.get(i+o),u=this.get(s-o),f=h.dist(n,e),l=h.dist(n,r),y=h.dist(n,u);return G(l-f)+G(y-f)}_iterate(n,e){let i=0,s=1,o;do{o=0,s=1;let r=this.get(i),u,f,l,y,a=!1,x=!1,p,g=s,_=1,q=0;do if(x=a,y=l,g=(i+s)/2,q++,u=this.get(g),f=this.get(s),l=h.getccenter(r,u,f),l.interval={start:i,end:s},a=this._error(l,r,i,s)<=n,p=x&&!a,p||(_=s),a){if(s>=1){if(l.interval.end=_=1,y=l,s>1){let M={x:l.x+l.r*nt(l.e),y:l.y+l.r*et(l.e)};l.e+=h.angle({x:l.x,y:l.y},M,this.get(1))}break}s=s+(s-i)/2}else s=g;while(!p&&o++<100);if(o>=100)break;y=y||l,e.push(y),i=_}while(s<1);return e}};})(); diff --git a/package-lock.json b/package-lock.json index 7a63ea1..2ab8b92 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,10 +8,8 @@ "name": "bezier-js", "version": "6.1.4", "license": "MIT", - "dependencies": { - "cross-env": "^7.0.3" - }, "devDependencies": { + "cross-env": "^7.0.3", "esbuild": "^0.14.10", "jest": "^27.4.7", "npm-run-all": "^4.1.5", @@ -1799,6 +1797,7 @@ "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-env/-/cross-env-7.0.3.tgz", "integrity": "sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw==", + "dev": true, "dependencies": { "cross-spawn": "^7.0.1" }, @@ -1816,6 +1815,7 @@ "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", @@ -1829,6 +1829,7 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, "engines": { "node": ">=8" } @@ -1837,6 +1838,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, "dependencies": { "shebang-regex": "^3.0.0" }, @@ -1848,6 +1850,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, "engines": { "node": ">=8" } @@ -1856,6 +1859,7 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, "dependencies": { "isexe": "^2.0.0" }, @@ -2940,7 +2944,8 @@ "node_modules/isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true }, "node_modules/istanbul-lib-coverage": { "version": "3.2.0", @@ -7772,6 +7777,7 @@ "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-env/-/cross-env-7.0.3.tgz", "integrity": "sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw==", + "dev": true, "requires": { "cross-spawn": "^7.0.1" }, @@ -7780,6 +7786,7 @@ "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, "requires": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", @@ -7789,12 +7796,14 @@ "path-key": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==" + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true }, "shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, "requires": { "shebang-regex": "^3.0.0" } @@ -7802,12 +7811,14 @@ "shebang-regex": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==" + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true }, "which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, "requires": { "isexe": "^2.0.0" } @@ -8579,7 +8590,8 @@ "isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true }, "istanbul-lib-coverage": { "version": "3.2.0", diff --git a/src/utils.js b/src/utils.js index e4ab49c..51e1000 100644 --- a/src/utils.js +++ b/src/utils.js @@ -624,7 +624,11 @@ const utils = { c = p[2], d = a - 2 * b + c; if (d !== 0) { - const m1 = -sqrt(b * b - a * c), + const m1Pow2 = b * b - a * c; + if (m1Pow2 < 0) { + return []; + } + const m1 = -sqrt(m1Pow2), m2 = -a + b, v1 = -(m1 + m2) / d, v2 = -(-m1 + m2) / d;