Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Swift: Is there an easy way to draw shapes and detect whether they intersect? [duplicate]

Is there an easy way to draw shapes in Swift (preferrably with Sprite-Kit) and then detect if and where they intersect? Like here's an intersecting shape:

enter image description here

like image 220
user3673836 Avatar asked Nov 15 '14 05:11

user3673836


1 Answers

If this consists of a series of line segments, one can adapt Martin R’s answer to UIBezierPath intersect to not only detect intersections, but to also identify where the intersections are:

func intersectionBetweenSegments(_ p0: CGPoint, _ p1: CGPoint, _ p2: CGPoint, _ p3: CGPoint) -> CGPoint? {
    var denominator = (p3.y - p2.y) * (p1.x - p0.x) - (p3.x - p2.x) * (p1.y - p0.y)
    var ua = (p3.x - p2.x) * (p0.y - p2.y) - (p3.y - p2.y) * (p0.x - p2.x)
    var ub = (p1.x - p0.x) * (p0.y - p2.y) - (p1.y - p0.y) * (p0.x - p2.x)
    if (denominator < 0) {
        ua = -ua; ub = -ub; denominator = -denominator
    }
    
    guard ua >= 0 && ua <= denominator && ub >= 0 && ub <= denominator && denominator != 0 else {
        return nil
    }

    return CGPoint(x: p0.x + ua / denominator * (p1.x - p0.x), y: p0.y + ua / denominator * (p1.y - p0.y))
}

Thus, if you have an array of CGPoint values and you want to identify all of the intersections, you could do something like:

let n = points.count - 1

for i in 1 ..< n {
    for j in 0 ..< i-1 {
        if let intersection = intersectionBetweenSegments(points[i], points[i+1], points[j], points[j+1]) {
            // do whatever you want with `intersection`
        }
    }
}

For example, you can add a dot to the screen where the segments intersect:

bezier curve intersections

If, however, your curve consists of cubic bezier curves, it is more complicated. You might consider, though, Checking if two cubic Bézier curves intersect.

like image 192
Rob Avatar answered Nov 01 '22 03:11

Rob