How to draw 720 data points using Swift

心已入冬 提交于 2019-12-25 08:03:12

问题


I am currently writing a joystick app and I want to display the contours of my lidar sensor; I am using sprite kit but it's lagging; I am assuming that it is taking up too much memory

My lidar sensor returns to me 360 data points where each degree represents the distances of where it hit an object (wall)

I am initializing all of my sprite kit nodes in didMoveToView, is there a better way to achieve this? perhaps in init?

I am creating 720 sprite kit nodes because 360 are for the lines and 360 are for the data points (distances)

It seems as if I am creating too many sprite kit nodes (720+)

Also, I am planning to provide video streaming through my app; is Sprite Kit the best option to do this?

import Foundation
import UIKit
import SpriteKit

class GameScene: SKScene {


    var visual = SKSpriteNode()

    let button = SKShapeNode(rect: CGRect(x: 0, y: 0, width: 100, height: 50), cornerRadius: 10)

    var distances: [Int] = [2601, 2600, 33, 2608, 2601, 2594, 2625, 2633, 2637, 2651, 2656, 2666, 2683, 2690, 2705, 2712, 2712, 2739, 2752, 53, 1103, 1060, 1019, 980, 944, 911, 33, 851, 826, 801, 777, 757, 737, 718, 701, 683, 667, 654, 53, 486, 470, 457, 448, 440, 432, 424, 416, 409, 403, 396, 389, 383, 378, 372, 367, 362, 357, 353, 348, 344, 340, 336, 333, 329, 326, 323, 319, 317, 314, 311, 309, 307, 305, 303, 301, 299, 298, 297, 295, 294, 293, 292, 291, 290, 290, 290, 290, 291, 293, 295, 303, 386, 383, 53, 350, 53, 53, 53, 53, 53, 3, 364, 362, 360, 356, 358, 355, 353, 351, 350, 349, 347, 345, 53, 53, 53, 308, 3, 309, 309, 312, 313, 315, 316, 319, 321, 53, 329, 332, 335, 332, 53, 53, 53, 53, 53, 53, 53, 3, 53, 53, 53, 53, 53, 53, 670, 33, 706, 728, 750, 772, 799, 825, 856, 887, 925, 755, 749, 744, 739, 734, 730, 727, 722, 719, 716, 714, 634, 709, 706, 704, 703, 701, 699, 700, 695, 697, 697, 338, 696, 697, 696, 698, 698, 700, 702, 703, 705, 707, 710, 712, 714, 718, 53, 53, 53, 53, 53, 53, 53, 53, 3, 53, 53, 53, 53, 53, 53, 53, 53, 3, 53, 53, 53, 53, 53, 53, 53, 3412, 3397, 3384, 53, 3538, 3603, 53, 2426, 2412, 2363, 2330, 2288, 2262, 2214, 2190, 2162, 2130, 53, 53, 53, 2807, 2631, 2408, 2638, 2607, 2601, 2562, 2534, 2515, 2496, 2478, 2462, 2445, 53, 53, 53, 1751, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 3, 53, 53, 53, 53, 53, 2643, 2643, 53, 2660, 53, 2528, 2523, 2221, 1955, 1684, 1677, 1684, 1694, 1705, 1202, 1204, 1211, 1217, 1225, 1233, 1239, 1249, 1259, 1270, 1280, 1289, 1280, 1011, 991, 977, 968, 966, 964, 968, 975, 984, 1003, 2, 53, 1297, 53, 53, 33, 1321, 1299, 1274, 1254, 1233, 1232, 1264, 1293, 3802, 53, 53, 53, 53, 53, 53, 53, 3, 53, 2878, 2870, 2848, 2821, 2803, 2788, 2769, 2753, 2740, 2708, 2711, 2701, 2682, 2656, 2664, 2644, 2644, 2631, 2626, 2616, 2610, 2604, 2605, 2605, 2600, 2598, 2603]

    var scalex: [Double] = []
    var scaley: [Double] = []
    var disx: [Double] = []
    var disy: [Double] = []

    var somenodes = [SKSpriteNode()]
    var newnodes = [SKShapeNode()]

