path.js 42 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", { value: true });
  3. exports.rectPath = exports.pathToCurve = exports.pathToAbsolute = exports.parsePathString = exports.parsePathArray = exports.intersection = exports.formatPath = exports.fillPathByDiff = exports.fillPath = exports.catmullRomToBezier = void 0;
  4. var util_1 = require("@antv/util");
  5. var SPACES = '\x09\x0a\x0b\x0c\x0d\x20\xa0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\u2028\u2029';
  6. var PATH_COMMAND = new RegExp("([a-z])[" + SPACES + ",]*((-?\\d*\\.?\\d*(?:e[\\-+]?\\d+)?[" + SPACES + "]*,?[" + SPACES + "]*)+)", 'ig');
  7. var PATH_VALUES = new RegExp("(-?\\d*\\.?\\d*(?:e[\\-+]?\\d+)?)[" + SPACES + "]*,?[" + SPACES + "]*", 'ig');
  8. // Parse given path string into an array of arrays of path segments
  9. var parsePathString = function (pathString) {
  10. if (!pathString) {
  11. return null;
  12. }
  13. if (util_1.isArray(pathString)) {
  14. return pathString;
  15. }
  16. var paramCounts = {
  17. a: 7,
  18. c: 6,
  19. o: 2,
  20. h: 1,
  21. l: 2,
  22. m: 2,
  23. r: 4,
  24. q: 4,
  25. s: 4,
  26. t: 2,
  27. v: 1,
  28. u: 3,
  29. z: 0,
  30. };
  31. var data = [];
  32. String(pathString).replace(PATH_COMMAND, function (a, b, c) {
  33. var params = [];
  34. var name = b.toLowerCase();
  35. c.replace(PATH_VALUES, function (a, b) {
  36. b && params.push(+b);
  37. });
  38. if (name === 'm' && params.length > 2) {
  39. data.push([b].concat(params.splice(0, 2)));
  40. name = 'l';
  41. b = b === 'm' ? 'l' : 'L';
  42. }
  43. if (name === 'o' && params.length === 1) {
  44. data.push([b, params[0]]);
  45. }
  46. if (name === 'r') {
  47. data.push([b].concat(params));
  48. }
  49. else {
  50. while (params.length >= paramCounts[name]) {
  51. data.push([b].concat(params.splice(0, paramCounts[name])));
  52. if (!paramCounts[name]) {
  53. break;
  54. }
  55. }
  56. }
  57. return pathString;
  58. });
  59. return data;
  60. };
  61. exports.parsePathString = parsePathString;
  62. // http://schepers.cc/getting-to-the-point
  63. var catmullRomToBezier = function (crp, z) {
  64. var d = [];
  65. // @ts-ignore
  66. for (var i = 0, iLen = crp.length; iLen - 2 * !z > i; i += 2) {
  67. var p = [
  68. {
  69. x: +crp[i - 2],
  70. y: +crp[i - 1],
  71. },
  72. {
  73. x: +crp[i],
  74. y: +crp[i + 1],
  75. },
  76. {
  77. x: +crp[i + 2],
  78. y: +crp[i + 3],
  79. },
  80. {
  81. x: +crp[i + 4],
  82. y: +crp[i + 5],
  83. },
  84. ];
  85. if (z) {
  86. if (!i) {
  87. p[0] = {
  88. x: +crp[iLen - 2],
  89. y: +crp[iLen - 1],
  90. };
  91. }
  92. else if (iLen - 4 === i) {
  93. p[3] = {
  94. x: +crp[0],
  95. y: +crp[1],
  96. };
  97. }
  98. else if (iLen - 2 === i) {
  99. p[2] = {
  100. x: +crp[0],
  101. y: +crp[1],
  102. };
  103. p[3] = {
  104. x: +crp[2],
  105. y: +crp[3],
  106. };
  107. }
  108. }
  109. else {
  110. if (iLen - 4 === i) {
  111. p[3] = p[2];
  112. }
  113. else if (!i) {
  114. p[0] = {
  115. x: +crp[i],
  116. y: +crp[i + 1],
  117. };
  118. }
  119. }
  120. d.push([
  121. 'C',
  122. (-p[0].x + 6 * p[1].x + p[2].x) / 6,
  123. (-p[0].y + 6 * p[1].y + p[2].y) / 6,
  124. (p[1].x + 6 * p[2].x - p[3].x) / 6,
  125. (p[1].y + 6 * p[2].y - p[3].y) / 6,
  126. p[2].x,
  127. p[2].y,
  128. ]);
  129. }
  130. return d;
  131. };
  132. exports.catmullRomToBezier = catmullRomToBezier;
  133. var ellipsePath = function (x, y, rx, ry, a) {
  134. var res = [];
  135. if (a === null && ry === null) {
  136. ry = rx;
  137. }
  138. x = +x;
  139. y = +y;
  140. rx = +rx;
  141. ry = +ry;
  142. if (a !== null) {
  143. var rad = Math.PI / 180;
  144. var x1 = x + rx * Math.cos(-ry * rad);
  145. var x2 = x + rx * Math.cos(-a * rad);
  146. var y1 = y + rx * Math.sin(-ry * rad);
  147. var y2 = y + rx * Math.sin(-a * rad);
  148. res = [
  149. ['M', x1, y1],
  150. ['A', rx, rx, 0, +(a - ry > 180), 0, x2, y2],
  151. ];
  152. }
  153. else {
  154. res = [['M', x, y], ['m', 0, -ry], ['a', rx, ry, 0, 1, 1, 0, 2 * ry], ['a', rx, ry, 0, 1, 1, 0, -2 * ry], ['z']];
  155. }
  156. return res;
  157. };
  158. var pathToAbsolute = function (pathArray) {
  159. pathArray = parsePathString(pathArray);
  160. if (!pathArray || !pathArray.length) {
  161. return [['M', 0, 0]];
  162. }
  163. var res = [];
  164. var x = 0;
  165. var y = 0;
  166. var mx = 0;
  167. var my = 0;
  168. var start = 0;
  169. var pa0;
  170. var dots;
  171. if (pathArray[0][0] === 'M') {
  172. x = +pathArray[0][1];
  173. y = +pathArray[0][2];
  174. mx = x;
  175. my = y;
  176. start++;
  177. res[0] = ['M', x, y];
  178. }
  179. var crz = pathArray.length === 3 &&
  180. pathArray[0][0] === 'M' &&
  181. pathArray[1][0].toUpperCase() === 'R' &&
  182. pathArray[2][0].toUpperCase() === 'Z';
  183. for (var r = void 0, pa = void 0, i = start, ii = pathArray.length; i < ii; i++) {
  184. res.push((r = []));
  185. pa = pathArray[i];
  186. pa0 = pa[0];
  187. if (pa0 !== pa0.toUpperCase()) {
  188. r[0] = pa0.toUpperCase();
  189. switch (r[0]) {
  190. case 'A':
  191. r[1] = pa[1];
  192. r[2] = pa[2];
  193. r[3] = pa[3];
  194. r[4] = pa[4];
  195. r[5] = pa[5];
  196. r[6] = +pa[6] + x;
  197. r[7] = +pa[7] + y;
  198. break;
  199. case 'V':
  200. r[1] = +pa[1] + y;
  201. break;
  202. case 'H':
  203. r[1] = +pa[1] + x;
  204. break;
  205. case 'R':
  206. dots = [x, y].concat(pa.slice(1));
  207. for (var j = 2, jj = dots.length; j < jj; j++) {
  208. dots[j] = +dots[j] + x;
  209. dots[++j] = +dots[j] + y;
  210. }
  211. res.pop();
  212. res = res.concat(catmullRomToBezier(dots, crz));
  213. break;
  214. case 'O':
  215. res.pop();
  216. dots = ellipsePath(x, y, pa[1], pa[2]);
  217. dots.push(dots[0]);
  218. res = res.concat(dots);
  219. break;
  220. case 'U':
  221. res.pop();
  222. res = res.concat(ellipsePath(x, y, pa[1], pa[2], pa[3]));
  223. r = ['U'].concat(res[res.length - 1].slice(-2));
  224. break;
  225. case 'M':
  226. mx = +pa[1] + x;
  227. my = +pa[2] + y;
  228. break; // for lint
  229. default:
  230. for (var j = 1, jj = pa.length; j < jj; j++) {
  231. r[j] = +pa[j] + (j % 2 ? x : y);
  232. }
  233. }
  234. }
  235. else if (pa0 === 'R') {
  236. dots = [x, y].concat(pa.slice(1));
  237. res.pop();
  238. res = res.concat(catmullRomToBezier(dots, crz));
  239. r = ['R'].concat(pa.slice(-2));
  240. }
  241. else if (pa0 === 'O') {
  242. res.pop();
  243. dots = ellipsePath(x, y, pa[1], pa[2]);
  244. dots.push(dots[0]);
  245. res = res.concat(dots);
  246. }
  247. else if (pa0 === 'U') {
  248. res.pop();
  249. res = res.concat(ellipsePath(x, y, pa[1], pa[2], pa[3]));
  250. r = ['U'].concat(res[res.length - 1].slice(-2));
  251. }
  252. else {
  253. for (var k = 0, kk = pa.length; k < kk; k++) {
  254. r[k] = pa[k];
  255. }
  256. }
  257. pa0 = pa0.toUpperCase();
  258. if (pa0 !== 'O') {
  259. switch (r[0]) {
  260. case 'Z':
  261. x = +mx;
  262. y = +my;
  263. break;
  264. case 'H':
  265. x = r[1];
  266. break;
  267. case 'V':
  268. y = r[1];
  269. break;
  270. case 'M':
  271. mx = r[r.length - 2];
  272. my = r[r.length - 1];
  273. break; // for lint
  274. default:
  275. x = r[r.length - 2];
  276. y = r[r.length - 1];
  277. }
  278. }
  279. }
  280. return res;
  281. };
  282. exports.pathToAbsolute = pathToAbsolute;
  283. var l2c = function (x1, y1, x2, y2) {
  284. return [x1, y1, x2, y2, x2, y2];
  285. };
  286. var q2c = function (x1, y1, ax, ay, x2, y2) {
  287. var _13 = 1 / 3;
  288. var _23 = 2 / 3;
  289. return [_13 * x1 + _23 * ax, _13 * y1 + _23 * ay, _13 * x2 + _23 * ax, _13 * y2 + _23 * ay, x2, y2];
  290. };
  291. var a2c = function (x1, y1, rx, ry, angle, large_arc_flag, sweep_flag, x2, y2, recursive) {
  292. // for more information of where this math came from visit:
  293. // http://www.w3.org/TR/SVG11/implnote.html#ArcImplementationNotes
  294. if (rx === ry) {
  295. rx += 1;
  296. }
  297. var _120 = (Math.PI * 120) / 180;
  298. var rad = (Math.PI / 180) * (+angle || 0);
  299. var res = [];
  300. var xy;
  301. var f1;
  302. var f2;
  303. var cx;
  304. var cy;
  305. var rotate = function (x, y, rad) {
  306. var X = x * Math.cos(rad) - y * Math.sin(rad);
  307. var Y = x * Math.sin(rad) + y * Math.cos(rad);
  308. return {
  309. x: X,
  310. y: Y,
  311. };
  312. };
  313. if (!recursive) {
  314. xy = rotate(x1, y1, -rad);
  315. x1 = xy.x;
  316. y1 = xy.y;
  317. xy = rotate(x2, y2, -rad);
  318. x2 = xy.x;
  319. y2 = xy.y;
  320. if (x1 === x2 && y1 === y2) {
  321. // 若弧的起始点和终点重叠则错开一点
  322. x2 += 1;
  323. y2 += 1;
  324. }
  325. // const cos = Math.cos(Math.PI / 180 * angle);
  326. // const sin = Math.sin(Math.PI / 180 * angle);
  327. var x = (x1 - x2) / 2;
  328. var y = (y1 - y2) / 2;
  329. var h = (x * x) / (rx * rx) + (y * y) / (ry * ry);
  330. if (h > 1) {
  331. h = Math.sqrt(h);
  332. rx = h * rx;
  333. ry = h * ry;
  334. }
  335. var rx2 = rx * rx;
  336. var ry2 = ry * ry;
  337. var k = (large_arc_flag === sweep_flag ? -1 : 1) *
  338. Math.sqrt(Math.abs((rx2 * ry2 - rx2 * y * y - ry2 * x * x) / (rx2 * y * y + ry2 * x * x)));
  339. cx = (k * rx * y) / ry + (x1 + x2) / 2;
  340. cy = (k * -ry * x) / rx + (y1 + y2) / 2;
  341. // @ts-ignore
  342. f1 = Math.asin(((y1 - cy) / ry).toFixed(9));
  343. // @ts-ignore
  344. f2 = Math.asin(((y2 - cy) / ry).toFixed(9));
  345. f1 = x1 < cx ? Math.PI - f1 : f1;
  346. f2 = x2 < cx ? Math.PI - f2 : f2;
  347. f1 < 0 && (f1 = Math.PI * 2 + f1);
  348. f2 < 0 && (f2 = Math.PI * 2 + f2);
  349. if (sweep_flag && f1 > f2) {
  350. f1 = f1 - Math.PI * 2;
  351. }
  352. if (!sweep_flag && f2 > f1) {
  353. f2 = f2 - Math.PI * 2;
  354. }
  355. }
  356. else {
  357. f1 = recursive[0];
  358. f2 = recursive[1];
  359. cx = recursive[2];
  360. cy = recursive[3];
  361. }
  362. var df = f2 - f1;
  363. if (Math.abs(df) > _120) {
  364. var f2old = f2;
  365. var x2old = x2;
  366. var y2old = y2;
  367. f2 = f1 + _120 * (sweep_flag && f2 > f1 ? 1 : -1);
  368. x2 = cx + rx * Math.cos(f2);
  369. y2 = cy + ry * Math.sin(f2);
  370. res = a2c(x2, y2, rx, ry, angle, 0, sweep_flag, x2old, y2old, [f2, f2old, cx, cy]);
  371. }
  372. df = f2 - f1;
  373. var c1 = Math.cos(f1);
  374. var s1 = Math.sin(f1);
  375. var c2 = Math.cos(f2);
  376. var s2 = Math.sin(f2);
  377. var t = Math.tan(df / 4);
  378. var hx = (4 / 3) * rx * t;
  379. var hy = (4 / 3) * ry * t;
  380. var m1 = [x1, y1];
  381. var m2 = [x1 + hx * s1, y1 - hy * c1];
  382. var m3 = [x2 + hx * s2, y2 - hy * c2];
  383. var m4 = [x2, y2];
  384. m2[0] = 2 * m1[0] - m2[0];
  385. m2[1] = 2 * m1[1] - m2[1];
  386. if (recursive) {
  387. return [m2, m3, m4].concat(res);
  388. }
  389. res = [m2, m3, m4].concat(res).join().split(',');
  390. var newres = [];
  391. for (var i = 0, ii = res.length; i < ii; i++) {
  392. newres[i] = i % 2 ? rotate(res[i - 1], res[i], rad).y : rotate(res[i], res[i + 1], rad).x;
  393. }
  394. return newres;
  395. };
  396. var pathToCurve = function (path, path2) {
  397. var p = pathToAbsolute(path);
  398. var p2 = path2 && pathToAbsolute(path2);
  399. var attrs = {
  400. x: 0,
  401. y: 0,
  402. bx: 0,
  403. by: 0,
  404. X: 0,
  405. Y: 0,
  406. qx: null,
  407. qy: null,
  408. };
  409. var attrs2 = {
  410. x: 0,
  411. y: 0,
  412. bx: 0,
  413. by: 0,
  414. X: 0,
  415. Y: 0,
  416. qx: null,
  417. qy: null,
  418. };
  419. var pcoms1 = []; // path commands of original path p
  420. var pcoms2 = []; // path commands of original path p2
  421. var pfirst = ''; // temporary holder for original path command
  422. var pcom = ''; // holder for previous path command of original path
  423. var ii;
  424. var processPath = function (path, d, pcom) {
  425. var nx;
  426. var ny;
  427. if (!path) {
  428. return ['C', d.x, d.y, d.x, d.y, d.x, d.y];
  429. }
  430. !(path[0] in
  431. {
  432. T: 1,
  433. Q: 1,
  434. }) && (d.qx = d.qy = null);
  435. switch (path[0]) {
  436. case 'M':
  437. d.X = path[1];
  438. d.Y = path[2];
  439. break;
  440. case 'A':
  441. path = ['C'].concat(a2c.apply(0, [d.x, d.y].concat(path.slice(1))));
  442. break;
  443. case 'S':
  444. if (pcom === 'C' || pcom === 'S') {
  445. // In "S" case we have to take into account, if the previous command is C/S.
  446. nx = d.x * 2 - d.bx; // And reflect the previous
  447. ny = d.y * 2 - d.by; // command's control point relative to the current point.
  448. }
  449. else {
  450. // or some else or nothing
  451. nx = d.x;
  452. ny = d.y;
  453. }
  454. path = ['C', nx, ny].concat(path.slice(1));
  455. break;
  456. case 'T':
  457. if (pcom === 'Q' || pcom === 'T') {
  458. // In "T" case we have to take into account, if the previous command is Q/T.
  459. d.qx = d.x * 2 - d.qx; // And make a reflection similar
  460. d.qy = d.y * 2 - d.qy; // to case "S".
  461. }
  462. else {
  463. // or something else or nothing
  464. d.qx = d.x;
  465. d.qy = d.y;
  466. }
  467. path = ['C'].concat(q2c(d.x, d.y, d.qx, d.qy, path[1], path[2]));
  468. break;
  469. case 'Q':
  470. d.qx = path[1];
  471. d.qy = path[2];
  472. path = ['C'].concat(q2c(d.x, d.y, path[1], path[2], path[3], path[4]));
  473. break;
  474. case 'L':
  475. path = ['C'].concat(l2c(d.x, d.y, path[1], path[2]));
  476. break;
  477. case 'H':
  478. path = ['C'].concat(l2c(d.x, d.y, path[1], d.y));
  479. break;
  480. case 'V':
  481. path = ['C'].concat(l2c(d.x, d.y, d.x, path[1]));
  482. break;
  483. case 'Z':
  484. path = ['C'].concat(l2c(d.x, d.y, d.X, d.Y));
  485. break;
  486. default:
  487. break;
  488. }
  489. return path;
  490. };
  491. var fixArc = function (pp, i) {
  492. if (pp[i].length > 7) {
  493. pp[i].shift();
  494. var pi = pp[i];
  495. while (pi.length) {
  496. pcoms1[i] = 'A'; // if created multiple C:s, their original seg is saved
  497. p2 && (pcoms2[i] = 'A'); // the same as above
  498. pp.splice(i++, 0, ['C'].concat(pi.splice(0, 6)));
  499. }
  500. pp.splice(i, 1);
  501. ii = Math.max(p.length, (p2 && p2.length) || 0);
  502. }
  503. };
  504. var fixM = function (path1, path2, a1, a2, i) {
  505. if (path1 && path2 && path1[i][0] === 'M' && path2[i][0] !== 'M') {
  506. path2.splice(i, 0, ['M', a2.x, a2.y]);
  507. a1.bx = 0;
  508. a1.by = 0;
  509. a1.x = path1[i][1];
  510. a1.y = path1[i][2];
  511. ii = Math.max(p.length, (p2 && p2.length) || 0);
  512. }
  513. };
  514. ii = Math.max(p.length, (p2 && p2.length) || 0);
  515. for (var i = 0; i < ii; i++) {
  516. p[i] && (pfirst = p[i][0]); // save current path command
  517. if (pfirst !== 'C') {
  518. // C is not saved yet, because it may be result of conversion
  519. pcoms1[i] = pfirst; // Save current path command
  520. i && (pcom = pcoms1[i - 1]); // Get previous path command pcom
  521. }
  522. p[i] = processPath(p[i], attrs, pcom); // Previous path command is inputted to processPath
  523. if (pcoms1[i] !== 'A' && pfirst === 'C')
  524. pcoms1[i] = 'C'; // A is the only command
  525. // which may produce multiple C:s
  526. // so we have to make sure that C is also C in original path
  527. fixArc(p, i); // fixArc adds also the right amount of A:s to pcoms1
  528. if (p2) {
  529. // the same procedures is done to p2
  530. p2[i] && (pfirst = p2[i][0]);
  531. if (pfirst !== 'C') {
  532. pcoms2[i] = pfirst;
  533. i && (pcom = pcoms2[i - 1]);
  534. }
  535. p2[i] = processPath(p2[i], attrs2, pcom);
  536. if (pcoms2[i] !== 'A' && pfirst === 'C') {
  537. pcoms2[i] = 'C';
  538. }
  539. fixArc(p2, i);
  540. }
  541. fixM(p, p2, attrs, attrs2, i);
  542. fixM(p2, p, attrs2, attrs, i);
  543. var seg = p[i];
  544. var seg2 = p2 && p2[i];
  545. var seglen = seg.length;
  546. var seg2len = p2 && seg2.length;
  547. attrs.x = seg[seglen - 2];
  548. attrs.y = seg[seglen - 1];
  549. attrs.bx = parseFloat(seg[seglen - 4]) || attrs.x;
  550. attrs.by = parseFloat(seg[seglen - 3]) || attrs.y;
  551. attrs2.bx = p2 && (parseFloat(seg2[seg2len - 4]) || attrs2.x);
  552. attrs2.by = p2 && (parseFloat(seg2[seg2len - 3]) || attrs2.y);
  553. attrs2.x = p2 && seg2[seg2len - 2];
  554. attrs2.y = p2 && seg2[seg2len - 1];
  555. }
  556. return p2 ? [p, p2] : p;
  557. };
  558. exports.pathToCurve = pathToCurve;
  559. var p2s = /,?([a-z]),?/gi;
  560. var parsePathArray = function (path) {
  561. return path.join(',').replace(p2s, '$1');
  562. };
  563. exports.parsePathArray = parsePathArray;
  564. var base3 = function (t, p1, p2, p3, p4) {
  565. var t1 = -3 * p1 + 9 * p2 - 9 * p3 + 3 * p4;
  566. var t2 = t * t1 + 6 * p1 - 12 * p2 + 6 * p3;
  567. return t * t2 - 3 * p1 + 3 * p2;
  568. };
  569. var bezlen = function (x1, y1, x2, y2, x3, y3, x4, y4, z) {
  570. if (z === null) {
  571. z = 1;
  572. }
  573. z = z > 1 ? 1 : z < 0 ? 0 : z;
  574. var z2 = z / 2;
  575. var n = 12;
  576. var Tvalues = [
  577. -0.1252, 0.1252, -0.3678, 0.3678, -0.5873, 0.5873, -0.7699, 0.7699, -0.9041, 0.9041, -0.9816, 0.9816,
  578. ];
  579. var Cvalues = [0.2491, 0.2491, 0.2335, 0.2335, 0.2032, 0.2032, 0.1601, 0.1601, 0.1069, 0.1069, 0.0472, 0.0472];
  580. var sum = 0;
  581. for (var i = 0; i < n; i++) {
  582. var ct = z2 * Tvalues[i] + z2;
  583. var xbase = base3(ct, x1, x2, x3, x4);
  584. var ybase = base3(ct, y1, y2, y3, y4);
  585. var comb = xbase * xbase + ybase * ybase;
  586. sum += Cvalues[i] * Math.sqrt(comb);
  587. }
  588. return z2 * sum;
  589. };
  590. var curveDim = function (x0, y0, x1, y1, x2, y2, x3, y3) {
  591. var tvalues = [];
  592. var bounds = [[], []];
  593. var a;
  594. var b;
  595. var c;
  596. var t;
  597. for (var i = 0; i < 2; ++i) {
  598. if (i === 0) {
  599. b = 6 * x0 - 12 * x1 + 6 * x2;
  600. a = -3 * x0 + 9 * x1 - 9 * x2 + 3 * x3;
  601. c = 3 * x1 - 3 * x0;
  602. }
  603. else {
  604. b = 6 * y0 - 12 * y1 + 6 * y2;
  605. a = -3 * y0 + 9 * y1 - 9 * y2 + 3 * y3;
  606. c = 3 * y1 - 3 * y0;
  607. }
  608. if (Math.abs(a) < 1e-12) {
  609. if (Math.abs(b) < 1e-12) {
  610. continue;
  611. }
  612. t = -c / b;
  613. if (t > 0 && t < 1) {
  614. tvalues.push(t);
  615. }
  616. continue;
  617. }
  618. var b2ac = b * b - 4 * c * a;
  619. var sqrtb2ac = Math.sqrt(b2ac);
  620. if (b2ac < 0) {
  621. continue;
  622. }
  623. var t1 = (-b + sqrtb2ac) / (2 * a);
  624. if (t1 > 0 && t1 < 1) {
  625. tvalues.push(t1);
  626. }
  627. var t2 = (-b - sqrtb2ac) / (2 * a);
  628. if (t2 > 0 && t2 < 1) {
  629. tvalues.push(t2);
  630. }
  631. }
  632. var j = tvalues.length;
  633. var jlen = j;
  634. var mt;
  635. while (j--) {
  636. t = tvalues[j];
  637. mt = 1 - t;
  638. bounds[0][j] = mt * mt * mt * x0 + 3 * mt * mt * t * x1 + 3 * mt * t * t * x2 + t * t * t * x3;
  639. bounds[1][j] = mt * mt * mt * y0 + 3 * mt * mt * t * y1 + 3 * mt * t * t * y2 + t * t * t * y3;
  640. }
  641. bounds[0][jlen] = x0;
  642. bounds[1][jlen] = y0;
  643. bounds[0][jlen + 1] = x3;
  644. bounds[1][jlen + 1] = y3;
  645. bounds[0].length = bounds[1].length = jlen + 2;
  646. return {
  647. min: {
  648. x: Math.min.apply(0, bounds[0]),
  649. y: Math.min.apply(0, bounds[1]),
  650. },
  651. max: {
  652. x: Math.max.apply(0, bounds[0]),
  653. y: Math.max.apply(0, bounds[1]),
  654. },
  655. };
  656. };
  657. var intersect = function (x1, y1, x2, y2, x3, y3, x4, y4) {
  658. if (Math.max(x1, x2) < Math.min(x3, x4) ||
  659. Math.min(x1, x2) > Math.max(x3, x4) ||
  660. Math.max(y1, y2) < Math.min(y3, y4) ||
  661. Math.min(y1, y2) > Math.max(y3, y4)) {
  662. return;
  663. }
  664. var nx = (x1 * y2 - y1 * x2) * (x3 - x4) - (x1 - x2) * (x3 * y4 - y3 * x4);
  665. var ny = (x1 * y2 - y1 * x2) * (y3 - y4) - (y1 - y2) * (x3 * y4 - y3 * x4);
  666. var denominator = (x1 - x2) * (y3 - y4) - (y1 - y2) * (x3 - x4);
  667. if (!denominator) {
  668. return;
  669. }
  670. var px = nx / denominator;
  671. var py = ny / denominator;
  672. var px2 = +px.toFixed(2);
  673. var py2 = +py.toFixed(2);
  674. if (px2 < +Math.min(x1, x2).toFixed(2) ||
  675. px2 > +Math.max(x1, x2).toFixed(2) ||
  676. px2 < +Math.min(x3, x4).toFixed(2) ||
  677. px2 > +Math.max(x3, x4).toFixed(2) ||
  678. py2 < +Math.min(y1, y2).toFixed(2) ||
  679. py2 > +Math.max(y1, y2).toFixed(2) ||
  680. py2 < +Math.min(y3, y4).toFixed(2) ||
  681. py2 > +Math.max(y3, y4).toFixed(2)) {
  682. return;
  683. }
  684. return {
  685. x: px,
  686. y: py,
  687. };
  688. };
  689. var isPointInsideBBox = function (bbox, x, y) {
  690. return x >= bbox.x && x <= bbox.x + bbox.width && y >= bbox.y && y <= bbox.y + bbox.height;
  691. };
  692. var rectPath = function (x, y, w, h, r) {
  693. if (r) {
  694. return [
  695. ['M', +x + +r, y],
  696. ['l', w - r * 2, 0],
  697. ['a', r, r, 0, 0, 1, r, r],
  698. ['l', 0, h - r * 2],
  699. ['a', r, r, 0, 0, 1, -r, r],
  700. ['l', r * 2 - w, 0],
  701. ['a', r, r, 0, 0, 1, -r, -r],
  702. ['l', 0, r * 2 - h],
  703. ['a', r, r, 0, 0, 1, r, -r],
  704. ['z'],
  705. ];
  706. }
  707. var res = [['M', x, y], ['l', w, 0], ['l', 0, h], ['l', -w, 0], ['z']];
  708. // @ts-ignore
  709. res.parsePathArray = parsePathArray;
  710. return res;
  711. };
  712. exports.rectPath = rectPath;
  713. var box = function (x, y, width, height) {
  714. if (x === null) {
  715. x = y = width = height = 0;
  716. }
  717. if (y === null) {
  718. y = x.y;
  719. width = x.width;
  720. height = x.height;
  721. x = x.x;
  722. }
  723. return {
  724. x: x,
  725. y: y,
  726. width: width,
  727. w: width,
  728. height: height,
  729. h: height,
  730. x2: x + width,
  731. y2: y + height,
  732. cx: x + width / 2,
  733. cy: y + height / 2,
  734. r1: Math.min(width, height) / 2,
  735. r2: Math.max(width, height) / 2,
  736. r0: Math.sqrt(width * width + height * height) / 2,
  737. path: rectPath(x, y, width, height),
  738. vb: [x, y, width, height].join(' '),
  739. };
  740. };
  741. var isBBoxIntersect = function (bbox1, bbox2) {
  742. bbox1 = box(bbox1);
  743. bbox2 = box(bbox2);
  744. return (isPointInsideBBox(bbox2, bbox1.x, bbox1.y) ||
  745. isPointInsideBBox(bbox2, bbox1.x2, bbox1.y) ||
  746. isPointInsideBBox(bbox2, bbox1.x, bbox1.y2) ||
  747. isPointInsideBBox(bbox2, bbox1.x2, bbox1.y2) ||
  748. isPointInsideBBox(bbox1, bbox2.x, bbox2.y) ||
  749. isPointInsideBBox(bbox1, bbox2.x2, bbox2.y) ||
  750. isPointInsideBBox(bbox1, bbox2.x, bbox2.y2) ||
  751. isPointInsideBBox(bbox1, bbox2.x2, bbox2.y2) ||
  752. (((bbox1.x < bbox2.x2 && bbox1.x > bbox2.x) || (bbox2.x < bbox1.x2 && bbox2.x > bbox1.x)) &&
  753. ((bbox1.y < bbox2.y2 && bbox1.y > bbox2.y) || (bbox2.y < bbox1.y2 && bbox2.y > bbox1.y))));
  754. };
  755. var bezierBBox = function (p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y) {
  756. if (!util_1.isArray(p1x)) {
  757. p1x = [p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y];
  758. }
  759. var bbox = curveDim.apply(null, p1x);
  760. return box(bbox.min.x, bbox.min.y, bbox.max.x - bbox.min.x, bbox.max.y - bbox.min.y);
  761. };
  762. var findDotsAtSegment = function (p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, t) {
  763. var t1 = 1 - t;
  764. var t13 = Math.pow(t1, 3);
  765. var t12 = Math.pow(t1, 2);
  766. var t2 = t * t;
  767. var t3 = t2 * t;
  768. var x = t13 * p1x + t12 * 3 * t * c1x + t1 * 3 * t * t * c2x + t3 * p2x;
  769. var y = t13 * p1y + t12 * 3 * t * c1y + t1 * 3 * t * t * c2y + t3 * p2y;
  770. var mx = p1x + 2 * t * (c1x - p1x) + t2 * (c2x - 2 * c1x + p1x);
  771. var my = p1y + 2 * t * (c1y - p1y) + t2 * (c2y - 2 * c1y + p1y);
  772. var nx = c1x + 2 * t * (c2x - c1x) + t2 * (p2x - 2 * c2x + c1x);
  773. var ny = c1y + 2 * t * (c2y - c1y) + t2 * (p2y - 2 * c2y + c1y);
  774. var ax = t1 * p1x + t * c1x;
  775. var ay = t1 * p1y + t * c1y;
  776. var cx = t1 * c2x + t * p2x;
  777. var cy = t1 * c2y + t * p2y;
  778. var alpha = 90 - (Math.atan2(mx - nx, my - ny) * 180) / Math.PI;
  779. // (mx > nx || my < ny) && (alpha += 180);
  780. return {
  781. x: x,
  782. y: y,
  783. m: {
  784. x: mx,
  785. y: my,
  786. },
  787. n: {
  788. x: nx,
  789. y: ny,
  790. },
  791. start: {
  792. x: ax,
  793. y: ay,
  794. },
  795. end: {
  796. x: cx,
  797. y: cy,
  798. },
  799. alpha: alpha,
  800. };
  801. };
  802. var interHelper = function (bez1, bez2, justCount) {
  803. var bbox1 = bezierBBox(bez1);
  804. var bbox2 = bezierBBox(bez2);
  805. if (!isBBoxIntersect(bbox1, bbox2)) {
  806. return justCount ? 0 : [];
  807. }
  808. var l1 = bezlen.apply(0, bez1);
  809. var l2 = bezlen.apply(0, bez2);
  810. var n1 = ~~(l1 / 8);
  811. var n2 = ~~(l2 / 8);
  812. var dots1 = [];
  813. var dots2 = [];
  814. var xy = {};
  815. var res = justCount ? 0 : [];
  816. for (var i = 0; i < n1 + 1; i++) {
  817. var d = findDotsAtSegment.apply(0, bez1.concat(i / n1));
  818. dots1.push({
  819. x: d.x,
  820. y: d.y,
  821. t: i / n1,
  822. });
  823. }
  824. for (var i = 0; i < n2 + 1; i++) {
  825. var d = findDotsAtSegment.apply(0, bez2.concat(i / n2));
  826. dots2.push({
  827. x: d.x,
  828. y: d.y,
  829. t: i / n2,
  830. });
  831. }
  832. for (var i = 0; i < n1; i++) {
  833. for (var j = 0; j < n2; j++) {
  834. var di = dots1[i];
  835. var di1 = dots1[i + 1];
  836. var dj = dots2[j];
  837. var dj1 = dots2[j + 1];
  838. var ci = Math.abs(di1.x - di.x) < 0.001 ? 'y' : 'x';
  839. var cj = Math.abs(dj1.x - dj.x) < 0.001 ? 'y' : 'x';
  840. var is = intersect(di.x, di.y, di1.x, di1.y, dj.x, dj.y, dj1.x, dj1.y);
  841. if (is) {
  842. if (xy[is.x.toFixed(4)] === is.y.toFixed(4)) {
  843. continue;
  844. }
  845. xy[is.x.toFixed(4)] = is.y.toFixed(4);
  846. var t1 = di.t + Math.abs((is[ci] - di[ci]) / (di1[ci] - di[ci])) * (di1.t - di.t);
  847. var t2 = dj.t + Math.abs((is[cj] - dj[cj]) / (dj1[cj] - dj[cj])) * (dj1.t - dj.t);
  848. if (t1 >= 0 && t1 <= 1 && t2 >= 0 && t2 <= 1) {
  849. if (justCount) {
  850. // @ts-ignore
  851. res += 1;
  852. }
  853. else {
  854. // @ts-ignore
  855. res.push({
  856. x: is.x,
  857. y: is.y,
  858. t1: t1,
  859. t2: t2,
  860. });
  861. }
  862. }
  863. }
  864. }
  865. }
  866. return res;
  867. };
  868. var interPathHelper = function (path1, path2, justCount) {
  869. path1 = pathToCurve(path1);
  870. path2 = pathToCurve(path2);
  871. var x1;
  872. var y1;
  873. var x2;
  874. var y2;
  875. var x1m;
  876. var y1m;
  877. var x2m;
  878. var y2m;
  879. var bez1;
  880. var bez2;
  881. var res = justCount ? 0 : [];
  882. for (var i = 0, ii = path1.length; i < ii; i++) {
  883. var pi = path1[i];
  884. if (pi[0] === 'M') {
  885. x1 = x1m = pi[1];
  886. y1 = y1m = pi[2];
  887. }
  888. else {
  889. if (pi[0] === 'C') {
  890. bez1 = [x1, y1].concat(pi.slice(1));
  891. x1 = bez1[6];
  892. y1 = bez1[7];
  893. }
  894. else {
  895. bez1 = [x1, y1, x1, y1, x1m, y1m, x1m, y1m];
  896. x1 = x1m;
  897. y1 = y1m;
  898. }
  899. for (var j = 0, jj = path2.length; j < jj; j++) {
  900. var pj = path2[j];
  901. if (pj[0] === 'M') {
  902. x2 = x2m = pj[1];
  903. y2 = y2m = pj[2];
  904. }
  905. else {
  906. if (pj[0] === 'C') {
  907. bez2 = [x2, y2].concat(pj.slice(1));
  908. x2 = bez2[6];
  909. y2 = bez2[7];
  910. }
  911. else {
  912. bez2 = [x2, y2, x2, y2, x2m, y2m, x2m, y2m];
  913. x2 = x2m;
  914. y2 = y2m;
  915. }
  916. var intr = interHelper(bez1, bez2, justCount);
  917. if (justCount) {
  918. // @ts-ignore
  919. res += intr;
  920. }
  921. else {
  922. // @ts-ignore
  923. for (var k = 0, kk = intr.length; k < kk; k++) {
  924. intr[k].segment1 = i;
  925. intr[k].segment2 = j;
  926. intr[k].bez1 = bez1;
  927. intr[k].bez2 = bez2;
  928. }
  929. // @ts-ignore
  930. res = res.concat(intr);
  931. }
  932. }
  933. }
  934. }
  935. }
  936. return res;
  937. };
  938. var intersection = function (path1, path2) {
  939. return interPathHelper(path1, path2);
  940. };
  941. exports.intersection = intersection;
  942. function decasteljau(points, t) {
  943. var left = [];
  944. var right = [];
  945. function recurse(points, t) {
  946. if (points.length === 1) {
  947. left.push(points[0]);
  948. right.push(points[0]);
  949. }
  950. else {
  951. var middlePoints = [];
  952. for (var i = 0; i < points.length - 1; i++) {
  953. if (i === 0) {
  954. left.push(points[0]);
  955. }
  956. if (i === points.length - 2) {
  957. right.push(points[i + 1]);
  958. }
  959. middlePoints[i] = [
  960. (1 - t) * points[i][0] + t * points[i + 1][0],
  961. (1 - t) * points[i][1] + t * points[i + 1][1],
  962. ];
  963. }
  964. recurse(middlePoints, t);
  965. }
  966. }
  967. if (points.length) {
  968. recurse(points, t);
  969. }
  970. return { left: left, right: right.reverse() };
  971. }
  972. function splitCurve(start, end, count) {
  973. var points = [[start[1], start[2]]];
  974. count = count || 2;
  975. var segments = [];
  976. if (end[0] === 'A') {
  977. points.push(end[6]);
  978. points.push(end[7]);
  979. }
  980. else if (end[0] === 'C') {
  981. points.push([end[1], end[2]]);
  982. points.push([end[3], end[4]]);
  983. points.push([end[5], end[6]]);
  984. }
  985. else if (end[0] === 'S' || end[0] === 'Q') {
  986. points.push([end[1], end[2]]);
  987. points.push([end[3], end[4]]);
  988. }
  989. else {
  990. points.push([end[1], end[2]]);
  991. }
  992. var leftSegments = points;
  993. var t = 1 / count;
  994. for (var i = 0; i < count - 1; i++) {
  995. var rt = t / (1 - t * i);
  996. var split = decasteljau(leftSegments, rt);
  997. segments.push(split.left);
  998. leftSegments = split.right;
  999. }
  1000. segments.push(leftSegments);
  1001. var result = segments.map(function (segment) {
  1002. var cmd = [];
  1003. if (segment.length === 4) {
  1004. cmd.push('C');
  1005. cmd = cmd.concat(segment[2]);
  1006. }
  1007. if (segment.length >= 3) {
  1008. if (segment.length === 3) {
  1009. cmd.push('Q');
  1010. }
  1011. cmd = cmd.concat(segment[1]);
  1012. }
  1013. if (segment.length === 2) {
  1014. cmd.push('L');
  1015. }
  1016. cmd = cmd.concat(segment[segment.length - 1]);
  1017. return cmd;
  1018. });
  1019. return result;
  1020. }
  1021. var splitSegment = function (start, end, count) {
  1022. if (count === 1) {
  1023. return [[].concat(start)];
  1024. }
  1025. var segments = [];
  1026. if (end[0] === 'L' || end[0] === 'C' || end[0] === 'Q') {
  1027. segments = segments.concat(splitCurve(start, end, count));
  1028. }
  1029. else {
  1030. var temp = [].concat(start);
  1031. if (temp[0] === 'M') {
  1032. temp[0] = 'L';
  1033. }
  1034. for (var i = 0; i <= count - 1; i++) {
  1035. segments.push(temp);
  1036. }
  1037. }
  1038. return segments;
  1039. };
  1040. var fillPath = function (source, target) {
  1041. if (source.length === 1) {
  1042. return source;
  1043. }
  1044. var sourceLen = source.length - 1;
  1045. var targetLen = target.length - 1;
  1046. var ratio = sourceLen / targetLen;
  1047. var segmentsToFill = [];
  1048. if (source.length === 1 && source[0][0] === 'M') {
  1049. for (var i = 0; i < targetLen - sourceLen; i++) {
  1050. source.push(source[0]);
  1051. }
  1052. return source;
  1053. }
  1054. for (var i = 0; i < targetLen; i++) {
  1055. var index = Math.floor(ratio * i);
  1056. segmentsToFill[index] = (segmentsToFill[index] || 0) + 1;
  1057. }
  1058. var filled = segmentsToFill.reduce(function (filled, count, i) {
  1059. if (i === sourceLen) {
  1060. return filled.concat(source[sourceLen]);
  1061. }
  1062. return filled.concat(splitSegment(source[i], source[i + 1], count));
  1063. }, []);
  1064. filled.unshift(source[0]);
  1065. if (target[targetLen] === 'Z' || target[targetLen] === 'z') {
  1066. filled.push('Z');
  1067. }
  1068. return filled;
  1069. };
  1070. exports.fillPath = fillPath;
  1071. var isEqual = function (obj1, obj2) {
  1072. if (obj1.length !== obj2.length) {
  1073. return false;
  1074. }
  1075. var result = true;
  1076. util_1.each(obj1, function (item, i) {
  1077. if (item !== obj2[i]) {
  1078. result = false;
  1079. return false;
  1080. }
  1081. });
  1082. return result;
  1083. };
  1084. function getMinDiff(del, add, modify) {
  1085. var type = null;
  1086. var min = modify;
  1087. if (add < min) {
  1088. min = add;
  1089. type = 'add';
  1090. }
  1091. if (del < min) {
  1092. min = del;
  1093. type = 'del';
  1094. }
  1095. return {
  1096. type: type,
  1097. min: min,
  1098. };
  1099. }
  1100. /*
  1101. * https://en.wikipedia.org/wiki/Levenshtein_distance
  1102. * 计算两条path的编辑距离
  1103. */
  1104. var levenshteinDistance = function (source, target) {
  1105. var sourceLen = source.length;
  1106. var targetLen = target.length;
  1107. var sourceSegment;
  1108. var targetSegment;
  1109. var temp = 0;
  1110. if (sourceLen === 0 || targetLen === 0) {
  1111. return null;
  1112. }
  1113. var dist = [];
  1114. for (var i = 0; i <= sourceLen; i++) {
  1115. dist[i] = [];
  1116. dist[i][0] = { min: i };
  1117. }
  1118. for (var j = 0; j <= targetLen; j++) {
  1119. dist[0][j] = { min: j };
  1120. }
  1121. for (var i = 1; i <= sourceLen; i++) {
  1122. sourceSegment = source[i - 1];
  1123. for (var j = 1; j <= targetLen; j++) {
  1124. targetSegment = target[j - 1];
  1125. if (isEqual(sourceSegment, targetSegment)) {
  1126. temp = 0;
  1127. }
  1128. else {
  1129. temp = 1;
  1130. }
  1131. var del = dist[i - 1][j].min + 1;
  1132. var add = dist[i][j - 1].min + 1;
  1133. var modify = dist[i - 1][j - 1].min + temp;
  1134. dist[i][j] = getMinDiff(del, add, modify);
  1135. }
  1136. }
  1137. return dist;
  1138. };
  1139. var fillPathByDiff = function (source, target) {
  1140. var diffMatrix = levenshteinDistance(source, target);
  1141. var sourceLen = source.length;
  1142. var targetLen = target.length;
  1143. var changes = [];
  1144. var index = 1;
  1145. var minPos = 1;
  1146. // 如果source和target不是完全不相等
  1147. if (diffMatrix[sourceLen][targetLen].min !== sourceLen) {
  1148. // 获取从source到target所需改动
  1149. for (var i = 1; i <= sourceLen; i++) {
  1150. var min = diffMatrix[i][i].min;
  1151. minPos = i;
  1152. for (var j = index; j <= targetLen; j++) {
  1153. if (diffMatrix[i][j].min < min) {
  1154. min = diffMatrix[i][j].min;
  1155. minPos = j;
  1156. }
  1157. }
  1158. index = minPos;
  1159. if (diffMatrix[i][index].type) {
  1160. changes.push({ index: i - 1, type: diffMatrix[i][index].type });
  1161. }
  1162. }
  1163. // 对source进行增删path
  1164. for (var i = changes.length - 1; i >= 0; i--) {
  1165. index = changes[i].index;
  1166. if (changes[i].type === 'add') {
  1167. source.splice(index, 0, [].concat(source[index]));
  1168. }
  1169. else {
  1170. source.splice(index, 1);
  1171. }
  1172. }
  1173. }
  1174. // source尾部补齐
  1175. sourceLen = source.length;
  1176. var diff = targetLen - sourceLen;
  1177. if (sourceLen < targetLen) {
  1178. for (var i = 0; i < diff; i++) {
  1179. if (source[sourceLen - 1][0] === 'z' || source[sourceLen - 1][0] === 'Z') {
  1180. source.splice(sourceLen - 2, 0, source[sourceLen - 2]);
  1181. }
  1182. else {
  1183. source.push(source[sourceLen - 1]);
  1184. }
  1185. sourceLen += 1;
  1186. }
  1187. }
  1188. return source;
  1189. };
  1190. exports.fillPathByDiff = fillPathByDiff;
  1191. // 将两个点均分成count个点
  1192. function _splitPoints(points, former, count) {
  1193. var result = [].concat(points);
  1194. var index;
  1195. var t = 1 / (count + 1);
  1196. var formerEnd = _getSegmentPoints(former)[0];
  1197. for (var i = 1; i <= count; i++) {
  1198. t *= i;
  1199. index = Math.floor(points.length * t);
  1200. if (index === 0) {
  1201. result.unshift([formerEnd[0] * t + points[index][0] * (1 - t), formerEnd[1] * t + points[index][1] * (1 - t)]);
  1202. }
  1203. else {
  1204. result.splice(index, 0, [
  1205. formerEnd[0] * t + points[index][0] * (1 - t),
  1206. formerEnd[1] * t + points[index][1] * (1 - t),
  1207. ]);
  1208. }
  1209. }
  1210. return result;
  1211. }
  1212. /*
  1213. * 抽取pathSegment中的关键点
  1214. * M,L,A,Q,H,V一个端点
  1215. * Q, S抽取一个端点,一个控制点
  1216. * C抽取一个端点,两个控制点
  1217. */
  1218. function _getSegmentPoints(segment) {
  1219. var points = [];
  1220. switch (segment[0]) {
  1221. case 'M':
  1222. points.push([segment[1], segment[2]]);
  1223. break;
  1224. case 'L':
  1225. points.push([segment[1], segment[2]]);
  1226. break;
  1227. case 'A':
  1228. points.push([segment[6], segment[7]]);
  1229. break;
  1230. case 'Q':
  1231. points.push([segment[3], segment[4]]);
  1232. points.push([segment[1], segment[2]]);
  1233. break;
  1234. case 'T':
  1235. points.push([segment[1], segment[2]]);
  1236. break;
  1237. case 'C':
  1238. points.push([segment[5], segment[6]]);
  1239. points.push([segment[1], segment[2]]);
  1240. points.push([segment[3], segment[4]]);
  1241. break;
  1242. case 'S':
  1243. points.push([segment[3], segment[4]]);
  1244. points.push([segment[1], segment[2]]);
  1245. break;
  1246. case 'H':
  1247. points.push([segment[1], segment[1]]);
  1248. break;
  1249. case 'V':
  1250. points.push([segment[1], segment[1]]);
  1251. break;
  1252. default:
  1253. }
  1254. return points;
  1255. }
  1256. var formatPath = function (fromPath, toPath) {
  1257. if (fromPath.length <= 1) {
  1258. return fromPath;
  1259. }
  1260. var points;
  1261. for (var i = 0; i < toPath.length; i++) {
  1262. if (fromPath[i][0] !== toPath[i][0]) {
  1263. // 获取fromPath的pathSegment的端点,根据toPath的指令对其改造
  1264. points = _getSegmentPoints(fromPath[i]);
  1265. switch (toPath[i][0]) {
  1266. case 'M':
  1267. fromPath[i] = ['M'].concat(points[0]);
  1268. break;
  1269. case 'L':
  1270. fromPath[i] = ['L'].concat(points[0]);
  1271. break;
  1272. case 'A':
  1273. fromPath[i] = [].concat(toPath[i]);
  1274. fromPath[i][6] = points[0][0];
  1275. fromPath[i][7] = points[0][1];
  1276. break;
  1277. case 'Q':
  1278. if (points.length < 2) {
  1279. if (i > 0) {
  1280. points = _splitPoints(points, fromPath[i - 1], 1);
  1281. }
  1282. else {
  1283. fromPath[i] = toPath[i];
  1284. break;
  1285. }
  1286. }
  1287. fromPath[i] = ['Q'].concat(points.reduce(function (arr, i) {
  1288. return arr.concat(i);
  1289. }, []));
  1290. break;
  1291. case 'T':
  1292. fromPath[i] = ['T'].concat(points[0]);
  1293. break;
  1294. case 'C':
  1295. if (points.length < 3) {
  1296. if (i > 0) {
  1297. points = _splitPoints(points, fromPath[i - 1], 2);
  1298. }
  1299. else {
  1300. fromPath[i] = toPath[i];
  1301. break;
  1302. }
  1303. }
  1304. fromPath[i] = ['C'].concat(points.reduce(function (arr, i) {
  1305. return arr.concat(i);
  1306. }, []));
  1307. break;
  1308. case 'S':
  1309. if (points.length < 2) {
  1310. if (i > 0) {
  1311. points = _splitPoints(points, fromPath[i - 1], 1);
  1312. }
  1313. else {
  1314. fromPath[i] = toPath[i];
  1315. break;
  1316. }
  1317. }
  1318. fromPath[i] = ['S'].concat(points.reduce(function (arr, i) {
  1319. return arr.concat(i);
  1320. }, []));
  1321. break;
  1322. default:
  1323. fromPath[i] = toPath[i];
  1324. }
  1325. }
  1326. }
  1327. return fromPath;
  1328. };
  1329. exports.formatPath = formatPath;
  1330. //# sourceMappingURL=path.js.map