4

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))
Kolkos
  • 43
  • 4
  • Your `topLeft` becomes bottom left (1:1) after rotation by -90 about center point (and topRight becomes top left), so it is worth to specify problem more clear. – MBo Aug 19 '19 at 09:47

2 Answers2

7

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.

vacawama
  • 150,663
  • 30
  • 266
  • 294
  • @vacawame thank you, this is what i need, now i see why all my tries failed. Thank you so much. One more thing, how can i make it for bottom left and bottom right? – Kolkos Aug 19 '19 at 10:04
  • 1
    @vacawama Seems you understood author's needs right. Just note - it is enough to use a single rotation - rotate center of small cell, then add offsets of corners. – MBo Aug 19 '19 at 10:06
  • @MBo, that is correct. If the cell is always 1x1, you could just rotate the center and add the offsets. I was trying to keep it general in case they later rotated cells of other sizes and dimensions. – vacawama Aug 19 '19 at 10:08
  • `squareCenter` is based upon the square you are rotating. You can use `topRight.x - topLeft.x` to compute the dimensions and add half of that to `topLeft.x` and `topLeft.y` to find the `squareCenter`. If you are asking about a larger grid, the center of rotation is just `(gridWidth/2.0, gridHeight/2.0)`. – vacawama Aug 19 '19 at 10:28
  • @vacawama I've been struggling for a while with a very similar issue. I want to convert a CGPoint from landscape to its corresponding portrait location and vice versa after orientation changes. In other words the point should say in the exact same location. Can you take a look at my attempt? – Leo Dabus Jan 04 '21 at 20:22
1

You can just transform you view like so

yourView.transform = CGAffineTransform(rotationAngle: -CGFloat.pi/2)

EDIT: My bad.

Use CGFloat.pi when working with degrees

print(rotatePoint1(topLeft, -CGFloat.pi/2))

Use sin and cos functions directly

let s = sin(degrees)
let c = cos(degrees)

iOS coordinate system is a bit flipped compared to standard one so you will have to adjust the angle (you can see simulation)

print(rotatePoint1(topLeft, -CGFloat.pi/2)) // (1.0000000000000002, -2.0)
print(rotatePoint1(topRight, -CGFloat.pi/2)) // (1.0000000000000002, -3.0)
wootage
  • 936
  • 6
  • 14
  • hey, the output is not correct, please check images in my post: topLeft will be 1:0, topRight 2:0 – Kolkos Aug 19 '19 at 09:53