svg-path-simplify 0.0.1 → 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. package/README.md +28 -1
  2. package/dist/svg-path-simplify.esm.js +4040 -0
  3. package/dist/svg-path-simplify.esm.min.js +1 -0
  4. package/dist/svg-path-simplify.js +4065 -0
  5. package/dist/svg-path-simplify.min.js +1 -0
  6. package/dist/svg-path-simplify.node.js +4062 -0
  7. package/dist/svg-path-simplify.node.min.js +1 -0
  8. package/index.html +222 -0
  9. package/package.json +2 -2
  10. package/src/constants.js +4 -0
  11. package/src/index.js +18 -3
  12. package/src/pathData_simplify_cubic.js +324 -0
  13. package/src/pathData_simplify_cubic_arr.js +50 -0
  14. package/src/pathData_simplify_cubic_extrapolate.js +220 -0
  15. package/src/pathSimplify-main.js +294 -0
  16. package/src/svgii/...parse.js +402 -0
  17. package/src/svgii/geometry.js +1096 -0
  18. package/src/svgii/geometry_area.js +265 -0
  19. package/src/svgii/geometry_bbox.js +223 -0
  20. package/src/svgii/pathData_analyze.js +896 -0
  21. package/src/svgii/pathData_convert.js +1180 -0
  22. package/src/svgii/pathData_parse.js +487 -0
  23. package/src/svgii/pathData_remove_collinear.js +85 -0
  24. package/src/svgii/pathData_remove_zerolength.js +28 -0
  25. package/src/svgii/pathData_reorder.js +204 -0
  26. package/src/svgii/pathData_reverse.js +124 -0
  27. package/src/svgii/pathData_scale.js +42 -0
  28. package/src/svgii/pathData_split.js +449 -0
  29. package/src/svgii/pathData_stringify.js +146 -0
  30. package/src/svgii/pathData_toPolygon.js +92 -0
  31. package/src/svgii/pathdata_cleanup.js +363 -0
  32. package/src/svgii/poly_analyze.js +172 -0
  33. package/src/svgii/poly_to_pathdata.js +185 -0
  34. package/src/svgii/rounding.js +154 -0
  35. package/src/svgii/simplify.js +248 -0
  36. package/src/svgii/simplify_bezier.js +470 -0
  37. package/src/svgii/simplify_linetos.js +93 -0
  38. package/src/svgii/simplify_polygon.js +135 -0
  39. package/src/svgii/stringify.js +103 -0
  40. package/src/svgii/svg_cleanup.js +80 -0
  41. package/src/svgii/visualize.js +317 -0
  42. package/LICENSE +0 -21
