Newer
Older
pixi.js / packages / graphics / src / utils / QuadraticUtils.js
@Ivan Popelyshev Ivan Popelyshev on 14 Feb 2019 2 KB Fix Adaptive curve formulas (#5442)
import { GRAPHICS_CURVES } from '../const';

/**
 * Utilities for quadratic curves
 * @class
 * @private
 */
export default class QuadraticUtils
{
    /**
     * Calculate length of quadratic curve
     * @see {@link http://www.malczak.linuxpl.com/blog/quadratic-bezier-curve-length/}
     * for the detailed explanation of math behind this.
     *
     * @private
     * @param {number} fromX - x-coordinate of curve start point
     * @param {number} fromY - y-coordinate of curve start point
     * @param {number} cpX - x-coordinate of curve control point
     * @param {number} cpY - y-coordinate of curve control point
     * @param {number} toX - x-coordinate of curve end point
     * @param {number} toY - y-coordinate of curve end point
     * @return {number} Length of quadratic curve
     */
    static curveLength(fromX, fromY, cpX, cpY, toX, toY)
    {
        const ax = fromX - (2.0 * cpX) + toX;
        const ay = fromY - (2.0 * cpY) + toY;
        const bx = (2.0 * cpX) - (2.0 * fromX);
        const by = (2.0 * cpY) - (2.0 * fromY);
        const a = 4.0 * ((ax * ax) + (ay * ay));
        const b = 4.0 * ((ax * bx) + (ay * by));
        const c = (bx * bx) + (by * by);

        const s = 2.0 * Math.sqrt(a + b + c);
        const a2 = Math.sqrt(a);
        const a32 = 2.0 * a * a2;
        const c2 = 2.0 * Math.sqrt(c);
        const ba = b / a2;

        return (
            (a32 * s)
                + (a2 * b * (s - c2))
                + (
                    ((4.0 * c * a) - (b * b))
                   * Math.log(((2.0 * a2) + ba + s) / (ba + c2))
                )
        ) / (4.0 * a32);
    }

    /**
     * Calculate the points for a quadratic bezier curve and then draws it.
     * Based on: https://stackoverflow.com/questions/785097/how-do-i-implement-a-bezier-curve-in-c
     *
     * @private
     * @param {number} cpX - Control point x
     * @param {number} cpY - Control point y
     * @param {number} toX - Destination point x
     * @param {number} toY - Destination point y
     * @param {number[]} points - Points to add segments to.
     */
    static curveTo(cpX, cpY, toX, toY, points)
    {
        const fromX = points[points.length - 2];
        const fromY = points[points.length - 1];

        const n = GRAPHICS_CURVES._segmentsCount(
            QuadraticUtils.curveLength(fromX, fromY, cpX, cpY, toX, toY)
        );

        let xa = 0;
        let ya = 0;

        for (let i = 1; i <= n; ++i)
        {
            const j = i / n;

            xa = fromX + ((cpX - fromX) * j);
            ya = fromY + ((cpY - fromY) * j);

            points.push(xa + (((cpX + ((toX - cpX) * j)) - xa) * j),
                ya + (((cpY + ((toY - cpY) * j)) - ya) * j));
        }
    }
}