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..
            Asked
            
        
        
            Active
            
        
            Viewed 350 times
        
    0
            
            
         
    
    
        Geoff H
        
- 3,107
- 1
- 28
- 53
- 
                    This isn’t really a swift/scenekit/ios question. – Xartec Oct 23 '17 at 18:03
2 Answers
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