@@ -0,0 +1 @@
1
+ "use strict";const{abs:e,acos:t,asin:l,atan:a,atan2:s,ceil:n,cos:r,exp:p,floor:u,log:y,max:h,min:i,pow:o,random:c,round:x,sin:f,sqrt:g,tan:v,PI:d}=Math;function M(e,t,l=!1){let a=s(t.y-e.y,t.x-e.x);return l&&a<0&&(a+=2*Math.PI),a}function m(e,t,l,a,s=!0){let n,r,p,u,y,h={};try{if(n=(a.y-l.y)*(t.x-e.x)-(a.x-l.x)*(t.y-e.y),0==n)return!1}catch{console.log("!catch",e,t,"p3:",l,a)}r=e.y-l.y,p=e.x-l.x,u=(a.x-l.x)*r-(a.y-l.y)*p,y=(t.x-e.x)*r-(t.y-e.y)*p,r=u/n,p=y/n,h={x:e.x+r*(t.x-e.x),y:e.y+r*(t.y-e.y)};let i=!1;return r>0&&r<1&&p>0&&p<1&&(i=!0),!(s&&!i)&&h}function b(e,t){return g((t.x-e.x)*(t.x-e.x)+(t.y-e.y)*(t.y-e.y))}function C(e,t){return(t.x-e.x)**2+(t.y-e.y)**2}function A(e,t,l,a=!1){let s={x:(t.x-e.x)*l+e.x,y:(t.y-e.y)*l+e.y};return a&&(s.angle=M(e,t),s.angle<0&&(s.angle+=2*d)),s}function w(e,t=.5,l=!1,a=!1){let s;return s=e.length>2?((e,t,l=!1)=>{let s=4===e.length,n=e[0],r=e[1],p=s?e[2]:e[1],u=e[e.length-1],y={x:0,y:0};if(l||a){let e,l,h,i,o,c=n.x===r.x&&n.y===r.y,x=u.x===p.x&&u.y===p.y;0!==t||c?1!==t||x?(c&&(t+=1e-7),x&&(t-=1e-7),e=A(n,r,t),s?(l=A(r,p,t),h=A(p,u,t),i=A(e,l,t),o=A(l,h,t),y=A(i,o,t),y.angle=M(i,o),a&&(y.cpts=[l,h,i,o])):(l=A(n,r,t),h=A(r,u,t),y=A(l,h,t),y.angle=M(l,h),a&&(y.cpts=[l,h]))):(y.x=u.x,y.y=u.y,y.angle=M(p,u)):(y.x=n.x,y.y=n.y,y.angle=M(n,r))}else{let e=1-t;y=s?{x:e**3*n.x+3*e**2*t*r.x+3*e*t**2*p.x+t**3*u.x,y:e**3*n.y+3*e**2*t*r.y+3*e*t**2*p.y+t**3*u.y}:{x:e*e*n.x+2*e*t*r.x+t**2*u.x,y:e*e*n.y+2*e*t*r.y+t**2*u.y}}return y})(e,t,l):A(e[0],e[1],t,l),l&&s.angle<0&&(s.angle+=2*d),s}function P(e,t,l,s,n,p=0,u=!0,y=!1){if(n=y?n*d/180:n,p=y?p*d/180:p,p=l!==s&&p!==2*d?p:0,u&&l!==s){let e=a(v(n=p?n-p:n)*(l/s));n=r(n)<0?e+d:e}let h=e+l*r(n),i=t+s*f(n),o={x:h,y:i};return p&&(o.x=e+(h-e)*r(p)-(i-t)*f(p),o.y=t+(h-e)*f(p)+(i-t)*r(p)),o}function L(e,t=[],l=.05){let a=3===t.length,s=t[0]||null,n=a?t[1]:null,r=a?t[2]:t[1],p=.5*Math.PI,u=!1,y=!1,h=s?M(r,s,!0):null;if(u=Math.abs(h%p)<l||Math.abs(h%p-p)<l,a){let e=n?M(n,r,!0):0;y=Math.abs(e%p)<=l||Math.abs(e%p-p)<=l}return u||y}function I(e){return 4===e.length?function(e,t,l,a){let[s,n,r,p,u,y,h,i]=[e.x,e.y,t.x,t.y,l.x,l.y,a.x,a.y],o=Math.min(e.y,a.y),c=Math.min(e.x,a.x),x=Math.max(e.x,a.x),f=Math.max(e.y,a.y);if(t.y>=o&&t.y<=f&&l.y>=o&&l.y<=f&&t.x>=c&&t.x<=x&&l.x>=c&&l.x<=x)return[];let g,v,d,M,m,b,C,A,w=[];for(let e=0;e<2;++e)if(0==e?(v=6*s-12*r+6*u,g=-3*s+9*r-9*u+3*h,d=3*r-3*s):(v=6*n-12*p+6*y,g=-3*n+9*p-9*y+3*i,d=3*p-3*n),Math.abs(g)<1e-12){if(Math.abs(v)<1e-12)continue;M=-d/v,0<M&&M<1&&w.push(M)}else C=v*v-4*d*g,C<0?Math.abs(C)<1e-12&&(M=-v/(2*g),0<M&&M<1&&w.push(M)):(A=Math.sqrt(C),m=(-v+A)/(2*g),0<m&&m<1&&w.push(m),b=(-v-A)/(2*g),0<b&&b<1&&w.push(b));let P=w.length;for(;P--;)M=w[P];return w}(e[0],e[1],e[2],e[3]):function(e,t,l){let a,s,n,r=Math.min(e.y,l.y),p=Math.min(e.x,l.x),u=Math.max(e.x,l.x),y=Math.max(e.y,l.y);if(t.y>=r&&t.y<=y&&t.x>=p&&t.x<=u)return[];let[h,i,o,c,x,f]=[e.x,e.y,t.x,t.y,l.x,l.y],g=[];for(let e=0;e<2;++e)a=0==e?h-2*o+x:i-2*c+f,s=0==e?-2*h+2*o:-2*i+2*c,Math.abs(a)>1e-12&&(n=-s/(2*a),n>0&&n<1&&g.push(n));return g}(e[0],e[1],e[2])}function $(e,t=.025){let l=e[0],a=e[e.length-1],s=e.map(e=>e.x),n=e.map(e=>e.y),r=Math.min(...s),p=Math.max(...s),u=Math.min(...n),y=p-r,h=Math.max(...n)-u;if(e.length<3||0===y||0===h)return{area:0,flat:!0,thresh:1e-4,ratio:0};let i=C(l,a),o=C(l,e[0]),c=(o+(e.length>3?C(a,e[1]):o))/2;let x=.5*(y+h)*.5,f=0;for(let t=0,l=e.length;t<l;t++){f+=e[t].x*e[t===e.length-1?0:t+1].y*.5-e[t===e.length-1?0:t+1].x*e[t].y*.5}f=+Math.abs(f).toFixed(9);return{area:f,flat:0===f||f<c/1e3,thresh:x,ratio:f/c,squareDist:i,areaThresh:i/1e3}}function k(e,t){return(Math.abs(e.x-t.x)+Math.abs(e.y-t.y))/2}function Q(e){let t=[];try{e.map((e,t)=>"m"===e.type.toLowerCase()?t:-1).filter(e=>-1!==e)}catch{console.log("catch",e)}let l=e.map((e,t)=>"m"===e.type.toLowerCase()?t:-1).filter(e=>-1!==e);return 1===l.length?[e]:(l.forEach((a,s)=>{t.push(e.slice(a,l[s+1]))}),t)}function S(e,t){let l,a,s,n,r,p,u=[],y=[],h=e[0],i=e[1],o=e[e.length-2],c=e[e.length-1];return 4===e.length?(l=w([h,i],t),a=w([i,o],t),s=w([o,c],t),n=w([l,a],t),r=w([a,s],t),p=w([n,r],t),u.push({x:h.x,y:h.y},{x:l.x,y:l.y},{x:n.x,y:n.y},{x:p.x,y:p.y}),y.push({x:p.x,y:p.y},{x:r.x,y:r.y},{x:s.x,y:s.y},{x:c.x,y:c.y})):3===e.length?(a=w([h,i],t),s=w([i,c],t),p=w([a,s],t),u.push({x:h.x,y:h.y},{x:a.x,y:a.y},{x:p.x,y:p.y}),y.push({x:p.x,y:p.y},{x:s.x,y:s.y},{x:c.x,y:c.y})):2===e.length&&(a=w([h,c],t),u.push({x:h.x,y:h.y},{x:a.x,y:a.y}),y.push({x:a.x,y:a.y},{x:c.x,y:c.y})),[u,y]}function T(e,t,l=0,a=1){let s=[],n=6===t.length?"C":"Q",r={x:t[0],y:t[1]},p="C"===n?{x:t[2],y:t[3]}:r,u={x:t[4],y:t[5]},y=Math.max(u.x,e.x),h=Math.min(u.x,e.x),i=Math.max(u.y,e.y),o=Math.min(u.y,e.y),c=0;if(r.x<h||r.x>y||r.y<o||r.y>i||p.x<h||p.x>y||p.y<o||p.y>i){let y=I("C"===n?[e,r,p,u]:[e,r,u]).sort();if(y=y.filter(e=>e>l&&e<a),y.length){let l=function(e,t,l,a=!0){let s=[];if(!l.length)return!1;let n,r,p,u=t.length,y={x:t[u-2],y:t[u-1]};2===t.length?p=[e,y]:4===t.length?(n={x:t[0],y:t[1]},p=[e,n,y]):6===t.length&&(n={x:t[0],y:t[1]},r={x:t[2],y:t[3]},p=[e,n,r,y]);if(l.length)if(1===l.length){let e=S(p,l[0]),t=e[0],a=e[1];s.push(t,a)}else{let e=l[0],t=S(p,e),a=t[0];s.push(a),p=t[1];for(let t=1;t<l.length;t++){e=l[t-1];let a=S(p,(l[t]-e)/(1-e));s.push(a[0]),t===l.length-1&&s.push(a[a.length-1]),p=a[1]}}if(a){let e,t,l=[];return s.forEach(a=>{e={type:"",values:[]},a.shift(),t=a.map(e=>Object.values(e)).flat(),e.values=t,3===a.length?e.type="C":2===a.length?e.type="Q":1===a.length&&(e.type="L"),l.push(e)}),l}return s}(e,t,y);s.push(...l),c+=l.length}else s.push({type:n,values:t})}else s.push({type:n,values:t});return{pathData:s,count:c}}function z(e,t=0,l=1){let a=[e[0]],s={x:e[0].values[0],y:e[0].values[1]},n={x:e[0].values[0],y:e[0].values[1]},r=e.length;for(let p=1;r&&p<r;p++){let r=e[p],{type:u,values:y}=r,h=y.slice(-2);if(h[0],h[1],"C"!==u&&"Q"!==u)a.push(r);else if("C"===u||"Q"===u){let e=T(s,y,t,l).pathData;a.push(...e)}s={x:h[0],y:h[1]},"z"===u.toLowerCase()?s=n:"M"===u&&(n={x:h[0],y:h[1]})}return a}function E(e,t=-1){let l=e.map(e=>e.x),a=e.map(e=>e.y),s=Math.min(...l),n=Math.max(...l),r=Math.min(...a),p=Math.max(...a),u={x:s,left:s,right:n,y:r,top:r,bottom:p,width:n-s,height:p-r};if(t>-1)for(let e in u)u[e]=+u[e].toFixed(t);return u}function q(e){let t=[];return e.forEach(e=>{let l=function(e){let t=function(e){let t=[];for(let l=0;l<e.length;l++){let a=e[l],s=l>0?e[l-1]:e[l],{type:n,values:r}=a,p={x:s.values[s.values.length-2],y:s.values[s.values.length-1]},u=r.length?{x:r[r.length-2],y:r[r.length-1]}:"",y=r.length?{x:r[0],y:r[1]}:"";switch(n){case"A":if("function"!=typeof arcToBezier){let e=b(p,u)/2,l=A(p,u,.5),a=P(l.x,l.y,e,e,0),s=P(l.x,l.y,e,e,Math.PI);t.push(a,s,u);break}arcToBezier(p,r).forEach(e=>{let l=e.values,a={x:l[0],y:l[1]},s={x:l[2],y:l[3]},n={x:l[4],y:l[5]};t.push(a,s,n)});break;case"C":let e={x:r[2],y:r[3]};t.push(y,e);break;case"Q":t.push(y)}"z"!==n.toLowerCase()&&t.push(u)}return t}(e),l=E(t);return l}(e);t.push(l)}),t}function F(e,t){let[l,a,s,n,r,p]=[e.x,e.y,e.width,e.height,e.x+e.width,e.y+e.height],[u,y,h,i,o,c]=[t.x,t.y,t.width,t.height,t.x+t.width,t.y+t.height],x=!1;return s*n!=h*i&&s*n>h*i&&l<u&&r>o&&a<y&&p>c&&(x=!0),x}function D(t,l=9){let a=0,n=[],p=Q(t),u=p.length>1,y=[];if(u){let e=q(p);e.forEach(function(t,l){for(let l=0;l<e.length;l++){let a=e[l];if(t!=a){F(t,a)&&y.push(l)}}})}return p.forEach((t,l)=>{n=[];let p=0,u=0,h=1,i=[];t.forEach(function(l,a){let[u,y]=[l.type,l.values],h=y.length;if(y.length){let o=(a>0?t[a-1]:t[0]).values,c=o.length,x={x:o[c-2],y:o[c-1]},v={x:y[h-2],y:y[h-1]};if("C"===u||"Q"===u){let e={x:y[0],y:y[1]};i="C"===u?[x,e,{x:y[2],y:y[3]},v]:[x,e,v];let t=Math.abs(function(e,t=!1){let l,[a,s,n,r]=[e[0],e[1],e[2],e[e.length-1]];if(e.length<3)return 0;3===e.length&&(s={x:1*e[0].x/3+2*e[1].x/3,y:1*e[0].y/3+2*e[1].y/3},n={x:1*e[2].x/3+2*e[1].x/3,y:1*e[2].y/3+2*e[1].y/3});return l=3*(a.x*(-2*s.y-n.y+3*r.y)+s.x*(2*a.y-n.y-r.y)+n.x*(a.y+s.y-2*r.y)+r.x*(-3*a.y+s.y+2*n.y))/20,t?Math.abs(l):l}(i));p+=t,n.push(x,v)}else if("A"===u){let t=function(t,l,a,n,p,u,y,h,i){const o=(e,t,l,a)=>s(a-t,l-e);let c={cx:0,cy:0,rx:a=e(a),ry:n=e(n),startAngle:0,endAngle:0,deltaAngle:0,clockwise:y,xAxisRotation:p,largeArc:u,sweep:y};if(0==a||0==n)throw Error("rx and ry can not be 0");if(a===n){let e=Math.abs(h-t),a=Math.abs(i-l),s=e,n=Math.min(t,h),r=Math.min(l,i),p=.5*Math.PI;if(0===e&&a||0===a&&e)return s=0===e&&a?a/2:e/2,c.rx=s,c.ry=s,0===e&&a?(c.cx=t,c.cy=r+a/2,c.startAngle=l>i?p:-p,c.endAngle=l>i?-p:p,c.deltaAngle=y?Math.PI:-Math.PI):0===a&&e&&(c.cx=n+e/2,c.cy=l,c.startAngle=t>h?Math.PI:0,c.endAngle=t>h?-Math.PI:Math.PI,c.deltaAngle=y?Math.PI:-Math.PI),c}let x,v,M=a===n?0:p*d/180,m=M?f(M):0,b=M?r(M):1,C=(t-h)/2,A=(l-i)/2,w=(t+h)/2,P=(l+i)/2,L=M?b*C+m*A:C,I=M?b*A-m*C:A,$=L*L/(a*a)+I*I/(n*n);$>1&&(a*=g($),n*=g($),c.rx=a,c.ry=n);let k=a*n,Q=a*I,S=n*L,T=Q**2+S**2;if(!T)throw Error("start point can not be same as end point");let z=g(e((k*k-T)/T));u==y&&(z=-z);let E=z*Q/n,q=-z*S/a;x=M?b*E-m*q+w:w+E,v=M?m*E+b*q+P:P+q,c.cy=v,c.cx=x;let F=o(x,v,t,l),D=o(x,v,h,i);!y&&D>F&&(D-=2*Math.PI),y&&F>D&&(D=D<=0?D+2*Math.PI:D);let Z=D-F;return c.startAngle=F,c.endAngle=D,c.deltaAngle=Z,c}(x.x,x.y,l.values[0],l.values[1],l.values[2],l.values[3],l.values[4],v.x,v.y),{cx:a,cy:u,rx:y,ry:h,startAngle:i,endAngle:o,deltaAngle:c}=t,M=Math.abs(function(e,t,l,a){const s=Math.PI*e*t;let n=(a-l+2*Math.PI)%(2*Math.PI);if(e===t)return s*(n/(2*Math.PI));const r=l=>Math.atan2(e*Math.sin(l),t*Math.cos(l));return l=r(l),a=r(a),n=(a-l+2*Math.PI)%(2*Math.PI),s*(n/(2*Math.PI))}(y,h,i,o));M-=Math.abs(Z([x,{x:a,y:u},v])),n.push(x,v),p+=M}else n.push(x,v)}});let o=Z(n);-1!==y.indexOf(l)&&(h=-1),u=o<0&&p<0?(Math.abs(p)-Math.abs(o))*h:(Math.abs(p)+Math.abs(o))*h,a+=u}),a}function Z(e,t=!1){let l=0;for(let t=0,a=e.length;a&&t<a;t++){l+=e[t].x*e[t===e.length-1?0:t+1].y*.5-e[t===e.length-1?0:t+1].x*e[t].y*.5}return t&&(l=Math.abs(l)),l}function j(e,t=0){let l=(t=parseFloat(t))>1,a=!l&&!t;"l"===e[1].type&&a&&(e[0].type="m");let s="",n=l?"\n":" ";s=a?`${e[0].type} ${e[0].values.join(" ")}`:`${e[0].type} ${e[0].values.join(" ")}${n}`;for(let t=1,l=e.length;t<l;t++){let l=e[t-1],r=e[t],{type:p,values:u}=r;if(!a||"A"!==p&&"a"!==p||(u=[u[0],u[1],u[2],`${u[3]}${u[4]}${u[5]}`,u[6]]),p=l.type===r.type&&"m"!==r.type.toLowerCase()&&a||("m"===l.type&&"l"===r.type||"M"===l.type&&"l"===r.type||"M"===l.type&&"L"===r.type)&&a?" ":r.type,a){let e="",t=!1;for(let l=0,a=u.length;l<a;l++){let a=u[l],s=a.toString(),n=s.includes(".")&&Math.abs(a)<1;n&&t&&(s=s.replace(/^0\./,".")),!(l>0)||t&&n||(e+=" "),e+=s,t=n}s+=`${p}${e}`}else s+=`${p} ${u.join(" ")}${n}`}return a&&(s=s.replace(/ 0\./g," .").replace(/ -/g,"-").replace(/-0\./g,"-.").replace(/Z/g,"z")),s}function O(e,t,l=!1,a=1){let s=[e,t],n=function(e,t){let l=m(e.p0,e.cp1,t.cp2,t.p,!1),a=m(l,t.p,t.p0,t.cp1,!1),s=b(l,t.p),n=b(a,t.p),r=1-n/s,p=b(e.cp2,e.p),u=b(e.cp2,t.cp1);return r=Math.min(p)/u,r}(e,t),r=k(e.p0,e.p),p=k(t.p0,t.p),u=.05*Math.min(r,p)*a,y=function(e,t,l=0,a=0){let{p0:s,cp1:n}=e,{p:r,cp2:p}=t,u={x:(n.x-(1-l)*s.x)/l,y:(n.y-(1-l)*s.y)/l},y={x:(p.x-a*r.x)/(1-a),y:(p.y-a*r.y)/(1-a)},h={p0:s,cp1:u,cp2:y,p:r};return h}(e,t,n,n),h=w([y.p0,y.cp1,y.cp2,y.p],n),i=k(e.p,h),o=0,c=0,x=!1,f=i;if(i<u){let l=.5*(1+n);if(o=k(w([t.p0,t.cp1,t.cp2,t.p],.5),w([y.p0,y.cp1,y.cp2,y.p],l)),f+=o,o<u){let t=.5*n;c=k(w([e.p0,e.cp1,e.cp2,e.p],.5),w([y.p0,y.cp1,y.cp2,y.p],t)),o+c<u&&(x=!0),f+=c}}if(l&&!x){let l=function(e,t,l=0,a=1){const s=(e,t,l,a,s)=>{let n=1-s;return{x:3*n*n*(t.x-e.x)+6*n*s*(l.x-t.x)+3*s*s*(a.x-l.x),y:3*n*n*(t.y-e.y)+6*n*s*(l.y-t.y)+3*s*s*(a.y-l.y)}};let n=[e,t],r=C(e.p0,e.p)>C(t.p0,t.p),p=JSON.parse(JSON.stringify(e)),u=JSON.parse(JSON.stringify(t)),y=m(p.p0,p.cp1,u.p,u.cp2,!1);if(!y)return n;if(r){let l={p0:{x:e.p.x,y:e.p.y},cp1:{x:e.cp2.x,y:e.cp2.y},cp2:{x:e.cp1.x,y:e.cp1.y},p:{x:e.p0.x,y:e.p0.y}};e={p0:{x:t.p.x,y:t.p.y},cp1:{x:t.cp2.x,y:t.cp2.y},cp2:{x:t.cp1.x,y:t.cp1.y},p:{x:t.p0.x,y:t.p0.y}},t=l}let h=(e,t)=>({x:e.x-t.x,y:e.y-t.y}),i=(e,t)=>({x:e.x*t,y:e.y*t}),o=(e,t)=>e.x*t.x+e.y*t.y,c=t.p0,x=s(t.p0,t.cp1,t.cp2,t.p,0),f=o(h(e.p0,c),x)/o(x,x),g=w([t.p0,t.cp1,t.cp2,t.p],f),v=s(t.p0,t.cp1,t.cp2,t.p,f);f-=o(h(g,e.p0),v)/o(v,v);let d=w([t.p0,t.cp1,t.cp2,t.p],f),M=t.p,b=s(t.p0,t.cp1,t.cp2,t.p,f),P=s(t.p0,t.cp1,t.cp2,t.p,1),L=1-f,I=($=d,Q=i(b,L/3),{x:$.x+Q.x,y:$.y+Q.y});var $,Q;let S=h(M,i(P,L/3)),T={p0:d,cp1:I,cp2:S,p:M};r&&(T={p0:M,cp1:S,cp2:I,p:d});let z=w([T.p0,T.cp1,T.cp2,T.p],.5,!1,!0),E=z.cpts[2],q=m(z,E,T.p0,y,!1),F=m(z,E,T.p,y,!1),Z=A(T.p0,q,1.333),O=A(T.p,F,1.333);if(m(p.p0,Z,u.p,O,!0))return n;T.cp1=Z,T.cp2=O;let R=k(p.p0,T.p0)+k(u.p,T.p);if(T.p0=p.p0,T.p=u.p,T.extreme=u.extreme,T.corner=u.corner,T.dimA=u.dimA,T.directionChange=u.directionChange,T.values=[T.cp1.x,T.cp1.y,T.cp2.x,T.cp2.y,T.p.x,T.p.y],R<l){let e=D([{type:"M",values:[p.p0.x,p.p0.y]},{type:"C",values:[p.cp1.x,p.cp1.y,p.cp2.x,p.cp2.y,p.p.x,p.p.y]},{type:"C",values:[u.cp1.x,u.cp1.y,u.cp2.x,u.cp2.y,u.p.x,u.p.y]}]),t=[{type:"M",values:[T.p0.x,T.p0.y]},{type:"C",values:[T.cp1.x,T.cp1.y,T.cp2.x,T.cp2.y,T.p.x,T.p.y]}],l=D(t),s=Math.abs(l/e-1);T.error=10*s*a,j(t),s<.01&&(n=[T])}return n}(e,t,u,a);1===l.length&&(x=!0,y=l[0],f=y.error)}return x&&(y.p0=e.p0,y.p=t.p,y.dimA=k(y.p0,y.p),y.type="C",y.extreme=t.extreme,y.directionChange=t.directionChange,y.corner=t.corner,y.values=[y.cp1.x,y.cp1.y,y.cp2.x,y.cp2.y,y.p.x,y.p.y],y.error=f/u,s=[y]),s}function R(e=[]){let t,l=[],a=function(e){let t=[],l={x:e[0].values[0],y:e[0].values[1]};return e.forEach(e=>{let{type:a,values:s}=e;if(s.length){let e=s.length>1?{x:s[s.length-2],y:s[s.length-1]}:"V"===a?{x:l.x,y:s[0]}:{x:s[0],y:l.y};t.push(e),l=e}}),t}(e),s=E(a),{left:n,right:r,top:p,bottom:u,width:y,height:h}=s,i=e[0].values[0],o=e[0].values[1],c={x:e[0].values[0],y:e[0].values[1]},x={x:e[0].values[0],y:e[0].values[1]};e[0].idx=0,e[0].p0=c,e[0].p=c,e[0].lineto=!1,e[0].corner=!1,e[0].extreme=!1,e[0].directionChange=!1,e[0].closePath=!1,e[0].dimA=0;let f=[e[0]],g=0,v=e.length;for(let l=2;v&&l<=v;l++){let a=e[l-1],{type:s,values:y}=a,h=y.slice(-2),v=[x],d=!1;a.idx=l-1,a.lineto=!1,a.corner=!1,a.extreme=!1,a.directionChange=!1,a.closePath=!1,a.dimA=0;let m,b,A,w,P,I,Q,S=.05;t=h.length?{x:h[0],y:h[1]}:c,"M"===s?(c=t,x=t):"z"===s.toLowerCase()&&(t=c),a.p0=x,a.p=t;let T=k(x,t);if(a.dimA=T,"L"===s&&(a.lineto=!0),"Z"===s&&(a.closePath=!0,c.x!==i&&c.y!==o&&(a.lineto=!0)),"Q"!==s&&"C"!==s||(m={x:y[0],y:y[1]},b="C"===s?{x:y[2],y:y[3]}:null,a.cp1=m,b&&(a.cp2=b)),y.length>2){"Q"!==s&&"C"!==s||v.push(m),"C"===s&&v.push(b),v.push(t),d=$(v).flat,a.flat=d,d&&(a.extreme=!1)}d||"L"===s||t.x!==n&&t.y!==p&&t.x!==r&&t.y!==u||(a.extreme=!0);let z=e[l]?e[l]:null,E=z?z.values.slice(-2):null;I=z?z.type:null,!z||"Q"!==z.type&&"C"!==z.type||(P=z?{x:E[0],y:E[1]}:null,A={x:z.values[0],y:z.values[1]},w="C"===z.type?{x:z.values[2],y:z.values[3]}:null),Q=Z(v);let q=g<0&&Q>0||g>0&&Q<0;if(g=Q,q&&(a.directionChange=!0),("Q"===s||"C"===s)&&("Q"===s&&"Q"===I||"C"===s&&"C"===I)){let e=v.slice(1),l=$("C"===s?[t,A,w,P]:[t,A,P],((P?Math.abs(P.x-x.x):0)+(P?Math.abs(P.y-x.y):0))/2*.1).flat;if((!d||!l)&&(!!a.extreme||L(0,e,S)))a.extreme=!0;else{let e=b?[b,t]:[m,t],l=[t,A],s=M(...e,!0),n=M(...l,!0),r=180*Math.abs(s-n)/Math.PI,p=C(...e),u=C(...l);r>10&&p&&u&&(a.corner=!0)}}f.push(a),x=t}return l={pathData:f,bb:s,dimA:(y+h)/2},l}function J(e,t=-1){let l=!("auto"!=t||!e[0].hasOwnProperty("decimals"));for(let a=0,s=e.length;a<s;a++){let s=e[a];(t>-1||l)&&(t=l?s.decimals:t,e[a].values=s.values.map(e=>e?+e.toFixed(t):e))}return e}function N(e={},t={},l={},a={}){let s=A(e,t,1.5),n=A(a,l,1.5),r=.01*k(e,a),p=k(s,n),u=null,y="C",h=[t.x,t.y,l.x,l.y,a.x,a.y];return p<r&&(u=m(e,t,a,l,!1),u&&(y="Q",h=[u.x,u.y,a.x,a.y])),{type:y,values:h}}function B(e,{toShorthands:t=!0,toRelative:l=!0,decimals:a=3}={}){return t&&(e=function(e,t=-1,l=!0){let a;if(l){let t=e.map(e=>e.type).join("");a=/[astvqmhlc]/g.test(t)}e=l&&a?U(e,t):e;let s={type:"M",values:e[0].values};e[0].decimals&&(s.decimals=e[0].decimals);let n,r=[s],p={x:e[0].values[0],y:e[0].values[1]},u=.01;for(let l=1,a=e.length;l<a;l++){let a=e[l],{type:y,values:h}=a,i=h.slice(-2),o=e[l-1],c=o.type;n={x:i[0],y:i[1]};let x,f,g,v,d={x:h[0],y:h[1]},M=Math.abs(n.x-p.x),m=Math.abs(n.y-p.y),b=(M+m)/2*u;switch(y){case"L":s=0===m||m<b&&M>b?{type:"H",values:[h[0]]}:0===M||m>b&&M<b?{type:"V",values:[h[1]]}:a;break;case"Q":if("Q"!==c){p={x:i[0],y:i[1]},r.push(a);continue}let e={x:o.values[0],y:o.values[1]};v={x:2*p.x-e.x,y:2*p.y-e.y},x=Math.abs(d.x-v.x),f=Math.abs(d.y-v.y),g=(x+f)/2,s=g<b?{type:"T",values:[n.x,n.y]}:a;break;case"C":let t={x:h[2],y:h[3]};if("C"!==c){r.push(a),p={x:i[0],y:i[1]};continue}let l={x:o.values[2],y:o.values[3]};v={x:2*p.x-l.x,y:2*p.y-l.y},x=Math.abs(d.x-v.x),f=Math.abs(d.y-v.y),g=(x+f)/2,s=g<b?{type:"S",values:[t.x,t.y,n.x,n.y]}:a;break;default:s={type:y,values:h}}(a.decimals||0===a.decimals)&&(s.decimals=a.decimals),t>-1&&(s.values=s.values.map(e=>+e.toFixed(t))),p={x:i[0],y:i[1]},r.push(s)}return r}(e)),e=J(e,a),l&&(e=function(e,t=-1){return V(e,!0,t)}(e)),a>-1&&(e=J(e,a)),e}function H(e,t){Array.isArray(e)&&(e={x:e[0],y:e[1]});let l={x:e.x+2/3*(t[0]-e.x),y:e.y+2/3*(t[1]-e.y)},a={x:t[2]+2/3*(t[0]-t[2]),y:t[3]+2/3*(t[1]-t[3])};return{type:"C",values:[l.x,l.y,a.x,a.y,t[2],t[3]]}}function V(e,t=!1,l=-1){l>=0&&(e[0].values=e[0].values.map(e=>+e.toFixed(l)));let a=e[0].values,s=a[0],n=a[1],r=s,p=n;for(let a=1,u=e.length;a<u;a++){let u=e[a],{type:y,values:h}=u,i=t?y.toLowerCase():y.toUpperCase();if(y!==i)switch(y=i,u.type=y,y){case"a":case"A":h[5]=t?h[5]-s:h[5]+s,h[6]=t?h[6]-n:h[6]+n;break;case"v":case"V":h[0]=t?h[0]-n:h[0]+n;break;case"h":case"H":h[0]=t?h[0]-s:h[0]+s;break;case"m":case"M":t?(h[0]-=s,h[1]-=n):(h[0]+=s,h[1]+=n),r=t?h[0]+s:h[0],p=t?h[1]+n:h[1];break;default:if(h.length)for(let e=0;e<h.length;e++)h[e]=t?h[e]-(e%2?n:s):h[e]+(e%2?n:s)}let o=h.length;switch(y){case"z":case"Z":s=r,n=p;break;case"h":case"H":s=t?s+h[0]:h[0];break;case"v":case"V":n=t?n+h[0]:h[0];break;case"m":case"M":r=h[o-2]+(t?s:0),p=h[o-1]+(t?n:0);default:s=h[o-2]+(t?s:0),n=h[o-1]+(t?n:0)}l>=0&&(u.values=u.values.map(e=>+e.toFixed(l)))}return e}function U(e,t=-1){return V(e,!1,t)}function G(e,t,l=1){const a=2*Math.PI;let[s,n,r,p,u,y,h]=t;if(0===s||0===n)return[];let i=r?r*a/360:0,o=i?Math.sin(i):0,c=i?Math.cos(i):1,x=c*(e.x-y)/2+o*(e.y-h)/2,f=-o*(e.x-y)/2+c*(e.y-h)/2;if(0===x&&0===f)return[];s=Math.abs(s),n=Math.abs(n);let g=x*x/(s*s)+f*f/(n*n);if(g>1){let e=Math.sqrt(g);s*=e,n*=e}let v=s*s,d=s===n?v:n*n,M=x*x,m=f*f,b=v*d-v*m-d*M;b<=0?b=0:(b/=v*m+d*M,b=Math.sqrt(b)*(p===u?-1:1));let C=b?b*s/n*f:0,A=b?b*-n/s*x:0,w=c*C-o*A+(e.x+y)/2,P=o*C+c*A+(e.y+h)/2,L=(x-C)/s,I=(f-A)/n,$=(-x-C)/s,k=(-f-A)/n;const Q=(e,t,l,a)=>{let s=+(e*l+t*a).toFixed(9);return 1===s||-1===s?1===s?0:Math.PI:(s=s>1?1:s<-1?-1:s,(e*a-t*l<0?-1:1)*Math.acos(s))};let S=Q(1,0,L,I),T=Q(L,I,$,k);0===u&&T>0?T-=2*Math.PI:1===u&&T<0&&(T+=2*Math.PI);let z=(+(Math.abs(T)/(a/4)).toFixed(0)||1)*l;T/=z;let E=[];const q=1.5707963267948966,F=.551785;let D=T===q?F:T===-q?-F:4/3*Math.tan(T/4),Z=T?Math.cos(T):1,j=T?Math.sin(T):0;const O=(e,t,l,a,s)=>{let n=e!=t?Math.cos(e):a,r=e!=t?Math.sin(e):s,p=Math.cos(e+t),u=Math.sin(e+t);return[{x:n-r*l,y:r+n*l},{x:p+u*l,y:u-p*l},{x:p,y:u}]};for(let e=0;e<z;e++){let e={type:"C",values:[]};O(S,T,D,Z,j).forEach(t=>{let l=t.x*s,a=t.y*n;e.values.push(c*l-o*a+w,o*l+c*a+P)}),E.push(e),S+=T}return E}function K(e,t,l,a,s=7.5){let n={type:"C",values:[t.x,t.y,l.x,l.y,a.x,a.y]},r=0,p=!1,u=M(e,t,!0),y=M(a,l,!0),h=180*Math.abs(u-y)/Math.PI;if(Math.abs(h%180-90)<3){let u=m(e,t,a,l,!1);if(u){let y=b(e,u),h=b(a,u),i=+Math.max(y,h).toFixed(8),o=+Math.min(y,h).toFixed(8),c=o,x=i,f=Z([e,t,l,a])<0?0:1,g=Math.abs(a.x-e.x)>Math.abs(a.y-e.y);100/c*Math.abs(c-x)<5&&(c=i,x=c),g&&(c=i,x=o);let v=D([{type:"M",values:[e.x,e.y]},{type:"C",values:[t.x,t.y,l.x,l.y,a.x,a.y]}]),d={type:"A",values:[c,x,0,0,f,a.x,a.y]};r=Math.PI*(c*x)/4,r-=Math.abs(Z([e,a,u])),function(e,t){let l=Math.abs(e-t);return Math.abs(100-100/e*(e+l))}(v,r)<s&&(p=!0,n=d)}}return{com:n,isArc:p,area:r}}function W(e){let t,l=[[]],a=0,s=[[]],n={x:e[0].values[0],y:e[0].values[1]};for(let r=0,p=e.length;r<p;r++){let p=e[r],{type:u,values:y}=p;if("A"===u){let u=e[r-1].values.slice(-2);n={x:u[0],y:u[1]};let[h,i,o,c,x,f,g]=y,v=100/h*Math.abs(h-i)<5;t={x:y[5],y:y[6]},p.p0=n,p.p=t,p.circular=v;let d=e[r+1];if(!l[a].length&&d&&"A"===d.type&&(l[a].push(p),s[a].push(r)),d&&"A"===d.type){let[e,p,u,y,o,c,x]=d.values,f=h!=e?100/h*Math.abs(h-e):0,g=i!=p?100/i*Math.abs(i-p):0;t={x:d.values[5],y:d.values[6]},d.p0=n,d.p=t,f<5&&g<5?(l[a].push(d),s[a].push(r+1)):(l.push([]),s.push([]),a++)}else l.push([]),s.push([]),a++}}if(!s.length)return e;l=l.filter(e=>e.length),s=s.filter(e=>e.length);for(let t=l.length-1;t>=0;t--){const a=l[t],n=s[t][0],r=a.length;let p=0,u=0;a.forEach(({values:e})=>{const[t,l]=e;p+=t,u+=l}),p/=r,u/=r;let y=100/p*Math.abs(p-u)<5;y&&(p=(p+u)/2,u=p);let h=e[n-1].values.slice(-2);if(h[0],h[1],4===r){let[t,l,s,h,i,o,c]=a[1].values,[,,,,,x,f]=a[3].values;y&&(p=1,u=1);let g={type:"A",values:[p,u,s,h,i,o,c]},v={type:"A",values:[p,u,s,h,i,x,f]};e.splice(n,r,g,v)}else if(3===r){let[t,l,s,y,h,i,o]=a[0].values,[c,x,,,,f,g]=a[2].values;y=1;let v={type:"A",values:[p,u,s,y,h,f,g]};e.splice(n,r,v)}else if(2===r){let[t,l,s,h,i,o,c]=a[0].values,[x,f,,,,g,v]=a[1].values;y&&(p=1,u=1,s=0);let{p0:d,p:M}=a[0],[m,b]=[a[1].p0,a[1].p];if(d.x!==b.x||d.y!==b.y){let t={type:"A",values:[p,u,s,h,i,g,v]};e.splice(n,r,t)}}}return e}function X(e=[],{toAbsolute:t=!0,toLonghands:l=!0,quadraticToCubic:a=!1,arcToCubic:s=!1,arcAccuracy:n=2}={},{hasRelatives:r=!0,hasShorthands:p=!0,hasQuadratics:u=!0,hasArcs:y=!0,testTypes:h=!1}={}){if(h){let t=Array.from(new Set(e.map(e=>e.type))).join("");r=/[lcqamts]/gi.test(t),u=/[qt]/gi.test(t),y=/[a]/gi.test(t),p=/[vhst]/gi.test(t),isPoly=/[mlz]/gi.test(t)}return(u&&a||y&&s)&&(l=!0,t=!0),r&&t&&(e=V(e,!1)),p&&l&&(e=function(e,t=-1,l=!0){let a=!1;if(l){let t=e.map(e=>e.type).join(""),l=/[hstv]/gi.test(t);if(a=/[astvqmhlc]/g.test(t),!l)return e}let s=[],n={type:"M",values:(e=l&&a?U(e,t):e)[0].values};s.push(n);for(let l=1,a=e.length;l<a;l++){let a,r,p,u,y,h,i,o,c=e[l],{type:x,values:f}=c,g=f.length,v=n.values,d=v.length,[M,m]=[f[g-2],f[g-1]],[b,C]=[v[d-2],v[d-1]];switch(x){case"H":n={type:"L",values:[f[0],C]};break;case"V":n={type:"L",values:[b,f[0]]};break;case"T":[a,r]=[v[0],v[1]],[b,C]=[v[d-2],v[d-1]],p=b+(b-a),u=C+(C-r),n={type:"Q",values:[p,u,M,m]};break;case"S":[a,r]=[v[0],v[1]],[b,C]=[v[d-2],v[d-1]],[i,o]=d>2&&"A"!==n.type?[v[2],v[3]]:[b,C],p=2*b-i,u=2*C-o,y=f[0],h=f[1],n={type:"C",values:[p,u,y,h,M,m]};break;default:n={type:x,values:f}}t>-1&&(n.values=n.values.map(e=>+e.toFixed(t))),s.push(n)}return s}(e,-1,!1)),y&&s&&(e=function(e,{arcAccuracy:t=1}={}){let l=[e[0]];for(let a=1,s=e.length;a<s;a++){let s=e[a],n=e[a-1].values,r=n.length,p={x:n[r-2],y:n[r-1]};"A"===s.type?G(p,s.values,t).forEach(e=>{l.push(e)}):l.push(s)}return l}(e,n)),u&&a&&(e=function(e){let t=[e[0]];for(let l=1,a=e.length;l<a;l++){let a=e[l],s=e[l-1].values,n=s.length,r={x:s[n-2],y:s[n-1]};"Q"===a.type?t.push(H(r,a.values)):t.push(a)}return t}(e)),e}function Y(e,{toAbsolute:t=!0,toLonghands:l=!0,quadraticToCubic:a=!1,arcToCubic:s=!1,arcAccuracy:n=4}={}){let r=function(e,t=!0){if(e=e.trim(),""===e)return{pathData:[],hasRelatives:!1,hasShorthands:!1,hasQuadratics:!1,hasArcs:!1};const l=new Set([5760,6158,8192,8193,8194,8195,8196,8197,8198,8199,8200,8201,8202,8239,8287,12288,65279]),a=e=>32===e||44===e||10===e||13===e||8232===e||8233===e||9===e||11===e||12===e||160===e||e>=5760&&l.has(e);let s,n=0,r=e.length,p="",u=[],y=-1,h="",i=!1,o=0,c=0,x=0,f=!1,g=new Set([]),v=[];const d=()=>{f&&("M"===p?p="L":"m"===p&&(p="l"),u.push({type:p,values:[]}),y++,c=0,f=!1)},M=(e=!1)=>{(e?o>0:""!==h)&&(t&&-1===y&&(s="Pathdata must start with M command",v.push(s),p="M",u.push({type:p,values:[]}),x=2,c=0,y++),"A"===p||"a"===p?(h=m(),u[y].values.push(...h)):(t&&h[1]&&"."!==h[1]&&"0"===h[0]&&(s=`${y}. command: Leading zeros not valid: ${h}`,v.push(s)),u[y].values.push(+h)),c++,h="",o=0,f=c>=x)},m=()=>{let e=h.length,t=!1;return 3===c&&2===e||4===c&&e>1?(h=[+h[0],+h[1]],t=!0,c++):3===c&&e>=3&&(h=[+h[0],+h[1],+h.substring(2)],t=!0,c+=2),t?h:[+h]},b=()=>{if(y>0){let e=u[y].values.length;if(e&&e<x||e&&e>x||("z"===p||"Z"===p)&&e>0){s=`${y}. command of type "${p}": ${x-e} values too few - ${x} expected`,v[v.length-1]!==s&&v.push(s)}}};let C=!1,A=!1,w=!1;for(;n<r;){let l=e.charCodeAt(n),r=l>47&&l<58;if(r||(C=101===l||69===l,A=45===l||43===l,w=46===l),r||A||w||C){if(i||45!==l&&46!==l)d();else{let e=46===l;M(e),d(),e&&o++}h+=e[n],i=C,n++}else if((l<48||l>5759)&&a(l))M(),n++;else{if(l>64){if(!_.has(l)){s=`${y}. command "${e[n]}" is not a valid type`,v.push(s),n++;continue}""!==h&&(u[y].values.push(+h),c++,h=""),t&&b(),p=e[n],x=ee[l];let a="M"===p||"m"===p,r=y>0&&("z"===u[y].type||"Z"===u[y].type);g.add(p),r&&!a&&(u.push({type:"m",values:[0,0]}),y++),u.push({type:p,values:[]}),y++,o=0,c=0,f=!1,n++;continue}r||(s=`${y}. ${e[n]} is not a valid separarator or token`,v.push(s),h=""),n++}}M(),t&&b();if(t&&v.length){if(s="Invalid path data:\n"+v.join("\n"),"log"!==t)throw new Error(s);console.log(s)}u[0].type="M";let P=Array.from(g).join(""),L=/[lcqamts]/g.test(P),I=/[vhst]/gi.test(P),$=/[a]/gi.test(P),k=/[qt]/gi.test(P);return{pathData:u,hasRelatives:L,hasShorthands:I,hasQuadratics:k,hasArcs:$}}(e),{hasRelatives:p,hasShorthands:u,hasQuadratics:y,hasArcs:h}=r,i=r.pathData;return i=X(i,{toAbsolute:t,toLonghands:l,quadraticToCubic:a,arcToCubic:s,arcAccuracy:n},{hasRelatives:p,hasShorthands:u,hasQuadratics:y,hasArcs:h}),i}const _=new Set([77,109,65,97,67,99,76,108,81,113,83,115,84,116,72,104,86,118,90,122]),ee=new Uint8Array(128);function te(e,t=1,l=!0){let a=[e[0]],s={x:e[0].values[0],y:e[0].values[1]},n=s,r=s;e[e.length-1].type.toLowerCase();for(let p=1,u=e.length;p<u;p++){let y=e[p-1],h=e[p],i=e[p+1]||e[u-1],o="Z"===i.type?s:{x:i.values[i.values.length-2],y:i.values[i.values.length-1]},{type:c,values:x}=h,f=x.slice(-2);r="Z"!==c?{x:f[0],y:f[1]}:s;let g="C"===c?[{x:x[0],y:x[1]},{x:x[2],y:x[3]}]:"Q"===c?[{x:x[0],y:x[1]}]:[],v=Z([n,...g,r,o],!0),d=C(n,r),M=v<d/500*t;if(l||"C"!==c||(M=!1),l&&"C"===c){Z([n,...g,r],!0)<d/1e3&&"C"!==y.type&&(h.type="L",h.values=f)}n=r,"A"!==c&&M&&p<u-1||("M"===c?(s=r,n=s):"Z"===c&&(n=s),a.push(h))}return a}function le(e){let t={x:e[0].values[0],y:e[0].values[1]},l=t,a=[e[0]];for(let s=1,n=e.length;s<n;s++){let n=e[s],{type:r,values:p}=n,u=p.slice(-2);l={x:u[0],y:u[1]},"L"===r&&l.x===t.x&&l.y===t.y||(a.push(n),t=l)}return a}function ae(e,t=!1,l=!0){let a=[],s=e.length,n=e[0].values[0],r=e[0].values[1],p="z"===e[s-1].type.toLowerCase(),u=e.filter(e=>"L"===e.type),y=e[s-2],h=y.type,i=y.values.slice(-2).map(e=>+e.toFixed(8)),o=i[0]===n&&i[1]===r,c="L"!==e[1].type&&(!o||"L"===h);if(c=!1,!p)return e;let x=0;{let t=[];for(let l=0,a=e.length;l<a;l++){let a=e[l],{type:s,values:n}=a;if(n.length){let a=n.slice(-2),r=e[l-1]&&"L"===e[l-1].type,p=e[l+1]&&"L"===e[l+1].type,u=e[l-1]?e[l-1].type.toUpperCase():null,y=e[l+1]?e[l+1].type.toUpperCase():null,h={type:s,x:a[0],y:a[1],dist:0,index:0,prevL:r,nextL:p,prevCom:u,nextCom:y};h.index=l,t.push(h)}}if(u.length){let e=t.filter(e=>"L"!==e.type&&"M"!==e.type&&e.prevCom&&"L"===e.prevCom||"M"===e.prevCom&&"L"===h).sort((e,t)=>e.y-t.y||e.x-t.x)[0];x=e?e.index-1:0}else t=t.sort((e,t)=>+e.y.toFixed(1)-+t.y.toFixed(1)||e.x-t.x),x=t[0].index;e=x?function(e,t){let l=e.length,a=0,s=e[l-1].type,n="z"===s.toLowerCase();if(!n||t<1||e.length<3)return e;let r=n?1:0;(function(e){let t=e.length,l="z"===e[t-1].type.toLowerCase(),a=e[0],[s,n]=[a.values[0],a.values[1]].map(e=>+e.toFixed(8)),r=l?e[t-2]:e[t-1],p=r.values.length,[u,y]=[r.values[p-2],r.values[p-1]].map(e=>+e.toFixed(8));!l||s==u&&n==y||(e.pop(),e.push({type:"L",values:[s,n]},{type:"Z",values:[]}))})(e),a=t+1<e.length-1?t+1:e.length-1-r;let p=e.slice(a),u=e.slice(0,a);u.shift();let y,h,i=u.length;y=u[i-1].values||[],h=[y[y.length-2],y[y.length-1]],r&&(p.pop(),u.push({type:"Z",values:[]}));return e=[{type:"M",values:h},...p,...u],e}(e,x):e}return s=e.length,y=e[s-2],h=y.type,i=y.values.slice(-2),o="L"===h&&i[0]===n&&i[1]===r,t&&o&&e.splice(s-2,1),a.push(...e),a}function se(e,{arcToCubic:t=!1,quadraticToCubic:l=!1,toClockwise:a=!1,returnD:s=!1}={}){const n=(e,t)=>{let l=[],a=[];if("A"!==e){for(let e=0;e<t.length;e+=2)l.push([t[e],t[e+1]]);a=l.pop(),l.reverse()}else{let e=0==t[4]?1:0;l=[t[0],t[1],t[2],t[3],e],a=[t[5],t[6]]}return{controlPoints:l,endPoints:a}};let r=[],p="z"===e[e.length-1].type.toLowerCase();p&&(e=(e=>{let t="z"===e[e.length-1].type.toLowerCase(),l=e[0],[a,s]=[l.values[0],l.values[1]],n=t?e[e.length-2]:e[e.length-1],[r,p]=[n.values[n.values.length-2],n.values[n.values.length-1]];return!t||a==r&&s==p||(e.pop(),e.push({type:"L",values:[a,s]},{type:"Z",values:[]})),e})(e),e.pop());let u=e[e.length-1].values,y=u.length,h=p?e[0]:{type:"M",values:[u[y-2],u[y-1]]};r.push(h),e.reverse();for(let t=1;t<e.length;t++){let l=e[t],a=l.type,s=l.values,p=e[t-1],u=p.type,y=[];y=[n(u,p.values).controlPoints,n(a,s).endPoints].flat(),r.push({type:u,values:y.flat()})}return p&&r.push({type:"z",values:[]}),r}function ne(e="",{toAbsolute:t=!0,toRelative:l=!0,toShorthands:a=!0,decimals:s=3,quadraticToCubic:n=!0,arcToCubic:r=!1,cubicToArc:p=!1,arcAccuracy:u=4,keepExtremes:y=!0,keepCorners:h=!0,keepInflections:i=!0,extrapolateDominant:o=!1,addExtremes:c=!1,optimizeOrder:x=!0,removeColinear:f=!0,simplifyBezier:g=!0,autoAccuracy:v=!0,flatBezierToLinetos:d=!0,revertToQuadratics:M=!0,minifyD:m=0,tolerance:b=1,reverse:C=!1}={}){let A=Y(e,{quadraticToCubic:n,toAbsolute:t,arcToCubic:r}),w=JSON.parse(JSON.stringify(A)),P=A.length,L=Q(w),I=[];for(let e=0,t=L.length;e<t;e++){let t=L[e];C&&(t=se(t)),f&&(t=le(t)),c&&(t=z(t,0,1)),x&&(t=ae(t)),f&&(t=te(t,b,d));let l=R(t),{pathData:a,bb:s,dimA:n}=l,r=a;if(r=g?re(r,{simplifyBezier:g,keepInflections:i,keepExtremes:y,keepCorners:h,extrapolateDominant:o,revertToQuadratics:M,tolerance:b,reverse:C}):r,p){let e=3;r.forEach((t,l)=>{let{type:a,values:s,p0:n,cp1:p=null,cp2:u=null,p:y=null}=t;if("C"===a){let t=K(n,p,u,y,e);t.isArc&&(r[l]=t.com)}}),r=W(r)}M&&r.forEach((e,t)=>{let{type:l,values:a,p0:s,cp1:n=null,cp2:p=null,p:u=null}=e;if("C"===l){let e=N(s,n,p,u);"Q"===e.type&&(r[t]=e)}}),I.push(r)}let $=I.flat();v&&(s=function(e){let t={x:e[0].values[0],y:e[0].values[1]},l=t,a=t;e[0].decimals=0;let s=1/0;for(let n=0,r=e.length;n<r;n++){let r=e[n],{type:p,values:u}=r,y=u.length?u.slice(-2):[t.x,t.y];a={x:y[0],y:y[1]};let h=r.dimA?+r.dimA.toFixed(8):"M"!==p?+k(l,a).toFixed(8):0;h&&h<s&&(s=h),"M"===p&&(t=a),l=a}let n=Math.floor(50/s).toString().length;return Math.min(Math.max(0,n),8)}($));let S=$.length;return w=B($,{toRelative:l,toShorthands:a,decimals:s}),{pathData:w,d:j(w,m),report:{original:P,new:S,saved:P-S,decimals:s,success:S<P}}}function re(e,{keepExtremes:t=!0,keepInflections:l=!0,keepCorners:a=!0,extrapolateDominant:s=!0,tolerance:n=1,reverse:r=!1}={}){let p=[e[0]];for(let r=2,u=e.length;u&&r<=u;r++){let y=e[r-1],h=r<u?e[r]:null,i=h?.type||null,o=y?.directionChange||null,c=h?.directionChange||null,{type:x,values:f,p0:g,p:v,cp1:d=null,cp2:M=null,extreme:m=!1,corner:b=!1,dimA:C=0}=y;if("C"===x&&"C"===i)if(l&&c||a&&b||!o&&t&&m)p.push(y);else{let i=O(y,h,s,n),o=0;if(1===i.length){y=i[0];let h=1;o+=y.error;for(let p=r+1;o<n&&p<u;p++){let r=e[p];if("C"!==r.type||l&&r.directionChange||a&&y.corner||t&&y.extreme)break;let u=O(y,r,s,n);1===u.length&&h++,y=u[0]}p.push(y),r<u&&(r+=h)}else p.push(y)}else p.push(y)}return r&&(p=se(p)),p}ee[77]=2,ee[109]=2,ee[65]=7,ee[97]=7,ee[67]=6,ee[99]=6,ee[76]=2,ee[108]=2,ee[81]=4,ee[113]=4,ee[83]=4,ee[115]=4,ee[84]=2,ee[116]=2,ee[72]=1,ee[104]=1,ee[86]=1,ee[118]=1,ee[90]=0,ee[122]=0;const{abs:pe,acos:ue,asin:ye,atan:he,atan2:ie,ceil:oe,cos:ce,exp:xe,floor:fe,log:ge,hypot:ve,max:de,min:Me,pow:me,random:be,round:Ce,sin:Ae,sqrt:we,tan:Pe,PI:Le}=Math;"undefined"!=typeof window&&(window.svgPathSimplify=ne,window.renderPoint=function(e,t,l="red",a="1%",s="1",n="",r=!0,p="",u=""){Array.isArray(t)&&(t={x:t[0],y:t[1]});let y=`<circle class="${u}" opacity="${s}" id="${p}" cx="${t.x}" cy="${t.y}" r="${a}" fill="${l}">\n <title>${n}</title></circle>`;if(!r)return y;e.insertAdjacentHTML("beforeend",y)}),exports.PI=Le,exports.abs=pe,exports.acos=ue,exports.asin=ye,exports.atan=he,exports.atan2=ie,exports.ceil=oe,exports.cos=ce,exports.exp=xe,exports.floor=fe,exports.hypot=ve,exports.log=ge,exports.max=de,exports.min=Me,exports.pow=me,exports.random=be,exports.round=Ce,exports.sin=Ae,exports.sqrt=we,exports.svgPathSimplify=ne,exports.tan=Pe;
package/index.html CHANGED
@@ -0,0 +1,222 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+
4
+ <head>
5
+ <meta charset="UTF-8">
6
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
7
+ <title>SVG path simplifier</title>
8
+
9
+
10
+ <!--
11
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/enhance-inputs@latest/dist/enhanceInputs.css">
12
+ <script src="https://cdn.jsdelivr.net/npm/enhance-inputs@latest/dist/enhanceInputs.js" defer></script>
13
+
14
+ <link rel="stylesheet" href="//localhost/___git/enhance-inputs/enhance-inputs/dist/enhanceInputs.css">
15
+ <script src="//localhost/___git/enhance-inputs/enhance-inputs/dist/enhanceInputs.js" defer></script>
16
+
17
+
18
+
19
+ -->
20
+
21
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/enhance-inputs@latest/dist/enhanceInputs.css">
22
+ <script src="https://cdn.jsdelivr.net/npm/enhance-inputs@latest/dist/enhanceInputs.js" defer></script>
23
+
24
+ <script src="demo/lib/elzoomo/elzoomo.js" defer></script>
25
+
26
+
27
+ <script src="dist/svg-path-simplify.js" defer></script>
28
+
29
+ <script src="demo/samples.js"></script>
30
+ <script src="demo/app.js" defer></script>
31
+
32
+
33
+ <link rel="stylesheet" href="demo/css/app.css">
34
+
35
+
36
+ </head>
37
+
38
+
39
+ <body class="enhance-inputs-init --scrollbar --scroll-content pdd-0 mrg-0"
40
+ data-enhance-inputs='{"storageName":"svgPathSimplify", "getQuery":true, "cacheToStorage":true,"icons":"all"}'>
41
+
42
+ <div class="grd-main hgh-100vh grd grd-md-3 grd-ld-5 gap-1em">
43
+ <div class="sidebar-wrap scrollbar scroll-content scroll-track">
44
+
45
+ <!--toolbars-->
46
+ <aside class="aside aside-1 hgh-100 aside scrollbar scroll-content-ld scroll-track pdd-1em pos-rlt">
47
+
48
+ <h1>Simplify pathdata</h1>
49
+ <p>Enter your SVG pathData</p>
50
+
51
+ <p><input type="file" class="dsp-non --btn-neg" id="inputFile" name="svgFile" value="upload"
52
+ data-label="Upload file" accept=".svg"></p>
53
+
54
+
55
+ <p class="--btn-neg" data-ui="reset"></p>
56
+
57
+ <p>
58
+ <label>
59
+ <select name="inputSamples" id="inputSamples" data-options="samples"></select>
60
+ </label>
61
+ </p>
62
+
63
+
64
+ <label>Input SVG
65
+ <textarea name="dInput" id="inputSvg" data-tools="size upload copy"></textarea>
66
+ </label>
67
+
68
+ <h3>SVG normalization</h3>
69
+ <p>
70
+ <label><input type="checkbox" name="arcToCubic" >arcToCubic</label>
71
+ <label><input type="checkbox" name="quadraticToCubic" >quadraticToCubic</label>
72
+ </p>
73
+
74
+
75
+
76
+ </aside>
77
+
78
+ <aside class="aside aside-2 pdd-1em pdd-top scrollbar scroll-content-ld scroll-track">
79
+
80
+ <h3>Simplification</h3>
81
+ <p>
82
+ <label><input type="checkbox" name="simplifyBezier" checked>simplifyBezier</label>
83
+ <label><input type="checkbox" name="removeColinear" checked>remove colinear linetos</label>
84
+
85
+ <label><input type="checkbox" name="flatBezierToLinetos" checked>flat beziers to linetos</label>
86
+
87
+
88
+ <label><input type="checkbox" name="optimizeOrder" checked>optimize path order</label>
89
+ <label><input type="checkbox" name="keepExtremes" checked>keepExtremes</label>
90
+ <label><input type="checkbox" name="keepCorners" checked>keepCorners</label>
91
+
92
+ <label><input type="checkbox" name="keepInflections"
93
+ data-info="retain inflections e.g spine of an S shape">keepInflections</label>
94
+
95
+ <label><input type="checkbox" name="extrapolateDominant"
96
+ data-info="extrapolates dominant bezier segment – rather sloppy">extrapolateDominant</label>
97
+
98
+ <label><input type="checkbox" name="revertToQuadratics"
99
+ data-info="Reverts cubic to quadratic Béziers if applicable" checked>revert
100
+ revertToQuadratics</label>
101
+
102
+ <label><input type="checkbox" name="cubicToArc"
103
+ data-info="Reverts cubic to arcs if applicable">cubicToArc</label>
104
+
105
+
106
+ <label><input type="checkbox" name="reverse">try with reversed drawing direction</label>
107
+
108
+
109
+
110
+ <label><input type="checkbox" name="multipass"
111
+ data-info="takes better simplification – slower">multipass</label>
112
+
113
+
114
+ <label><input type="checkbox" name="addExtremes">addExtremes</label>
115
+
116
+
117
+
118
+ </p>
119
+
120
+ <p>
121
+ <label>tolerance<input type="number" name="tolerance" min="0.1" max="10" step="0.1" value="1"
122
+ data-info="higher tolerance = sloppier approximations – default 1"></label>
123
+ </p>
124
+
125
+
126
+ <p id="commandInfo"></p>
127
+
128
+ <h3>SVG settings</h3>
129
+ <p>
130
+ <label><input type="checkbox" name="toRelative" checked>toRelative</label>
131
+ <label><input type="checkbox" name="toShorthands" checked>toShorthands</label>
132
+ </p>
133
+
134
+ <h3>SVG string optimization</h3>
135
+ <p><label><input type="radio" name="minifyD" value="0" checked>minify</label>
136
+ <label><input type="radio" name="minifyD" value="1">verbose</label>
137
+ <label><input type="radio" name="minifyD" value="2">beautify</label>
138
+ </p>
139
+ <p>
140
+ <label><input type="checkbox" name="autoAccuracy" checked>autoAccuracy</label>
141
+
142
+ <label class="wdt-100">decimals <input type="number" name="decimals" min="0" value="1"
143
+ data-info="reduces floating point precision: reduces filesize significantly!"></label>
144
+ </p>
145
+
146
+ <p>
147
+ <label><input type="checkbox" name="showMarkers" checked>showMarkers</label>
148
+ </p>
149
+
150
+ <p>
151
+ <label>Output SVG
152
+ <textarea name="dOutput" id="outputSvg" data-tools="size upload copy"></textarea>
153
+ </label>
154
+ </p>
155
+
156
+
157
+
158
+ </aside>
159
+ </div>
160
+
161
+ <!--main-->
162
+ <main class="main --spn-ld-2 --spn-ld-3 scrollbar scroll-content pst-rlt">
163
+
164
+ <header class="pst-sticky --pdd-1em z-ind-1000">
165
+ <label class="navToggle"><input type="checkbox" name="showNav" class="showNav"
166
+ data-icon="adjustments-vertical" data-tooltip2="show settings" title="show settings"></label>
167
+
168
+ <a class="lnk-github" href="https://github.com/herrstrietzel/svg-path-simplify"
169
+ title="See github repository">
170
+ <svg viewBox="0 0 24 24" class="icn-svg">
171
+ <use href="#github"></use>
172
+ </svg>
173
+ </a>
174
+ </header>
175
+
176
+ <!--preview-->
177
+ <div id="previewWrp" class="preview --pdd-1em pst-rlt">
178
+
179
+ <div class="wrp-zoom"
180
+ data-zoom='{"minScale":0.1,"maxScale":10,"zoom":1,"zoomStep":1.001, "toolbar":true}'>
181
+
182
+ <svg id="svg" viewBox="0 0 100 100">
183
+
184
+ <path id="path1" class="path pathO" d="M54,40.938C68.946,36.071,72.99,30.492,72.992,27
185
+ c0.004-5.928-11.632-5.845-1.367,13.938" />
186
+ <path id="pathS" class="path pathS" d="" />
187
+
188
+ <g id="markers"></g>
189
+ </svg>
190
+
191
+ </div>
192
+
193
+ </div>
194
+
195
+
196
+
197
+ </main>
198
+
199
+
200
+
201
+ </div>
202
+
203
+
204
+ <!-- markers to show commands -->
205
+ <svg id="svgMarkers" class="sr-only" style="width:0; height:0; position:absolute; z-index:-1;float:left;">
206
+ <defs>
207
+ <marker id="markerStart" overflow="visible" viewBox="0 0 10 10" refX="5" refY="5" markerUnits="strokeWidth"
208
+ markerWidth="10" markerHeight="10" orient="auto-start-reverse">
209
+ <circle cx="5" cy="5" r="3" fill="var(--color-focus, #ccc)"></circle>
210
+
211
+ <marker id="markerRound" overflow="visible" viewBox="0 0 10 10" refX="5" refY="5"
212
+ markerUnits="strokeWidth" markerWidth="10" markerHeight="10" orient="auto-start-reverse">
213
+ <circle cx="5" cy="5" r="2" fill="var(--color-focus, #ccc)"></circle>
214
+ </marker>
215
+ </defs>
216
+ </svg>
217
+
218
+
219
+
220
+ </body>
221
+
222
+ </html>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "svg-path-simplify",
3
- "version": "0.0.1",
3
+ "version": "0.0.2",
4
4
  "main": "./dist/svg-path-simplify.node.js",
5
5
  "module": "./dist/svg-path-simplify.esm.js",
6
6
  "browser": "./dist/svg-path-simplify.js",
@@ -38,7 +38,7 @@
38
38
  "license": "MIT",
39
39
  "description": "Simplify path Bézier geometry or polyline structures",
40
40
  "dependencies": {
41
- "terser": "^5.39.0"
41
+ "terser": "^5.43.1"
42
42
  },
43
43
  "bugs": {
44
44
  "url": "https://github.com/herrstrietzel/svg-path-simplify/issues"
@@ -0,0 +1,4 @@
1
+ export const {
2
+ abs, acos, asin, atan, atan2, ceil, cos, exp, floor,
3
+ log, hypot, max, min, pow, random, round, sin, sqrt, tan, PI
4
+ } = Math;
package/src/index.js CHANGED
@@ -1,7 +1,22 @@
1
- function svgPathSimplify(){
1
+ // just for visual debugging
2
+ import { renderPoint } from './svgii/visualize';
2
3
 
4
+ import {svgPathSimplify} from './pathSimplify-main';
5
+
6
+
7
+ export {svgPathSimplify as svgPathSimplify};
8
+
9
+ export {
10
+ abs, acos, asin, atan, atan2, ceil, cos, exp, floor, hypot,
11
+ log, max, min, pow, random, round, sin, sqrt, tan, PI
12
+ } from './constants';
13
+
14
+
15
+ // IIFE
16
+ if (typeof window !== 'undefined') {
17
+ window.svgPathSimplify = svgPathSimplify;
18
+ window.renderPoint = renderPoint;
19
+ }
3
20
 
4
21
 
5
22
 
6
-
7
- }
@@ -0,0 +1,324 @@
1
+ import { getCombinedByDominant } from "./pathData_simplify_cubic_extrapolate";
2
+ import { getDistance, getSquareDistance, checkLineIntersection, pointAtT, getDistAv, interpolate } from "./svgii/geometry";
3
+ import { getBezierArea, getPolygonArea } from "./svgii/geometry_area";
4
+ import { renderPoint } from "./svgii/visualize";
5
+
6
+
7
+
8
+ function findSplitParameter(com1, com2) {
9
+
10
+ let chordLength1 = getDistance(com1.p0, com1.p);
11
+ let totalChord = getDistance(com1.p0, com2.p);
12
+
13
+ let t = chordLength1 / totalChord;
14
+
15
+ return refineParameter(com1, com2, t);
16
+
17
+ return t
18
+ }
19
+
20
+ function refineParameter(com1, com2, tEstimate, maxIterations = 10) {
21
+ let t = tEstimate;
22
+
23
+ for (let i = 0; i < maxIterations; i++) {
24
+ // Calculate error based on Q2 and R1 relationships
25
+ const P0 = com1.p0;
26
+ const P3 = com2.p;
27
+
28
+ // Reconstruct P1 and P2 at current t
29
+ const P1 = {
30
+ x: (com1.cp1.x - (1 - t) * P0.x) / t,
31
+ y: (com1.cp1.y - (1 - t) * P0.y) / t
32
+ };
33
+
34
+ const P2 = {
35
+ x: (com2.cp2.x - t * P3.x) / (1 - t),
36
+ y: (com2.cp2.y - t * P3.y) / (1 - t)
37
+ };
38
+
39
+ // Calculate what Q2 and R1 should be
40
+ const Q1 = interpolate(P0, P1, t);
41
+ const P1P2_mid = interpolate(P1, P2, t);
42
+ const Q2_calc = interpolate(Q1, P1P2_mid, t);
43
+
44
+ const P2P3_mid = interpolate(P2, P3, t);
45
+ const R1_calc = interpolate(P1P2_mid, P2P3_mid, t);
46
+
47
+ // Calculate errors
48
+ const errorQ2 = getDistance(Q2_calc, com1.cp2);
49
+ const errorR1 = getDistance(R1_calc, com2.cp1);
50
+ const totalError = errorQ2 + errorR1;
51
+
52
+ if (totalError < 1e-9) {
53
+ break;
54
+ }
55
+
56
+ // Simple adjustment - in practice you'd use proper Newton step
57
+ t = t * 0.5 + 0.5 * (errorQ2 < errorR1 ? t + 0.01 : t - 0.01);
58
+ t = Math.max(0.001, Math.min(0.999, t));
59
+ }
60
+
61
+ return t;
62
+ }
63
+
64
+
65
+
66
+ export function combineCubicPairs(com1, com2, extrapolateDominant = false, tolerance = 1) {
67
+
68
+ let commands = [com1, com2];
69
+ let t = findSplitT(com1, com2);
70
+
71
+ //threshold = 0.01
72
+
73
+ let distAv1 = getDistAv(com1.p0, com1.p);
74
+ let distAv2 = getDistAv(com2.p0, com2.p);
75
+ let distMin = Math.min(distAv1, distAv2)
76
+ //let distMax = Math.max(distAv1, distAv2)
77
+
78
+ let distScale = 0.05
79
+ let maxDist = distMin * distScale * tolerance
80
+ //tolerance = distMax * threshold
81
+
82
+ let comS = getExtrapolatedCommand(com1, com2, t, t)
83
+
84
+ // test on path point against original
85
+ let pt = pointAtT([comS.p0, comS.cp1, comS.cp2, comS.p], t)
86
+
87
+
88
+ //let tolerance = Math.min(Math.max(com1.dimA, com2.dimA), Math.min(com1.dimA, com2.dimA)) * 0.05
89
+
90
+ let dist0 = getDistAv(com1.p, pt)
91
+ let dist1 = 0, dist2 = 0;
92
+ let close = dist0 < maxDist;
93
+ let success = false;
94
+
95
+ // collect error data
96
+ let error = dist0;
97
+
98
+
99
+
100
+ /*
101
+ if (com2.directionChange) {
102
+ //renderPoint(markers, com2.p0)
103
+ }
104
+ */
105
+
106
+ //console.log('tolerance', tolerance, close, dist0);
107
+
108
+ if (close) {
109
+
110
+ /**
111
+ * check additional points
112
+ * to prevent distortions
113
+ */
114
+
115
+ // 2nd segment mid
116
+ let pt_2 = pointAtT([com2.p0, com2.cp1, com2.cp2, com2.p], 0.5)
117
+
118
+ // simplified path
119
+ let t3 = (1 + t) * 0.5;
120
+ let ptS_2 = pointAtT([comS.p0, comS.cp1, comS.cp2, comS.p], t3)
121
+ dist1 = getDistAv(pt_2, ptS_2)
122
+
123
+ error += dist1;
124
+
125
+
126
+ // quit - paths not congruent
127
+ //if (dist2 > tolerance) return commands;
128
+
129
+
130
+ if (dist1 < maxDist) {
131
+
132
+ //renderPoint(markers, pt_2, 'magenta')
133
+ //renderPoint(markers, ptS_2, 'green', '0.5%')
134
+
135
+ // 1st segment mid
136
+ let pt_1 = pointAtT([com1.p0, com1.cp1, com1.cp2, com1.p], 0.5)
137
+
138
+ let t2 = t * 0.5;
139
+ let ptS_1 = pointAtT([comS.p0, comS.cp1, comS.cp2, comS.p], t2)
140
+ dist2 = getDistAv(pt_1, ptS_1)
141
+
142
+ /*
143
+ if(dist1>tolerance){
144
+ renderPoint(markers, pt_1, 'blue')
145
+ renderPoint(markers, ptS_1, 'orange', '0.5%')
146
+ }
147
+ */
148
+
149
+ // quit - paths not congruent
150
+ if (dist1 + dist2 < maxDist) success = true;
151
+
152
+ // collect error data
153
+ error += dist2;
154
+
155
+ //console.log('simpl1');
156
+
157
+ }
158
+
159
+ } // end 1st try
160
+
161
+
162
+
163
+ /*
164
+ if (extrapolateDominant && com2.extreme) {
165
+ renderPoint(markers, com2.p)
166
+ //renderPoint(markers, com1.p, 'cyan')
167
+ //extrapolateDominant = false;
168
+ }
169
+ */
170
+
171
+
172
+
173
+
174
+ // try extrapolated dominant curve
175
+ //&& !com2.extreme
176
+ // && !com1.extreme
177
+ if (extrapolateDominant && !success ) {
178
+
179
+ let combinedEx = getCombinedByDominant(com1, com2, maxDist, tolerance);
180
+
181
+ //console.log('???combinedEx', combinedEx);
182
+
183
+ if(combinedEx.length===1){
184
+ success = true
185
+ comS = combinedEx[0]
186
+ error = comS.error
187
+
188
+ //console.log('!!!combinedEx', combinedEx);
189
+ }
190
+
191
+
192
+ }
193
+
194
+ // add meta
195
+ if (success) {
196
+
197
+ //comS.dimA = (Math.abs(comS.p0.x - comS.p.x) + Math.abs(comS.p0.y - comS.p.y)) / 2
198
+
199
+
200
+ // correct to exact start and end points
201
+ comS.p0 = com1.p0
202
+ comS.p = com2.p
203
+
204
+ comS.dimA = getDistAv(comS.p0, comS.p);
205
+ comS.type = 'C';
206
+ comS.extreme = com2.extreme;
207
+ comS.directionChange = com2.directionChange;
208
+ comS.corner = com2.corner;
209
+
210
+ comS.values = [comS.cp1.x, comS.cp1.y, comS.cp2.x, comS.cp2.y, comS.p.x, comS.p.y]
211
+
212
+ // relative error
213
+ comS.error = error / maxDist;
214
+
215
+ //comS.p0 = com1.p0;
216
+ commands = [comS];
217
+
218
+ //console.log('commands combined', commands);
219
+
220
+ }
221
+
222
+
223
+ //renderPoint(markers, com1.p, 'green', '1%', '0.5')
224
+ //renderPoint(markers, pt, 'red', '0.75%', '0.5')
225
+
226
+ return commands;
227
+ }
228
+
229
+
230
+
231
+
232
+
233
+ export function getError(com, area = 0, threshold = 0) {
234
+ let areaN = getBezierCommandArea([com])
235
+ let areaDiff = Math.abs(area - areaN)
236
+ let error = areaDiff / threshold
237
+
238
+ return error
239
+ }
240
+
241
+
242
+ export function getExtrapolatedCommand(com1, com2, t1 = 0, t2 = 0) {
243
+
244
+ let { p0, cp1 } = com1;
245
+ let { p, cp2 } = com2;
246
+
247
+ // extrapolate control points
248
+ let cp1_S = {
249
+ x: (cp1.x - (1 - t1) * p0.x) / t1,
250
+ y: (cp1.y - (1 - t1) * p0.y) / t1
251
+ };
252
+
253
+
254
+ let cp2_S = {
255
+ x: (cp2.x - t2 * p.x) / (1 - t2),
256
+ y: (cp2.y - t2 * p.y) / (1 - t2)
257
+ };
258
+
259
+ let comS = { p0, cp1: cp1_S, cp2: cp2_S, p };
260
+ //let pt = pointAtT([p0, cp1_S, cp2_S, p], (t1 + t2) / 2);
261
+
262
+ return comS
263
+
264
+ }
265
+
266
+
267
+ export function getBezierCommandArea(commands = [com1, com2], absolute = true) {
268
+
269
+ let bezArea = 0;
270
+ let polyArea = 0;
271
+ let poly = [commands[0].p0];
272
+
273
+ commands.forEach(com => {
274
+ bezArea += getBezierArea([com.p0, com.cp1, com.cp2, com.p])
275
+ poly.push(com.p)
276
+
277
+ })
278
+ polyArea += getPolygonArea(poly)
279
+ return Math.abs(bezArea + polyArea);
280
+
281
+ }
282
+
283
+
284
+ function findSplitT(com1, com2) {
285
+
286
+ //let selfIntersecting = false
287
+
288
+ // control tangent intersection
289
+ let pt1 = checkLineIntersection(com1.p0, com1.cp1, com2.cp2, com2.p, false)
290
+
291
+ // intersection 2nd cp1 tangent and global tangent intersection
292
+ let ptI = checkLineIntersection(pt1, com2.p, com2.p0, com2.cp1, false)
293
+
294
+
295
+ let len1 = getDistance(pt1, com2.p)
296
+ let len2 = getDistance(ptI, com2.p)
297
+
298
+ //let t = !t3 ? 1-len2/len1 : (t3+len2/len1)*0.5
299
+ let t = 1 - len2 / len1
300
+
301
+
302
+ // check self intersections
303
+ //let ptI2 = checkLineIntersection(com1.cp1, com2.cp2, com1.p0, com2.p, true)
304
+ //let hasInfliction = ptI2!==null
305
+
306
+
307
+ let len3 = getDistance(com1.cp2, com1.p)
308
+ let len4 = getDistance(com1.cp2, com2.cp1)
309
+
310
+ //let t5 = 1-Math.min(len7, len8)/len9
311
+ t = Math.min(len3) / len4
312
+
313
+ //console.log('???selfIntersecting:', t, hasInfliction, ptI2)
314
+
315
+ return t
316
+
317
+
318
+ }
319
+
320
+
321
+
322
+
323
+
324
+