我正在使用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
有人能解决这个问题吗?
答案 0 :(得分:0)
从局部空间转换为世界空间时,不应将z位置设置为零。您可以使用边界框min
和max
的值,而无需修改它们:
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)
然后可以使用minScreen
和maxScreen
的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
这很好用。我希望有人能解释我在那做的事。