Created
September 28, 2022 10:28
-
-
Save eeropic/61143810ddb2bfa0fa365b16a665ccbe to your computer and use it in GitHub Desktop.
Revisions
-
eeropic created this gist
Sep 28, 2022 .There are no files selected for viewing
This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,98 @@ // http://svn.webkit.org/repository/webkit/trunk/Source/WebCore/platform/graphics/UnitBezier.h class UnitBezier { constructor(p1x,p1y,p2x,p2y){ // Calculate the polynomial coefficients, implicit first and last control points are (0,0) and (1,1). this.cx = 3.0 * p1x; this.bx = 3.0 * (p2x - p1x) - this.cx; this.ax = 1.0 - this.cx - this.bx; this.cy = 3.0 * p1y; this.by = 3.0 * (p2y - p1y) - this.cy; this.ay = 1.0 - this.cy - this.by; Object.assign(this, {p1x, p1y, p2x, p2y}) } sampleCurveX(t){ // `ax t^3 + bx t^2 + cx t' expanded using Horner's rule. return ((this.ax * t + this.bx) * t + this.cx) * t; } sampleCurveY(t){ return ((this.ay * t + this.by) * t + this.cy) * t; } sampleCurveDerivativeX(t){ return (3.0 * this.ax * t + 2.0 * this.bx) * t + this.cx; } solveCurveX(x, epsilon){ if (epsilon === undefined) epsilon = 1e-6; if (x < 0.0) return 0.0; if (x > 1.0) return 1.0; var t = x; // First try a few iterations of Newton's method - normally very fast. for (var i = 0; i < 8; i++) { var x2 = this.sampleCurveX(t) - x; if (Math.abs(x2) < epsilon) return t; var d2 = this.sampleCurveDerivativeX(t); if (Math.abs(d2) < 1e-6) break; t = t - x2 / d2; } // Fall back to the bisection method for reliability. var t0 = 0.0; var t1 = 1.0; t = x; for (i = 0; i < 20; i++) { x2 = this.sampleCurveX(t); if (Math.abs(x2 - x) < epsilon) break; if (x > x2) { t0 = t; } else { t1 = t; } t = (t1 - t0) * 0.5 + t0; } return t; } solve(x, epsilon) { return this.sampleCurveY(this.solveCurveX(x, epsilon)); } } let testPath = new Path({ segments: [ new Segment({ point: [180,200], handleOut: [200,20] }), new Segment({ point: [400,500], handleIn: [-200,60] }) ], strokeColor: "red" }) function curveToUnit(curve){ const [x0, y0, x1, y1, x2, y2, x3, y3] = curve.values let w = x3 - x0 let h = y3 - y0 let p1x = (x1 - x0) / w let p1y = (y1 - y0) / h let p2x = (x2 - x0) / w let p2y = (y2 - y0) / h let kek2 = new UnitBezier(p1x, p1y, p2x, p2y) let steps = 40; for(let i = 0; i <= steps; i++){ let xPos = i / steps let yPos = kek2.solve(xPos) let circ = new Shape.Circle({ fillColor:"blue", radius: 2, position: [x0 + xPos * w, y0 + yPos * h] }) } } curveToUnit(testPath.curves[0])