NIrA
NIrA

Reputation: 13

How to accurately calculate PD (Pupil Distance) measurement in swiftUI?

This is the code I tried but farPD works fine however for LeftPD and rightPD I'm getting accurate output even for FarPD I don't know if this code is getting accurate output.:

import SwiftUI
import ARKit
import RealityKit

struct MeasurePDView: View {
    @State private var farPD: Double = 0.0
    @State private var leftPD: Double = 0.0
    @State private var rightPD: Double = 0.0
    @State private var nearPD: Double = 0.0

    var body: some View {
        VStack {
            Text("Far PD: \(farPD, specifier: "%.2f") mm")
            Text("Left PD: \(leftPD, specifier: "%.2f") mm")
            Text("Right PD: \(rightPD, specifier: "%.2f") mm")
            Text("Near PD: \(nearPD, specifier: "%.2f") mm")
            ARMeasurementView(farPD: $farPD, leftPD: $leftPD, rightPD: $rightPD, nearPD: $nearPD)
                .edgesIgnoringSafeArea(.all)
        }
    }
}

struct ARMeasurementView: UIViewRepresentable {
    @Binding var farPD: Double
    @Binding var leftPD: Double
    @Binding var rightPD: Double
    @Binding var nearPD: Double

    class Coordinator: NSObject, ARSessionDelegate {
        var parent: ARMeasurementView

        init(parent: ARMeasurementView) {
            self.parent = parent
        }

        func session(_ session: ARSession, didUpdate anchors: [ARAnchor]) {
            guard let faceAnchor = anchors.compactMap({ $0 as? ARFaceAnchor }).first else { return }
            
            let leftEyePosition = SIMD3<Float>(faceAnchor.leftEyeTransform.columns.3.x,
                                               faceAnchor.leftEyeTransform.columns.3.y,
                                               faceAnchor.leftEyeTransform.columns.3.z)
            let rightEyePosition = SIMD3<Float>(faceAnchor.rightEyeTransform.columns.3.x,
                                                faceAnchor.rightEyeTransform.columns.3.y,
                                                faceAnchor.rightEyeTransform.columns.3.z)
            
            // Estimate nose position
            let nosePosition: SIMD3<Float>
            if let noseVertexIndex = faceAnchor.geometry.vertices.indices.max(by: { a, b in
                faceAnchor.geometry.vertices[a].z < faceAnchor.geometry.vertices[b].z
            }) {
                nosePosition = faceAnchor.geometry.vertices[noseVertexIndex]
            } else {
                
                nosePosition = (leftEyePosition + rightEyePosition) / 2
            }
            
            let farPDDistance = distance(leftEyePosition, rightEyePosition)
            let leftPDDistance = distance(leftEyePosition, nosePosition)
            let rightPDDistance = distance(rightEyePosition, nosePosition)
            
            
            print("Left Eye: \(leftEyePosition)")
            print("Right Eye: \(rightEyePosition)")
            print("Nose: \(nosePosition)")
            print("Raw Far PD: \(farPDDistance)")
            print("Raw Left PD: \(leftPDDistance)")
            print("Raw Right PD: \(rightPDDistance)")

            let scaleFactor = 1000.0

            DispatchQueue.main.async {
                self.parent.farPD = Double(farPDDistance * Float(scaleFactor))
                self.parent.leftPD = Double(leftPDDistance * Float(scaleFactor))
                self.parent.rightPD = Double(rightPDDistance * Float(scaleFactor))
                
                
                print("Calculated Far PD: \(self.parent.farPD)")
                print("Sum of Left and Right PD: \(self.parent.leftPD + self.parent.rightPD)")
            }
        }

        func distance(_ a: SIMD3<Float>, _ b: SIMD3<Float>) -> Float {
            return sqrt(pow(b.x - a.x, 2) + pow(b.y - a.y, 2) + pow(b.z - a.z, 2))
        }
        
    }

    func makeCoordinator() -> Coordinator {
        Coordinator(parent: self)
    }

    func makeUIView(context: Context) -> ARView {
        let arView = ARView(frame: .zero)
        arView.session.delegate = context.coordinator
        
        let configuration = ARFaceTrackingConfiguration()
        arView.session.run(configuration)
        
        return arView
    }

    func updateUIView(_ uiView: ARView, context: Context) {}
}



struct MeasurePDView_Previews: PreviewProvider {
    static var previews: some View {
        MeasurePDView()
    }
}

I tried this code snippet from chatGPT but it seems like Far PD is working fine but the Left PD and Right PD value is inaccurate and its not accurate.

Upvotes: 0

Views: 84

Answers (0)

Related Questions