bezier.js 2.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", { value: true });
  3. exports.snapLength = exports.nearestPoint = void 0;
  4. var util_1 = require("./util");
  5. var EPSILON = 0.0001;
  6. /**
  7. * 使用牛顿切割法求最近的点
  8. * @param {number[]} xArr 点的 x 数组
  9. * @param {number[]} yArr 点的 y 数组
  10. * @param {number} x 指定的点 x
  11. * @param {number} y 指定的点 y
  12. * @param {Function} tCallback 差值函数
  13. */
  14. function nearestPoint(xArr, yArr, x, y, tCallback, length) {
  15. var t;
  16. var d = Infinity;
  17. var v0 = [x, y];
  18. var segNum = 20;
  19. if (length && length > 200) {
  20. segNum = length / 10;
  21. }
  22. var increaseRate = 1 / segNum;
  23. var interval = increaseRate / 10;
  24. for (var i = 0; i <= segNum; i++) {
  25. var _t = i * increaseRate;
  26. var v1 = [tCallback.apply(null, xArr.concat([_t])), tCallback.apply(null, yArr.concat([_t]))];
  27. var d1 = util_1.distance(v0[0], v0[1], v1[0], v1[1]);
  28. if (d1 < d) {
  29. t = _t;
  30. d = d1;
  31. }
  32. }
  33. // 提前终止
  34. if (t === 0) {
  35. return {
  36. x: xArr[0],
  37. y: yArr[0],
  38. };
  39. }
  40. if (t === 1) {
  41. var count = xArr.length;
  42. return {
  43. x: xArr[count - 1],
  44. y: yArr[count - 1],
  45. };
  46. }
  47. d = Infinity;
  48. for (var i = 0; i < 32; i++) {
  49. if (interval < EPSILON) {
  50. break;
  51. }
  52. var prev = t - interval;
  53. var next = t + interval;
  54. var v1 = [tCallback.apply(null, xArr.concat([prev])), tCallback.apply(null, yArr.concat([prev]))];
  55. var d1 = util_1.distance(v0[0], v0[1], v1[0], v1[1]);
  56. if (prev >= 0 && d1 < d) {
  57. t = prev;
  58. d = d1;
  59. }
  60. else {
  61. var v2 = [tCallback.apply(null, xArr.concat([next])), tCallback.apply(null, yArr.concat([next]))];
  62. var d2 = util_1.distance(v0[0], v0[1], v2[0], v2[1]);
  63. if (next <= 1 && d2 < d) {
  64. t = next;
  65. d = d2;
  66. }
  67. else {
  68. interval *= 0.5;
  69. }
  70. }
  71. }
  72. return {
  73. x: tCallback.apply(null, xArr.concat([t])),
  74. y: tCallback.apply(null, yArr.concat([t])),
  75. };
  76. }
  77. exports.nearestPoint = nearestPoint;
  78. // 近似求解 https://community.khronos.org/t/3d-cubic-bezier-segment-length/62363/2
  79. function snapLength(xArr, yArr) {
  80. var totalLength = 0;
  81. var count = xArr.length;
  82. for (var i = 0; i < count; i++) {
  83. var x = xArr[i];
  84. var y = yArr[i];
  85. var nextX = xArr[(i + 1) % count];
  86. var nextY = yArr[(i + 1) % count];
  87. totalLength += util_1.distance(x, y, nextX, nextY);
  88. }
  89. return totalLength / 2;
  90. }
  91. exports.snapLength = snapLength;
  92. //# sourceMappingURL=bezier.js.map