一步仿射变换绕点旋转?

时间:2023-02-09 11:57:14

How can I make a Core Graphics affine transform for rotation around a point x,y of angle a, using only a single call to CGAffineTransformMake() plus math.h trig functions such as sin(), cos(), etc., and no other CG calls.

如何使用对CGAffineTransformMake()()和math的一次调用,使核心图形仿射变换围绕角a的x、y旋转。h三角函数,如sin(), cos()等,没有其他的CG调用。

Other answers here seem to be about using multiple stacked transforms or multi-step transforms to move, rotate and move, using multiple Core Graphics calls. Those answers do not meet my specific requirements.

这里的其他答案似乎是关于使用多个堆栈转换或多步转换来移动、旋转和移动,使用多个核心图形调用。这些答案不符合我的具体要求。

4 个解决方案

#1


105  

A rotation of angle a around the point (x,y) corresponds to the affine transformation:

角A的旋转(x,y)对应于仿射变换:

CGAffineTransform transform = CGAffineTransformMake(cos(a),sin(a),-sin(a),cos(a),x-x*cos(a)+y*sin(a),y-x*sin(a)-y*cos(a));

You may need to plug in -a instead of a depending on whether you want the rotation to be clockwise or counterclockwise. Also, you may need to plug in -y instead of y depending on whether or not your coordinate system is upside down.

你可能需要代入-a而不是a,这取决于你想要的旋转是顺时针还是逆时针。同样,你可能需要代入-y而不是y,这取决于你的坐标系是否颠倒。

Also, you can accomplish precisely the same thing in three lines of code using:

同样,您可以使用以下三行代码来完成同样的事情:

CGAffineTransform transform = CGAffineTransformMakeTranslation(x, y);
transform = CGAffineTransformRotate(transform, a);
transform = CGAffineTransformTranslate(transform,-x,-y);

If you were applying this to a view, you could also simply use a rotation transform via CGAffineTransformMakeRotation(a), provided you set the view's layer's anchorPoint property to reflect the point you want to rotate around. However, is sounds like you aren't interested in applying this to a view.

如果您将此应用于视图,您还可以通过CGAffineTransformMakeRotation(a)使用旋转转换,前提是您设置了视图层的锚点属性以反映您想要旋转的点。然而,听起来您似乎对将其应用到视图不感兴趣。

Finally, if you are applying this to a non-Euclidean 2D space, you may not want an affine transformation at all. Affine transformations are isometries of Euclidean space, meaning that they preserve the standard Euclidean distance, as well as angles. If your space is not Euclidean, then the transformation you want may not actually be affine, or if it is affine, the matrix for the rotation might not be as simple as what I wrote above with sin and cos. For instance, if you were in a hyperbolic space, you might need to use the hyperbolic trig functions sinh and cosh, along with different + and - signs in the formula.

最后,如果你把这个应用到非欧几里得二维空间,你可能根本不想要一个仿射变换。仿射变换是欧几里得空间的等距,这意味着它们保留了标准欧几里得距离和角度。如果你的空间不是欧几里得,那么你想要的变换可能不是仿射,或者如果它是仿射,旋转的矩阵可能不会像我上面写的sin和cos那样简单。例如,如果你在一个双曲空间,你可能需要使用双曲三角函数sinh和cosh,以及公式中的不同的+和-符号。

P.S. I also wanted to remind anyone reading this far that "affine" is pronounced with a short "a" as in "ask", not a long "a" as in "able". I have even heard Apple employees mispronouncing it in their WWDC talks.

附注:我也想提醒读到这里的读者,“affine”的发音是“a”在“ask”中,而不是“able”中的长“a”。我甚至听说苹果公司的员工在他们的WWDC的谈话中读错了。

#2


1  

Check out this link: Rotating an iPhone View Around a Point. It may help you. Towards the bottom of the article, there is a section titled "Change the Anchor Point". This is probably most suited for your needs, though there is some compensation that must be done in order to not offset the view.

看看这个链接:围绕一个点旋转iPhone视图。它可以帮助你。在文章的末尾,有一个章节叫做“改变锚点”。这可能最适合您的需求,尽管为了不抵消视图,必须做一些补偿。

#3


1  

For those like me, that are struggling in search of a complete solution to rotate an image and scale it properly, in order to fill the containing frame, after a couple of hours this is the most complete and flawless solution that I have obtained.

对于像我这样的人来说,他们正在努力寻找一个完整的解决方案来旋转一个图像并适当地缩放它,为了填充这个包含的框架,在几个小时之后,这是我得到的最完整、最完美的解决方案。

The trick here is to translate the reference point, before any trasformation involved (both scale and rotation). After that, you have to concatenate the two transform in order to obtain a complete affine transform.

这里的诀窍是在涉及到任何trasformation(规模和旋转)之前转换参考点。在此之后,您必须将两个转换连接起来以获得一个完整的仿射转换。

I have packed the whole solution in a CIFilter subclass that you can gist here.

我已经将整个解决方案打包在CIFilter子类中,您可以在这里进行分析。

Following the relevant part of code:

根据守则的有关部分:

CGFloat a = _inputDegree.floatValue;
CGFloat x = _inputImage.extent.size.width/2.0;
CGFloat y = _inputImage.extent.size.height/2.0;

CGFloat scale = [self calculateScaleForAngle:GLKMathRadiansToDegrees(a)];

CGAffineTransform transform = CGAffineTransformMakeTranslation(x, y);
transform = CGAffineTransformRotate(transform, a);
transform = CGAffineTransformTranslate(transform,-x,-y);


