为什么连线不会四舍五入?

时间:2011-05-03 14:34:07

标签: ios core-graphics

我有以下代码:

- (void)drawRect:(CGRect)rect {
    CGContextRef c = UIGraphicsGetCurrentContext();

    CGContextSetFillColorWithColor(c, [UIColor blackColor].CGColor);
    CGContextFillRect(c, rect);

    CGContextSetLineJoin(c, kCGLineJoinRound);
    CGContextSetLineCap(c, kCGLineCapRound);
    CGContextSetLineWidth(c, 50.0);

    CGContextSetStrokeColorWithColor(c, [UIColor redColor].CGColor);
    CGContextBeginPath(c);
    CGContextMoveToPoint(c, 60, 60);
    CGContextAddLineToPoint(c, 60, 250);
    CGContextAddLineToPoint(c, 60, 249);
    CGContextStrokePath(c);

    CGContextSetStrokeColorWithColor(c, [UIColor blueColor].CGColor);
    CGContextBeginPath(c);
    CGContextMoveToPoint(c, 160, 60);
    CGContextAddLineToPoint(c, 160, 250);
    CGContextAddLineToPoint(c, 160.01, 249);
    CGContextStrokePath(c);
}

这会生成以下输出:

Output of the code

红色形状的底边是否有圆角?或者,当这条线与自身完全相加时,它是Core Graphics中的一个错误吗?

2 个答案:

答案 0 :(得分:4)

这绝对是个错误。如果您尝试在路径中添加另一行,则可以看到Core Graphics无法处理它。

CGContextMoveToPoint(c, 60.0, 60.0);
CGContextAddLineToPoint(c, 60.0, 250.0);
CGContextAddLineToPoint(c, 60.0, 249.0);
CGContextAddLineToPoint(c, 60.0, 250.0);

enter image description here

就好像创建圆角帽和连接的蒙版在加倍时会被反转。

答案 1 :(得分:3)

mortenfast证明这是一个错误。但是我会发布这个答案来提供我的解决方法。

解决方法是检测这种情况并添加一条与现有线垂直的非常短的线段,如下所示:

- (void)addPtToPath:(CGPoint)newPt {
    // CoreGraphics seems to have a bug if a path doubles back on itself.
    // Detect that and apply a workaround.
    CGPoint curPt = CGPathGetCurrentPoint(self.currentPath);
    if (!CGPointEqualToPoint(newPt, curPt)) {
        CGFloat slope1 = (curPt.y - prevPt.y) / (curPt.x - prevPt.x);
        CGFloat slope2 = (curPt.y - newPt.y) / (curPt.x - newPt.x);
        CGFloat diff;
        BOOL between;
        if (isinf(slope1) && isinf(slope2)) {
            // Special-case vertical lines
            diff = 0;
            between = ((prevPt.y < curPt.y) != (curPt.y < newPt.y));
        } else {
            diff = slope1 - slope2;
            between = ((prevPt.x < curPt.x) != (curPt.x < newPt.x));
        }
        if (between && diff > -0.1 && diff < 0.1) {
            //NSLog(@"Hack alert! (%g,%g) (%g,%g) (%g,%g) => %g %g => %g", prevPt.x, prevPt.y, curPt.x, curPt.y, newPt.x, newPt.y, slope1, slope2, diff);
            if (isinf(slope1)) {
                curPt.x += 0.1;
            } else if (slope1 == 0) {
                curPt.y += 0.1;
            } else if (slope1 < -1 || slope1 > 1) {
                curPt.x += 0.1; curPt.y -= 0.1 / slope1;
            } else {
                curPt.x -= 0.1 * slope1; curPt.y += 0.1;
            }
            CGPathAddLineToPoint(self.currentPath, NULL, curPt.x, curPt.y);
        }
        prevPt = curPt;
    }
    CGPathAddLineToPoint(self.currentPath, NULL, newPt.x, newPt.y);
}

这需要一个名为prevPt的ivar,并在ivar currentPath的路径上运行。