Search code examples
swiftuibezierpathguardtouchesbegantouches

get line to remain a perfect 90 degrees when create


My swift code's goal is to get every line to only be able to be place at a 90 degree angle. Right now the code has two points a start and end where the start point is fixed upon touching the uiview. I would the user to be able to touch a point and only be able to extend the line at a 90 degree angle. Look at the gif below for more info. The bottom line is what i am trying to acheive. I think you have to use guard in touches began.

enter image description here

import UIKit

class ViewController2: UIViewController {

    @IBOutlet weak var drawingPlace: UIImageView!

    var startTouch : CGPoint?
    var secondTouch : CGPoint?
    var currentContext : CGContext?
    var prevImage : UIImage?


    override func viewDidLoad() {
        super.viewDidLoad()
    }


    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        let touch = touches.first
        startTouch = touch?.location(in: drawingPlace)
    }

    override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {

        for touch in touches{
            secondTouch = touch.location(in: drawingPlace)

            if(self.currentContext == nil){
                UIGraphicsBeginImageContext(drawingPlace.frame.size)
                self.currentContext = UIGraphicsGetCurrentContext()
            }else{
                self.currentContext?.clear(CGRect(x: 0, y: 0, width: drawingPlace.frame.width, height: drawingPlace.frame.height))
            }

            self.prevImage?.draw(in: self.drawingPlace.bounds)

            let bezier = UIBezierPath()

            bezier.move(to: startTouch!)
            bezier.addLine(to: secondTouch!)
            bezier.close()

            UIColor.blue.set()

            self.currentContext?.setLineWidth(4)
            self.currentContext?.addPath(bezier.cgPath)
            self.currentContext?.strokePath()
            let img2 = self.currentContext?.makeImage()
            drawingPlace.image = UIImage.init(cgImage: img2!)

        }
    }


    override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {

        self.currentContext = nil
        self.prevImage = self.drawingPlace.image
    }

}

Solution

  • The problem is this line:

    bezier.addLine(to: secondTouch!)
    

    This causes the line to follow the position of the touch, wherever it is. Instead, drop a perpendicular to the horizontal (I presume that is what you mean by 90 degrees) and add the line to that point on the horizontal. In other words, use the x component of secondTouch, but use as the y component the y component of startTouch.

    bezier.addLine(to: CGPoint(x:secondTouch!.x, y:startTouch!.y)