在添加新节点之前删除节点Swift

时间:2018-07-17 23:47:37

标签: ios swift arkit scnnode coreml

我正在使用一个iOS应用程序,该应用程序应该识别墙上的一个数字(使用CoreML + Vision),然后在同一壁上添加几架飞机(飞机的数量取决于该房间的时间表(水平))。各种内容,例如工作日和营业时间(营业时间)或营业时间(营业时间)。我遇到的问题是,如果我在添加第一个平面之后继续将相机对准数字,那么该平面会连续添加,这是不可能发生的。不过,我有一些类似的操作,例如删除所有节点/让它们在添加新节点之前立即消失,或者停止为已经检测到的特定房间添加添加,但是您可以随意考虑并提出不同的建议!

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
    }
}

1 个答案:

答案 0 :(得分:0)

在没有看到所有代码的情况下,很难提供正确的答案。

但是,您可以考虑一些事情。

首先,您可以创建一个名为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

        }
    }
}

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

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