在ARKit体验中计算旋转的SCNPlane的4个顶点的位置

时间:2019-04-17 13:15:30

标签: ios swift xcode scenekit arkit

我正在使用iOS App,目前正在尝试获取AR体验中旋转的SCNNode的4个顶点的坐标(参考world / rootNode)

从调试此混乱中所看到的,旋转和倾斜的SCNPlane的边界框仍然与世界原点齐平。

我已经在this线程中尝试过该解决方案。

我要检测的平面直接放在ARKit检测到的图像上方:

func renderer(_ renderer: SCNSceneRenderer, didAdd node: SCNNode, for anchor: ARAnchor) {
    guard let imageAnchor = anchor as? ARImageAnchor else { return }
    let referenceImage = imageAnchor.referenceImage

    updateQueue.async {

        // Create a plane to visualize the initial position of the detected image.
        let plane = SCNPlane(width: referenceImage.physicalSize.width,
                             height: referenceImage.physicalSize.height)
        let planeNode = SCNNode(geometry: plane)
        planeNode.opacity = 0.25

        /*
         `SCNPlane` is vertically oriented in its local coordinate space, but
         `ARImageAnchor` assumes the image is horizontal in its local space, so
         rotate the plane to match.
         */
        planeNode.eulerAngles.x = -.pi / 2

        /*
         Image anchors are not tracked after initial detection, so create an
         animation that limits the duration for which the plane visualization appears.
         */
        planeNode.runAction(self.imageHighlightAction)

        // This is where I tried to calculate the edge
        let (min, max) = planeNode.boundingBox

        let topLeft = SCNVector3(min.x, max.y, 0)

        let worldTopLeft = planeNode.convertPosition(topLeft, to: self.sceneView.scene.rootNode)

        let world2dTopLeft = self.sceneView.projectPoint(worldTopLeft)


        node.addChildNode(planeNode)
    }
}

预期结果是屏幕上的某种2D位置,该位置将直接位于3D视图的角上,但是我总是得到的是巨大的数字,例如x: 8847.291, y: -10651.121

有人能解决这个问题吗?

2 个答案:

答案 0 :(得分:0)

从局部空间转换为世界空间时,不应将z位置设置为零。您可以使用边界框minmax的值,而无需修改它们:

let (min, max) = planeNode.boundingBox

// local space to world space
let minWorld = planeNode.convertPosition(min, to: self.sceneView.scene.rootNode)
let maxWorld = planeNode.convertPosition(max, to: self.sceneView.scene.rootNode)

// world space to screen space
let minScreen = self.sceneView.projectPoint(minWorld)
let maxScreen = self.sceneView.projectPoint(maxWorld)

然后可以使用minScreenmaxScreen的x和y坐标并忽略z。

答案 1 :(得分:0)

好,我找到了解决方法:

我需要做一些高级数学计算,一些人可能比我更好地解释。

(适用于Swift 4.2的)工作副本为:

 CASE 
     WHEN o.concat IN  (SELECT DISTINCT ac.id 
                                      || '-' 
                                      || e.DATE :: DATE AS concant 
                      FROM   payment AS e 
                             left join (SELECT id, 
                                               alias 
                                        FROM   account) ac 
                                    ON ac.alias = e.account_alias 
                      WHERE  e.DATE :: DATE = (SELECT Min(e2.DATE :: DATE) 
                                               FROM   payment AS e2 
                                               WHERE 
                             e2.account_alias = e.account_alias) 
                             AND ac.id BETWEEN 600 AND 800) THEN 1 
     ELSE 0 
   END 

这很好用。我希望有人能解释我在那做的事。