计算贝塞尔曲线各个坐标点

计算贝塞尔曲线各个坐标点

class Bezier {
    //  对外变量
    private p0: egret.Point;                    // 起点
    private p1: egret.Point;                    // 贝塞尔点
    private p2: egret.Point;                    // 终点
    private step: number;                        // 分割份数

    private A: number;
    private B: number;
    private C: number;

    private total_length: number;            // 长度
    //  =====================================  方法

    //  速度函数
    private s(t: number): number {
        return Math.sqrt(this.A * t * t + this.B * t + this.C);
    }

    //  长度函数
    private L(t: number): number {
        let temp1: number = Math.sqrt(this.C + t * (this.B + this.A * t));
        let temp2: number = (2 * this.A * t * temp1 + this.B * (temp1 - Math.sqrt(this.C)));
        let temp3: number = Math.log(this.B + 2 * Math.sqrt(this.A) * Math.sqrt(this.C));
        let temp4: number = Math.log(this.B + 2 * this.A * t + 2 * Math.sqrt(this.A) * temp1);
        let temp5: number = 2 * Math.sqrt(this.A) * temp2;
        let temp6: number = (this.B * this.B - 4 * this.A * this.C) * (temp3 - temp4);

        return (temp5 + temp6) / (8 * Math.pow(this.A, 1.5));
    }

    //  长度函数反函数,使用牛顿切线法求解
    private InvertL(t: number, l: number): number {
        let t1: number = t;
        let t2: number;
        do {
            t2 = t1 - (this.L(t1) - l) / this.s(t1);
            if (Math.abs(t1 - t2) < 0.000001) break;
            t1 = t2;
        } while (true);
        return t2;
    }

    //  =====================================  封装
    //  返回所需总步数
    public init(p0: egret.Point, p1: egret.Point, p2: egret.Point, speed: number): number {
        this.p0 = p0;
        this.p1 = p1;
        this.p2 = p2;
        //step = 30;

        let ax = this.p0.x - 2 * this.p1.x + this.p2.x;
        let ay = this.p0.y - 2 * this.p1.y + this.p2.y;
        let bx = 2 * this.p1.x - 2 * this.p0.x;
        let by = 2 * this.p1.y - 2 * this.p0.y;

        this.A = 4 * (ax * ax + ay * ay);
        this.B = 4 * (ax * bx + ay * by);
        this.C = bx * bx + by * by;

        //  计算长度
        this.total_length = this.L(1);

        //  计算步数
        this.step = Math.floor(this.total_length / speed);
        if (this.total_length % speed > speed / 2) this.step++;

        return this.step;
    }

    // 根据指定nIndex位置获取锚点:返回坐标和角度
    public getAnchorPoint(nIndex: number) {
        if (nIndex >= 0 && nIndex <= this.step) {
            let t: number = nIndex / this.step;
            //  如果按照线行增长,此时对应的曲线长度
            let l: number = t * this.total_length;
            //  根据this.L函数的反函数,求得l对应的t值
            t = this.InvertL(t, l);

            //  根据贝塞尔曲线函数,求得取得此时的x,y坐标
            let xx: number = (1 - t) * (1 - t) * this.p0.x + 2 * (1 - t) * t * this.p1.x + t * t * this.p2.x;
            let yy: number = (1 - t) * (1 - t) * this.p0.y + 2 * (1 - t) * t * this.p1.y + t * t * this.p2.y;

            //  获取切线
            let Q0: egret.Point = new egret.Point((1 - t) * this.p0.x + t * this.p1.x, (1 - t) * this.p0.y + t * this.p1.y);
            let Q1: egret.Point = new egret.Point((1 - t) * this.p1.x + t * this.p2.x, (1 - t) * this.p1.y + t * this.p2.y);

            //  计算角度
            let dx: number = Q1.x - Q0.x;
            let dy: number = Q1.y - Q0.y;
            let radian: number = Math.atan2(dy, dx);
            let angle: number = radian * 180 / Math.PI;

            return [xx, yy, angle];
        } else {
            return [];
        }
    }
}

 

this.MapList = []   //生成的坐标数组
let list = this.MapData.mapPos  //写入的坐标数组
let bezier = new Bezier()
for (let i = 0; i < list.length - 2; i++) {
    let p0: egret.Point = (i == 0) ? new egret.Point(list[0][0], list[0][1]) : new egret.Point((list[i][0] + list[i + 1][0]) / 2, (list[i][1] + list[i + 1][1]) / 2);
    let p1: egret.Point = new egret.Point(list[i + 1][0], list[i + 1][1]);
    let p2: egret.Point = (i <= list.length - 4) ? new egret.Point((list[i + 1][0] + list[i + 2][0]) / 2, (list[i + 1][1] + list[i + 2][1]) / 2) : new egret.Point(list[i + 2][0], list[i + 2][1]);
    let steps = bezier.init(p0, p1, p2, 2);
    for (let m = 1; m <= steps; ++m) {
        let data = bezier.getAnchorPoint(m);
        this.MapList.push(data);
    }
}

 

posted @ 2018-12-03 14:38 HaoK 阅读( ...) 评论( ...) 编辑 收藏

你可能感兴趣的:(计算贝塞尔曲线各个坐标点)