AR测量
2017-07-26 本文已影响82人
KeepFighting
- 启动ARSession
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
// Create a session configuration
let configuration = ARWorldTrackingSessionConfiguration()
configuration.planeDetection = .horizontal
// Run the view's session
sceneView.session.run(configuration)
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
// Pause the view's session
sceneView.session.pause()
}
- 提示检测状态
sceneView.debugOptions = [ARSCNDebugOptions.showWorldOrigin,ARSCNDebugOptions.showFeaturePoints]
sceneView.showsStatistics = true
func session(_ session: ARSession, cameraDidChangeTrackingState camera: ARCamera) {
switch camera.trackingState {
case .normal:
// tipLabel.text = "Tracking State Normal!"
tipLabel.text = "跟踪状态正常!"
tipLabel.textColor = .green
case .notAvailable:
// tipLabel.text = "Tracking State notAvailable!"
tipLabel.text = "跟踪状态无效!"
tipLabel.textColor = .red
case .limited(let reason):
switch reason {
case .excessiveMotion:
// tipLabel.text = "Tracking limited: excessiveMotion!"
tipLabel.text = "摄像头过度运动!"
case .initializing:
// tipLabel.text = "Tracking limited: initializing!"
tipLabel.text = "正在初始化!"
case .insufficientFeatures:
// tipLabel.text = "Tracking limited: insufficientFeatures!"
tipLabel.text = "特征点不够多!"
case .none:
// tipLabel.text = "Tracking limited!"
tipLabel.text = "检测异常"
}
tipLabel.textColor = .yellow
}
}
- 屏幕坐标转换成世界坐标
//from apple
extension ViewController {
func worldPositionFromScreenPosition(_ position: CGPoint,
objectPos: SCNVector3?,
infinitePlane: Bool = false) -> (position: SCNVector3?, planeAnchor: ARPlaneAnchor?, hitAPlane: Bool) {
// -------------------------------------------------------------------------------
// 1. Always do a hit test against exisiting plane anchors first.
// (If any such anchors exist & only within their extents.)
let planeHitTestResults = sceneView.hitTest(position, types: .existingPlaneUsingExtent)
if let result = planeHitTestResults.first {
let planeHitTestPosition = SCNVector3.positionFromTransform(result.worldTransform)
let planeAnchor = result.anchor
// Return immediately - this is the best possible outcome.
return (planeHitTestPosition, planeAnchor as? ARPlaneAnchor, true)
}
// -------------------------------------------------------------------------------
// 2. Collect more information about the environment by hit testing against
// the feature point cloud, but do not return the result yet.
var featureHitTestPosition: SCNVector3?
var highQualityFeatureHitTestResult = false
let highQualityfeatureHitTestResults = sceneView.hitTestWithFeatures(position, coneOpeningAngleInDegrees: 18, minDistance: 0.0, maxDistance: 0.05)
if !highQualityfeatureHitTestResults.isEmpty {
let result = highQualityfeatureHitTestResults[0]
featureHitTestPosition = result.position
highQualityFeatureHitTestResult = true
}
// -------------------------------------------------------------------------------
// 3. If desired or necessary (no good feature hit test result): Hit test
// against an infinite, horizontal plane (ignoring the real world).
if infinitePlane || !highQualityFeatureHitTestResult {
let pointOnPlane = objectPos ?? SCNVector3Zero
let pointOnInfinitePlane = sceneView.hitTestWithInfiniteHorizontalPlane(position, pointOnPlane)
if pointOnInfinitePlane != nil {
return (pointOnInfinitePlane, nil, true)
}
}
// -------------------------------------------------------------------------------
// 4. If available, return the result of the hit test against high quality
// features if the hit tests against infinite planes were skipped or no
// infinite plane was hit.
if highQualityFeatureHitTestResult {
return (featureHitTestPosition, nil, false)
}
// -------------------------------------------------------------------------------
// 5. As a last resort, perform a second, unfiltered hit test against features.
// If there are no features in the scene, the result returned here will be nil.
let unfilteredFeatureHitTestResults = sceneView.hitTestWithFeatures(position)
if !unfilteredFeatureHitTestResults.isEmpty {
let result = unfilteredFeatureHitTestResults[0]
return (result.position, nil, false)
}
return (nil, nil, false)
}
}
- 算出2个世界坐标的差值
// 计算2个点的距离
func distance(startNode: SCNNode, endNode: SCNNode) -> Float {
let vector = SCNVector3Make(startNode.position.x - endNode.position.x, startNode.position.y - endNode.position.y, startNode.position.z - endNode.position.z)
// Scene units map to meters in ARKit.
return sqrtf(vector.x * vector.x + vector.y * vector.y + vector.z * vector.z)
}
```
- 连线