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