如何设置具有缩放功能的用户Quartz2D坐标系,避免模糊绘图?

Jea*_*uys 5 iphone cocoa cocoa-touch quartz-2d

这个话题被刮了一两次,但我仍然感到困惑.谷歌也不友好.

由于Quartz允许使用仿射变换的任意坐标系,我希望能够使用真实坐标(例如英尺)绘制诸如平面图之类的东西.

所以基本上,为了一个例子,我想缩放视图,以便当我绘制一个10x10的矩形(例如一个10英寸的盒子)时,我得到一个60x60像素的矩形.

它工作,除了我得到的矩形非常模糊.这里的另一个问题得到了解释原因的答案.但是,我不确定我理解为什么,而且,我不知道如何解决它.这是我的代码:

我在awakeFromNib自定义视图方法中设置了坐标系:

- (void) awakeFromNib {
    CGAffineTransform scale = CGAffineTransformMakeScale(6.0, 6.0);
    self.transform = scale;
}
Run Code Online (Sandbox Code Playgroud)

这是我的抽奖例程:

- (void)drawRect:(CGRect)rect {
    CGContextRef context = UIGraphicsGetCurrentContext();
    CGRect r = CGRectMake(10., 10., 10., 10.);
    CGFloat lineWidth = 1.0;
    CGContextStrokeRectWithWidth(context, r, lineWidth);
}
Run Code Online (Sandbox Code Playgroud)

我得到的正方形缩放得很好,但完全模糊.玩耍lineWidth并没有帮助:当lineWidth设置得更小时,它变得更轻,但不会更加清爽.

那么有没有办法设置一个视图来建立一个缩放的坐标系,以便我可以使用我的域坐标?或者我应该回去并在绘图程序中实现缩放?

请注意,转换或轮换不会发生此问题.

谢谢

Pet*_*sey 10

我得到的[抚摸]矩形非常模糊.

通常,这是因为您在整数坐标上绘制了矩形,并且线宽为1.

在PostScript中(因此在其后代中:AppKit,PDF和Quartz),绘图单位默认为点,1点正好是1/72英寸.Mac和iPhone目前*将每个这样的点视为1个像素,无论屏幕的实际分辨率如何,因此,在实际意义上,点(默认情况下,在Mac和iPhone上)等于像素.

在PostScript及其后代中,积分坐标在点之间运行.例如,0,0是左下角的左下角.1,0是同一点的右下角(和下一个点的左下角).

笔划以您正在抚摸的路径为中心.因此,一半将在路径内,一半在外面.

在(概念上)72-dpi的Mac世界中,这两个事实相结合产生了一个问题.如果1 pt等于1像素,并且在两个像素之间应用1 pt笔划,则笔划的一半将击中每个像素.

至少石英会通过将当前颜色绘制到颜色alpha的一半的两个像素来渲染.它通过概念笔划覆盖了多少像素来确定这一点; 如果您使用1.5磅的线宽,其中一半是0.75磅,这是每个1磅像素的四分之三,因此颜色将呈现0.75 alpha.当然,这得出了一个自然的结论:如果你使用2磅的线宽,每个像素都被完全覆盖,那么alpha就是1.这就是为什么你可以用1-pt的中风看到这种效果而不是2节中风.

有几种解决方法:

  • 半点翻译:正如它在盒子上所说的那样,你向上翻转半个点,补偿前面提到的1-pt-cut-half-half分区.

    这在简单的情况下有效,但是当你涉及除了全点翻译之外的任何其他坐标转换时,它就会消失.也就是说,你可以翻译30,20,它仍然可以工作,但如果你翻译33 + 1/3,25.252525 ......,或者你完全缩放或旋转,你的半点翻译将毫无用处.

  • 内部笔划:首先剪裁,然后将线宽加倍(因为你只画了一半),然后是笔画.

    如果你有很多其他的绘图要做,这可能需要gstate杂耍,因为你不希望那个剪切路径影响你的其他绘图.

  • 外部笔划:基本上与内部笔划相同,只是在剪切之前反转路径.

    如果您确定要中风的路径不会重叠,那么可以比内部笔划更好(更少gstate杂耍).另一方面,如果你还想填充路径,gstate杂耍会返回.

*这不会永远持续下去.一段时间以来苹果公司一直在暗示它们至少会改变Mac的绘图分辨率.这种变化的API基础现在几乎全部存在; 这完全是苹果投掷开关的问题.


Jea*_*uys 2

嗯,就像往常一样,解释这个问题会让我找到解决方案。

问题在于,在将其绘制到位缓冲区后,才对其应用视图变换属性。缩放变换必须在绘制之前应用,即。在方法中drawRect。所以从awakeFromNib我给出的开始,这是一个正确的drawRect:

- (void)drawRect:(CGRect)rect {
    CGContextRef context = UIGraphicsGetCurrentContext();
    CGAffineTransform scale = CGAffineTransformMakeScale(6.0, 6.0);
    CGContextConcatCTM(context, scale);
    CGRect r = CGRectMake(10., 10., 10., 10.);
    CGFloat lineWidth = 0.1;
    CGContextStrokeRectWithWidth(context, r, lineWidth);
}
Run Code Online (Sandbox Code Playgroud)