iosswiftmathrotationcgpoint

Swift: make rotation of point in 2D


I want to make a rotation of point by -90 degrees

Initial

https://ibb.co/HHCCSyp

Final

https://ibb.co/3vyV7PG

Let's take a look on top left and top right points of Initial. Their coordinates are:

let topLeft = CGPoint(x: 2, y: 1)  
let topRight = CGPoint(x: 3, y: 1) 

And after rotation coordinates of them should become:

topLeft 1:0
topRight 2:0

How can i do it ?

I have tried several answers but none of them give me my final results.

did not work: Rotating a CGPoint around another CGPoint

What is the best way to rotate a CGPoint on a grid?

Here are some code from my playground:

 let topLeft = CGPoint(x: 2, y: 1)   
 let topRight = CGPoint(x: 3, y: 1)  

 func rotatePoint1(_ point: CGPoint, _ degrees: CGFloat) -> CGPoint {
     let s = CGFloat(sinf(Float(degrees)))
     let c = CGFloat(cosf(Float(degrees)));
     return CGPoint(x: c * point.x - s * point.y, y: s * point.x + c * point.y)
 }

 func rotatePoint2(_ point: CGPoint, _ degrees: CGFloat, _ origin: CGPoint) -> CGPoint {
     let dx = point.x - origin.x
     let dy = point.y - origin.y
     let radius = sqrt(dx * dx + dy * dy)
     let azimuth = atan2(dy, dx) // in radians
     let newAzimuth = azimuth + degrees * CGFloat(M_PI / 180.0) // convert it to radians
     let x = origin.x + radius * cos(newAzimuth)
     let y = origin.y + radius * sin(newAzimuth)
     return CGPoint(x: x, y: y)
 }

 func rotatePoint3(_ point: CGPoint, _ degrees: CGFloat) -> CGPoint {
     let translateTransform = CGAffineTransform(translationX: point.x, y: point.y)
     let rotationTransform = CGAffineTransform(rotationAngle: degrees)
     let customRotation = (rotationTransform.concatenating(translateTransform.inverted())).concatenating(translateTransform)
     return point.applying(customRotation)
 }

 print(rotatePoint1(topLeft, -90))
 print(rotatePoint1(topRight, -90))

Solution

  • You are really describing two rotations with your example:

    1. The points are rotated by -90 degrees around the center of the 3x3 grid. When this happens, the topLeft point becomes bottomLeft, and topRight becomes topLeft.
    2. Then you rotate those points around the center of the square 90 degrees (ie. the other direction) to make them topLeft and topRight again.

    Using this function from this answer:

    func rotatePoint(target: CGPoint, aroundOrigin origin: CGPoint, byDegrees: CGFloat) -> CGPoint {
        let dx = target.x - origin.x
        let dy = target.y - origin.y
        let radius = sqrt(dx * dx + dy * dy)
        let azimuth = atan2(dy, dx) // in radians
        let newAzimuth = azimuth + byDegrees * .pi / 180 // convert it to radians
        let x = origin.x + radius * cos(newAzimuth)
        let y = origin.y + radius * sin(newAzimuth)
        return CGPoint(x: x, y: y)
    }
    
    let topLeft = CGPoint(x: 2, y: 1)
    let topRight = CGPoint(x: 3, y: 1)
    let squareCenter = CGPoint(x: 2.5, y: 1.5)
    
    // First rotate around the center of the 3 x 3 square
    let centerOfRotation = CGPoint(x: 1.5, y: 1.5)
    
    let tl1 = rotatePoint(target: topLeft, aroundOrigin: centerOfRotation, byDegrees: -90)  // (x 1 y 1)
    let tr1 = rotatePoint(target: topRight, aroundOrigin: centerOfRotation, byDegrees: -90) // (x 1 y 0)
    let sc1 = rotatePoint(target: squareCenter, aroundOrigin: centerOfRotation, byDegrees: -90)  // (x 1.5 y 0.5)
    
    // Now rotate the 1x1 square the other way around new position of square center
    let tl2 = rotatePoint(target: tl1, aroundOrigin: sc1, byDegrees: 90)  // (x 1 y 0)
    let tr2 = rotatePoint(target: tr1, aroundOrigin: sc1, byDegrees: 90)  // (x 2 y 0)
    

    Note: As @MBo noted in the comments, if your cell is always 1x1, it is sufficient to rotate the center of your cell and then just add and subtract the 0.5 offsets to find the four corners.