Created
June 20, 2020 10:06
-
-
Save Guseyn/2c25e0c9c8ce56b745b01a54156e78a5 to your computer and use it in GitHub Desktop.
Bezier curve interpolation as svg path
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Based on this excellent article (https://apoorvaj.io/cubic-bezier-through-four-points/) | |
const vectorLength = (p1, p2) => { | |
return Math.sqrt(Math.pow(p1.x - p2.x, 2) + Math.pow(p1.y - p2.y, 2)) | |
} | |
const middleCurvePoints = (firstPoint, secondPoint, thirdPoint, fourthPoint, alpha, epsilon) => { | |
const d1 = Math.pow(vectorLength(secondPoint, firstPoint), alpha) | |
const d2 = Math.pow(vectorLength(thirdPoint, secondPoint), alpha) | |
const d3 = Math.pow(vectorLength(fourthPoint, thirdPoint), alpha) | |
const a1 = Math.pow(d1, 2) | |
const b1 = Math.pow(d2, 2) | |
const c1 = 2 * a1 + 3 * d1 * d2 + b1 | |
const denominator1 = (3 * d1 * (d1 + d2)) || epsilon | |
const firstControlPoint = { | |
x: (a1 * thirdPoint.x - b1 * firstPoint.x + c1 * secondPoint.x) / denominator1, | |
y: (a1 * thirdPoint.y - b1 * firstPoint.y + c1 * secondPoint.y) / denominator1 | |
} | |
const a2 = Math.pow(d3, 2) | |
const b2 = Math.pow(d2, 2) | |
const c2 = 2 * a2 + 3 * d3 * d2 + b2 | |
const denominator2 = (3 * d3 * (d3 + d2)) || epsilon | |
const secondControlPoint = { | |
x: (a2 * secondPoint.x - b2 * fourthPoint.x + c2 * thirdPoint.x) / denominator2, | |
y: (a2 * secondPoint.y - b2 * fourthPoint.y + c2 * thirdPoint.y) / denominator2 | |
} | |
return [ | |
secondPoint.x, secondPoint.y, | |
firstControlPoint.x, firstControlPoint.y, | |
secondControlPoint.x, secondControlPoint.y, | |
thirdPoint.x, thirdPoint.y | |
] | |
} | |
module.exports = (firstPoint, secondPoint, thirdPoint, fourthPoint, alpha = 1) => { | |
// alpha can be also 0.5 or 0 (it's a coefficient of tightness of the line) | |
const epsilon = 0.0001 | |
const firstPhantomPoint = { | |
x: firstPoint.x + epsilon * (firstPoint.x - secondPoint.x), | |
y: firstPoint.y + epsilon * (firstPoint.y - secondPoint.y) | |
} | |
const secondPhantomPoint = { | |
x: thirdPoint.x + epsilon * (thirdPoint.x - fourthPoint.x), | |
y: thirdPoint.y + epsilon * (thirdPoint.x - fourthPoint.x) | |
} | |
const curvePointsBetweenFirstAndSecondPoints = middleCurvePoints(firstPhantomPoint, firstPoint, secondPoint, thirdPoint, alpha, epsilon) | |
const curvePointsBetweenSecondAndThirdPoints = middleCurvePoints(firstPoint, secondPoint, thirdPoint, fourthPoint, alpha, epsilon) | |
const curvePointsBetweenThirdAndFourthPoints = middleCurvePoints(secondPoint, thirdPoint, fourthPoint, secondPhantomPoint, alpha, epsilon) | |
return [ | |
/* 'M', | |
firstPoint.x, firstPoint.y, | |
'L', | |
secondPoint.x, secondPoint.y, | |
'L', | |
thirdPoint.x, thirdPoint.y, | |
'L', | |
fourthPoint.x, fourthPoint.y, */ | |
'M', | |
curvePointsBetweenFirstAndSecondPoints[0], curvePointsBetweenFirstAndSecondPoints[1], | |
'C', | |
curvePointsBetweenFirstAndSecondPoints[2], curvePointsBetweenFirstAndSecondPoints[3], | |
curvePointsBetweenFirstAndSecondPoints[4], curvePointsBetweenFirstAndSecondPoints[5], | |
curvePointsBetweenFirstAndSecondPoints[6], curvePointsBetweenFirstAndSecondPoints[7], | |
// 'M', | |
// curvePointsBetweenSecondAndThirdPoints[0], curvePointsBetweenSecondAndThirdPoints[1], | |
'C', | |
curvePointsBetweenSecondAndThirdPoints[2], curvePointsBetweenSecondAndThirdPoints[3], | |
curvePointsBetweenSecondAndThirdPoints[4], curvePointsBetweenSecondAndThirdPoints[5], | |
curvePointsBetweenSecondAndThirdPoints[6], curvePointsBetweenSecondAndThirdPoints[7], | |
// 'M', | |
// curvePointsBetweenThirdAndFourthPoints[0], curvePointsBetweenThirdAndFourthPoints[1], | |
'C', | |
curvePointsBetweenThirdAndFourthPoints[2], curvePointsBetweenThirdAndFourthPoints[3], | |
curvePointsBetweenThirdAndFourthPoints[4], curvePointsBetweenThirdAndFourthPoints[5], | |
curvePointsBetweenThirdAndFourthPoints[6], curvePointsBetweenThirdAndFourthPoints[7] | |
] | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment