calculating the point of intersection of two lines

前端 未结 5 1181
栀梦
栀梦 2020-12-05 21:16

I have dynamically generated lines that animate and I want to detect when a lines hits another. I\'m trying to implement some basic linear algebra to obtain the equation of

相关标签:
5条回答
  • 2020-12-05 21:49

    I found a great solution by Paul Bourke. Here it is, implemented in JavaScript:

    function line_intersect(x1, y1, x2, y2, x3, y3, x4, y4)
    {
        var ua, ub, denom = (y4 - y3)*(x2 - x1) - (x4 - x3)*(y2 - y1);
        if (denom == 0) {
            return null;
        }
        ua = ((x4 - x3)*(y1 - y3) - (y4 - y3)*(x1 - x3))/denom;
        ub = ((x2 - x1)*(y1 - y3) - (y2 - y1)*(x1 - x3))/denom;
        return {
            x: x1 + ua * (x2 - x1),
            y: y1 + ua * (y2 - y1),
            seg1: ua >= 0 && ua <= 1,
            seg2: ub >= 0 && ub <= 1
        };
    }
    
    0 讨论(0)
  • 2020-12-05 21:50

    For line segment-line segment intersections, use Paul Borke's solution:

    // line intercept math by Paul Bourke http://paulbourke.net/geometry/pointlineplane/
    // Determine the intersection point of two line segments
    // Return FALSE if the lines don't intersect
    function intersect(x1, y1, x2, y2, x3, y3, x4, y4) {
    
      // Check if none of the lines are of length 0
        if ((x1 === x2 && y1 === y2) || (x3 === x4 && y3 === y4)) {
            return false
        }
    
        denominator = ((y4 - y3) * (x2 - x1) - (x4 - x3) * (y2 - y1))
    
      // Lines are parallel
        if (denominator === 0) {
            return false
        }
    
        let ua = ((x4 - x3) * (y1 - y3) - (y4 - y3) * (x1 - x3)) / denominator
        let ub = ((x2 - x1) * (y1 - y3) - (y2 - y1) * (x1 - x3)) / denominator
    
      // is the intersection along the segments
        if (ua < 0 || ua > 1 || ub < 0 || ub > 1) {
            return false
        }
    
      // Return a object with the x and y coordinates of the intersection
        let x = x1 + ua * (x2 - x1)
        let y = y1 + ua * (y2 - y1)
    
        return {x, y}
    }
    

    For infinite line intersections, use Justin C. Round's algorithm:

    function checkLineIntersection(line1StartX, line1StartY, line1EndX, line1EndY, line2StartX, line2StartY, line2EndX, line2EndY) {
        // if the lines intersect, the result contains the x and y of the intersection (treating the lines as infinite) and booleans for whether line segment 1 or line segment 2 contain the point
        var denominator, a, b, numerator1, numerator2, result = {
            x: null,
            y: null,
            onLine1: false,
            onLine2: false
        };
        denominator = ((line2EndY - line2StartY) * (line1EndX - line1StartX)) - ((line2EndX - line2StartX) * (line1EndY - line1StartY));
        if (denominator == 0) {
            return result;
        }
        a = line1StartY - line2StartY;
        b = line1StartX - line2StartX;
        numerator1 = ((line2EndX - line2StartX) * a) - ((line2EndY - line2StartY) * b);
        numerator2 = ((line1EndX - line1StartX) * a) - ((line1EndY - line1StartY) * b);
        a = numerator1 / denominator;
        b = numerator2 / denominator;
    
        // if we cast these lines infinitely in both directions, they intersect here:
        result.x = line1StartX + (a * (line1EndX - line1StartX));
        result.y = line1StartY + (a * (line1EndY - line1StartY));
    
        // if line1 is a segment and line2 is infinite, they intersect if:
        if (a > 0 && a < 1) {
            result.onLine1 = true;
        }
        // if line2 is a segment and line1 is infinite, they intersect if:
        if (b > 0 && b < 1) {
            result.onLine2 = true;
        }
        // if line1 and line2 are segments, they intersect if both of the above are true
        return result;
    };
    
    0 讨论(0)
  • 2020-12-05 21:54

    You don't need to alternate between adding/subtracting y-intersects when plugging 'found-x' back into one of the equations:

    (function () {
        window.linear = {
            slope: function (x1, y1, x2, y2) {
                if (x1 == x2) return false;
                return (y1 - y2) / (x1 - x2);
            },
            yInt: function (x1, y1, x2, y2) {
                if (x1 === x2) return y1 === 0 ? 0 : false;
                if (y1 === y2) return y1;
                return y1 - this.slope(x1, y1, x2, y2) * x1 ;
            },
            getXInt: function (x1, y1, x2, y2) {
                var slope;
                if (y1 === y2) return x1 == 0 ? 0 : false;
                if (x1 === x2) return x1;
                return (-1 * ((slope = this.slope(x1, y1, x2, y2)) * x1 - y1)) / slope;
            },
            getIntersection: function (x11, y11, x12, y12, x21, y21, x22, y22) {
                var slope1, slope2, yint1, yint2, intx, inty;
                if (x11 == x21 && y11 == y21) return [x11, y11];
                if (x12 == x22 && y12 == y22) return [x12, y22];
    
                slope1 = this.slope(x11, y11, x12, y12);
                slope2 = this.slope(x21, y21, x22, y22);
                if (slope1 === slope2) return false;
    
                yint1 = this.yInt(x11, y11, x12, y12);
                yint2 = this.yInt(x21, y21, x22, y22);
                if (yint1 === yint2) return yint1 === false ? false : [0, yint1];
    
                if (slope1 === false) return [y21, slope2 * y21 + yint2];
                if (slope2 === false) return [y11, slope1 * y11 + yint1];
                intx = (slope1 * x11 + yint1 - yint2)/ slope2;
                return [intx, slope1 * intx + yint1];
            }
        }
    }());
    
    0 讨论(0)
  • 2020-12-05 21:59

    You may do as follows;

    function lineIntersect(a,b){
      a.m = (a[0].y-a[1].y)/(a[0].x-a[1].x);  // slope of line 1
      b.m = (b[0].y-b[1].y)/(b[0].x-b[1].x);  // slope of line 2
      return a.m - b.m < Number.EPSILON ? undefined
                                        : { x: (a.m * a[0].x - b.m*b[0].x + b[0].y - a[0].y) / (a.m - b.m),
                                            y: (a.m*b.m*(b[0].x-a[0].x) + b.m*a[0].y - a.m*b[0].y) / (b.m - a.m)};
    }
    
    var line1 = [{x:3, y:3},{x:17, y:8}],
        line2 = [{x:7, y:10},{x:11, y:2}];
    console.log(lineIntersect(line1, line2));

    0 讨论(0)
  • 2020-12-05 22:12

    There is an npm module that does just that: line-intersect.

    Install it using

    npm install --save line-intersect
    

    ES6 usage:

    import { checkIntersection } from "line-intersect";
    
    const result = lineIntersect.checkIntersection(
      line1.start.x, line1.start.y, line1.end.x, line1.end.y,
      line2.start.x, line2.start.y, line2.end.x, line2.end.y
    );
    
    result.type  // any of "none", "parallel", "colinear", "intersecting"
    result.point // only exists when result.type == 'intersecting'
    

    If you're using typescript, here are the typings:

    declare module "line-intersect" {
      export function checkIntersection(
        x1: number, y1: number,
        x2: number, y2: number,
        x3: number, y3: number,
        x4: number, y4: number): {
            type: string,
            point: {x:number, y:number}
        }; 
    }
    

    Put it in a file and reference if in tsconfig.json's "files" section.

    0 讨论(0)
提交回复
热议问题