CGAffineTransform transform2 = CGAffineTransformMakeTranslation(x, y);
transform2 = CGAffineTransformScale(transform2, scale, scale);
transform2 = CGAffineTransformTranslate(transform2,-x,-y);

CGAffineTransform concate   = CGAffineTransformConcat(transform2, transform);

#4


0  

Use the view's layer and anchor point. e.g.

使用视图的层和锚点。如。

view.layer.anchorPoint = CGPoint(x:0,y:1.0)

#1


105  

A rotation of angle a around the point (x,y) corresponds to the affine transformation:

角A的旋转(x,y)对应于仿射变换:

CGAffineTransform transform = CGAffineTransformMake(cos(a),sin(a),-sin(a),cos(a),x-x*cos(a)+y*sin(a),y-x*sin(a)-y*cos(a));

You may need to plug in -a instead of a depending on whether you want the rotation to be clockwise or counterclockwise. Also, you may need to plug in -y instead of y depending on whether or not your coordinate system is upside down.

你可能需要代入-a而不是a,这取决于你想要的旋转是顺时针还是逆时针。同样,你可能需要代入-y而不是y,这取决于你的坐标系是否颠倒。

Also, you can accomplish precisely the same thing in three lines of code using:

同样,您可以使用以下三行代码来完成同样的事情:

CGAffineTransform transform = CGAffineTransformMakeTranslation(x, y);
transform = CGAffineTransformRotate(transform, a);
transform = CGAffineTransformTranslate(transform,-x,-y);

If you were applying this to a view, you could also simply use a rotation transform via CGAffineTransformMakeRotation(a), provided you set the view's layer's anchorPoint property to reflect the point you want to rotate around. However, is sounds like you aren't interested in applying this to a view.

如果您将此应用于视图,您还可以通过CGAffineTransformMakeRotation(a)使用旋转转换,前提是您设置了视图层的锚点属性以反映您想要旋转的点。然而,听起来您似乎对将其应用到视图不感兴趣。

Finally, if you are applying this to a non-Euclidean 2D space, you may not want an affine transformation at all. Affine transformations are isometries of Euclidean space, meaning that they preserve the standard Euclidean distance, as well as angles. If your space is not Euclidean, then the transformation you want may not actually be affine, or if it is affine, the matrix for the rotation might not be as simple as what I wrote above with sin and cos. For instance, if you were in a hyperbolic space, you might need to use the hyperbolic trig functions sinh and cosh, along with different + and - signs in the formula.

最后,如果你把这个应用到非欧几里得二维空间,你可能根本不想要一个仿射变换。仿射变换是欧几里得空间的等距,这意味着它们保留了标准欧几里得距离和角度。如果你的空间不是欧几里得,那么你想要的变换可能不是仿射,或者如果它是仿射,旋转的矩阵可能不会像我上面写的sin和cos那样简单。例如,如果你在一个双曲空间,你可能需要使用双曲三角函数sinh和cosh,以及公式中的不同的+和-符号。

P.S. I also wanted to remind anyone reading this far that "affine" is pronounced with a short "a" as in "ask", not a long "a" as in "able". I have even heard Apple employees mispronouncing it in their WWDC talks.

附注:我也想提醒读到这里的读者,“affine”的发音是“a”在“ask”中,而不是“able”中的长“a”。我甚至听说苹果公司的员工在他们的WWDC的谈话中读错了。

#2


1  

Check out this link: Rotating an iPhone View Around a Point. It may help you. Towards the bottom of the article, there is a section titled "Change the Anchor Point". This is probably most suited for your needs, though there is some compensation that must be done in order to not offset the view.

看看这个链接:围绕一个点旋转iPhone视图。它可以帮助你。在文章的末尾,有一个章节叫做“改变锚点”。这可能最适合您的需求,尽管为了不抵消视图,必须做一些补偿。

#3


1  

For those like me, that are struggling in search of a complete solution to rotate an image and scale it properly, in order to fill the containing frame, after a couple of hours this is the most complete and flawless solution that I have obtained.

对于像我这样的人来说,他们正在努力寻找一个完整的解决方案来旋转一个图像并适当地缩放它,为了填充这个包含的框架,在几个小时之后,这是我得到的最完整、最完美的解决方案。

The trick here is to translate the reference point, before any trasformation involved (both scale and rotation). After that, you have to concatenate the two transform in order to obtain a complete affine transform.

这里的诀窍是在涉及到任何trasformation(规模和旋转)之前转换参考点。在此之后,您必须将两个转换连接起来以获得一个完整的仿射转换。

I have packed the whole solution in a CIFilter subclass that you can gist here.

我已经将整个解决方案打包在CIFilter子类中,您可以在这里进行分析。

Following the relevant part of code:

根据守则的有关部分:

CGFloat a = _inputDegree.floatValue;
CGFloat x = _inputImage.extent.size.width/2.0;
CGFloat y = _inputImage.extent.size.height/2.0;

CGFloat scale = [self calculateScaleForAngle:GLKMathRadiansToDegrees(a)];

CGAffineTransform transform = CGAffineTransformMakeTranslation(x, y);
transform = CGAffineTransformRotate(transform, a);
transform = CGAffineTransformTranslate(transform,-x,-y);


CGAffineTransform transform2 = CGAffineTransformMakeTranslation(x, y);
transform2 = CGAffineTransformScale(transform2, scale, scale);
transform2 = CGAffineTransformTranslate(transform2,-x,-y);

CGAffineTransform concate   = CGAffineTransformConcat(transform2, transform);

#4


0  

Use the view's layer and anchor point. e.g.

使用视图的层和锚点。如。

view.layer.anchorPoint = CGPoint(x:0,y:1.0)