0

I have a bunch of markers placed in my scene as childNodes at fixed node positions in 3D world. When I move the phone around, I need to determine which marker node is the closest to the 2D screen center, so I can get the text description corresponding to that node and display it.

Right now, in a renderloop, I just determined the distance of each node from the screen center in a forEach loop, and decide if that distance is <150, if so get title and copy of that node. However, this doesn't solve my problem because there could be multiple nodes that satisfy that condition. I need to compare the distances from the center across all the nodes and get that one node that's is closest

func renderer(_ renderer: SCNSceneRenderer, willRenderScene scene: SCNScene, atTime time: TimeInterval){

    scene.rootNode.childNodes.filter{ $0.name != nil }.forEach{ node in

        guard let pointOfView = sceneView.pointOfView else { return }
        let isVisible = sceneView.isNode(node, insideFrustumOf: pointOfView)
        if isVisible {

            let nodePos = sceneView.projectPoint(node.position)
            let nodeScreenPos = CGPoint(x: CGFloat(nodePos.x), y: CGFloat(nodePos.y))
            let distance = CGPointDistance(from: nodeScreenPos, to: view.center)

            if distance < 150.0 {
                print("display description of: \(node.name!)")
                guard let title = ar360Experience?.threeSixtyHotspot?[Int(node.name!)!].title else { return }
                guard let copy = ar360Experience?.threeSixtyHotspot?[Int(node.name!)!].copy else { return }
                titleLabel.text = title
                copyLabel.text = copy

                cardView.isHidden = false

            }else {
                cardView.isHidden = true
            }
        }

    }
}
ada10086
  • 292
  • 5
  • 8

1 Answers1

0

There are various ways to do this. Like iterating all the nodes to find their distance. But like you said this becomes inefficient.

What you can do is to store your node data in a different format using something like GKQuadTree... https://developer.apple.com/documentation/gameplaykit/gkquadtree

This is a GameplayKit That will allow you to much more quickly iterate the data set so that you can find the node closest to the centre.

It works by breaking down the area into four (hence quad) sections and storing nodes into one of those sections storing the rect of the section too. It then breaks down each of those four sections into four more and so on.

So when you ask for the nodes closest to a given point it can quickly eliminate the majority of the nodes.

Fogmeister
  • 76,236
  • 42
  • 207
  • 306
  • Thanks for your response. I looked into it, however the only function I found that closest to what I want to achieve is func elements which returns all elements found within the specified bounding region, which still doesn't give me the one element that is closest, am I missing something? – ada10086 Jun 08 '19 at 18:13
  • @ada10086 there are many resources about algorithms for quad trees. The algorithm you want is a nearest neighbour search. Where your centre point is the point to find the nearest node. https://stackoverflow.com/questions/32412107/quadtree-find-neighbor – Fogmeister Jun 08 '19 at 19:48