【问题标题】:Remove nodes before Adding new ones Swift在添加新节点之前删除节点 Swift
【发布时间】:2018-12-25 18:16:42
【问题描述】:

我正在开发一个 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
    }
}

【问题讨论】:

  • 所有数字都是唯一的吗?
  • @JoshRobbins 是的!所有数字都是唯一的!

标签: ios swift arkit scnnode coreml


【解决方案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

        }
    }
}

希望我设法以一种对我以外的其他人有意义的方式表达我的想法:)

当然,希望它为您指明正确的方向...

【讨论】:

  • 非常感谢!我一定会看看这个!同时,如果您想查看完整的代码,我刚刚发布了另一个问题,代码就在那里!顺便说一句,您也可以尝试帮助我解决其他问题:D
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多