0

The problem:

The problem: I have two points in 3D space A & B which define an axis. A & B constantly change. I also have a point C which moves around arbitrarily. I need to write a function in Swift func isInsideCapsule() -> Bool which returns whether point C is inside the imaginary 3D capsule formed around the axis A-B. The function takes the three points A,B,C & radius of capsule r as inputs & returns a Bool, true or false. Can anyone solve this, and in swift? Even just the maths to point me in the right direction would help & I could work-out the Swift..

Geoff H
  • 3,107
  • 1
  • 28
  • 53

2 Answers2

0

If distance from point C to lineAB < radius then point C is inside the capsule.

So all you need really is a function that checks the distance from a line segment to a point. In the following SO question there are many valid answers for different languages you can easily translate to Swift. Shortest distance between a point and a line segment Use one for finite lines.

Xartec
  • 2,369
  • 11
  • 22
0

For those who are interested, here's how I did it (with option for bounding volume style), in Swift 4;

enum LineBoundingPrimitive: String {

    case infiniteCylinder
    case cylinder
    case capsule

}

func cameraIsOutsideLineBoundingPrimitive(_ boundingPrimitive: LineBoundingPrimitive, A: SCNVector3!, B: SCNVector3!, radius: Float!) -> Bool! {

    guard let C = viewController?.ARView.pointOfView?.worldPosition else { return true }

    // First find the relative positions
    let BA = SCNVector3Make(B.x-A.x, B.y-A.y, B.z-A.z)
    let CA = SCNVector3Make(C.x-C.x, C.y-A.y, C.z-A.z)

    let lengthBA = SCNVector3Distance(vectorStart: A, vectorEnd: B)
    let lengthCA = SCNVector3Distance(vectorStart: A, vectorEnd: C)

    // Find position of closest point along the length of the line, normalized to it's length
    let k = SCNVector3DotProduct(left: BA, right: CA)/(lengthBA*lengthBA)

    switch boundingPrimitive {
    case .infiniteCylinder:
        break
    case .cylinder:
        if k < 0 || k > 1 { return true }
    case .capsule:
        if k < 0 {                
            //Is C within sphere around A
            return lengthPA > radius ? true : false                
        } else if k > 1 {                
            let lengthPB = SCNVector3Distance(vectorStart: P, vectorEnd: B)                
            //Is C within sphere around B
            return lengthPB > radius ? true : false                
        }
    }

    let rightAngleDistanceFromLine = lengthPA-lengthBA*k

    // Are we inside the capsule?
    return radius < distanceFromTether ? true : false

}

func SCNVector3Distance(vectorStart: SCNVector3, vectorEnd: SCNVector3) -> Float {

    return SCNVector3Length(vectorEnd - vectorStart)

}

func SCNVector3DotProduct(left: SCNVector3, right: SCNVector3) -> Float {

    return left.x * right.x + left.y * right.y + left.z * right.z

}
Geoff H
  • 3,107
  • 1
  • 28
  • 53