0
votes

I’m developing a project with ARKit. I want to calculate the measure from a wall to the camera and it updates when I move away or I move closer.

Now, i have activated that it detects horizontal and vertical surfaces. When I get a surface, I calculate the distance from the camera position and the center of the surface. After I apply the calculus that it gets the distance between 2 points in a 3D space (Euclidean). https://math.stackexchange.com/questions/42640/calculate-distance-in-3d-space

Is it correct? Can you help me?

class ViewController: UIViewController, ARSCNViewDelegate, ARSessionDelegate {

    let configuration = ARWorldTrackingConfiguration()

    override func viewDidAppear(_ animated: Bool) {
      super.viewDidAppear(animated)
      configuration.planeDetection = [.horizontal, .vertical]
      sceneView.session.run(configuration)
      ......
    }

    func renderer(_ renderer: SCNSceneRenderer, didAdd node: SCNNode, for anchor: ARAnchor) {
      guard let planeAnchor = anchor as? ARPlaneAnchor else { return }
      let plane = SCNPlane(width: CGFloat(planeAnchor.extent.x), height: 
      CGFloat(planeAnchor.extent.z))
      let planeNode = SCNNode(geometry: plane)
      planeNode.simdPosition = float3(planeAnchor.center.x, 0, 
      planeAnchor.center.z)
      planeNode.eulerAngles.x = -.pi / 2   
      node.addChildNode(planeNode)
      let distance = distanceFromCamera(x: planeAnchor.center.x, y: 0, z: planeAnchor.center.z)
      let formatted = String(format: "Distance: %.2f", distance)
      print(formatted) q 
    }

    private func distanceFromCamera(x: Float, y:Float, z:Float) -> Float {
            let cameraPosition =  self.sceneView.session.currentFrame!.camera.transform.columns.3
            print("Camera: \(cameraPosition)")
            let vector = SCNVector3Make(cameraPosition.x - x, cameraPosition.y - y, cameraPosition.z - z)

            // Scene units map to meters in ARKit.
            return sqrtf(vector.x * vector.x + vector.y * vector.y + vector.z * vector.z)
        }
}
1

1 Answers

0
votes

Add Following method

func renderer(_ renderer: SCNSceneRenderer, updateAtTime time: TimeInterval) {
    guard let currentBall = self.currentBall else {return}

    DispatchQueue.main.async {
        if let centerPosition = self.hitTestCenterVector() {
            let startPositionOfBall = currentBall.position
            let distance = self.getDistanceBetween(vector1: centerPosition, vector2: startPositionOfBall)
            self.lblDistance.text = String(format: "%.1f", distance) //meter
        }
    }
}

Just replace self.currentBall in guard statement with your SCNNode it is from where you want to cal. distance

Now This is method to for calculations

func hitTestCenterVector () -> SCNVector3? {
    let results =  self.sceneView.hitTest(self.sceneView.center, types: .existingPlane)

    if let firstObject = results.first  {
        return SCNVector3(firstObject.worldTransform.columns.3.x, firstObject.worldTransform.columns.3.y, firstObject.worldTransform.columns.3.z)
    }

    return nil
}


func getDistanceBetween(vector1:SCNVector3, vector2:SCNVector3) -> CGFloat {
   return  CGFloat(sqrt((vector1.x - vector2.x) * (vector1.x - vector2.x)
     + (vector1.y - vector2.y) * (vector1.y - vector2.y)
    + (vector1.z - vector2.z) * (vector1.z - vector2.z)))
}

Hope it is helpful