cs193p – Project #3 Assignment #3 Extra Task #2

von SPYDERMAN360 (IMG_7929-1) [CC BY 2.0 (http://creativecommons.org/licenses/by/2.0)], via Wikimedia Commons

Please note, this blog entry is from a previous course. You might want to check out the current one.

Use the information you found above to improve panning performance. Do NOT turn your code into a mess to do this. Your solution should be simple and elegant. There is a strong temptation when optimizing to sacrifice readability or to violate MVC boundaries, but you are NOT allowed to do that for this Extra Credit!

… not drawing the axis would not really help that much. Drawing using lower resolution would not really look that nice. Caching data would violate our MVC boundaries, even if that’s debatable …

Let’s go for the last solution, we create a snapshot of the current graph:

    var snapshot:UIView?


When we start panning, create the snapshot and add it to the view – slightly transparent, so that we can see what we are doing.During the gesture we move only the snapshot image. Afterwards we copy the changes from the snapshot to the graph and remove the snapshot image from the view:

    func move(gesture: UIPanGestureRecognizer) {
        switch gesture.state {
        case .Began:
            snapshot = self.snapshotViewAfterScreenUpdates(false)
            snapshot!.alpha = 0.8
            self.addSubview(snapshot!)
        case .Changed:
            let translation = gesture.translationInView(self)
            snapshot!.center.x += translation.x
            snapshot!.center.y += translation.y
            gesture.setTranslation(CGPointZero, inView: self)
        case .Ended:
            origin.x += snapshot!.frame.origin.x
            origin.y += snapshot!.frame.origin.y
            snapshot!.removeFromSuperview()
            snapshot = nil
        default: break
        }
    }

Zooming works basically the same way – at least the creation of the snapshot. During the zoom we not only need to change the size of the snapshot, but also its position. Because we have to do that any way, I added a little feature to zoom around the actual point of touch. And finally we translate the changes back to the view:

    func zoom(gesture: UIPinchGestureRecognizer) {
        switch gesture.state {
        case .Began:
            snapshot = self.snapshotViewAfterScreenUpdates(false)
            snapshot!.alpha = 0.8
            self.addSubview(snapshot!)
        case .Changed:
            let touch = gesture.locationInView(self)
            snapshot!.frame.size.height *= gesture.scale
            snapshot!.frame.size.width *= gesture.scale
            snapshot!.frame.origin.x = snapshot!.frame.origin.x * gesture.scale + (1 - gesture.scale) * touch.x
            snapshot!.frame.origin.y = snapshot!.frame.origin.y * gesture.scale + (1 - gesture.scale) * touch.y
            gesture.scale = 1.0
        case .Ended:
            let changedScale = snapshot!.frame.height / self.frame.height
            scale *= changedScale
            origin.x = origin.x * changedScale + snapshot!.frame.origin.x
            origin.y = origin.y * changedScale + snapshot!.frame.origin.y
            snapshot!.removeFromSuperview()
            snapshot = nil
        default: break
        }
    }

If you run the profiler again, panning and zooming will be neglectable …

The complete code for the extra task #2 is available on GitHub.

FacebooktwitterredditpinterestlinkedintumblrmailFacebooktwitterredditpinterestlinkedintumblrmail

11 thoughts on “cs193p – Project #3 Assignment #3 Extra Task #2”

  1. Really a great solution, I’m programming my calculator for draw Bode-Diagrams, using primitives method. (Series and Parallels components, a graphical Method that I learn here in Germany), but the equations includes many terms, many of them complex. Each change in gesture produces a delay, that makes my solution non-viable. Your snapshots solution is clear and looks great in the devices. Thank’s. I take this portion of your code and include it in mine. (I made you reference in my code). Do you have an idea how to transform the axes Stanford Code in a Log-Linear or Log-Log scale. This is my task after I made my calculator to solve correctly all the Complex values.

    1. To draw log-linear an log-log scales you need to solve tow problems, how to translate your coordinate system to the screen and – most likely more difficult – which hashmarks you want/need to draw.

      1. Yes, I thought that, it’s a good challenge, but first, I will finish the Course to learn about all the basics, and after that I will take and build a new axes solution. Thank’s again, I follow now your page, you present very well the CS193p topics.

  2. Hi
    Sorry for asking but could you please please explain how you get to
    snapshot!.frame.origin.y * gesture.scale + (1 – gesture.scale) * touch.y
    Very nice and simple solution.
    I would like to learn how to create such code.
    Thank you

  3. Hi
    I want to thanks you again for you work. Amazing help for all of us!
    You are legend!
    By the way I was looking for something more easy to do instead pen and paper.
    Please look on that

    func zoom(gesture:UIPinchGestureRecognizer){
    switch gesture.state{
    case .Began:snapshot = self.snapshotViewAfterScreenUpdates(false)
    snapshot!.alpha = 0.7
    self.addSubview(snapshot!)
    case .Changed:
    let touch = gesture.locationInView(self)
    snapshot!.frame.size.width *= gesture.scale
    snapshot!.frame.size.height *= gesture.scale
    snapshot!.center.x = self.center.x
    snapshot!.center.y = self.center.y
    gesture.scale = 1
    case .Ended:
    let changeScale = snapshot!.frame.height / self.frame.height
    scale *= changeScale
    origin.x = snapshot!.center.x
    origin.y = snapshot!.center.y
    snapshot!.removeFromSuperview()
    snapshot = nil
    default:break
    }
    }

    Thank you

  4. Still not working.
    I mean how to zoom when the origin of graph is out of view.
    That zoom code maybe is working but now I have problem with move code.
    How to move origin of graph outside the iPhone screen?
    How to make setNeedsDisplay?
    func zoom(gesture:UIPinchGestureRecognizer){
    switch gesture.state{
    case .Began:snapshot = self.snapshotViewAfterScreenUpdates(false)
    snapshot!.alpha = 0.7
    self.addSubview(snapshot!)
    case .Changed:
    let touch = gesture.locationInView(self)
    snapshot!.frame.size.width *= gesture.scale
    snapshot!.frame.size.height *= gesture.scale
    snapshot!.center.x = self.center.x
    snapshot!.center.y = self.center.y
    gesture.scale = 1
    case .Ended:
    let changeScale = snapshot!.frame.height / self.frame.height
    scale *= changeScale
    self.center.x = snapshot!.center.x
    self.center.y = snapshot!.center.y
    snapshot!.removeFromSuperview()
    snapshot = nil
    default:break
    }
    }
    func move(gesture:UIPanGestureRecognizer){
    switch gesture.state{
    case .Began: snapshot = self.snapshotViewAfterScreenUpdates(false)
    snapshot!.alpha = 0.7
    self.addSubview(snapshot!)
    case .Changed:let translation = gesture.translationInView(self)
    snapshot!.frame.origin.x += translation.x
    snapshot!.frame.origin.y += translation.y
    gesture.setTranslation(CGPointZero, inView: self)
    case .Ended:
    //self.center.x = snapshot!.center.x
    //self.center.y = snapshot!.center.y
    let trasnslationX = snapshot!.center.x – self.center.x
    let trasnslationY = snapshot!.center.y – self.center.y
    self.origin.x += trasnslationX
    self.origin.y += trasnslationY
    snapshot!.removeFromSuperview()
    snapshot = nil
    default:break
    }
    }
    Thank you

  5. I don’t understand that snapshot. In your code I cannot move origin of graph out of the view but in my I can only north or south (no problems look ok) but if I move west or east points and text disappear! Why what is going on?
    Please help

Leave a Reply

Your email address will not be published.