【问题标题】:Transforming iOS device coordinates to user coordinates outside drawRect将 iOS 设备坐标转换为 drawRect 之外的用户坐标
【发布时间】:2014-03-05 14:02:42
【问题描述】:

我在 UIView 中使用 CoreGraphics 来绘制图形,我希望能够使用触摸输入与图形进行交互。由于在设备坐标中接收到触摸,因此我需要将其转换为用户坐标以便将其与图形相关联,但这已成为一个障碍,因为 CGContextConvertPointToUserSpace 在图形绘制上下文之外不起作用。

这是我尝试过的。

在drawRect中:

CGContextScaleCTM(ctx,...);     
CGContextTranslateCTM(ctx,...); // transform graph to fit the view nicely
self.ctm = CGContextGetCTM(ctx); // save for later
// draw points using user coordinates

在我的触摸事件处理程序中:

CGPoint touchDevice = [gesture locationInView:self]; // touch point in device coords
CGPoint touchUser = CGPointApplyAffineTransform(touchDevice, self.ctm); // doesn't give me what I want
// CGContextConvertPointToUserSpace(touchDevice) <- what I want, but doesn't work here

使用 ctm 的倒数也不起作用。我承认我很难理解设备坐标、用户坐标和转换矩阵之间的含义和关系。我认为这并不像我想要的那么简单。

编辑:来自 Apple 文档(iOS Coordinate SystemsDrawing Model)的一些背景。

“窗口在屏幕坐标中定位和调整大小,屏幕坐标由显示器的坐标系定义。”

“绘图命令引用一个固定比例的绘图空间,称为用户坐标空间。操作系统将这个绘图空间中的坐标单位映射到相应目标设备的实际像素上。 "

“您可以通过修改当前变换矩阵 (CTM) 来更改视图的默认坐标系。CTM 将视图坐标系中的点映射到设备屏幕上的点。”

【问题讨论】:

  • 不明白..屏幕坐标不是用户坐标?我很困惑
  • 我删除了我的答案(它得到了屏幕坐标),因为我显然弄错了——感谢一些见解
  • 感谢您的帮助。我也很困惑!查看我的编辑。
  • @Daij-Djan 希望我下面的回答有意义!

标签: ios objective-c core-graphics coordinate-systems coordinate-transformation


【解决方案1】:

我发现 CTM已经包含了将 视图坐标(原点在左上角)映射到 屏幕坐标(使用原点在左下角)。所以 (0,0) 转换为 (0,800),我的视图高度为 800,而 (0,2) 映射到 (0,798) 等等。所以我认为我们正在讨论 3 个坐标系:屏幕坐标、视图/设备坐标用户坐标。 (如果我错了,请纠正我。)

CGContext 变换 (CTM) 从用户坐标一直映射到屏幕坐标。我的解决方案是分别维护我自己的变换,该变换从用户坐标映射到视图坐标。然后我可以使用它从视图坐标返回用户坐标。

我的解决方案:

在drawRect中:

CGAffineTransform scale = CGAffineTransformMakeScale(...);
CGAffineTransform translate = CGAffineTransformMakeTranslation(...);
self.myTransform = CGAffineTransformConcat(translate, scale);
// draw points using user coordinates

在我的触摸事件处理程序中:

CGPoint touch = [gesture locationInView:self]; // touch point in view coords
CGPoint touchUser = CGPointApplyAffineTransform(touchPoint, CGAffineTransformInvert(self.myTransform)); // this does the trick

替代解决方案:

另一种方法是手动设置相同的上下文,但我认为这更像是一种 hack。

在我的触摸事件处理程序中:

#import <QuartzCore/QuartzCore.h>

CGPoint touch = [gesture locationInView:self]; // view coords

CGSize layerSize = [self.layer frame].size;
UIGraphicsBeginImageContext(layerSize);
CGContextRef context = UIGraphicsGetCurrentContext();

// as in drawRect:
CGContextScaleCTM(...); 
CGContextTranslateCTM(...);

CGPoint touchUser = CGContextConvertPointToUserSpace(context, touch); // now it gives me what I want

UIGraphicsEndImageContext();

【讨论】:

    猜你喜欢
    • 2012-09-06
    • 2011-11-09
    • 1970-01-01
    • 1970-01-01
    • 2020-02-06
    • 1970-01-01
    • 2012-01-17
    • 2018-05-25
    • 1970-01-01
    相关资源
    最近更新 更多