svg-path-properties
Advanced tools
Comparing version 0.4.2 to 0.4.3
@@ -1,2 +0,2 @@ | ||
// http://geoexamples.com/path-properties/ Version 0.4.2. Copyright 2018 Roger Veciana i Rovira. | ||
// http://geoexamples.com/path-properties/ Version 0.4.3. Copyright 2018 Roger Veciana i Rovira. | ||
(function (global, factory) { | ||
@@ -337,210 +337,26 @@ typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : | ||
//This file is taken from the following project: https://github.com/fontello/svgpath | ||
// Convert an arc to a sequence of cubic bézier curves | ||
// | ||
var TAU = Math.PI * 2; | ||
//Calculate ans Arc curve length and positionAtLength | ||
//The point in ellipse functions have been taken from https://github.com/MadLittleMods/svg-curve-lib/tree/f07d6008a673816f4cb74a3269164b430c3a95cb | ||
var Arc = function(x0, y0, rx,ry, xAxisRotate, LargeArcFlag,SweepFlag, x,y) { | ||
return new Arc$1(x0, y0, rx,ry, xAxisRotate, LargeArcFlag,SweepFlag, x,y); | ||
}; | ||
/* eslint-disable space-infix-ops */ | ||
function Arc$1(x0, y0,rx,ry, xAxisRotate, LargeArcFlag, SweepFlag,x1,y1) { | ||
this.x0 = x0; | ||
this.y0 = y0; | ||
this.rx = rx; | ||
this.ry = ry; | ||
this.xAxisRotate = xAxisRotate; | ||
this.LargeArcFlag = LargeArcFlag; | ||
this.SweepFlag = SweepFlag; | ||
this.x1 = x1; | ||
this.y1 = y1; | ||
// Calculate an angle between two unit vectors | ||
// | ||
// Since we measure angle between radii of circular arcs, | ||
// we can use simplified math (without length normalization) | ||
// | ||
function unit_vector_angle(ux, uy, vx, vy) { | ||
var sign = (ux * vy - uy * vx < 0) ? -1 : 1; | ||
var dot = ux * vx + uy * vy; | ||
// Add this to work with arbitrary vectors: | ||
// dot /= Math.sqrt(ux * ux + uy * uy) * Math.sqrt(vx * vx + vy * vy); | ||
// rounding errors, e.g. -1.0000000000000002 can screw up this | ||
if (dot > 1.0) { dot = 1.0; } | ||
if (dot < -1.0) { dot = -1.0; } | ||
return sign * Math.acos(dot); | ||
} | ||
// Convert from endpoint to center parameterization, | ||
// see http://www.w3.org/TR/SVG11/implnote.html#ArcImplementationNotes | ||
// | ||
// Return [cx, cy, theta1, delta_theta] | ||
// | ||
function get_arc_center(x1, y1, x2, y2, fa, fs, rx, ry, sin_phi, cos_phi) { | ||
// Step 1. | ||
// | ||
// Moving an ellipse so origin will be the middlepoint between our two | ||
// points. After that, rotate it to line up ellipse axes with coordinate | ||
// axes. | ||
// | ||
var x1p = cos_phi*(x1-x2)/2 + sin_phi*(y1-y2)/2; | ||
var y1p = -sin_phi*(x1-x2)/2 + cos_phi*(y1-y2)/2; | ||
var rx_sq = rx * rx; | ||
var ry_sq = ry * ry; | ||
var x1p_sq = x1p * x1p; | ||
var y1p_sq = y1p * y1p; | ||
// Step 2. | ||
// | ||
// Compute coordinates of the centre of this ellipse (cx', cy') | ||
// in the new coordinate system. | ||
// | ||
var radicant = (rx_sq * ry_sq) - (rx_sq * y1p_sq) - (ry_sq * x1p_sq); | ||
if (radicant < 0) { | ||
// due to rounding errors it might be e.g. -1.3877787807814457e-17 | ||
radicant = 0; | ||
} | ||
radicant /= (rx_sq * y1p_sq) + (ry_sq * x1p_sq); | ||
radicant = Math.sqrt(radicant) * (fa === fs ? -1 : 1); | ||
var cxp = radicant * rx/ry * y1p; | ||
var cyp = radicant * -ry/rx * x1p; | ||
// Step 3. | ||
// | ||
// Transform back to get centre coordinates (cx, cy) in the original | ||
// coordinate system. | ||
// | ||
var cx = cos_phi*cxp - sin_phi*cyp + (x1+x2)/2; | ||
var cy = sin_phi*cxp + cos_phi*cyp + (y1+y2)/2; | ||
// Step 4. | ||
// | ||
// Compute angles (theta1, delta_theta). | ||
// | ||
var v1x = (x1p - cxp) / rx; | ||
var v1y = (y1p - cyp) / ry; | ||
var v2x = (-x1p - cxp) / rx; | ||
var v2y = (-y1p - cyp) / ry; | ||
var theta1 = unit_vector_angle(1, 0, v1x, v1y); | ||
var delta_theta = unit_vector_angle(v1x, v1y, v2x, v2y); | ||
if (fs === 0 && delta_theta > 0) { | ||
delta_theta -= TAU; | ||
} | ||
if (fs === 1 && delta_theta < 0) { | ||
delta_theta += TAU; | ||
} | ||
return [ cx, cy, theta1, delta_theta ]; | ||
} | ||
// | ||
// Approximate one unit arc segment with bézier curves, | ||
// see http://math.stackexchange.com/questions/873224 | ||
// | ||
function approximate_unit_arc(theta1, delta_theta) { | ||
var alpha = 4/3 * Math.tan(delta_theta/4); | ||
var x1 = Math.cos(theta1); | ||
var y1 = Math.sin(theta1); | ||
var x2 = Math.cos(theta1 + delta_theta); | ||
var y2 = Math.sin(theta1 + delta_theta); | ||
return [ x1, y1, x1 - y1*alpha, y1 + x1*alpha, x2 + y2*alpha, y2 - x2*alpha, x2, y2 ]; | ||
} | ||
var a2c = function(x1, y1, rx, ry, phi, fa, fs, x2, y2) { | ||
var sin_phi = Math.sin(phi * TAU / 360); | ||
var cos_phi = Math.cos(phi * TAU / 360); | ||
// Make sure radii are valid | ||
// | ||
var x1p = cos_phi*(x1-x2)/2 + sin_phi*(y1-y2)/2; | ||
var y1p = -sin_phi*(x1-x2)/2 + cos_phi*(y1-y2)/2; | ||
if (x1p === 0 && y1p === 0) { | ||
// we're asked to draw line to itself | ||
return []; | ||
} | ||
if (rx === 0 || ry === 0) { | ||
// one of the radii is zero | ||
return []; | ||
} | ||
// Compensate out-of-range radii | ||
// | ||
rx = Math.abs(rx); | ||
ry = Math.abs(ry); | ||
var lambda = (x1p * x1p) / (rx * rx) + (y1p * y1p) / (ry * ry); | ||
if (lambda > 1) { | ||
rx *= Math.sqrt(lambda); | ||
ry *= Math.sqrt(lambda); | ||
} | ||
// Get center parameters (cx, cy, theta1, delta_theta) | ||
// | ||
var cc = get_arc_center(x1, y1, x2, y2, fa, fs, rx, ry, sin_phi, cos_phi); | ||
var result = []; | ||
var theta1 = cc[2]; | ||
var delta_theta = cc[3]; | ||
// Split an arc to multiple segments, so each segment | ||
// will be less than τ/4 (= 90°) | ||
// | ||
var segments = Math.max(Math.ceil(Math.abs(delta_theta) / (TAU / 4)), 1); | ||
delta_theta /= segments; | ||
for (var i = 0; i < segments; i++) { | ||
result.push(approximate_unit_arc(theta1, delta_theta)); | ||
theta1 += delta_theta; | ||
} | ||
// We have a bezier approximation of a unit circle, | ||
// now need to transform back to the original ellipse | ||
// | ||
return result.map(function (curve) { | ||
for (var i = 0; i < curve.length; i += 2) { | ||
var x = curve[i + 0]; | ||
var y = curve[i + 1]; | ||
// scale | ||
x *= rx; | ||
y *= ry; | ||
// rotate | ||
var xp = cos_phi*x - sin_phi*y; | ||
var yp = sin_phi*x + cos_phi*y; | ||
// translate | ||
curve[i + 0] = xp + cc[0]; | ||
curve[i + 1] = yp + cc[1]; | ||
} | ||
return curve; | ||
var lengthProperties = approximateArcLengthOfCurve(300, function(t) { | ||
return pointOnEllipticalArc({x: x0, y:y0}, rx, ry, xAxisRotate, | ||
LargeArcFlag, SweepFlag, {x: x1, y:y1}, t); | ||
}); | ||
}; | ||
//Calculate ans Arc curve length and positionAtLength | ||
//Definitions taken from https://developer.mozilla.org/en-US/docs/Web/SVG/Tutorial/Paths | ||
var Arc = function(x0, y0, rx,ry, xAxisRotate, LargeArcFlag,SweepFlag, x,y) { | ||
return new Arc$1(x0, y0, rx,ry, xAxisRotate, LargeArcFlag,SweepFlag, x,y); | ||
}; | ||
function Arc$1(x0, y0,rx,ry, xAxisRotate, LargeArcFlag,SweepFlag,x,y) { | ||
var length = 0; | ||
var partialLengths = []; | ||
var curves = []; | ||
var res = a2c(x0, y0,rx,ry, xAxisRotate, LargeArcFlag,SweepFlag,x,y); | ||
res.forEach(function(d){ | ||
var curve = new Bezier(d[0], d[1], d[2], d[3], d[4], d[5], d[6], d[7]); | ||
var curveLength = curve.getTotalLength(); | ||
length += curveLength; | ||
partialLengths.push(curveLength); | ||
curves.push(curve); | ||
}); | ||
this.length = length; | ||
this.partialLengths = partialLengths; | ||
this.curves = curves; | ||
this.length = lengthProperties.arcLength; | ||
} | ||
@@ -565,17 +381,11 @@ | ||
} | ||
var i = this.partialLengths.length - 1; | ||
var position = pointOnEllipticalArc({x: this.x0, y:this.y0}, | ||
this.rx, this.ry, this.xAxisRotate, | ||
this.LargeArcFlag, this.SweepFlag, | ||
{x: this.x1, y: this.y1}, | ||
fractionLength/this.length); | ||
return {x: position.x, y: position.y}; | ||
while(this.partialLengths[i] >= fractionLength && this.partialLengths[i] > 0){ | ||
i--; | ||
} | ||
if(i<this.partialLengths.length-1){ | ||
i++; | ||
} | ||
var lengthOffset = 0; | ||
for(var j=0; j<i; j++){ | ||
lengthOffset += this.partialLengths[j]; | ||
} | ||
return this.curves[i].getPointAtLength(fractionLength - lengthOffset); | ||
}, | ||
@@ -588,17 +398,10 @@ getTangentAtLength: function(fractionLength) { | ||
} | ||
var i = this.partialLengths.length - 1; | ||
while(this.partialLengths[i] >= fractionLength && this.partialLengths[i] > 0){ | ||
i--; | ||
} | ||
if(i<this.partialLengths.length-1){ | ||
i++; | ||
} | ||
var lengthOffset = 0; | ||
for(var j=0; j<i; j++){ | ||
lengthOffset += this.partialLengths[j]; | ||
} | ||
return this.curves[i].getTangentAtLength(fractionLength - lengthOffset); | ||
var position = pointOnEllipticalArc({x: this.x0, y:this.y0}, | ||
this.rx, this.ry, this.xAxisRotate, | ||
this.LargeArcFlag, this.SweepFlag, | ||
{x: this.x1, y: this.y1}, | ||
fractionLength/this.length); | ||
return {x: position.x, y: position.y}; | ||
}, | ||
@@ -612,2 +415,174 @@ getPropertiesAtLength: function(fractionLength){ | ||
function pointOnEllipticalArc(p0, rx, ry, xAxisRotation, largeArcFlag, sweepFlag, p1, t) { | ||
// In accordance to: http://www.w3.org/TR/SVG/implnote.html#ArcOutOfRangeParameters | ||
rx = Math.abs(rx); | ||
ry = Math.abs(ry); | ||
xAxisRotation = mod(xAxisRotation, 360); | ||
var xAxisRotationRadians = toRadians(xAxisRotation); | ||
// If the endpoints are identical, then this is equivalent to omitting the elliptical arc segment entirely. | ||
if(p0.x === p1.x && p0.y === p1.y) { | ||
return p0; | ||
} | ||
// If rx = 0 or ry = 0 then this arc is treated as a straight line segment joining the endpoints. | ||
if(rx === 0 || ry === 0) { | ||
return this.pointOnLine(p0, p1, t); | ||
} | ||
// Following "Conversion from endpoint to center parameterization" | ||
// http://www.w3.org/TR/SVG/implnote.html#ArcConversionEndpointToCenter | ||
// Step #1: Compute transformedPoint | ||
var dx = (p0.x-p1.x)/2; | ||
var dy = (p0.y-p1.y)/2; | ||
var transformedPoint = { | ||
x: Math.cos(xAxisRotationRadians)*dx + Math.sin(xAxisRotationRadians)*dy, | ||
y: -Math.sin(xAxisRotationRadians)*dx + Math.cos(xAxisRotationRadians)*dy | ||
}; | ||
// Ensure radii are large enough | ||
var radiiCheck = Math.pow(transformedPoint.x, 2)/Math.pow(rx, 2) + Math.pow(transformedPoint.y, 2)/Math.pow(ry, 2); | ||
if(radiiCheck > 1) { | ||
rx = Math.sqrt(radiiCheck)*rx; | ||
ry = Math.sqrt(radiiCheck)*ry; | ||
} | ||
// Step #2: Compute transformedCenter | ||
var cSquareNumerator = Math.pow(rx, 2)*Math.pow(ry, 2) - Math.pow(rx, 2)*Math.pow(transformedPoint.y, 2) - Math.pow(ry, 2)*Math.pow(transformedPoint.x, 2); | ||
var cSquareRootDenom = Math.pow(rx, 2)*Math.pow(transformedPoint.y, 2) + Math.pow(ry, 2)*Math.pow(transformedPoint.x, 2); | ||
var cRadicand = cSquareNumerator/cSquareRootDenom; | ||
// Make sure this never drops below zero because of precision | ||
cRadicand = cRadicand < 0 ? 0 : cRadicand; | ||
var cCoef = (largeArcFlag !== sweepFlag ? 1 : -1) * Math.sqrt(cRadicand); | ||
var transformedCenter = { | ||
x: cCoef*((rx*transformedPoint.y)/ry), | ||
y: cCoef*(-(ry*transformedPoint.x)/rx) | ||
}; | ||
// Step #3: Compute center | ||
var center = { | ||
x: Math.cos(xAxisRotationRadians)*transformedCenter.x - Math.sin(xAxisRotationRadians)*transformedCenter.y + ((p0.x+p1.x)/2), | ||
y: Math.sin(xAxisRotationRadians)*transformedCenter.x + Math.cos(xAxisRotationRadians)*transformedCenter.y + ((p0.y+p1.y)/2) | ||
}; | ||
// Step #4: Compute start/sweep angles | ||
// Start angle of the elliptical arc prior to the stretch and rotate operations. | ||
// Difference between the start and end angles | ||
var startVector = { | ||
x: (transformedPoint.x-transformedCenter.x)/rx, | ||
y: (transformedPoint.y-transformedCenter.y)/ry | ||
}; | ||
var startAngle = angleBetween({ | ||
x: 1, | ||
y: 0 | ||
}, startVector); | ||
var endVector = { | ||
x: (-transformedPoint.x-transformedCenter.x)/rx, | ||
y: (-transformedPoint.y-transformedCenter.y)/ry | ||
}; | ||
var sweepAngle = angleBetween(startVector, endVector); | ||
if(!sweepFlag && sweepAngle > 0) { | ||
sweepAngle -= 2*Math.PI; | ||
} | ||
else if(sweepFlag && sweepAngle < 0) { | ||
sweepAngle += 2*Math.PI; | ||
} | ||
// We use % instead of `mod(..)` because we want it to be -360deg to 360deg(but actually in radians) | ||
sweepAngle %= 2*Math.PI; | ||
// From http://www.w3.org/TR/SVG/implnote.html#ArcParameterizationAlternatives | ||
var angle = startAngle+(sweepAngle*t); | ||
var ellipseComponentX = rx*Math.cos(angle); | ||
var ellipseComponentY = ry*Math.sin(angle); | ||
var point = { | ||
x: Math.cos(xAxisRotationRadians)*ellipseComponentX - Math.sin(xAxisRotationRadians)*ellipseComponentY + center.x, | ||
y: Math.sin(xAxisRotationRadians)*ellipseComponentX + Math.cos(xAxisRotationRadians)*ellipseComponentY + center.y | ||
}; | ||
// Attach some extra info to use | ||
point.ellipticalArcStartAngle = startAngle; | ||
point.ellipticalArcEndAngle = startAngle+sweepAngle; | ||
point.ellipticalArcAngle = angle; | ||
point.ellipticalArcCenter = center; | ||
point.resultantRx = rx; | ||
point.resultantRy = ry; | ||
return point; | ||
} | ||
function approximateArcLengthOfCurve(resolution, pointOnCurveFunc) { | ||
// Resolution is the number of segments we use | ||
resolution = resolution ? resolution : 500; | ||
var resultantArcLength = 0; | ||
var arcLengthMap = []; | ||
var approximationLines = []; | ||
var prevPoint = pointOnCurveFunc(0); | ||
var nextPoint; | ||
for(var i = 0; i < resolution; i++) { | ||
var t = clamp(i*(1/resolution), 0, 1); | ||
nextPoint = pointOnCurveFunc(t); | ||
resultantArcLength += distance(prevPoint, nextPoint); | ||
approximationLines.push([prevPoint, nextPoint]); | ||
arcLengthMap.push({ | ||
t: t, | ||
arcLength: resultantArcLength | ||
}); | ||
prevPoint = nextPoint; | ||
} | ||
// Last stretch to the endpoint | ||
nextPoint = pointOnCurveFunc(1); | ||
approximationLines.push([prevPoint, nextPoint]); | ||
resultantArcLength += distance(prevPoint, nextPoint); | ||
arcLengthMap.push({ | ||
t: 1, | ||
arcLength: resultantArcLength | ||
}); | ||
return { | ||
arcLength: resultantArcLength, | ||
arcLengthMap: arcLengthMap, | ||
approximationLines: approximationLines | ||
}; | ||
} | ||
function mod(x, m) { | ||
return (x%m + m)%m; | ||
} | ||
function toRadians(angle) { | ||
return angle * (Math.PI / 180); | ||
} | ||
function distance(p0, p1) { | ||
return Math.sqrt(Math.pow(p1.x-p0.x, 2) + Math.pow(p1.y-p0.y, 2)); | ||
} | ||
function clamp(val, min, max) { | ||
return Math.min(Math.max(val, min), max); | ||
} | ||
function angleBetween(v0, v1) { | ||
var p = v0.x*v1.x + v0.y*v1.y; | ||
var n = Math.sqrt((Math.pow(v0.x, 2)+Math.pow(v0.y, 2)) * (Math.pow(v1.x, 2)+Math.pow(v1.y, 2))); | ||
var sign = v0.x*v1.y - v0.y*v1.x < 0 ? -1 : 1; | ||
var angle = sign*Math.acos(p/n); | ||
//var angle = Math.atan2(v0.y, v0.x) - Math.atan2(v1.y, v1.x); | ||
return angle; | ||
} | ||
var LinearPosition = function(x0, x1, y0, y1) { | ||
@@ -614,0 +589,0 @@ return new LinearPosition$1(x0, x1, y0, y1); |
@@ -1,2 +0,2 @@ | ||
// http://geoexamples.com/path-properties/ Version 0.4.2. Copyright 2018 Roger Veciana i Rovira. | ||
!function(t,n){"object"==typeof exports&&"undefined"!=typeof module?n(exports):"function"==typeof define&&define.amd?define(["exports"],n):n(t.spp=t.spp||{})}(this,function(t){"use strict";function n(t){var n=t.match(d);return n?n.map(Number):[]}function h(t,n,h,r,g,u,c,p){this.a={x:t,y:n},this.b={x:h,y:r},this.c={x:g,y:u},this.d={x:c,y:p},null!==c&&void 0!==c&&null!==p&&void 0!==p?(this.getArcLength=f,this.getPoint=a,this.getDerivative=i):(this.getArcLength=o,this.getPoint=s,this.getDerivative=e),this.init()}function e(t,n,h){return{x:2*(1-h)*(t[1]-t[0])+2*h*(t[2]-t[1]),y:2*(1-h)*(n[1]-n[0])+2*h*(n[2]-n[1])}}function i(t,n,h){return s([3*(t[1]-t[0]),3*(t[2]-t[1]),3*(t[3]-t[2])],[3*(n[1]-n[0]),3*(n[2]-n[1]),3*(n[3]-n[2])],h)}function r(t,n,h,e,i){for(var r=1,s=t/n,a=(t-h(e,i,s))/n;r>.001;){var o=h(e,i,s+a),g=h(e,i,s-a),u=Math.abs(t-o)/n,c=Math.abs(t-g)/n;u<r?(r=u,s+=a):c<r?(r=c,s-=a):a/=2}return s}function s(t,n,h){return{x:(1-h)*(1-h)*t[0]+2*(1-h)*h*t[1]+h*h*t[2],y:(1-h)*(1-h)*n[0]+2*(1-h)*h*n[1]+h*h*n[2]}}function a(t,n,h){return{x:(1-h)*(1-h)*(1-h)*t[0]+3*(1-h)*(1-h)*h*t[1]+3*(1-h)*h*h*t[2]+h*h*h*t[3],y:(1-h)*(1-h)*(1-h)*n[0]+3*(1-h)*(1-h)*h*n[1]+3*(1-h)*h*h*n[2]+h*h*h*n[3]}}function o(t,n,h){void 0===h&&(h=1);var e=t[0]-2*t[1]+t[2],i=n[0]-2*n[1]+n[2],r=2*t[1]-2*t[0],s=2*n[1]-2*n[0],a=4*(e*e+i*i),o=4*(e*r+i*s),g=r*r+s*s;if(0===a)return h*Math.sqrt(Math.pow(t[2]-t[0],2)+Math.pow(n[2]-n[0],2));var u=o/(2*a),c=g/a,f=h+u,p=c-u*u,y=u+Math.sqrt(u*u+p)!==0?p*Math.log(Math.abs((f+Math.sqrt(f*f+p))/(u+Math.sqrt(u*u+p)))):0;return Math.sqrt(a)/2*(f*Math.sqrt(f*f+p)-u*Math.sqrt(u*u+p)+y)}function g(t,n){return T[t][n]}function u(t,n,h){var e,i,r,s=h.length-1;if(0===s)return 0;if(0===t){for(i=0,r=0;r<=s;r++)i+=g(s,r)*Math.pow(1-n,s-r)*Math.pow(n,r)*h[r];return i}for(e=new Array(s),r=0;r<s;r++)e[r]=s*(h[r+1]-h[r]);return u(t-1,n,e)}function c(t,n,h){var e=u(1,h,t),i=u(1,h,n),r=e*e+i*i;return Math.sqrt(r)}function f(t,n,h){var e,i,r,s;void 0===h&&(h=1);for(e=h/2,i=0,r=0;r<20;r++)s=e*b[20][r]+e,i+=P[20][r]*c(t,n,s);return e*i}function p(t,n,h,e){var i=t*e-n*h<0?-1:1,r=t*h+n*e;return r>1&&(r=1),r<-1&&(r=-1),i*Math.acos(r)}function y(t,n,h,e,i,r,s,a,o,g){var u=g*(t-h)/2+o*(n-e)/2,c=-o*(t-h)/2+g*(n-e)/2,f=s*s,y=a*a,x=u*u,l=c*c,v=f*y-f*l-y*x;v<0&&(v=0),v/=f*l+y*x,v=Math.sqrt(v)*(i===r?-1:1);var L=v*s/a*c,M=v*-a/s*u,w=g*L-o*M+(t+h)/2,d=o*L+g*M+(n+e)/2,A=(u-L)/s,b=(c-M)/a,P=(-u-L)/s,T=(-c-M)/a,m=p(1,0,A,b),z=p(A,b,P,T);return 0===r&&z>0&&(z-=q),1===r&&z<0&&(z+=q),[w,d,m,z]}function x(t,n){var h=4/3*Math.tan(n/4),e=Math.cos(t),i=Math.sin(t),r=Math.cos(t+n),s=Math.sin(t+n);return[e,i,e-i*h,i+e*h,r+s*h,s-r*h,r,s]}function l(t,n,h,e,i,r,s,a,o){var g=0,u=[],c=[];m(t,n,h,e,i,r,s,a,o).forEach(function(t){var n=new A(t[0],t[1],t[2],t[3],t[4],t[5],t[6],t[7]),h=n.getTotalLength();g+=h,u.push(h),c.push(n)}),this.length=g,this.partialLengths=u,this.curves=c}function v(t,n,h,e){this.x0=t,this.x1=n,this.y0=h,this.y1=e}var L={a:7,c:6,h:1,l:2,m:2,q:4,s:4,t:2,v:1,z:0},M=/([astvzqmhlc])([^astvzqmhlc]*)/gi,w=function(t){var h=[];return t.replace(M,function(t,e,i){var r=e.toLowerCase();for(i=n(i),"m"===r&&i.length>2&&(h.push([e].concat(i.splice(0,2))),r="l",e="m"===e?"l":"L");i.length>=0;){if(i.length===L[r])return i.unshift(e),h.push(i);if(i.length<L[r])throw new Error("malformed path data");h.push([e].concat(i.splice(0,L[r])))}}),h},d=/-?[0-9]*\.?[0-9]+(?:e[-+]?\d+)?/gi,A=function(t,n,e,i,r,s,a,o){return new h(t,n,e,i,r,s,a,o)};h.prototype={constructor:h,init:function(){this.length=this.getArcLength([this.a.x,this.b.x,this.c.x,this.d.x],[this.a.y,this.b.y,this.c.y,this.d.y])},getTotalLength:function(){return this.length},getPointAtLength:function(t){var n=r(t,this.length,this.getArcLength,[this.a.x,this.b.x,this.c.x,this.d.x],[this.a.y,this.b.y,this.c.y,this.d.y]);return this.getPoint([this.a.x,this.b.x,this.c.x,this.d.x],[this.a.y,this.b.y,this.c.y,this.d.y],n)},getTangentAtLength:function(t){var n=r(t,this.length,this.getArcLength,[this.a.x,this.b.x,this.c.x,this.d.x],[this.a.y,this.b.y,this.c.y,this.d.y]),h=this.getDerivative([this.a.x,this.b.x,this.c.x,this.d.x],[this.a.y,this.b.y,this.c.y,this.d.y],n),e=Math.sqrt(h.x*h.x+h.y*h.y);return e>0?{x:h.x/e,y:h.y/e}:{x:0,y:0}},getPropertiesAtLength:function(t){var n,h=r(t,this.length,this.getArcLength,[this.a.x,this.b.x,this.c.x,this.d.x],[this.a.y,this.b.y,this.c.y,this.d.y]),e=this.getDerivative([this.a.x,this.b.x,this.c.x,this.d.x],[this.a.y,this.b.y,this.c.y,this.d.y],h),i=Math.sqrt(e.x*e.x+e.y*e.y);n=i>0?{x:e.x/i,y:e.y/i}:{x:0,y:0};var s=this.getPoint([this.a.x,this.b.x,this.c.x,this.d.x],[this.a.y,this.b.y,this.c.y,this.d.y],h);return{x:s.x,y:s.y,tangentX:n.x,tangentY:n.y}}};var b=[[],[],[-.5773502691896257,.5773502691896257],[0,-.7745966692414834,.7745966692414834],[-.33998104358485626,.33998104358485626,-.8611363115940526,.8611363115940526],[0,-.5384693101056831,.5384693101056831,-.906179845938664,.906179845938664],[.6612093864662645,-.6612093864662645,-.2386191860831969,.2386191860831969,-.932469514203152,.932469514203152],[0,.4058451513773972,-.4058451513773972,-.7415311855993945,.7415311855993945,-.9491079123427585,.9491079123427585],[-.1834346424956498,.1834346424956498,-.525532409916329,.525532409916329,-.7966664774136267,.7966664774136267,-.9602898564975363,.9602898564975363],[0,-.8360311073266358,.8360311073266358,-.9681602395076261,.9681602395076261,-.3242534234038089,.3242534234038089,-.6133714327005904,.6133714327005904],[-.14887433898163122,.14887433898163122,-.4333953941292472,.4333953941292472,-.6794095682990244,.6794095682990244,-.8650633666889845,.8650633666889845,-.9739065285171717,.9739065285171717],[0,-.26954315595234496,.26954315595234496,-.5190961292068118,.5190961292068118,-.7301520055740494,.7301520055740494,-.8870625997680953,.8870625997680953,-.978228658146057,.978228658146057],[-.1252334085114689,.1252334085114689,-.3678314989981802,.3678314989981802,-.5873179542866175,.5873179542866175,-.7699026741943047,.7699026741943047,-.9041172563704749,.9041172563704749,-.9815606342467192,.9815606342467192],[0,-.2304583159551348,.2304583159551348,-.44849275103644687,.44849275103644687,-.6423493394403402,.6423493394403402,-.8015780907333099,.8015780907333099,-.9175983992229779,.9175983992229779,-.9841830547185881,.9841830547185881],[-.10805494870734367,.10805494870734367,-.31911236892788974,.31911236892788974,-.5152486363581541,.5152486363581541,-.6872929048116855,.6872929048116855,-.827201315069765,.827201315069765,-.9284348836635735,.9284348836635735,-.9862838086968123,.9862838086968123],[0,-.20119409399743451,.20119409399743451,-.3941513470775634,.3941513470775634,-.5709721726085388,.5709721726085388,-.7244177313601701,.7244177313601701,-.8482065834104272,.8482065834104272,-.937273392400706,.937273392400706,-.9879925180204854,.9879925180204854],[-.09501250983763744,.09501250983763744,-.2816035507792589,.2816035507792589,-.45801677765722737,.45801677765722737,-.6178762444026438,.6178762444026438,-.755404408355003,.755404408355003,-.8656312023878318,.8656312023878318,-.9445750230732326,.9445750230732326,-.9894009349916499,.9894009349916499],[0,-.17848418149584785,.17848418149584785,-.3512317634538763,.3512317634538763,-.5126905370864769,.5126905370864769,-.6576711592166907,.6576711592166907,-.7815140038968014,.7815140038968014,-.8802391537269859,.8802391537269859,-.9506755217687678,.9506755217687678,-.9905754753144174,.9905754753144174],[-.0847750130417353,.0847750130417353,-.2518862256915055,.2518862256915055,-.41175116146284263,.41175116146284263,-.5597708310739475,.5597708310739475,-.6916870430603532,.6916870430603532,-.8037049589725231,.8037049589725231,-.8926024664975557,.8926024664975557,-.9558239495713977,.9558239495713977,-.9915651684209309,.9915651684209309],[0,-.16035864564022537,.16035864564022537,-.31656409996362983,.31656409996362983,-.46457074137596094,.46457074137596094,-.600545304661681,.600545304661681,-.7209661773352294,.7209661773352294,-.8227146565371428,.8227146565371428,-.9031559036148179,.9031559036148179,-.96020815213483,.96020815213483,-.9924068438435844,.9924068438435844],[-.07652652113349734,.07652652113349734,-.22778585114164507,.22778585114164507,-.37370608871541955,.37370608871541955,-.5108670019508271,.5108670019508271,-.636053680726515,.636053680726515,-.7463319064601508,.7463319064601508,-.8391169718222188,.8391169718222188,-.912234428251326,.912234428251326,-.9639719272779138,.9639719272779138,-.9931285991850949,.9931285991850949],[0,-.1455618541608951,.1455618541608951,-.2880213168024011,.2880213168024011,-.4243421202074388,.4243421202074388,-.5516188358872198,.5516188358872198,-.6671388041974123,.6671388041974123,-.7684399634756779,.7684399634756779,-.8533633645833173,.8533633645833173,-.9200993341504008,.9200993341504008,-.9672268385663063,.9672268385663063,-.9937521706203895,.9937521706203895],[-.06973927331972223,.06973927331972223,-.20786042668822127,.20786042668822127,-.34193582089208424,.34193582089208424,-.469355837986757,.469355837986757,-.5876404035069116,.5876404035069116,-.6944872631866827,.6944872631866827,-.7878168059792081,.7878168059792081,-.8658125777203002,.8658125777203002,-.926956772187174,.926956772187174,-.9700604978354287,.9700604978354287,-.9942945854823992,.9942945854823992],[0,-.1332568242984661,.1332568242984661,-.26413568097034495,.26413568097034495,-.3903010380302908,.3903010380302908,-.5095014778460075,.5095014778460075,-.6196098757636461,.6196098757636461,-.7186613631319502,.7186613631319502,-.8048884016188399,.8048884016188399,-.8767523582704416,.8767523582704416,-.9329710868260161,.9329710868260161,-.9725424712181152,.9725424712181152,-.9947693349975522,.9947693349975522],[-.06405689286260563,.06405689286260563,-.1911188674736163,.1911188674736163,-.3150426796961634,.3150426796961634,-.4337935076260451,.4337935076260451,-.5454214713888396,.5454214713888396,-.6480936519369755,.6480936519369755,-.7401241915785544,.7401241915785544,-.820001985973903,.820001985973903,-.8864155270044011,.8864155270044011,-.9382745520027328,.9382745520027328,-.9747285559713095,.9747285559713095,-.9951872199970213,.9951872199970213]],P=[[],[],[1,1],[.8888888888888888,.5555555555555556,.5555555555555556],[.6521451548625461,.6521451548625461,.34785484513745385,.34785484513745385],[.5688888888888889,.47862867049936647,.47862867049936647,.23692688505618908,.23692688505618908],[.3607615730481386,.3607615730481386,.46791393457269104,.46791393457269104,.17132449237917036,.17132449237917036],[.4179591836734694,.3818300505051189,.3818300505051189,.27970539148927664,.27970539148927664,.1294849661688697,.1294849661688697],[.362683783378362,.362683783378362,.31370664587788727,.31370664587788727,.22238103445337448,.22238103445337448,.10122853629037626,.10122853629037626],[.3302393550012598,.1806481606948574,.1806481606948574,.08127438836157441,.08127438836157441,.31234707704000286,.31234707704000286,.26061069640293544,.26061069640293544],[.29552422471475287,.29552422471475287,.26926671930999635,.26926671930999635,.21908636251598204,.21908636251598204,.1494513491505806,.1494513491505806,.06667134430868814,.06667134430868814],[.2729250867779006,.26280454451024665,.26280454451024665,.23319376459199048,.23319376459199048,.18629021092773426,.18629021092773426,.1255803694649046,.1255803694649046,.05566856711617366,.05566856711617366],[.24914704581340277,.24914704581340277,.2334925365383548,.2334925365383548,.20316742672306592,.20316742672306592,.16007832854334622,.16007832854334622,.10693932599531843,.10693932599531843,.04717533638651183,.04717533638651183],[.2325515532308739,.22628318026289723,.22628318026289723,.2078160475368885,.2078160475368885,.17814598076194574,.17814598076194574,.13887351021978725,.13887351021978725,.09212149983772845,.09212149983772845,.04048400476531588,.04048400476531588],[.2152638534631578,.2152638534631578,.2051984637212956,.2051984637212956,.18553839747793782,.18553839747793782,.15720316715819355,.15720316715819355,.12151857068790319,.12151857068790319,.08015808715976021,.08015808715976021,.03511946033175186,.03511946033175186],[.2025782419255613,.19843148532711158,.19843148532711158,.1861610000155622,.1861610000155622,.16626920581699392,.16626920581699392,.13957067792615432,.13957067792615432,.10715922046717194,.10715922046717194,.07036604748810812,.07036604748810812,.03075324199611727,.03075324199611727],[.1894506104550685,.1894506104550685,.18260341504492358,.18260341504492358,.16915651939500254,.16915651939500254,.14959598881657674,.14959598881657674,.12462897125553388,.12462897125553388,.09515851168249279,.09515851168249279,.062253523938647894,.062253523938647894,.027152459411754096,.027152459411754096],[.17944647035620653,.17656270536699264,.17656270536699264,.16800410215645004,.16800410215645004,.15404576107681028,.15404576107681028,.13513636846852548,.13513636846852548,.11188384719340397,.11188384719340397,.08503614831717918,.08503614831717918,.0554595293739872,.0554595293739872,.02414830286854793,.02414830286854793],[.1691423829631436,.1691423829631436,.16427648374583273,.16427648374583273,.15468467512626524,.15468467512626524,.14064291467065065,.14064291467065065,.12255520671147846,.12255520671147846,.10094204410628717,.10094204410628717,.07642573025488905,.07642573025488905,.0497145488949698,.0497145488949698,.02161601352648331,.02161601352648331],[.1610544498487837,.15896884339395434,.15896884339395434,.15276604206585967,.15276604206585967,.1426067021736066,.1426067021736066,.12875396253933621,.12875396253933621,.11156664554733399,.11156664554733399,.09149002162245,.09149002162245,.06904454273764123,.06904454273764123,.0448142267656996,.0448142267656996,.019461788229726478,.019461788229726478],[.15275338713072584,.15275338713072584,.14917298647260374,.14917298647260374,.14209610931838204,.14209610931838204,.13168863844917664,.13168863844917664,.11819453196151841,.11819453196151841,.10193011981724044,.10193011981724044,.08327674157670475,.08327674157670475,.06267204833410907,.06267204833410907,.04060142980038694,.04060142980038694,.017614007139152118,.017614007139152118],[.14608113364969041,.14452440398997005,.14452440398997005,.13988739479107315,.13988739479107315,.13226893863333747,.13226893863333747,.12183141605372853,.12183141605372853,.10879729916714838,.10879729916714838,.09344442345603386,.09344442345603386,.0761001136283793,.0761001136283793,.057134425426857205,.057134425426857205,.036953789770852494,.036953789770852494,.016017228257774335,.016017228257774335],[.13925187285563198,.13925187285563198,.13654149834601517,.13654149834601517,.13117350478706238,.13117350478706238,.12325237681051242,.12325237681051242,.11293229608053922,.11293229608053922,.10041414444288096,.10041414444288096,.08594160621706773,.08594160621706773,.06979646842452049,.06979646842452049,.052293335152683286,.052293335152683286,.03377490158481415,.03377490158481415,.0146279952982722,.0146279952982722],[.13365457218610619,.1324620394046966,.1324620394046966,.12890572218808216,.12890572218808216,.12304908430672953,.12304908430672953,.11499664022241136,.11499664022241136,.10489209146454141,.10489209146454141,.09291576606003515,.09291576606003515,.07928141177671895,.07928141177671895,.06423242140852585,.06423242140852585,.04803767173108467,.04803767173108467,.030988005856979445,.030988005856979445,.013411859487141771,.013411859487141771],[.12793819534675216,.12793819534675216,.1258374563468283,.1258374563468283,.12167047292780339,.12167047292780339,.1155056680537256,.1155056680537256,.10744427011596563,.10744427011596563,.09761865210411388,.09761865210411388,.08619016153195327,.08619016153195327,.0733464814110803,.0733464814110803,.05929858491543678,.05929858491543678,.04427743881741981,.04427743881741981,.028531388628933663,.028531388628933663,.0123412297999872,.0123412297999872]],T=[[1],[1,1],[1,2,1],[1,3,3,1]],q=2*Math.PI,m=function(t,n,h,e,i,r,s,a,o){var g=Math.sin(i*q/360),u=Math.cos(i*q/360),c=u*(t-a)/2+g*(n-o)/2,f=-g*(t-a)/2+u*(n-o)/2;if(0===c&&0===f)return[];if(0===h||0===e)return[];h=Math.abs(h),e=Math.abs(e);var p=c*c/(h*h)+f*f/(e*e);p>1&&(h*=Math.sqrt(p),e*=Math.sqrt(p));var l=y(t,n,a,o,r,s,h,e,g,u),v=[],L=l[2],M=l[3],w=Math.max(Math.ceil(Math.abs(M)/(q/4)),1);M/=w;for(var d=0;d<w;d++)v.push(x(L,M)),L+=M;return v.map(function(t){for(var n=0;n<t.length;n+=2){var i=t[n+0],r=t[n+1];i*=h,r*=e;var s=u*i-g*r,a=g*i+u*r;t[n+0]=s+l[0],t[n+1]=a+l[1]}return t})},z=function(t,n,h,e,i,r,s,a,o){return new l(t,n,h,e,i,r,s,a,o)};l.prototype={constructor:l,init:function(){},getTotalLength:function(){return this.length},getPointAtLength:function(t){t<0?t=0:t>this.length&&(t=this.length);for(var n=this.partialLengths.length-1;this.partialLengths[n]>=t&&this.partialLengths[n]>0;)n--;n<this.partialLengths.length-1&&n++;for(var h=0,e=0;e<n;e++)h+=this.partialLengths[e];return this.curves[n].getPointAtLength(t-h)},getTangentAtLength:function(t){t<0?t=0:t>this.length&&(t=this.length);for(var n=this.partialLengths.length-1;this.partialLengths[n]>=t&&this.partialLengths[n]>0;)n--;n<this.partialLengths.length-1&&n++;for(var h=0,e=0;e<n;e++)h+=this.partialLengths[e];return this.curves[n].getTangentAtLength(t-h)},getPropertiesAtLength:function(t){var n=this.getTangentAtLength(t),h=this.getPointAtLength(t);return{x:h.x,y:h.y,tangentX:n.x,tangentY:n.y}}};var O=function(t,n,h,e){return new v(t,n,h,e)};v.prototype.getTotalLength=function(){return Math.sqrt(Math.pow(this.x0-this.x1,2)+Math.pow(this.y0-this.y1,2))},v.prototype.getPointAtLength=function(t){var n=t/Math.sqrt(Math.pow(this.x0-this.x1,2)+Math.pow(this.y0-this.y1,2)),h=(this.x1-this.x0)*n,e=(this.y1-this.y0)*n;return{x:this.x0+h,y:this.y0+e}},v.prototype.getTangentAtLength=function(){var t=Math.sqrt((this.x1-this.x0)*(this.x1-this.x0)+(this.y1-this.y0)*(this.y1-this.y0));return{x:(this.x1-this.x0)/t,y:(this.y1-this.y0)/t}},v.prototype.getPropertiesAtLength=function(t){var n=this.getPointAtLength(t),h=this.getTangentAtLength();return{x:n.x,y:n.y,tangentX:h.x,tangentY:h.y}};var C=function(t){function n(t){if(!t)return null;for(var r,s,a=w(t),o=[0,0],g=[0,0],u=0;u<a.length;u++)"M"===a[u][0]?(o=[a[u][1],a[u][2]],s=[o[0],o[1]],i.push(null)):"m"===a[u][0]?(o=[a[u][1]+o[0],a[u][2]+o[1]],s=[o[0],o[1]],i.push(null)):"L"===a[u][0]?(h+=Math.sqrt(Math.pow(o[0]-a[u][1],2)+Math.pow(o[1]-a[u][2],2)),i.push(new O(o[0],a[u][1],o[1],a[u][2])),o=[a[u][1],a[u][2]]):"l"===a[u][0]?(h+=Math.sqrt(Math.pow(a[u][1],2)+Math.pow(a[u][2],2)),i.push(new O(o[0],a[u][1]+o[0],o[1],a[u][2]+o[1])),o=[a[u][1]+o[0],a[u][2]+o[1]]):"H"===a[u][0]?(h+=Math.abs(o[0]-a[u][1]),i.push(new O(o[0],a[u][1],o[1],o[1])),o[0]=a[u][1]):"h"===a[u][0]?(h+=Math.abs(a[u][1]),i.push(new O(o[0],o[0]+a[u][1],o[1],o[1])),o[0]=a[u][1]+o[0]):"V"===a[u][0]?(h+=Math.abs(o[1]-a[u][1]),i.push(new O(o[0],o[0],o[1],a[u][1])),o[1]=a[u][1]):"v"===a[u][0]?(h+=Math.abs(a[u][1]),i.push(new O(o[0],o[0],o[1],o[1]+a[u][1])),o[1]=a[u][1]+o[1]):"z"===a[u][0]||"Z"===a[u][0]?(h+=Math.sqrt(Math.pow(s[0]-o[0],2)+Math.pow(s[1]-o[1],2)),i.push(new O(o[0],s[0],o[1],s[1])),o=[s[0],s[1]]):"C"===a[u][0]?(r=new A(o[0],o[1],a[u][1],a[u][2],a[u][3],a[u][4],a[u][5],a[u][6]),h+=r.getTotalLength(),o=[a[u][5],a[u][6]],i.push(r)):"c"===a[u][0]?(r=new A(o[0],o[1],o[0]+a[u][1],o[1]+a[u][2],o[0]+a[u][3],o[1]+a[u][4],o[0]+a[u][5],o[1]+a[u][6]),h+=r.getTotalLength(),o=[a[u][5]+o[0],a[u][6]+o[1]],i.push(r)):"S"===a[u][0]?(r=u>0&&["C","c","S","s"].indexOf(a[u-1][0])>-1?new A(o[0],o[1],2*o[0]-a[u-1][a[u-1].length-4],2*o[1]-a[u-1][a[u-1].length-3],a[u][1],a[u][2],a[u][3],a[u][4]):new A(o[0],o[1],o[0],o[1],a[u][1],a[u][2],a[u][3],a[u][4]),h+=r.getTotalLength(),o=[a[u][3],a[u][4]],i.push(r)):"s"===a[u][0]?(r=u>0&&["C","c","S","s"].indexOf(a[u-1][0])>-1?new A(o[0],o[1],o[0]+r.d.x-r.c.x,o[1]+r.d.y-r.c.y,o[0]+a[u][1],o[1]+a[u][2],o[0]+a[u][3],o[1]+a[u][4]):new A(o[0],o[1],o[0],o[1],o[0]+a[u][1],o[1]+a[u][2],o[0]+a[u][3],o[1]+a[u][4]),h+=r.getTotalLength(),o=[a[u][3]+o[0],a[u][4]+o[1]],i.push(r)):"Q"===a[u][0]?(r=o[0]==a[u][1]&&o[1]==a[u][2]?new O(a[u][1],a[u][3],a[u][2],a[u][4]):new A(o[0],o[1],a[u][1],a[u][2],a[u][3],a[u][4]),h+=r.getTotalLength(),i.push(r),o=[a[u][3],a[u][4]],g=[a[u][1],a[u][2]]):"q"===a[u][0]?(r=0!=a[u][1]||0!=a[u][2]?new A(o[0],o[1],o[0]+a[u][1],o[1]+a[u][2],o[0]+a[u][3],o[1]+a[u][4]):new O(o[0]+a[u][1],o[0]+a[u][3],o[1]+a[u][2],o[1]+a[u][4]),h+=r.getTotalLength(),g=[o[0]+a[u][1],o[1]+a[u][2]],o=[a[u][3]+o[0],a[u][4]+o[1]],i.push(r)):"T"===a[u][0]?(r=u>0&&["Q","q","T","t"].indexOf(a[u-1][0])>-1?new A(o[0],o[1],2*o[0]-g[0],2*o[1]-g[1],a[u][1],a[u][2]):new O(o[0],a[u][1],o[1],a[u][2]),i.push(r),h+=r.getTotalLength(),g=[2*o[0]-g[0],2*o[1]-g[1]],o=[a[u][1],a[u][2]]):"t"===a[u][0]?(r=u>0&&["Q","q","T","t"].indexOf(a[u-1][0])>-1?new A(o[0],o[1],2*o[0]-g[0],2*o[1]-g[1],o[0]+a[u][1],o[1]+a[u][2]):new O(o[0],o[0]+a[u][1],o[1],o[1]+a[u][2]),h+=r.getTotalLength(),g=[2*o[0]-g[0],2*o[1]-g[1]],o=[a[u][1]+o[0],a[u][2]+o[0]],i.push(r)):"A"===a[u][0]?(r=new z(o[0],o[1],a[u][1],a[u][2],a[u][3],a[u][4],a[u][5],a[u][6],a[u][7]),h+=r.getTotalLength(),o=[a[u][6],a[u][7]],i.push(r)):"a"===a[u][0]&&(r=new z(o[0],o[1],a[u][1],a[u][2],a[u][3],a[u][4],a[u][5],o[0]+a[u][6],o[1]+a[u][7]),h+=r.getTotalLength(),o=[o[0]+a[u][6],o[1]+a[u][7]],i.push(r)),e.push(h);return n}var h=0,e=[],i=[];n.getTotalLength=function(){return h},n.getPointAtLength=function(t){var n=r(t);return i[n.i].getPointAtLength(n.fraction)},n.getTangentAtLength=function(t){var n=r(t);return i[n.i].getTangentAtLength(n.fraction)},n.getPropertiesAtLength=function(t){var n=r(t);return i[n.i].getPropertiesAtLength(n.fraction)},n.getParts=function(){for(var t=[],n=0;n<i.length;n++)if(null!=i[n]){var h={};h.start=i[n].getPointAtLength(0),h.end=i[n].getPointAtLength(e[n]-e[n-1]),h.length=e[n]-e[n-1],function(t){h.getPointAtLength=function(n){return t.getPointAtLength(n)},h.getTangentAtLength=function(n){return t.getTangentAtLength(n)},h.getPropertiesAtLength=function(n){return t.getPropertiesAtLength(n)}}(i[n]),t.push(h)}return t};var r=function(t){t<0?t=0:t>h&&(t=h);for(var n=e.length-1;e[n]>=t&&e[n]>0;)n--;return n++,{fraction:t-e[n-1],i:n}};return n(t)};t.svgPathProperties=C,t.parse=w,t.Bezier=A,Object.defineProperty(t,"__esModule",{value:!0})}); | ||
// http://geoexamples.com/path-properties/ Version 0.4.3. Copyright 2018 Roger Veciana i Rovira. | ||
!function(t,n){"object"==typeof exports&&"undefined"!=typeof module?n(exports):"function"==typeof define&&define.amd?define(["exports"],n):n(t.spp=t.spp||{})}(this,function(t){"use strict";function n(t){var n=t.match(q);return n?n.map(Number):[]}function h(t,n,h,s,g,u,x,c){this.a={x:t,y:n},this.b={x:h,y:s},this.c={x:g,y:u},this.d={x:x,y:c},null!==x&&void 0!==x&&null!==c&&void 0!==c?(this.getArcLength=y,this.getPoint=a,this.getDerivative=i):(this.getArcLength=o,this.getPoint=r,this.getDerivative=e),this.init()}function e(t,n,h){return{x:2*(1-h)*(t[1]-t[0])+2*h*(t[2]-t[1]),y:2*(1-h)*(n[1]-n[0])+2*h*(n[2]-n[1])}}function i(t,n,h){return r([3*(t[1]-t[0]),3*(t[2]-t[1]),3*(t[3]-t[2])],[3*(n[1]-n[0]),3*(n[2]-n[1]),3*(n[3]-n[2])],h)}function s(t,n,h,e,i){for(var s=1,r=t/n,a=(t-h(e,i,r))/n;s>.001;){var o=h(e,i,r+a),g=h(e,i,r-a),u=Math.abs(t-o)/n,x=Math.abs(t-g)/n;u<s?(s=u,r+=a):x<s?(s=x,r-=a):a/=2}return r}function r(t,n,h){return{x:(1-h)*(1-h)*t[0]+2*(1-h)*h*t[1]+h*h*t[2],y:(1-h)*(1-h)*n[0]+2*(1-h)*h*n[1]+h*h*n[2]}}function a(t,n,h){return{x:(1-h)*(1-h)*(1-h)*t[0]+3*(1-h)*(1-h)*h*t[1]+3*(1-h)*h*h*t[2]+h*h*h*t[3],y:(1-h)*(1-h)*(1-h)*n[0]+3*(1-h)*(1-h)*h*n[1]+3*(1-h)*h*h*n[2]+h*h*h*n[3]}}function o(t,n,h){void 0===h&&(h=1);var e=t[0]-2*t[1]+t[2],i=n[0]-2*n[1]+n[2],s=2*t[1]-2*t[0],r=2*n[1]-2*n[0],a=4*(e*e+i*i),o=4*(e*s+i*r),g=s*s+r*r;if(0===a)return h*Math.sqrt(Math.pow(t[2]-t[0],2)+Math.pow(n[2]-n[0],2));var u=o/(2*a),x=g/a,y=h+u,c=x-u*u,p=u+Math.sqrt(u*u+c)!==0?c*Math.log(Math.abs((y+Math.sqrt(y*y+c))/(u+Math.sqrt(u*u+c)))):0;return Math.sqrt(a)/2*(y*Math.sqrt(y*y+c)-u*Math.sqrt(u*u+c)+p)}function g(t,n){return F[t][n]}function u(t,n,h){var e,i,s,r=h.length-1;if(0===r)return 0;if(0===t){for(i=0,s=0;s<=r;s++)i+=g(r,s)*Math.pow(1-n,r-s)*Math.pow(n,s)*h[s];return i}for(e=new Array(r),s=0;s<r;s++)e[s]=r*(h[s+1]-h[s]);return u(t-1,n,e)}function x(t,n,h){var e=u(1,h,t),i=u(1,h,n),s=e*e+i*i;return Math.sqrt(s)}function y(t,n,h){var e,i,s,r;void 0===h&&(h=1);for(e=h/2,i=0,s=0;s<20;s++)r=e*m[20][s]+e,i+=S[20][s]*x(t,n,r);return e*i}function c(t,n,h,e,i,s,r,a,o){this.x0=t,this.y0=n,this.rx=h,this.ry=e,this.xAxisRotate=i,this.LargeArcFlag=s,this.SweepFlag=r,this.x1=a,this.y1=o;var g=f(300,function(g){return p({x:t,y:n},h,e,i,s,r,{x:a,y:o},g)});this.length=g.arcLength}function p(t,n,h,e,i,s,r,a){n=Math.abs(n),h=Math.abs(h),e=M(e,360);var o=l(e);if(t.x===r.x&&t.y===r.y)return t;if(0===n||0===h)return this.pointOnLine(t,r,a);var g=(t.x-r.x)/2,u=(t.y-r.y)/2,x={x:Math.cos(o)*g+Math.sin(o)*u,y:-Math.sin(o)*g+Math.cos(o)*u},y=Math.pow(x.x,2)/Math.pow(n,2)+Math.pow(x.y,2)/Math.pow(h,2);y>1&&(n=Math.sqrt(y)*n,h=Math.sqrt(y)*h);var c=Math.pow(n,2)*Math.pow(h,2)-Math.pow(n,2)*Math.pow(x.y,2)-Math.pow(h,2)*Math.pow(x.x,2),p=Math.pow(n,2)*Math.pow(x.y,2)+Math.pow(h,2)*Math.pow(x.x,2),f=c/p;f=f<0?0:f;var w=(i!==s?1:-1)*Math.sqrt(f),v={x:w*(n*x.y/h),y:w*(-h*x.x/n)},A={x:Math.cos(o)*v.x-Math.sin(o)*v.y+(t.x+r.x)/2,y:Math.sin(o)*v.x+Math.cos(o)*v.y+(t.y+r.y)/2},d={x:(x.x-v.x)/n,y:(x.y-v.y)/h},P=L({x:1,y:0},d),b={x:(-x.x-v.x)/n,y:(-x.y-v.y)/h},q=L(d,b);!s&&q>0?q-=2*Math.PI:s&&q<0&&(q+=2*Math.PI),q%=2*Math.PI;var T=P+q*a,m=n*Math.cos(T),S=h*Math.sin(T),F={x:Math.cos(o)*m-Math.sin(o)*S+A.x,y:Math.sin(o)*m+Math.cos(o)*S+A.y};return F.ellipticalArcStartAngle=P,F.ellipticalArcEndAngle=P+q,F.ellipticalArcAngle=T,F.ellipticalArcCenter=A,F.resultantRx=n,F.resultantRy=h,F}function f(t,n){t=t||500;for(var h,e=0,i=[],s=[],r=n(0),a=0;a<t;a++){var o=v(a*(1/t),0,1);h=n(o),e+=w(r,h),s.push([r,h]),i.push({t:o,arcLength:e}),r=h}return h=n(1),s.push([r,h]),e+=w(r,h),i.push({t:1,arcLength:e}),{arcLength:e,arcLengthMap:i,approximationLines:s}}function M(t,n){return(t%n+n)%n}function l(t){return t*(Math.PI/180)}function w(t,n){return Math.sqrt(Math.pow(n.x-t.x,2)+Math.pow(n.y-t.y,2))}function v(t,n,h){return Math.min(Math.max(t,n),h)}function L(t,n){var h=t.x*n.x+t.y*n.y,e=Math.sqrt((Math.pow(t.x,2)+Math.pow(t.y,2))*(Math.pow(n.x,2)+Math.pow(n.y,2)));return(t.x*n.y-t.y*n.x<0?-1:1)*Math.acos(h/e)}function A(t,n,h,e){this.x0=t,this.x1=n,this.y0=h,this.y1=e}var d={a:7,c:6,h:1,l:2,m:2,q:4,s:4,t:2,v:1,z:0},P=/([astvzqmhlc])([^astvzqmhlc]*)/gi,b=function(t){var h=[];return t.replace(P,function(t,e,i){var s=e.toLowerCase();for(i=n(i),"m"===s&&i.length>2&&(h.push([e].concat(i.splice(0,2))),s="l",e="m"===e?"l":"L");i.length>=0;){if(i.length===d[s])return i.unshift(e),h.push(i);if(i.length<d[s])throw new Error("malformed path data");h.push([e].concat(i.splice(0,d[s])))}}),h},q=/-?[0-9]*\.?[0-9]+(?:e[-+]?\d+)?/gi,T=function(t,n,e,i,s,r,a,o){return new h(t,n,e,i,s,r,a,o)};h.prototype={constructor:h,init:function(){this.length=this.getArcLength([this.a.x,this.b.x,this.c.x,this.d.x],[this.a.y,this.b.y,this.c.y,this.d.y])},getTotalLength:function(){return this.length},getPointAtLength:function(t){var n=s(t,this.length,this.getArcLength,[this.a.x,this.b.x,this.c.x,this.d.x],[this.a.y,this.b.y,this.c.y,this.d.y]);return this.getPoint([this.a.x,this.b.x,this.c.x,this.d.x],[this.a.y,this.b.y,this.c.y,this.d.y],n)},getTangentAtLength:function(t){var n=s(t,this.length,this.getArcLength,[this.a.x,this.b.x,this.c.x,this.d.x],[this.a.y,this.b.y,this.c.y,this.d.y]),h=this.getDerivative([this.a.x,this.b.x,this.c.x,this.d.x],[this.a.y,this.b.y,this.c.y,this.d.y],n),e=Math.sqrt(h.x*h.x+h.y*h.y);return e>0?{x:h.x/e,y:h.y/e}:{x:0,y:0}},getPropertiesAtLength:function(t){var n,h=s(t,this.length,this.getArcLength,[this.a.x,this.b.x,this.c.x,this.d.x],[this.a.y,this.b.y,this.c.y,this.d.y]),e=this.getDerivative([this.a.x,this.b.x,this.c.x,this.d.x],[this.a.y,this.b.y,this.c.y,this.d.y],h),i=Math.sqrt(e.x*e.x+e.y*e.y);n=i>0?{x:e.x/i,y:e.y/i}:{x:0,y:0};var r=this.getPoint([this.a.x,this.b.x,this.c.x,this.d.x],[this.a.y,this.b.y,this.c.y,this.d.y],h);return{x:r.x,y:r.y,tangentX:n.x,tangentY:n.y}}};var m=[[],[],[-.5773502691896257,.5773502691896257],[0,-.7745966692414834,.7745966692414834],[-.33998104358485626,.33998104358485626,-.8611363115940526,.8611363115940526],[0,-.5384693101056831,.5384693101056831,-.906179845938664,.906179845938664],[.6612093864662645,-.6612093864662645,-.2386191860831969,.2386191860831969,-.932469514203152,.932469514203152],[0,.4058451513773972,-.4058451513773972,-.7415311855993945,.7415311855993945,-.9491079123427585,.9491079123427585],[-.1834346424956498,.1834346424956498,-.525532409916329,.525532409916329,-.7966664774136267,.7966664774136267,-.9602898564975363,.9602898564975363],[0,-.8360311073266358,.8360311073266358,-.9681602395076261,.9681602395076261,-.3242534234038089,.3242534234038089,-.6133714327005904,.6133714327005904],[-.14887433898163122,.14887433898163122,-.4333953941292472,.4333953941292472,-.6794095682990244,.6794095682990244,-.8650633666889845,.8650633666889845,-.9739065285171717,.9739065285171717],[0,-.26954315595234496,.26954315595234496,-.5190961292068118,.5190961292068118,-.7301520055740494,.7301520055740494,-.8870625997680953,.8870625997680953,-.978228658146057,.978228658146057],[-.1252334085114689,.1252334085114689,-.3678314989981802,.3678314989981802,-.5873179542866175,.5873179542866175,-.7699026741943047,.7699026741943047,-.9041172563704749,.9041172563704749,-.9815606342467192,.9815606342467192],[0,-.2304583159551348,.2304583159551348,-.44849275103644687,.44849275103644687,-.6423493394403402,.6423493394403402,-.8015780907333099,.8015780907333099,-.9175983992229779,.9175983992229779,-.9841830547185881,.9841830547185881],[-.10805494870734367,.10805494870734367,-.31911236892788974,.31911236892788974,-.5152486363581541,.5152486363581541,-.6872929048116855,.6872929048116855,-.827201315069765,.827201315069765,-.9284348836635735,.9284348836635735,-.9862838086968123,.9862838086968123],[0,-.20119409399743451,.20119409399743451,-.3941513470775634,.3941513470775634,-.5709721726085388,.5709721726085388,-.7244177313601701,.7244177313601701,-.8482065834104272,.8482065834104272,-.937273392400706,.937273392400706,-.9879925180204854,.9879925180204854],[-.09501250983763744,.09501250983763744,-.2816035507792589,.2816035507792589,-.45801677765722737,.45801677765722737,-.6178762444026438,.6178762444026438,-.755404408355003,.755404408355003,-.8656312023878318,.8656312023878318,-.9445750230732326,.9445750230732326,-.9894009349916499,.9894009349916499],[0,-.17848418149584785,.17848418149584785,-.3512317634538763,.3512317634538763,-.5126905370864769,.5126905370864769,-.6576711592166907,.6576711592166907,-.7815140038968014,.7815140038968014,-.8802391537269859,.8802391537269859,-.9506755217687678,.9506755217687678,-.9905754753144174,.9905754753144174],[-.0847750130417353,.0847750130417353,-.2518862256915055,.2518862256915055,-.41175116146284263,.41175116146284263,-.5597708310739475,.5597708310739475,-.6916870430603532,.6916870430603532,-.8037049589725231,.8037049589725231,-.8926024664975557,.8926024664975557,-.9558239495713977,.9558239495713977,-.9915651684209309,.9915651684209309],[0,-.16035864564022537,.16035864564022537,-.31656409996362983,.31656409996362983,-.46457074137596094,.46457074137596094,-.600545304661681,.600545304661681,-.7209661773352294,.7209661773352294,-.8227146565371428,.8227146565371428,-.9031559036148179,.9031559036148179,-.96020815213483,.96020815213483,-.9924068438435844,.9924068438435844],[-.07652652113349734,.07652652113349734,-.22778585114164507,.22778585114164507,-.37370608871541955,.37370608871541955,-.5108670019508271,.5108670019508271,-.636053680726515,.636053680726515,-.7463319064601508,.7463319064601508,-.8391169718222188,.8391169718222188,-.912234428251326,.912234428251326,-.9639719272779138,.9639719272779138,-.9931285991850949,.9931285991850949],[0,-.1455618541608951,.1455618541608951,-.2880213168024011,.2880213168024011,-.4243421202074388,.4243421202074388,-.5516188358872198,.5516188358872198,-.6671388041974123,.6671388041974123,-.7684399634756779,.7684399634756779,-.8533633645833173,.8533633645833173,-.9200993341504008,.9200993341504008,-.9672268385663063,.9672268385663063,-.9937521706203895,.9937521706203895],[-.06973927331972223,.06973927331972223,-.20786042668822127,.20786042668822127,-.34193582089208424,.34193582089208424,-.469355837986757,.469355837986757,-.5876404035069116,.5876404035069116,-.6944872631866827,.6944872631866827,-.7878168059792081,.7878168059792081,-.8658125777203002,.8658125777203002,-.926956772187174,.926956772187174,-.9700604978354287,.9700604978354287,-.9942945854823992,.9942945854823992],[0,-.1332568242984661,.1332568242984661,-.26413568097034495,.26413568097034495,-.3903010380302908,.3903010380302908,-.5095014778460075,.5095014778460075,-.6196098757636461,.6196098757636461,-.7186613631319502,.7186613631319502,-.8048884016188399,.8048884016188399,-.8767523582704416,.8767523582704416,-.9329710868260161,.9329710868260161,-.9725424712181152,.9725424712181152,-.9947693349975522,.9947693349975522],[-.06405689286260563,.06405689286260563,-.1911188674736163,.1911188674736163,-.3150426796961634,.3150426796961634,-.4337935076260451,.4337935076260451,-.5454214713888396,.5454214713888396,-.6480936519369755,.6480936519369755,-.7401241915785544,.7401241915785544,-.820001985973903,.820001985973903,-.8864155270044011,.8864155270044011,-.9382745520027328,.9382745520027328,-.9747285559713095,.9747285559713095,-.9951872199970213,.9951872199970213]],S=[[],[],[1,1],[.8888888888888888,.5555555555555556,.5555555555555556],[.6521451548625461,.6521451548625461,.34785484513745385,.34785484513745385],[.5688888888888889,.47862867049936647,.47862867049936647,.23692688505618908,.23692688505618908],[.3607615730481386,.3607615730481386,.46791393457269104,.46791393457269104,.17132449237917036,.17132449237917036],[.4179591836734694,.3818300505051189,.3818300505051189,.27970539148927664,.27970539148927664,.1294849661688697,.1294849661688697],[.362683783378362,.362683783378362,.31370664587788727,.31370664587788727,.22238103445337448,.22238103445337448,.10122853629037626,.10122853629037626],[.3302393550012598,.1806481606948574,.1806481606948574,.08127438836157441,.08127438836157441,.31234707704000286,.31234707704000286,.26061069640293544,.26061069640293544],[.29552422471475287,.29552422471475287,.26926671930999635,.26926671930999635,.21908636251598204,.21908636251598204,.1494513491505806,.1494513491505806,.06667134430868814,.06667134430868814],[.2729250867779006,.26280454451024665,.26280454451024665,.23319376459199048,.23319376459199048,.18629021092773426,.18629021092773426,.1255803694649046,.1255803694649046,.05566856711617366,.05566856711617366],[.24914704581340277,.24914704581340277,.2334925365383548,.2334925365383548,.20316742672306592,.20316742672306592,.16007832854334622,.16007832854334622,.10693932599531843,.10693932599531843,.04717533638651183,.04717533638651183],[.2325515532308739,.22628318026289723,.22628318026289723,.2078160475368885,.2078160475368885,.17814598076194574,.17814598076194574,.13887351021978725,.13887351021978725,.09212149983772845,.09212149983772845,.04048400476531588,.04048400476531588],[.2152638534631578,.2152638534631578,.2051984637212956,.2051984637212956,.18553839747793782,.18553839747793782,.15720316715819355,.15720316715819355,.12151857068790319,.12151857068790319,.08015808715976021,.08015808715976021,.03511946033175186,.03511946033175186],[.2025782419255613,.19843148532711158,.19843148532711158,.1861610000155622,.1861610000155622,.16626920581699392,.16626920581699392,.13957067792615432,.13957067792615432,.10715922046717194,.10715922046717194,.07036604748810812,.07036604748810812,.03075324199611727,.03075324199611727],[.1894506104550685,.1894506104550685,.18260341504492358,.18260341504492358,.16915651939500254,.16915651939500254,.14959598881657674,.14959598881657674,.12462897125553388,.12462897125553388,.09515851168249279,.09515851168249279,.062253523938647894,.062253523938647894,.027152459411754096,.027152459411754096],[.17944647035620653,.17656270536699264,.17656270536699264,.16800410215645004,.16800410215645004,.15404576107681028,.15404576107681028,.13513636846852548,.13513636846852548,.11188384719340397,.11188384719340397,.08503614831717918,.08503614831717918,.0554595293739872,.0554595293739872,.02414830286854793,.02414830286854793],[.1691423829631436,.1691423829631436,.16427648374583273,.16427648374583273,.15468467512626524,.15468467512626524,.14064291467065065,.14064291467065065,.12255520671147846,.12255520671147846,.10094204410628717,.10094204410628717,.07642573025488905,.07642573025488905,.0497145488949698,.0497145488949698,.02161601352648331,.02161601352648331],[.1610544498487837,.15896884339395434,.15896884339395434,.15276604206585967,.15276604206585967,.1426067021736066,.1426067021736066,.12875396253933621,.12875396253933621,.11156664554733399,.11156664554733399,.09149002162245,.09149002162245,.06904454273764123,.06904454273764123,.0448142267656996,.0448142267656996,.019461788229726478,.019461788229726478],[.15275338713072584,.15275338713072584,.14917298647260374,.14917298647260374,.14209610931838204,.14209610931838204,.13168863844917664,.13168863844917664,.11819453196151841,.11819453196151841,.10193011981724044,.10193011981724044,.08327674157670475,.08327674157670475,.06267204833410907,.06267204833410907,.04060142980038694,.04060142980038694,.017614007139152118,.017614007139152118],[.14608113364969041,.14452440398997005,.14452440398997005,.13988739479107315,.13988739479107315,.13226893863333747,.13226893863333747,.12183141605372853,.12183141605372853,.10879729916714838,.10879729916714838,.09344442345603386,.09344442345603386,.0761001136283793,.0761001136283793,.057134425426857205,.057134425426857205,.036953789770852494,.036953789770852494,.016017228257774335,.016017228257774335],[.13925187285563198,.13925187285563198,.13654149834601517,.13654149834601517,.13117350478706238,.13117350478706238,.12325237681051242,.12325237681051242,.11293229608053922,.11293229608053922,.10041414444288096,.10041414444288096,.08594160621706773,.08594160621706773,.06979646842452049,.06979646842452049,.052293335152683286,.052293335152683286,.03377490158481415,.03377490158481415,.0146279952982722,.0146279952982722],[.13365457218610619,.1324620394046966,.1324620394046966,.12890572218808216,.12890572218808216,.12304908430672953,.12304908430672953,.11499664022241136,.11499664022241136,.10489209146454141,.10489209146454141,.09291576606003515,.09291576606003515,.07928141177671895,.07928141177671895,.06423242140852585,.06423242140852585,.04803767173108467,.04803767173108467,.030988005856979445,.030988005856979445,.013411859487141771,.013411859487141771],[.12793819534675216,.12793819534675216,.1258374563468283,.1258374563468283,.12167047292780339,.12167047292780339,.1155056680537256,.1155056680537256,.10744427011596563,.10744427011596563,.09761865210411388,.09761865210411388,.08619016153195327,.08619016153195327,.0733464814110803,.0733464814110803,.05929858491543678,.05929858491543678,.04427743881741981,.04427743881741981,.028531388628933663,.028531388628933663,.0123412297999872,.0123412297999872]],F=[[1],[1,1],[1,2,1],[1,3,3,1]],O=function(t,n,h,e,i,s,r,a,o){return new c(t,n,h,e,i,s,r,a,o)};c.prototype={constructor:c,init:function(){},getTotalLength:function(){return this.length},getPointAtLength:function(t){t<0?t=0:t>this.length&&(t=this.length);var n=p({x:this.x0,y:this.y0},this.rx,this.ry,this.xAxisRotate,this.LargeArcFlag,this.SweepFlag,{x:this.x1,y:this.y1},t/this.length);return{x:n.x,y:n.y}},getTangentAtLength:function(t){t<0?t=0:t>this.length&&(t=this.length);var n=p({x:this.x0,y:this.y0},this.rx,this.ry,this.xAxisRotate,this.LargeArcFlag,this.SweepFlag,{x:this.x1,y:this.y1},t/this.length);return{x:n.x,y:n.y}},getPropertiesAtLength:function(t){var n=this.getTangentAtLength(t),h=this.getPointAtLength(t);return{x:h.x,y:h.y,tangentX:n.x,tangentY:n.y}}};var z=function(t,n,h,e){return new A(t,n,h,e)};A.prototype.getTotalLength=function(){return Math.sqrt(Math.pow(this.x0-this.x1,2)+Math.pow(this.y0-this.y1,2))},A.prototype.getPointAtLength=function(t){var n=t/Math.sqrt(Math.pow(this.x0-this.x1,2)+Math.pow(this.y0-this.y1,2)),h=(this.x1-this.x0)*n,e=(this.y1-this.y0)*n;return{x:this.x0+h,y:this.y0+e}},A.prototype.getTangentAtLength=function(){var t=Math.sqrt((this.x1-this.x0)*(this.x1-this.x0)+(this.y1-this.y0)*(this.y1-this.y0));return{x:(this.x1-this.x0)/t,y:(this.y1-this.y0)/t}},A.prototype.getPropertiesAtLength=function(t){var n=this.getPointAtLength(t),h=this.getTangentAtLength();return{x:n.x,y:n.y,tangentX:h.x,tangentY:h.y}};var C=function(t){function n(t){if(!t)return null;for(var s,r,a=b(t),o=[0,0],g=[0,0],u=0;u<a.length;u++)"M"===a[u][0]?(o=[a[u][1],a[u][2]],r=[o[0],o[1]],i.push(null)):"m"===a[u][0]?(o=[a[u][1]+o[0],a[u][2]+o[1]],r=[o[0],o[1]],i.push(null)):"L"===a[u][0]?(h+=Math.sqrt(Math.pow(o[0]-a[u][1],2)+Math.pow(o[1]-a[u][2],2)),i.push(new z(o[0],a[u][1],o[1],a[u][2])),o=[a[u][1],a[u][2]]):"l"===a[u][0]?(h+=Math.sqrt(Math.pow(a[u][1],2)+Math.pow(a[u][2],2)),i.push(new z(o[0],a[u][1]+o[0],o[1],a[u][2]+o[1])),o=[a[u][1]+o[0],a[u][2]+o[1]]):"H"===a[u][0]?(h+=Math.abs(o[0]-a[u][1]),i.push(new z(o[0],a[u][1],o[1],o[1])),o[0]=a[u][1]):"h"===a[u][0]?(h+=Math.abs(a[u][1]),i.push(new z(o[0],o[0]+a[u][1],o[1],o[1])),o[0]=a[u][1]+o[0]):"V"===a[u][0]?(h+=Math.abs(o[1]-a[u][1]),i.push(new z(o[0],o[0],o[1],a[u][1])),o[1]=a[u][1]):"v"===a[u][0]?(h+=Math.abs(a[u][1]),i.push(new z(o[0],o[0],o[1],o[1]+a[u][1])),o[1]=a[u][1]+o[1]):"z"===a[u][0]||"Z"===a[u][0]?(h+=Math.sqrt(Math.pow(r[0]-o[0],2)+Math.pow(r[1]-o[1],2)),i.push(new z(o[0],r[0],o[1],r[1])),o=[r[0],r[1]]):"C"===a[u][0]?(s=new T(o[0],o[1],a[u][1],a[u][2],a[u][3],a[u][4],a[u][5],a[u][6]),h+=s.getTotalLength(),o=[a[u][5],a[u][6]],i.push(s)):"c"===a[u][0]?(s=new T(o[0],o[1],o[0]+a[u][1],o[1]+a[u][2],o[0]+a[u][3],o[1]+a[u][4],o[0]+a[u][5],o[1]+a[u][6]),h+=s.getTotalLength(),o=[a[u][5]+o[0],a[u][6]+o[1]],i.push(s)):"S"===a[u][0]?(s=u>0&&["C","c","S","s"].indexOf(a[u-1][0])>-1?new T(o[0],o[1],2*o[0]-a[u-1][a[u-1].length-4],2*o[1]-a[u-1][a[u-1].length-3],a[u][1],a[u][2],a[u][3],a[u][4]):new T(o[0],o[1],o[0],o[1],a[u][1],a[u][2],a[u][3],a[u][4]),h+=s.getTotalLength(),o=[a[u][3],a[u][4]],i.push(s)):"s"===a[u][0]?(s=u>0&&["C","c","S","s"].indexOf(a[u-1][0])>-1?new T(o[0],o[1],o[0]+s.d.x-s.c.x,o[1]+s.d.y-s.c.y,o[0]+a[u][1],o[1]+a[u][2],o[0]+a[u][3],o[1]+a[u][4]):new T(o[0],o[1],o[0],o[1],o[0]+a[u][1],o[1]+a[u][2],o[0]+a[u][3],o[1]+a[u][4]),h+=s.getTotalLength(),o=[a[u][3]+o[0],a[u][4]+o[1]],i.push(s)):"Q"===a[u][0]?(s=o[0]==a[u][1]&&o[1]==a[u][2]?new z(a[u][1],a[u][3],a[u][2],a[u][4]):new T(o[0],o[1],a[u][1],a[u][2],a[u][3],a[u][4]),h+=s.getTotalLength(),i.push(s),o=[a[u][3],a[u][4]],g=[a[u][1],a[u][2]]):"q"===a[u][0]?(s=0!=a[u][1]||0!=a[u][2]?new T(o[0],o[1],o[0]+a[u][1],o[1]+a[u][2],o[0]+a[u][3],o[1]+a[u][4]):new z(o[0]+a[u][1],o[0]+a[u][3],o[1]+a[u][2],o[1]+a[u][4]),h+=s.getTotalLength(),g=[o[0]+a[u][1],o[1]+a[u][2]],o=[a[u][3]+o[0],a[u][4]+o[1]],i.push(s)):"T"===a[u][0]?(s=u>0&&["Q","q","T","t"].indexOf(a[u-1][0])>-1?new T(o[0],o[1],2*o[0]-g[0],2*o[1]-g[1],a[u][1],a[u][2]):new z(o[0],a[u][1],o[1],a[u][2]),i.push(s),h+=s.getTotalLength(),g=[2*o[0]-g[0],2*o[1]-g[1]],o=[a[u][1],a[u][2]]):"t"===a[u][0]?(s=u>0&&["Q","q","T","t"].indexOf(a[u-1][0])>-1?new T(o[0],o[1],2*o[0]-g[0],2*o[1]-g[1],o[0]+a[u][1],o[1]+a[u][2]):new z(o[0],o[0]+a[u][1],o[1],o[1]+a[u][2]),h+=s.getTotalLength(),g=[2*o[0]-g[0],2*o[1]-g[1]],o=[a[u][1]+o[0],a[u][2]+o[0]],i.push(s)):"A"===a[u][0]?(s=new O(o[0],o[1],a[u][1],a[u][2],a[u][3],a[u][4],a[u][5],a[u][6],a[u][7]),h+=s.getTotalLength(),o=[a[u][6],a[u][7]],i.push(s)):"a"===a[u][0]&&(s=new O(o[0],o[1],a[u][1],a[u][2],a[u][3],a[u][4],a[u][5],o[0]+a[u][6],o[1]+a[u][7]),h+=s.getTotalLength(),o=[o[0]+a[u][6],o[1]+a[u][7]],i.push(s)),e.push(h);return n}var h=0,e=[],i=[];n.getTotalLength=function(){return h},n.getPointAtLength=function(t){var n=s(t);return i[n.i].getPointAtLength(n.fraction)},n.getTangentAtLength=function(t){var n=s(t);return i[n.i].getTangentAtLength(n.fraction)},n.getPropertiesAtLength=function(t){var n=s(t);return i[n.i].getPropertiesAtLength(n.fraction)},n.getParts=function(){for(var t=[],n=0;n<i.length;n++)if(null!=i[n]){var h={};h.start=i[n].getPointAtLength(0),h.end=i[n].getPointAtLength(e[n]-e[n-1]),h.length=e[n]-e[n-1],function(t){h.getPointAtLength=function(n){return t.getPointAtLength(n)},h.getTangentAtLength=function(n){return t.getTangentAtLength(n)},h.getPropertiesAtLength=function(n){return t.getPropertiesAtLength(n)}}(i[n]),t.push(h)}return t};var s=function(t){t<0?t=0:t>h&&(t=h);for(var n=e.length-1;e[n]>=t&&e[n]>0;)n--;return n++,{fraction:t-e[n-1],i:n}};return n(t)};t.svgPathProperties=C,t.parse=b,t.Bezier=T,Object.defineProperty(t,"__esModule",{value:!0})}); |
{ | ||
"name": "svg-path-properties", | ||
"version": "0.4.2", | ||
"version": "0.4.3", | ||
"description": "Calculate the length for an SVG path, to use it with node or a Canvas element", | ||
@@ -33,8 +33,8 @@ "keywords": [ | ||
"devDependencies": { | ||
"eslint": "3.19.0", | ||
"eslint": "4.19", | ||
"package-preamble": "0.1.0", | ||
"rollup": "0.42.0", | ||
"tape": "4.6.3", | ||
"uglify-js": "2.8.28" | ||
"rollup": "0.58", | ||
"tape": "4.9", | ||
"uglify-js": "3.3" | ||
} | ||
} |
@@ -39,2 +39,3 @@ [![Build Status](https://travis-ci.org/rveciana/svg-path-properties.svg?branch=master)](https://travis-ci.org/rveciana/svg-path-properties) | ||
* http://pomax.github.io/bezierinfo | ||
* Arc elements calculation: https://github.com/MadLittleMods/svg-curve-lib/tree/f07d6008a673816f4cb74a3269164b430c3a95cb | ||
@@ -41,0 +42,0 @@ For path parsing: |
256
src/arc.js
//Calculate ans Arc curve length and positionAtLength | ||
//Definitions taken from https://developer.mozilla.org/en-US/docs/Web/SVG/Tutorial/Paths | ||
import a2c from "./a2c"; | ||
import Bezier from "./bezier"; | ||
//The point in ellipse functions have been taken from https://github.com/MadLittleMods/svg-curve-lib/tree/f07d6008a673816f4cb74a3269164b430c3a95cb | ||
export default function(x0, y0, rx,ry, xAxisRotate, LargeArcFlag,SweepFlag, x,y) { | ||
@@ -11,17 +8,19 @@ return new Arc(x0, y0, rx,ry, xAxisRotate, LargeArcFlag,SweepFlag, x,y); | ||
function Arc(x0, y0,rx,ry, xAxisRotate, LargeArcFlag,SweepFlag,x,y) { | ||
var length = 0; | ||
var partialLengths = []; | ||
var curves = []; | ||
var res = a2c(x0, y0,rx,ry, xAxisRotate, LargeArcFlag,SweepFlag,x,y); | ||
res.forEach(function(d){ | ||
var curve = new Bezier(d[0], d[1], d[2], d[3], d[4], d[5], d[6], d[7]); | ||
var curveLength = curve.getTotalLength(); | ||
length += curveLength; | ||
partialLengths.push(curveLength); | ||
curves.push(curve); | ||
}); | ||
this.length = length; | ||
this.partialLengths = partialLengths; | ||
this.curves = curves; | ||
function Arc(x0, y0,rx,ry, xAxisRotate, LargeArcFlag, SweepFlag,x1,y1) { | ||
this.x0 = x0; | ||
this.y0 = y0; | ||
this.rx = rx; | ||
this.ry = ry; | ||
this.xAxisRotate = xAxisRotate; | ||
this.LargeArcFlag = LargeArcFlag; | ||
this.SweepFlag = SweepFlag; | ||
this.x1 = x1; | ||
this.y1 = y1; | ||
var lengthProperties = approximateArcLengthOfCurve(300, function(t) { | ||
return pointOnEllipticalArc({x: x0, y:y0}, rx, ry, xAxisRotate, | ||
LargeArcFlag, SweepFlag, {x: x1, y:y1}, t); | ||
}); | ||
this.length = lengthProperties.arcLength; | ||
} | ||
@@ -46,17 +45,11 @@ | ||
} | ||
var i = this.partialLengths.length - 1; | ||
var position = pointOnEllipticalArc({x: this.x0, y:this.y0}, | ||
this.rx, this.ry, this.xAxisRotate, | ||
this.LargeArcFlag, this.SweepFlag, | ||
{x: this.x1, y: this.y1}, | ||
fractionLength/this.length); | ||
return {x: position.x, y: position.y}; | ||
while(this.partialLengths[i] >= fractionLength && this.partialLengths[i] > 0){ | ||
i--; | ||
} | ||
if(i<this.partialLengths.length-1){ | ||
i++; | ||
} | ||
var lengthOffset = 0; | ||
for(var j=0; j<i; j++){ | ||
lengthOffset += this.partialLengths[j]; | ||
} | ||
return this.curves[i].getPointAtLength(fractionLength - lengthOffset); | ||
}, | ||
@@ -69,17 +62,10 @@ getTangentAtLength: function(fractionLength) { | ||
} | ||
var i = this.partialLengths.length - 1; | ||
while(this.partialLengths[i] >= fractionLength && this.partialLengths[i] > 0){ | ||
i--; | ||
} | ||
if(i<this.partialLengths.length-1){ | ||
i++; | ||
} | ||
var lengthOffset = 0; | ||
for(var j=0; j<i; j++){ | ||
lengthOffset += this.partialLengths[j]; | ||
} | ||
return this.curves[i].getTangentAtLength(fractionLength - lengthOffset); | ||
var position = pointOnEllipticalArc({x: this.x0, y:this.y0}, | ||
this.rx, this.ry, this.xAxisRotate, | ||
this.LargeArcFlag, this.SweepFlag, | ||
{x: this.x1, y: this.y1}, | ||
fractionLength/this.length); | ||
return {x: position.x, y: position.y}; | ||
}, | ||
@@ -91,2 +77,174 @@ getPropertiesAtLength: function(fractionLength){ | ||
} | ||
}; | ||
}; | ||
function pointOnEllipticalArc(p0, rx, ry, xAxisRotation, largeArcFlag, sweepFlag, p1, t) { | ||
// In accordance to: http://www.w3.org/TR/SVG/implnote.html#ArcOutOfRangeParameters | ||
rx = Math.abs(rx); | ||
ry = Math.abs(ry); | ||
xAxisRotation = mod(xAxisRotation, 360); | ||
var xAxisRotationRadians = toRadians(xAxisRotation); | ||
// If the endpoints are identical, then this is equivalent to omitting the elliptical arc segment entirely. | ||
if(p0.x === p1.x && p0.y === p1.y) { | ||
return p0; | ||
} | ||
// If rx = 0 or ry = 0 then this arc is treated as a straight line segment joining the endpoints. | ||
if(rx === 0 || ry === 0) { | ||
return this.pointOnLine(p0, p1, t); | ||
} | ||
// Following "Conversion from endpoint to center parameterization" | ||
// http://www.w3.org/TR/SVG/implnote.html#ArcConversionEndpointToCenter | ||
// Step #1: Compute transformedPoint | ||
var dx = (p0.x-p1.x)/2; | ||
var dy = (p0.y-p1.y)/2; | ||
var transformedPoint = { | ||
x: Math.cos(xAxisRotationRadians)*dx + Math.sin(xAxisRotationRadians)*dy, | ||
y: -Math.sin(xAxisRotationRadians)*dx + Math.cos(xAxisRotationRadians)*dy | ||
}; | ||
// Ensure radii are large enough | ||
var radiiCheck = Math.pow(transformedPoint.x, 2)/Math.pow(rx, 2) + Math.pow(transformedPoint.y, 2)/Math.pow(ry, 2); | ||
if(radiiCheck > 1) { | ||
rx = Math.sqrt(radiiCheck)*rx; | ||
ry = Math.sqrt(radiiCheck)*ry; | ||
} | ||
// Step #2: Compute transformedCenter | ||
var cSquareNumerator = Math.pow(rx, 2)*Math.pow(ry, 2) - Math.pow(rx, 2)*Math.pow(transformedPoint.y, 2) - Math.pow(ry, 2)*Math.pow(transformedPoint.x, 2); | ||
var cSquareRootDenom = Math.pow(rx, 2)*Math.pow(transformedPoint.y, 2) + Math.pow(ry, 2)*Math.pow(transformedPoint.x, 2); | ||
var cRadicand = cSquareNumerator/cSquareRootDenom; | ||
// Make sure this never drops below zero because of precision | ||
cRadicand = cRadicand < 0 ? 0 : cRadicand; | ||
var cCoef = (largeArcFlag !== sweepFlag ? 1 : -1) * Math.sqrt(cRadicand); | ||
var transformedCenter = { | ||
x: cCoef*((rx*transformedPoint.y)/ry), | ||
y: cCoef*(-(ry*transformedPoint.x)/rx) | ||
}; | ||
// Step #3: Compute center | ||
var center = { | ||
x: Math.cos(xAxisRotationRadians)*transformedCenter.x - Math.sin(xAxisRotationRadians)*transformedCenter.y + ((p0.x+p1.x)/2), | ||
y: Math.sin(xAxisRotationRadians)*transformedCenter.x + Math.cos(xAxisRotationRadians)*transformedCenter.y + ((p0.y+p1.y)/2) | ||
}; | ||
// Step #4: Compute start/sweep angles | ||
// Start angle of the elliptical arc prior to the stretch and rotate operations. | ||
// Difference between the start and end angles | ||
var startVector = { | ||
x: (transformedPoint.x-transformedCenter.x)/rx, | ||
y: (transformedPoint.y-transformedCenter.y)/ry | ||
}; | ||
var startAngle = angleBetween({ | ||
x: 1, | ||
y: 0 | ||
}, startVector); | ||
var endVector = { | ||
x: (-transformedPoint.x-transformedCenter.x)/rx, | ||
y: (-transformedPoint.y-transformedCenter.y)/ry | ||
}; | ||
var sweepAngle = angleBetween(startVector, endVector); | ||
if(!sweepFlag && sweepAngle > 0) { | ||
sweepAngle -= 2*Math.PI; | ||
} | ||
else if(sweepFlag && sweepAngle < 0) { | ||
sweepAngle += 2*Math.PI; | ||
} | ||
// We use % instead of `mod(..)` because we want it to be -360deg to 360deg(but actually in radians) | ||
sweepAngle %= 2*Math.PI; | ||
// From http://www.w3.org/TR/SVG/implnote.html#ArcParameterizationAlternatives | ||
var angle = startAngle+(sweepAngle*t); | ||
var ellipseComponentX = rx*Math.cos(angle); | ||
var ellipseComponentY = ry*Math.sin(angle); | ||
var point = { | ||
x: Math.cos(xAxisRotationRadians)*ellipseComponentX - Math.sin(xAxisRotationRadians)*ellipseComponentY + center.x, | ||
y: Math.sin(xAxisRotationRadians)*ellipseComponentX + Math.cos(xAxisRotationRadians)*ellipseComponentY + center.y | ||
}; | ||
// Attach some extra info to use | ||
point.ellipticalArcStartAngle = startAngle; | ||
point.ellipticalArcEndAngle = startAngle+sweepAngle; | ||
point.ellipticalArcAngle = angle; | ||
point.ellipticalArcCenter = center; | ||
point.resultantRx = rx; | ||
point.resultantRy = ry; | ||
return point; | ||
} | ||
function approximateArcLengthOfCurve(resolution, pointOnCurveFunc) { | ||
// Resolution is the number of segments we use | ||
resolution = resolution ? resolution : 500; | ||
var resultantArcLength = 0; | ||
var arcLengthMap = []; | ||
var approximationLines = []; | ||
var prevPoint = pointOnCurveFunc(0); | ||
var nextPoint; | ||
for(var i = 0; i < resolution; i++) { | ||
var t = clamp(i*(1/resolution), 0, 1); | ||
nextPoint = pointOnCurveFunc(t); | ||
resultantArcLength += distance(prevPoint, nextPoint); | ||
approximationLines.push([prevPoint, nextPoint]); | ||
arcLengthMap.push({ | ||
t: t, | ||
arcLength: resultantArcLength | ||
}); | ||
prevPoint = nextPoint; | ||
} | ||
// Last stretch to the endpoint | ||
nextPoint = pointOnCurveFunc(1); | ||
approximationLines.push([prevPoint, nextPoint]); | ||
resultantArcLength += distance(prevPoint, nextPoint); | ||
arcLengthMap.push({ | ||
t: 1, | ||
arcLength: resultantArcLength | ||
}); | ||
return { | ||
arcLength: resultantArcLength, | ||
arcLengthMap: arcLengthMap, | ||
approximationLines: approximationLines | ||
}; | ||
} | ||
function mod(x, m) { | ||
return (x%m + m)%m; | ||
} | ||
function toRadians(angle) { | ||
return angle * (Math.PI / 180); | ||
} | ||
function distance(p0, p1) { | ||
return Math.sqrt(Math.pow(p1.x-p0.x, 2) + Math.pow(p1.y-p0.y, 2)); | ||
} | ||
function clamp(val, min, max) { | ||
return Math.min(Math.max(val, min), max); | ||
} | ||
function angleBetween(v0, v1) { | ||
var p = v0.x*v1.x + v0.y*v1.y; | ||
var n = Math.sqrt((Math.pow(v0.x, 2)+Math.pow(v0.y, 2)) * (Math.pow(v1.x, 2)+Math.pow(v1.y, 2))); | ||
var sign = v0.x*v1.y - v0.y*v1.x < 0 ? -1 : 1; | ||
var angle = sign*Math.acos(p/n); | ||
//var angle = Math.atan2(v0.y, v0.x) - Math.atan2(v1.y, v1.x); | ||
return angle; | ||
} |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
133210
44
15
1586