    override init(size: CGSize) {

        print("this is in init!")
        super.init(size: size)
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    let rotateAnalogStick = AnalogJoystick(diameter: 100)

    override func didMoveToView(view: SKView) {
        /* Setup your scene here */

        visual.color = UIColor.clearColor()
        visual.size = CGSize(width: 350, height: 350)
        visual.position = CGPointMake(frame.midX, frame.midY + 150)
        addChild(visual)


        for index in 0...356 {

            var radians = Double(index) * M_PI / 180.0
            var x = Double(distances[index]) * cos(Double(radians))
            var y = Double(distances[index]) * sin(Double(radians))

            disx.append(x)
            disy.append(y)
        }


        var path = CGPathCreateMutable()
        var xmin: Double = Double(disx.minElement()!)
        var xmax: Double = Double(disx.maxElement()!)
        var ymin: Double = Double(disy.minElement()!)
        var ymax: Double = Double(disy.maxElement()!)

        var scale = max(xmax - xmin, ymax - ymin)

        for index in 0...356 {

            var radians = Double(index) * M_PI / 180.0
            var x = (Double(distances[index]) * cos(Double(radians)) / scale) * 350
            var y = (Double(distances[index]) * sin(Double(radians)) / scale) * 350

            print("(\(x),\(y))")

            var mynode = SKSpriteNode()
            mynode.color = UIColor.redColor()
            mynode.size = CGSize(width: 2, height: 2)

            let circlenode = SKShapeNode()
            let circlePath = UIBezierPath(arcCenter: CGPoint(x: 0,y: 0), radius: CGFloat(5), startAngle: CGFloat(0), endAngle:CGFloat(M_PI * 2), clockwise: true)
            circlenode.path = circlePath.CGPath
            //change the fill color
            circlenode.fillColor = UIColor.blueColor()
            //you can change the stroke color
            circlenode.strokeColor = UIColor.redColor()
            //you can change the line width
            circlenode.lineWidth = 0.5
            circlenode.zPosition = 1
            circlenode.position = CGPointMake(CGFloat(x), CGFloat(y))
            newnodes.append(circlenode)

            CGPathMoveToPoint(path, nil, 0, 0) // from
            CGPathAddLineToPoint(path, nil, CGFloat(x), CGFloat(y)) // to

            let shape = SKShapeNode()
            shape.path = path
            shape.strokeColor = UIColor.purpleColor()
            shape.lineWidth = 1
            visual.addChild(shape)
            visual.addChild(newnodes[index])
        }

        let newscale = SKAction.scaleTo(0.1, duration: 0.5)
        let fadein = SKAction.fadeInWithDuration(0.5)
        let fadeout = SKAction.fadeOutWithDuration(0.5)
        let outsequence = SKAction.sequence([fadeout])
        let insequence = SKAction.sequence([fadein])

        for index in 0...visual.children.count {
//            visual.children[index].runAction(insequence)
//            visual.children[index].runAction(repeatout)
        }

        button.fillColor = UIColor.blueColor()
        button.position = CGPointMake(frame.midX - 50, frame.midY - 110)

        addChild(button)

        var mylabel = SKLabelNode()
        mylabel.color = UIColor.blackColor()
        mylabel.fontSize = 12
        mylabel.fontName = "AvenirNext-Bold"
        mylabel.text = "Contour Display"
        mylabel.position = CGPointMake(50, 20)
        mylabel.zPosition = 1
        button.addChild(mylabel)

        backgroundColor = UIColor.whiteColor()
        physicsBody = SKPhysicsBody(edgeLoopFromRect: frame)

        rotateAnalogStick.position = CGPointMake(frame.midX + 5, rotateAnalogStick.radius + 60)
        rotateAnalogStick.stick.color = UIColor.cyanColor()
        rotateAnalogStick.substrate.color = UIColor.blackColor()
        addChild(rotateAnalogStick)

        rotateAnalogStick.trackingHandler = { data in

            // cartesian to polar
            var r = sqrt(pow(Double(data.velocity.x), Double(2)) + pow(Double(data.velocity.y), Double(2)))
            var power = (r - 0)/(50 - 0) * (1-0) + 0
            var theta = atan2(Double(data.velocity.y), Double(data.velocity.x)) // atan(Double(data.velocity.y/data.velocity.x)) //
            var degrees = theta * (180.0 / M_PI)

            var packet = ""
            var offset = 0.0
            var rdirection = 0.0
            var ldirection = 0.0
            var rpower = 0.0
            var lpower = 0.0

            if (degrees >= 65 && degrees <= 115) { // move forward

                rpower = power
                lpower = power

                rdirection = 1
                ldirection = 1

            } else if (degrees <= 0 && degrees >= -65) || (degrees >= 0 && degrees <= 65) { // move right

                offset = 90 - degrees
                rdirection = min(degrees, offset)
                ldirection = max(degrees, offset)

                rpower = (rdirection - 0)/(50 - 0) * (power-0) + 0
                lpower = abs(1-rpower)

                rdirection = -1
                ldirection = 1

            } else if (degrees <= -115 && degrees >= -180) || (degrees > 115 && degrees < 180 ) { // move left

                offset = 90 - degrees
                rdirection = min(degrees, offset)
                ldirection = max(degrees, offset)

                rpower = abs(1-rpower)
                lpower = (rdirection - 0)/(50 - 0) * (power-0) + 0

                rdirection = 1
                ldirection = -1

            } else if (degrees <= -65 && degrees >= -115) { // move down

                rpower = power
                lpower = power

                rdirection = -1
                ldirection = -1
            }

            packet = "\(rdirection) \(ldirection) \(rpower) \(lpower)"

        }

        view.multipleTouchEnabled = true
    }

    override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
        /* Called when a touch begins */

        for touch: AnyObject in touches {
            // Get the location of the touch in this scene
            let location = touch.locationInNode(self)
            // Check if the location of the touch is within the button's bounds
            if button.containsPoint(location) {
                print("button tapped!")
            }
        }

    }

    override func update(currentTime: CFTimeInterval) {
        /* Called before each frame is rendered */
    }
}

回答1:


I'd like to think that SpriteKit can bang out 720 sprites no problem. As cited, your main issue is SKShapeNode usage.

What you should do is create your "dots" as textures. If you want color/outlines, put them in the texture. Additionally, create your lines out of colored rects (which can be SKSpriteNodes). If you have multiple circle colors, put them in a texture atlas.

This will give you the better chance of improved throughput with SpriteKit.

You are doing this work in didMoveToView. How often does it need to be refreshed? If the data is set and the one difference is transforming it (eg. rotate, scale, translate), another approach would be to pre-render the whole thing using Quartz/Core Graphics and then transforming the rendering.



来源:https://stackoverflow.com/questions/40078232/how-to-draw-720-data-points-using-swift

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!