polylineToBezierCurve.js 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. /**
  2. * @description Abstract the polyline formed by N points into a set of bezier curve
  3. * @param {Array} polyline A set of points that make up a polyline
  4. * @param {Boolean} close Closed curve
  5. * @param {Number} offsetA Smoothness
  6. * @param {Number} offsetB Smoothness
  7. * @return {Array|Boolean} A set of bezier curve (Invalid input will return false)
  8. */
  9. function polylineToBezierCurve (polyline, close = false, offsetA = 0.25, offsetB = 0.25) {
  10. if (!(polyline instanceof Array)) {
  11. console.error('polylineToBezierCurve: Parameter polyline must be an array!')
  12. return false
  13. }
  14. if (polyline.length <= 2) {
  15. console.error('polylineToBezierCurve: Converting to a curve requires at least 3 points!')
  16. return false
  17. }
  18. const startPoint = polyline[0]
  19. const bezierCurveLineNum = polyline.length - 1
  20. const bezierCurvePoints = new Array(bezierCurveLineNum).fill(0).map((foo, i) =>
  21. [...getBezierCurveLineControlPoints(polyline, i, close, offsetA, offsetB), polyline[i + 1]])
  22. if (close) closeBezierCurve(bezierCurvePoints, startPoint)
  23. bezierCurvePoints.unshift(polyline[0])
  24. return bezierCurvePoints
  25. }
  26. /**
  27. * @description Get the control points of the Bezier curve
  28. * @param {Array} polyline A set of points that make up a polyline
  29. * @param {Number} index The index of which get controls points's point in polyline
  30. * @param {Boolean} close Closed curve
  31. * @param {Number} offsetA Smoothness
  32. * @param {Number} offsetB Smoothness
  33. * @return {Array} Control points
  34. */
  35. function getBezierCurveLineControlPoints (polyline, index, close = false, offsetA = 0.25, offsetB = 0.25) {
  36. const pointNum = polyline.length
  37. if (pointNum < 3 || index >= pointNum) return
  38. let beforePointIndex = index - 1
  39. if (beforePointIndex < 0) beforePointIndex = (close ? pointNum + beforePointIndex : 0)
  40. let afterPointIndex = index + 1
  41. if (afterPointIndex >= pointNum) afterPointIndex = (close ? afterPointIndex - pointNum : pointNum - 1)
  42. let afterNextPointIndex = index + 2
  43. if (afterNextPointIndex >= pointNum) afterNextPointIndex = (close ? afterNextPointIndex - pointNum : pointNum - 1)
  44. const pointBefore = polyline[beforePointIndex]
  45. const pointMiddle = polyline[index]
  46. const pointAfter = polyline[afterPointIndex]
  47. const pointAfterNext = polyline[afterNextPointIndex]
  48. return [
  49. [
  50. pointMiddle[0] + offsetA * (pointAfter[0] - pointBefore[0]),
  51. pointMiddle[1] + offsetA * (pointAfter[1] - pointBefore[1])
  52. ],
  53. [
  54. pointAfter[0] - offsetB * (pointAfterNext[0] - pointMiddle[0]),
  55. pointAfter[1] - offsetB * (pointAfterNext[1] - pointMiddle[1])
  56. ]
  57. ]
  58. }
  59. /**
  60. * @description Get the last curve of the closure
  61. * @param {Array} bezierCurve A set of sub-curve
  62. * @param {Array} startPoint Start point
  63. * @return {Array} The last curve for closure
  64. */
  65. function closeBezierCurve (bezierCurve, startPoint) {
  66. const firstSubCurve = bezierCurve[0]
  67. const lastSubCurve = bezierCurve.slice(-1)[0]
  68. bezierCurve.push([
  69. getSymmetryPoint(lastSubCurve[1], lastSubCurve[2]),
  70. getSymmetryPoint(firstSubCurve[0], startPoint),
  71. startPoint
  72. ])
  73. return bezierCurve
  74. }
  75. /**
  76. * @description Get the symmetry point
  77. * @param {Array} point Symmetric point
  78. * @param {Array} centerPoint Symmetric center
  79. * @return {Array} Symmetric point
  80. */
  81. function getSymmetryPoint (point, centerPoint) {
  82. const [px, py] = point
  83. const [cx, cy] = centerPoint
  84. const minusX = cx - px
  85. const minusY = cy - py
  86. return [cx + minusX, cy + minusY]
  87. }
  88. export default polylineToBezierCurve