美文网首页
js 切割三角形

js 切割三角形

作者: CODERLIHAO | 来源:发表于2020-05-07 18:49 被阅读0次
    2020-05-07 18.04.12.gif

    前面我说过怎么切割圆形
    三角形的切割就是每一条边(注意是线段)与另一个线段的交点的问题
    我们把三角形的每一条边看成一个向量,切割的线段也是一个向量,这样就是两个向量求交点问题

    image.png
    现有向量AB 与向量CD 相交于P点
    设A(x1,y1) , B(x2, y2),C(x3,y3) , D(x4, y4) ,P(x,y)
    因为向量CP // 向量DP ,向量AP // 向量BP
    向量积

    向量CP = ( x - x3 ,y - y3 )
    向量DP = ( x - x4 ,y - y4 )
    所以 (x - x3(y - y4) - (y - y3)(x - x4) = 0
    x(y3 - y4) + y(x4 - x3) = x4y3 - x3y4
    至此方程1出来了,下面求出方程2

    向量AP = ( x - x1 ,y - y1 )
    向量BP = ( x - x2 ,y - y2 )
    (x - x1(y - y2) - (y - y1)(x - x2) = 0

    x(y1 - y2) + y(x2 - x1) = x2y1 - x1y2
    两个方程组成方程组
    x(y3 - y4) + y(x4 - x3) = x4y3 - x3y4
    x(y1 - y2) + y(x2 - x1) = x2y1 - x1y2
    用行列式求解

    image.png

    需要判断D不能等于0

    image.png image.png image.png
    image.png

    这样就求出交点

    但是有这种情况


    image.png

    线段没有相交,但是用向量计算时还是会计算出交点,此时可以用CP+ PD = CD 并且
    AP + PB = AB来排除这个点

    class TriangleShape extends Shape {
    
            points = null;
            strokeColor = "#098231";
            fillColor = "#098231";
            cutFillColor = "#098231";
            strokeWidth = 0;
    
    
            constructor(option) {
                super(option);
                this.strokeColor = option.strokeColor;
                this.fillColor = option.fillColor;
                this.cutFillColor = option.cutFillColor;
                this.strokeWidth = option.strokeWidth;
                this.points = option.points;
            }
    
            reset(ctx) {
                this.hitChild = null;
                this.child.length = 0;
                this.isCut = false;
                this.drawSelf(ctx);
            }
    
            drawSelf(ctx) {
                ctx.beginPath();
                ctx.fillStyle = this.fillColor;
                ctx.moveTo(this.points[0], this.points[1]);
                ctx.lineTo(this.points[2], this.points[3]);
                ctx.lineTo(this.points[4], this.points[5]);
                ctx.closePath();
                ctx.fill();
                ctx.beginPath();
                ctx.strokeStyle = this.strokeColor;
                ctx.lineWidth = this.strokeWidth;
                ctx.moveTo(this.points[0], this.points[1]);
                ctx.lineTo(this.points[2], this.points[3]);
                ctx.lineTo(this.points[4], this.points[5]);
                ctx.closePath();
                ctx.stroke();
    
                this.drawText("a", this.points[0], this.points[1]);
                this.drawText("b", this.points[2], this.points[3]);
                this.drawText("c", this.points[4], this.points[5]);
            }
    
    
            drawText(text, x, y) {
                ctx.beginPath();
                ctx.font = "40px Arial";
                ctx.fillText(text, x, y);
                ctx.stroke();
            }
    
    
            onTouchUp(event, ctx) {
                super.onTouchUp(event, ctx);
                this.hitChild = null;
                if (this.isCut) {
                    this.drawChild(ctx);
                    return;
                }
    
                const points = this.getPoint();
                if (points && points.length === 2) {
                    this.isCut = true;
                    const p1 = points[0];
                    const p2 = points[1];
    
                    const a = {x: this.points[0], y: this.points[1]};
                    const b = {x: this.points[2], y: this.points[3]};
                    const c = {x: this.points[4], y: this.points[5]};
    
                    const left = Math.min(Math.min(a.x, b.x), c.x);
                    const top = Math.min(Math.min(a.y, b.y), c.y);
                    const right = Math.max(Math.max(a.x, b.x), c.x);
                    const bottom = Math.max(Math.max(a.y, b.y), c.y);
    
                    const images = this.cutShape(p1, p2);
                    this.child.push(new ChildShape(left, top, right - left, bottom - top, images[0]));
                    this.child.push(new ChildShape(left, top, right - left, bottom - top, images[1]));
                    this.drawChild(ctx);
                } else {
                    this.drawSelf(ctx);
                }
            }
    
    
            cutShape(p1, p2) {
                const a = {x: this.points[0], y: this.points[1]};
                const b = {x: this.points[2], y: this.points[3]};
                const c = {x: this.points[4], y: this.points[5]};
                return Utils.toTriangleDataURL(a, b, c, p1, p2, this.fillColor, this.cutFillColor, this.strokeColor, this.strokeWidth);
            }
    
            getPoint() {
                const p = {x: this.cutLine.sx, y: this.cutLine.sy};
                const m = {x: this.cutLine.ex, y: this.cutLine.ey};
    
                const a = {x: this.points[0], y: this.points[1]};
                const b = {x: this.points[2], y: this.points[3]};
                const c = {x: this.points[4], y: this.points[5]};
    
                const array = [];
                const point1 = this.crossPoint(a, b, p, m);
                if (point1) {
                    array.push(point1);
                }
                const point2 = this.crossPoint(b, c, p, m);
                if (point2) {
                    array.push(point2);
                }
                const point3 = this.crossPoint(c, a, p, m);
                if (point3) {
                    array.push(point3);
                }
                return array;
    
            }
    
             crossPoint(a, b, p, m) {
                const D = (a.y - b.y) * (m.x - p.x) - (b.x - a.x) * (p.y - m.y);
                if (D === 0) {
                    //无解
                    return;
                }
                const D1 = (b.x * a.y - a.x * b.y) * (m.x - p.x) - (b.x - a.x) * (m.x * p.y - p.x * m.y);
                const D2 = (a.y - b.y) * (m.x * p.y - p.x * m.y) - (p.y - m.y) * (b.x * a.y - a.x * b.y);
                const point = {x: D1 / D, y: D2 / D};
                if (Math.sqrt(Math.pow(point.x - a.x, 2) + Math.pow(point.y - a.y, 2)) + Math.sqrt(Math.pow(point.x - b.x, 2) + Math.pow(point.y - b.y, 2)) > Math.sqrt(Math.pow(b.x - a.x, 2) + Math.pow(b.y - a.y, 2)) ||
                    Math.sqrt(Math.pow(point.x - p.x, 2) + Math.pow(point.y - p.y, 2)) + Math.sqrt(Math.pow(point.x - m.x, 2) + Math.pow(point.y - m.y, 2)) > Math.sqrt(Math.pow(p.x - m.x, 2) + Math.pow(p.y - m.y, 2))) {
                    return;
                }
                return point;
            }
        }
    

    Demo

    相关文章

      网友评论

          本文标题:js 切割三角形

          本文链接:https://www.haomeiwen.com/subject/xzxzghtx.html