【问题标题】:Swift: make rotation of point in 2DSwift:在 2D 中旋转点
【发布时间】:2019-12-24 10:58:15
【问题描述】:

我想将点旋转 -90 度

初始

决赛

让我们看一下 Initial 的左上角和右上角。它们的坐标是:

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

旋转后它们的坐标应该变成:

topLeft 1:0
topRight 2:0

我该怎么做?

我尝试了几个答案,但没有一个给出我的最终结果。

没用: Rotating a CGPoint around another CGPoint

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

以下是我操场上的一些代码:

 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))

【问题讨论】:

  • 您的topLeft 在围绕中心点旋转-90 后变为左下角(1:1)(并且topRight 变为左上角),因此值得更清楚地指定问题。

标签: ios swift math rotation cgpoint


【解决方案1】:

您实际上是在用您的示例描述两个旋转:

  1. 这些点围绕 3x3 网格的中心旋转了 -90 度。发生这种情况时,topLeft 点变为bottomLefttopRight 变为topLeft
  2. 然后将这些点围绕正方形的中心旋转 90 度(即另一个方向),使它们再次变为 topLefttopRight

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)

注意:正如@MBo 在 cmets 中指出的那样,如果您的单元格始终为 1x1,则旋转单元格的中心就足够了,然后只需添加和减去 0.5 偏移即可找到四个角。

【讨论】:

  • @vacawame 谢谢你,这就是我需要的,现在我明白为什么我所有的尝试都失败了。太感谢了。还有一件事,我怎样才能让它成为左下角和右下角?
  • @vacawama 看来您理解作者的需求是对的。请注意 - 使用单次旋转就足够了 - 旋转小单元的中心,然后添加角的偏移量。
  • @MBo,这是正确的。如果单元格始终为 1x1,则只需旋转中心并添加偏移量。我试图保持通用,以防他们后来旋转其他尺寸和尺寸的单元格。
  • squareCenter 基于您正在旋转的正方形。您可以使用topRight.x - topLeft.x 来计算尺寸并将其中的一半添加到topLeft.xtopLeft.y 以找到squareCenter。如果你问的是更大的网格,旋转中心就是(gridWidth/2.0, gridHeight/2.0)
  • @vacawama 我一直在为一个非常相似的问题苦苦挣扎。我想在方向更改后将 CGPoint 从横向转换为其相应的纵向位置,反之亦然。换句话说,该点应该在完全相同的位置。你能看看我的尝试吗?
【解决方案2】:

你可以像这样变换你的视图

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

编辑: 我的错。

使用度数时使用CGFloat.pi

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

直接使用 sin 和 cos 函数

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

iOS 坐标系与标准坐标系相比有点翻转,因此您必须调整角度(您可以查看simulation

print(rotatePoint1(topLeft, -CGFloat.pi/2)) // (1.0000000000000002, -2.0)
print(rotatePoint1(topRight, -CGFloat.pi/2)) // (1.0000000000000002, -3.0)

【讨论】:

  • 嘿,输出不正确,请检查我帖子中的图像:topLeft 为 1:0,topRight 为 2:0
猜你喜欢
  • 2010-10-21
  • 1970-01-01
  • 2023-01-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-10-16
相关资源
最近更新 更多