instructions

The intersection of a line and a sphere can be solved not only geometrically but also algebraically, that is, by solving a quadratic equation of one variable.

equation

The solution of the quadratic equation is relatively simple, and the formula can be directly applied to solve the problem:So, the final point of intersection is actually 0P + t * d. Whether t exists, that is, whether it intersects, needs to be judged according to the discriminant of the root formula of the quadratic equation of one variable:If the discriminant is greater than 0, there are two points of intersection; Equals 0, an intersection (tangent); Less than 0, no intersection.

Algebraic methods, which essentially replace vector normalization with squares, are theoretically more accurate.

code

static func isIntersection(line:Line.sphere:Sphere) -> Bool {
    let vector = line.position - sphere.position
    let a = length_squared(line.direction)
    let b = dot(line.direction, vector)
    let c = length_squared(vector) - sphere.radius * sphere.radius
    
    let discriminant = b * b - 4 * a * c
    return discriminant > = 0
}

static func intersectionPoint(line:Line.sphere:Sphere) -> (simd_float3, simd_float3)? {
    let vector = line.position - sphere.position
    let a = length_squared(line.direction)
    let b = dot(line.direction, vector)
    let c = length_squared(vector) - sphere.radius * sphere.radius
    
    let discriminant = b * b - 4 * a * c
    if discriminant < 0 {
        return nil
    }
    let x = sqrtf(discriminant)
    let t1 = (-b + x)/(2*a)
    let t2 = (-b - x)/(2*a)
    
    let point1 = line.position + t1 * line.direction
    let point2 = line.position + t2 * line.direction
    return (point1, point2)
}
Copy the code