Swift SceneKit是由两个3D点定义的轴内胶囊点

时间:2017-10-23 17:02:19

标签: ios swift math 3d scenekit

The problem:

问题:我在3D空间中有两点A& B定义轴。 A& B不断变化。我也有一个C点随意移动。我需要在Swift func isInsideCapsule() -> Bool中编写一个函数,它返回点C是否位于围绕轴A-B形成的虚拟3D封壳内。该功能采用三点 A B C &胶囊半径 r 作为输入&返回Bool,true或false。任何人都可以解决这个问题吗?即使只是指向正确方向的数学计算也会有所帮助。我可以解决Swift ..

2 个答案:

答案 0 :(得分:0)

如果从点C到线AB的距离<半径然后点C在胶囊内。

所以你真正需要的是一个检查从线段到点的距离的函数。在下面的SO问题中,您可以轻松地将不同语言的许多有效答案转换为Swift。 Shortest distance between a point and a line segment使用一个用于有限线。

答案 1 :(得分:0)

对于那些感兴趣的人,这里是我如何做到的(带有限制音量风格的选项),在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

}