1

I have a UIBezier path draw on my screen comprised of 5 different Lines.

[![enter image description here][1]][1]

What I'm trying to do is calculate the difference in angle between any 2 lines so that I can determine the direction of the next line relative to the last.

I can detect straight lines no problem. The issue I have is that I cant tell the difference between a line increasing on the x axis (Going Right) and a line decreasing on the x axis (Going left)

In these 2 cases the angle is 90.

By desired result would be "Left" to be somewhere between 90 and 270 degrees and "Right" to be somewhere between 270 and 90 degrees.

My Trig is quite rusty so I doubt Im on the right track.

Here's what I have attempted

Struct to model my lines

    struct Line
{
    var point1:CGPoint
    var point2: CGPoint
    var vector:CGVector {
        get {
            return CGVector(dx: point1.x - point2.x, dy: point1.y - point2.y)
        }
    }
}

Draw my Lines

let line1 = Line(point1: CGPoint(x: 100, y: 300), point2: CGPoint(x: 100, y: 200))
        let line2 = Line(point1: CGPoint(x: 100, y: 200), point2: CGPoint(x: 200, y: 200))
        let line3 = Line(point1: CGPoint(x: 200, y: 200), point2: CGPoint(x: 200, y: 150))
        let line4 = Line(point1: CGPoint(x: 200, y: 150), point2: CGPoint(x: 100, y: 150))
        let line5 = Line(point1: CGPoint(x: 100, y: 150), point2: CGPoint(x: 100, y: 50))

        lines = [line1,line2,line3,line4,line5]
        let path = UIBezierPath()

        for line in lines!{
            path.move(to: CGPoint(x: line.point1.x, y: line.point1.y))
            path.addLine(to: CGPoint(x:line.point2.x, y: line.point2.y))

        }

        let shapeLayer = CAShapeLayer()
        shapeLayer.path = path.cgPath
        shapeLayer.strokeColor = UIColor.blue.cgColor
        shapeLayer.lineWidth = 3.0

        testView.layer.addSublayer(shapeLayer)

Calculate Directions

 @IBAction func calculateAngles()
    {
        var i = 0
        let count = lines!.count - 1

        while i < count
        {
            let l1 = lines![i]
            let slope = (l1.point2.y - l1.point1.y) / (l1.point2.x - l1.point1.x)
            let theta1 = atan(slope)
            let l2 = lines![i + 1]
            let slope2 = (l2.point2.y - l2.point1.y) / (l2.point2.x - l2.point1.x)
            let theta2 = atan(slope2)

            let angleBetween = theta1 - theta2
            print(rad2deg(Double(angleBetween)))
            // - 90 , 90 , -90 , 90
            // desired result 0 , 270 , 180 , 270


            i += 1
        }

    }
dubbeat
  • 7,706
  • 18
  • 70
  • 122
  • See [Using atan2 to find angle between two vectors](https://stackoverflow.com/q/21483999/1187415) – Martin R May 01 '19 at 12:15
  • Btw, the now deleted answer from Kamran *did* help, it only remained to compare the angles of subsequent segments. – Martin R May 01 '19 at 12:19
  • Does that mean keep track of the last angle and compare that to the new angle? – dubbeat May 01 '19 at 12:20
  • To @Kamran: I think you were on the right track with your (now deleted) answer. Just note that the atan2 function takes the y-coordinate as the *first* argument, e.g. `let angleInDegrees = atan2(deltaY, deltaX)` – Martin R May 01 '19 at 12:27
  • I am tempted to close this question as a duplicate of https://stackoverflow.com/q/21483999/1187415 – please let me know if that Q&A solves your problem (and if not: what is missing?). – Martin R May 01 '19 at 12:58
  • @MartinR Thanks for correction on `atan2` argument. Your [answer](https://stackoverflow.com/a/21484228/2395636) is already doing the necessary calculation. OP should be able to compare the angles to get the direction. I think it should be marked as duplicate. – Kamran May 01 '19 at 13:20
  • Agreed on the duplication. Thankyou – dubbeat May 01 '19 at 13:26

0 Answers0