get-arc-params.js 3.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", { value: true });
  3. exports.isSamePoint = void 0;
  4. var mod = function (n, m) {
  5. return ((n % m) + m) % m;
  6. };
  7. // 向量长度
  8. function vMag(v) {
  9. return Math.sqrt(v[0] * v[0] + v[1] * v[1]);
  10. }
  11. // u.v/|u||v|,计算夹角的余弦值
  12. function vRatio(u, v) {
  13. // 当存在一个向量的长度为 0 时,夹角也为 0,即夹角的余弦值为 1
  14. return vMag(u) * vMag(v) ? (u[0] * v[0] + u[1] * v[1]) / (vMag(u) * vMag(v)) : 1;
  15. }
  16. // 向量角度
  17. function vAngle(u, v) {
  18. return (u[0] * v[1] < u[1] * v[0] ? -1 : 1) * Math.acos(vRatio(u, v));
  19. }
  20. /**
  21. * 判断两个点是否重合,点坐标的格式为 [x, y]
  22. * @param {Array} point1 第一个点
  23. * @param {Array} point2 第二个点
  24. */
  25. function isSamePoint(point1, point2) {
  26. return point1[0] === point2[0] && point1[1] === point2[1];
  27. }
  28. exports.isSamePoint = isSamePoint;
  29. // A 0:rx 1:ry 2:x-axis-rotation 3:large-arc-flag 4:sweep-flag 5: x 6: y
  30. function getArcParams(startPoint, params) {
  31. var rx = params[1];
  32. var ry = params[2];
  33. var xRotation = mod((params[3] * Math.PI) / 180, Math.PI * 2);
  34. var arcFlag = params[4];
  35. var sweepFlag = params[5];
  36. // 弧形起点坐标
  37. var x1 = startPoint[0];
  38. var y1 = startPoint[1];
  39. // 弧形终点坐标
  40. var x2 = params[6];
  41. var y2 = params[7];
  42. var xp = (Math.cos(xRotation) * (x1 - x2)) / 2.0 + (Math.sin(xRotation) * (y1 - y2)) / 2.0;
  43. var yp = (-1 * Math.sin(xRotation) * (x1 - x2)) / 2.0 + (Math.cos(xRotation) * (y1 - y2)) / 2.0;
  44. var lambda = (xp * xp) / (rx * rx) + (yp * yp) / (ry * ry);
  45. if (lambda > 1) {
  46. rx *= Math.sqrt(lambda);
  47. ry *= Math.sqrt(lambda);
  48. }
  49. var diff = rx * rx * (yp * yp) + ry * ry * (xp * xp);
  50. var f = diff ? Math.sqrt((rx * rx * (ry * ry) - diff) / diff) : 1;
  51. if (arcFlag === sweepFlag) {
  52. f *= -1;
  53. }
  54. if (isNaN(f)) {
  55. f = 0;
  56. }
  57. // 旋转前的起点坐标,且当长半轴和短半轴的长度为 0 时,坐标按 (0, 0) 处理
  58. var cxp = ry ? (f * rx * yp) / ry : 0;
  59. var cyp = rx ? (f * -ry * xp) / rx : 0;
  60. // 椭圆圆心坐标
  61. var cx = (x1 + x2) / 2.0 + Math.cos(xRotation) * cxp - Math.sin(xRotation) * cyp;
  62. var cy = (y1 + y2) / 2.0 + Math.sin(xRotation) * cxp + Math.cos(xRotation) * cyp;
  63. // 起始点的单位向量
  64. var u = [(xp - cxp) / rx, (yp - cyp) / ry];
  65. // 终止点的单位向量
  66. var v = [(-1 * xp - cxp) / rx, (-1 * yp - cyp) / ry];
  67. // 计算起始点和圆心的连线,与 x 轴正方向的夹角
  68. var theta = vAngle([1, 0], u);
  69. // 计算圆弧起始点和终止点与椭圆圆心连线的夹角
  70. var dTheta = vAngle(u, v);
  71. if (vRatio(u, v) <= -1) {
  72. dTheta = Math.PI;
  73. }
  74. if (vRatio(u, v) >= 1) {
  75. dTheta = 0;
  76. }
  77. if (sweepFlag === 0 && dTheta > 0) {
  78. dTheta = dTheta - 2 * Math.PI;
  79. }
  80. if (sweepFlag === 1 && dTheta < 0) {
  81. dTheta = dTheta + 2 * Math.PI;
  82. }
  83. return {
  84. cx: cx,
  85. cy: cy,
  86. // 弧形的起点和终点相同时,长轴和短轴的长度按 0 处理
  87. rx: isSamePoint(startPoint, [x2, y2]) ? 0 : rx,
  88. ry: isSamePoint(startPoint, [x2, y2]) ? 0 : ry,
  89. startAngle: theta,
  90. endAngle: theta + dTheta,
  91. xRotation: xRotation,
  92. arcFlag: arcFlag,
  93. sweepFlag: sweepFlag,
  94. };
  95. }
  96. exports.default = getArcParams;
  97. //# sourceMappingURL=get-arc-params.js.map