使用Swift的ARKit测量长度

您是否曾经历过需要测量设备的经历,但现在没有任何东西了? 不要害怕! 因为,实际上我们可以使用ARKit使用我们的iOS设备来测量从一个点到另一个点的对象。

在此应用程序中,我们将添加两个点,这些点将确定测量的开始和结束。 同样,长度为英寸的文本将显示在端点的正上方。

为了获得更好的参考,您可能还希望在此处查看整个代码库。

设定

首先,我们需要创建一个增强现实应用程序。 对于这种情况,我们将其命名为ARRuler。 选择Swift作为其语言,选择内容技术作为SceneKit 。 我们无法为此选中单元测试UI测试 ,因为我们不会使用它。

在我们的viewDidLoad()方法中,我们也可以删除以下行,因为我们不需要它们。

  sceneView.showsStatistics = true 
让场景= SCNScene(名称:“ art.scnassets / ship.scn”)!
sceneView.scene =场景

另外,在相同的viewDidLoad()方法中,让我们添加sceneView.debugOptions = [ARSCNDebugOptions.showFeaturePoints],以便我们可以跟踪ARKit将使用的设备位置。

添加起点和终点

现在我们的项目已经设置好,让我们使用以下代码覆盖touchesBegan(_:with) ,以检测触摸是否在视图中发生。

 覆盖func touchesBegan(_ touches:Set ,事件:UIEvent?){ 
}

接下来,我们需要在ARSCNView中获取第一次触摸的位置。 然后使用触摸位置执行命中测试,以查看它是否对应于特征点。 由于命中测试结果返回一个数组,因此我们将使用第一个数组添加一个点。

 如果让touchLocation = touches.first?.location(in:sceneView){ 
让hitTestResults = sceneView.hitTest(touchLocation,类型:.featurePoint)

如果让hitResult = hitTestResults.first {
addDot(at:hitResult)
}
}

正如您所注意到的,我们还没有创建addDot(at 🙂方法。 此方法应接受ARHitTestResult

  func addDot(在hitResult:ARHitTestResult){ 
}

addDot(at 🙂方法内部,我们将添加SCNSphere几何并为其赋予红色的材质。

 让dotGeometry = SCNSphere(半径:0.005) 
 让材质= SCNMaterial() 
material.diffuse.contents = UIColor.red
  dotGeometry.materials = [材料] 

然后,我们将创建一个具有SCNSphere几何形状的SCNNode 。 根据传递的ARHitTestResult ,我们的点节点应具有ax,y和z位置。 然后,我们将点节点添加到场景视图中。

 让dotNode = SCNNode(geometry:dotGeometry) 
dotNode.position = SCNVector3(hitResult.worldTransform.columns.3.x,
hitResult.worldTransform.columns.3.y,
hitResult.worldTransform.columns.3.z)
  sceneView.scene.rootNode.addChildNode(dotNode) 

您可能已经观察到我们仅添加了一个点。 因此,让我们创建一个SCNNode数组的全局变量以包含我们添加的点节点。

  var dotNodes = [SCNNode]() 

现在我们有了点节点数组,我们应该在场景视图中添加点节点之后立即在其中添加节点。

  dotNodes.append(dotNode) 

计算长度

如果我们现在测试该应用程序,则可以在场景视图中添加多个点。 我们只需要将其限制为两个,就可以测量从第一点到第二点的长度。

 如果dotNodes.count> = 2 { 
计算()
}

我们还没有calculate()方法,所以让我们现在使用funccalculate()创建一个方法。 在calculate()方法内部, SCNNode数组中的第一个节点将是起点,第二个节点将是终点。

 让开始= dotNodes [0] 
let end = dotNodes [1]

为了测量两个点的长度,我们将使用勾股定理。 公式将是d =√(a2 + b2 + c2)

 让a = end.position.x-start.position.x 
令b = end.position.y-start.position.y
令c = end.position.z-start.position.z
让距离= sqrt(pow(a,2)+ pow(b,2)+ pow(c,2))

结果将以米为单位,因此让我们将其转换为英寸,以便在短距离时更具可读性。

 让英寸=距离* 39.370079 

放置3D文字

现在我们已经获得了计算长度,让我们创建一个updateText(distance:atPosition 🙂方法,将值放置在场景视图中。 在我们的updateText(distance:atPosition 🙂方法中,我们将创建一个SCNText几何,其中包含红色材料。

 让textGeometry = SCNText(string:“ \(distance)in。”, 
挤压深度:1.0)
textGeometry.firstMaterial?.diffuse.contents = UIColor.red

然后,通过添加var textNode = SCNNode()来创建SCNNode的全局变量。 我们的SCNNode的位置将刚好在端点上方,并且缩放比例为0.1。

  textNode = SCNNode(geometry:textGeometry) 
textNode.position = SCNVector3(position.x,position.y + 0.01,position.z)
textNode.scale = SCNVector3(0.01,0.01,0.01)

创建完文本后,将文本节点添加到场景视图中。

  sceneView.scene.rootNode.addChildNode(textNode) 

重置测量

如果您到目前为止已经测试过该应用程序,则可以注意到,如果我们测量的长度超过两个,则它们可能会相互重叠,并且可能会造成混淆。 让我们修复它。

在我们的touchesBegan(_:with 🙂方法中,在找到触摸之前,我们将检查dotNodes是否已经超过两个项目,然后删除dotNodes并清除我们的dotNode数组。

 如果dotNodes.count> = 2 { 
对于dotNodes中的点{
dot.removeFromParentNode()
}
dotNodes = [SCNNode]()
}

另外,在检查两个以上dotNodes的过程中 ,我们将通过添加textNode.removeFromParentNode()来删除textNode

它应该看起来像这样!

现在继续尝试!

patricia serna Unsplash 上的 主要照片