Intersection between two lines in coordinates

后端 未结 6 1673
臣服心动
臣服心动 2020-12-31 19:42

I can detect the intersection point of two lines, but if my line don\'t has the length of my screen, it detects the point, where it shouldn\'t be.

Here a preview:

相关标签:
6条回答
  • 2020-12-31 19:59

    That's the correct equation:

    +(CGPoint) intersection2:(CGPoint)u1 u2:(CGPoint)u2 v1:(CGPoint)v1 v2:(CGPoint)v2 {  
        CGPoint ret=u1;  
        double t=((u1.x-v1.x)*(v1.y-v2.y)-(u1.y-v1.y)*(v1.x-v2.x))  
        /((u1.x-u2.x)*(v1.y-v2.y)-(u1.y-u2.y)*(v1.x-v2.x));  
        ret.x+=(u2.x-u1.x)*t;  
        ret.y+=(u2.y-u1.y)*t;  
        return ret;  
    }  
    

    Also, you can check this library to calculate line intersections: http://www.cprogramdevelop.com/5045485/

    0 讨论(0)
  • 2020-12-31 20:01

    If I understand your question correctly, you need to determine the intersection point of two line segments. This should work with the following method:

    - (NSValue *)intersectionOfLineFrom:(CGPoint)p1 to:(CGPoint)p2 withLineFrom:(CGPoint)p3 to:(CGPoint)p4
    {
        CGFloat d = (p2.x - p1.x)*(p4.y - p3.y) - (p2.y - p1.y)*(p4.x - p3.x);
        if (d == 0)
            return nil; // parallel lines
        CGFloat u = ((p3.x - p1.x)*(p4.y - p3.y) - (p3.y - p1.y)*(p4.x - p3.x))/d;
        CGFloat v = ((p3.x - p1.x)*(p2.y - p1.y) - (p3.y - p1.y)*(p2.x - p1.x))/d;
        if (u < 0.0 || u > 1.0)
            return nil; // intersection point not between p1 and p2
        if (v < 0.0 || v > 1.0)
            return nil; // intersection point not between p3 and p4
        CGPoint intersection;
        intersection.x = p1.x + u * (p2.x - p1.x);
        intersection.y = p1.y + u * (p2.y - p1.y);
    
        return [NSValue valueWithCGPoint:intersection];
    }
    
    0 讨论(0)
  • 2020-12-31 20:03

    This is a slightly modified version of Hayden Holligan's answer to work with Swift 3:

    func getIntersectionOfLines(line1: (a: CGPoint, b: CGPoint), line2: (a: CGPoint, b: CGPoint)) -> CGPoint {
    
        let distance = (line1.b.x - line1.a.x) * (line2.b.y - line2.a.y) - (line1.b.y - line1.a.y) * (line2.b.x - line2.a.x)
        if distance == 0 {
            print("error, parallel lines")
            return CGPoint.zero
        }
    
        let u = ((line2.a.x - line1.a.x) * (line2.b.y - line2.a.y) - (line2.a.y - line1.a.y) * (line2.b.x - line2.a.x)) / distance
        let v = ((line2.a.x - line1.a.x) * (line1.b.y - line1.a.y) - (line2.a.y - line1.a.y) * (line1.b.x - line1.a.x)) / distance
    
        if (u < 0.0 || u > 1.0) {
            print("error, intersection not inside line1")
            return CGPoint.zero
        }
        if (v < 0.0 || v > 1.0) {
            print("error, intersection not inside line2")
            return CGPoint.zero
        }
    
        return CGPoint(x: line1.a.x + u * (line1.b.x - line1.a.x), y: line1.a.y + u * (line1.b.y - line1.a.y))
    }
    
    0 讨论(0)
  • 2020-12-31 20:14

    Swift version

    func getIntersectionOfLines(line1: (a: CGPoint, b: CGPoint), line2: (a: CGPoint, b: CGPoint)) -> CGPoint {
            let distance = (line1.b.x - line1.a.x) * (line2.b.y - line2.a.y) - (line1.b.y - line1.a.y) * (line2.b.x - line2.a.x)
            if distance == 0 {
                print("error, parallel lines")
                return CGPointZero
            }
    
            let u = ((line2.a.x - line1.a.x) * (line2.b.y - line2.a.y) - (line2.a.y - line1.a.y) * (line2.b.x - line2.a.x)) / distance
            let v = ((line2.a.x - line1.a.x) * (line1.b.y - line1.a.y) - (line2.a.y - line1.a.y) * (line1.b.x - line1.a.x)) / distance
    
            if (u < 0.0 || u > 1.0) {
                print("error, intersection not inside line1")
                return CGPointZero
            }
            if (v < 0.0 || v > 1.0) {
                print("error, intersection not inside line2")
                return CGPointZero
            }
    
            return CGPointMake(line1.a.x + u * (line1.b.x - line1.a.x), line1.a.y + u * (line1.b.y - line1.a.y))
        }
    
    0 讨论(0)
  • 2020-12-31 20:16

    Here is another solution in Swift 4.2. This is functionally identical to MartinR's solution but uses simd vectors and matrices to clean it up.

    /// Protocol adoped by any type that models a line segment.
    protocol LineSegment
    {
        /// Point defining an end of a line segment.
        var p1: simd_double2 { get }
        /// Point defining an end of a line segment.
        var p2: simd_double2 { get }
    }
    
    extension LineSegment
    {
        /// Calcualte the intersection between this line segment and another line
        /// segment.
        ///
        /// Algorithm from here:
        /// http://www.cs.swan.ac.uk/~cssimon/line_intersection.html
        ///
        /// - Parameter other: The other line segment.
        /// - Returns: The intersection point, or `nil` if the two line segments are
        ///            parallel or the intersection point would be off the end of
        ///            one of the line segments.
        func intersection(lineSegment other: LineSegment) -> simd_double2?
        {
            let p3 = other.p1 // Name the points so they are consistent with the explanation below
            let p4 = other.p2
            let matrix = simd_double2x2(p4 - p3, p1 - p2)
            guard matrix.determinant != 0 else { return nil } // Determinent == 0 => parallel lines
            let multipliers = matrix.inverse * (p1 - p3)
            // If either of the multipliers is outside the range 0 ... 1, then the
            // intersection would be off the end of one of the line segments.
            guard (0.0 ... 1.0).contains(multipliers.x) && (0.0 ... 1.0).contains(multipliers.y)
                else { return nil }
            return p1 + multipliers.y * (p2 - p1)
        }
    }
    

    The algorithm works because, if you have line segment a defined by two points p1 and p2 and line segment b defined by p3 and p4 the points on a and b are respectively defined by

    • p1 + ta(p2 - p1)
    • p3 + tb(p4 - p3)

    so the point of intersection would be where

    p1 + ta(p2 - p1) = p3 + tb(p4 - p3)

    This can be rearranged as

    p1 - p3 = tb(p4 - p3) + ta(p1 - p2)

    and with a bit of jiggery pokery you can get to the following equivalent

    p1 - p3 = A.t

    where t is the vector (tb, ta) and A is the matrix whose columns are p4 - p3 and p1 - p2

    The equation can be rearranged as

    A-1(p1 - p3) = t

    Everything on the left hand side is already known or can be calculated to get us t. Either of the components of t can be plugged into the respective original equation to get the intersection point (NB floating point rounding errors will mean that the two answers probably aren't exactly the same but are very close).

    Note that, if the lines are parallel, the determinant of A will be zero. Also, if either component is outside the range 0 ... 1, then one or both line segments needs to be extended to get to the point of intersection.

    0 讨论(0)
  • 2020-12-31 20:17

    I know the answer is given and all of them are correct one still, I feel to give my answer to this question. So here it is.

    func linesCross(start1: CGPoint, end1: CGPoint, start2: CGPoint, end2: CGPoint) -> (x: CGFloat, y: CGFloat)? {
    // calculate the differences between the start and end X/Y positions for each of our points
    let delta1x = end1.x - start1.x
    let delta1y = end1.y - start1.y
    let delta2x = end2.x - start2.x
    let delta2y = end2.y - start2.y
    
    // create a 2D matrix from our vectors and calculate the determinant
    let determinant = delta1x * delta2y - delta2x * delta1y
    
    if abs(determinant) < 0.0001 {
        // if the determinant is effectively zero then the lines are parallel/colinear
        return nil
    }
    
    // if the coefficients both lie between 0 and 1 then we have an intersection
    let ab = ((start1.y - start2.y) * delta2x - (start1.x - start2.x) * delta2y) / determinant
    
    if ab > 0 && ab < 1 {
        let cd = ((start1.y - start2.y) * delta1x - (start1.x - start2.x) * delta1y) / determinant
    
        if cd > 0 && cd < 1 {
            // lines cross – figure out exactly where and return it
            let intersectX = start1.x + ab * delta1x
            let intersectY = start1.y + ab * delta1y
            return (intersectX, intersectY)
        }
    }
    
    // lines don't cross
    return nil
    }
    

    I get this from this site.

    This one is very simple and easy, too.

    Happy Coding :)

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