我正在开发一个 iOS 应用程序,它应该识别墙上的数字(使用 CoreML + Vision),然后将几个平面(平面数量取决于房间时间表(horario))添加到同一面墙上各种内容,如工作日和开盘 (inicio) 或闭盘 (fim) 时间。我遇到的问题是,如果我在添加第一架飞机后继续将相机对准数字,那么飞机会不断添加,这是不应该发生的。我有一些想法,比如删除所有节点/让它们在添加新节点之前立即消失,或者停止为已经检测到的特定房间添加,但请随意思考并提出不同的方法!
func renderer(_ renderer: SCNSceneRenderer, didAdd node: SCNNode, for anchor: ARAnchor)
{
guard let planeAnchor = anchor as? ARPlaneAnchor else { return }
let dataformatter = DateFormatter()
dataformatter.dateFormat = "HH:mm"
let dataformatter_wk = DateFormatter()
dataformatter_wk.dateFormat = "EEEE"
var i = 0
for horario in (self.room?.horario)!{
//Convert Dates
let comp_inicio: DateComponents = Calendar.current.dateComponents([.hour, .minute], from: (horario.hora_ini)!)
let comp_fim: DateComponents = Calendar.current.dateComponents([.hour, .minute], from: (horario.hora_fim)!)
let comp_wk: DateComponents = Calendar.current.dateComponents([.weekday, .day, .month, .year, .hour, .minute], from: (horario.hora_ini)!)
let data_inicio = Calendar.current.date(from: comp_inicio)
let data_fim = Calendar.current.date(from: comp_fim)
let data_wk = Calendar.current.date(from: comp_wk)
let hora_inicio = dataformatter.string(from: data_inicio!)
let hora_fim = dataformatter.string(from: data_fim!)
let horario_final = (hora_inicio + "-" + hora_fim).uppercased()
let weekday = dataformatter_wk.string(from: data_wk!).uppercased()
//Plane
let plane = SCNPlane(width: CGFloat(0.09), height: CGFloat(0.09))
plane.materials.first?.diffuse.contents = UIColor.planeColor
let planeNode = SCNNode(geometry: plane)
//Text
let material_text = SCNMaterial()
material_text.diffuse.contents = UIColor.black
//Get the content from JSON
let text_horario = SCNText(string: horario_final, extrusionDepth: 0.1)
let text_weekday = SCNText(string: weekday, extrusionDepth: 0.1)
let text_descr = SCNText(string: horario.descr?.uppercased() ?? 0, extrusionDepth: 0.1)
text_weekday.materials = [material_text]
text_descr.materials = [material_text]
text_horario.materials = [material_text]
let node_text_weekday = SCNNode(geometry: text_weekday)
let node_text_horario = SCNNode(geometry: text_horario)
let node_text_descr = SCNNode(geometry: text_descr)
//Piones
let piones = SCNCylinder(radius: 0.002, height: 0.005)
let material_piones = SCNMaterial()
material_piones.diffuse.contents = UIColor.red
piones.materials = [material_piones]
let node_piones = SCNNode(geometry: piones)
// 5 Get the planeAnchor positions
let x = CGFloat(planeAnchor.center.x) // Esquerda e direita
let y = CGFloat(planeAnchor.center.y) // +y = Mais perto do telemovel
let z = CGFloat(planeAnchor.center.z) // -z = Mais alto
// Rotate and scale the nodes
planeNode.eulerAngles.x = -.pi / 2
node_text_weekday.eulerAngles.x = -.pi / 2
node_text_horario.eulerAngles.x = -.pi / 2
node_text_descr.eulerAngles.x = -.pi / 2
node_text_weekday.scale = SCNVector3(x: 0.0005, y: 0.0005, z: 0.0005)
node_text_horario.scale = SCNVector3(x: 0.0005, y: 0.0005, z: 0.0005)
node_text_descr.scale = SCNVector3(x: 0.0007, y: 0.0007, z: 0.0007)
// Add the nodes positions
planeNode.position = SCNVector3(x + CGFloat(i%3)/10 ,y , z + CGFloat(i/3)/10)
node_text_weekday.position = SCNVector3(x - 0.025 + CGFloat(i%3)/10 ,y , z + CGFloat(i/3)/10)
node_text_horario.position = SCNVector3(x - 0.020 + CGFloat(i%3)/10 ,y , z+0.035 + CGFloat(i/3)/10)
node_text_descr.position = SCNVector3(x - 0.029 + CGFloat(i%3)/10 ,y , z-0.015 + CGFloat(i/3)/10)
node_piones.position = SCNVector3(x + CGFloat(i%3)/10 ,y , z-0.035 + CGFloat(i/3)/10)
node.addChildNode(planeNode)
node.addChildNode(node_text_weekday)
node.addChildNode(node_text_horario)
node.addChildNode(node_text_descr)
node.addChildNode(node_piones)
//Used for positioning of the planes on the wall
i=i+1
}
}
最佳答案
没有看到所有的代码,很难提供一个正确的答案。
但是,您可以考虑一些事项。
首先你可以创建一个 var
叫做:
var detectedRoomNumber: Int?
当 Vision Framework
检测到它时将设置它。
由于您还说每个房间号都是唯一的,因此您可以创建一个Array [Int]
来存储对这些房间号的初始引用,例如:
var roomNumbers: [Int] = [1, 2, 3, 4, 5]
一旦 Vision Framework
检测到一个数字,您就可以将其设置为 detectedRoomNumber
并将其从 Array
中删除,确保它只能检测一次。
此外,作为额外的保护措施,您可以存储对每个 ARPlaneAnchor
的引用。
每个 ARPlaneAnchor
都有一个唯一的 UUID
标识符,因此你可以创建一些逻辑来确保如果这个 ARPlaneAnchor 已经被检测到,新的内容将不会被检测到添加例如:
var roomPlanes = [UUID: ARPlaneAnchor]()
因此一些伪代码可能看起来像这样:
//---------------------------
// MARK: - ARSCNViewDelegate
//---------------------------
extension ViewController: ARSCNViewDelegate{
func renderer(_ renderer: SCNSceneRenderer, didAdd node: SCNNode, for anchor: ARAnchor) {
//1. Check To See Whether An ARPlaneAnchor Has Been Detected
guard let roomPlaneAnchor = anchor as? ARPlaneAnchor else { return }
/*
Vision Has Detected Our Room Number, So We Check To See If Our Array Of Room Numbers Contains The Room
We Also Check To See If The ARPlaneAnchor Has Already Been Detected
*/
if let validRoom = detectedRoomNumber, roomNumbers.contains(validRoom), !roomPlanes.keys.contains(roomPlaneAnchor.identifier){
//a. If Our Array Isnt Empty Get The Index Of The Room & Remove It From Our Array So It Cant Be Redected
if roomNumbers.count != 0, let itemIndexToRemove = roomNumbers.index(of: validRoom) {
roomNumbers.remove(at: itemIndexToRemove)
}
print("Room Area Not Detected Before Adding Content")
//b. Add The Plane Anchor To Our Array & Then Generate Our Content
roomPlanes[roomPlaneAnchor.identifier] = roomPlaneAnchor
let width = CGFloat(roomPlaneAnchor.extent.x)
let height = CGFloat(roomPlaneAnchor.extent.z)
let sphereNode = SCNNode(geometry: SCNPlane(width: width, height: height))
sphereNode.geometry?.firstMaterial?.diffuse.contents = colours[roomPlanes.keys.count-1]
sphereNode.transform = SCNMatrix4MakeRotation(-Float.pi / 2, 1, 0, 0)
node.addChildNode(sphereNode)
detectedRoomNumber = nil
}
}
}
希望我能够以一种对我以外的其他人有意义的方式表达我的想法:)
当然,希望它能为您指明正确的方向...
关于ios - 在添加新节点之前删除节点 Swift,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51391646/