在Quartz中从椭圆中心绘制径向

时间:2011-06-30 04:09:59

标签: iphone objective-c ipad quartz-2d cgcontext

我试图从石英中的椭圆中心绘制径向。

CGContextSetRGBStrokeColor(ctx, 0.0, 1.0, 1.0, 1.0); //cyan stroke
CGContextSetLineWidth(ctx, 2.0);
CGContextFillEllipseInRect(ctx, oRect);

CGContextSaveGState(ctx);        

CGPoint center = CGPointMake(CGRectGetMidX(oRect), CGRectGetMidY(oRect));
CGFloat maxX = CGRectGetMaxX(oRect);

for(int i = 0; i < 5; i++) {
    CGContextBeginPath(ctx);        
    CGContextMoveToPoint(ctx, maxX, center.y);
    CGContextAddLineToPoint(ctx, center.x, center.y);
    CGContextClosePath(ctx);
    CGContextStrokePath(ctx);
    CGContextRotateCTM(ctx, degreesToRadians(5.0));
}


CGContextRestoreGState(ctx);

结果: quartz result

它不是从椭圆中心发出的线条图,而是随着矩阵的每次变换而移动。为什么中心重置而不是旋转?

1 个答案:

答案 0 :(得分:1)

很简单,这是因为CGContextRotateCTM(ctx, degreesToRadians(5.0));调用在坐标系的原点周围应用了一个旋转矩阵。在这种情况下,原点似乎位于视图的左上角。整个事情围绕着左上角旋转,而不是围绕着视线的中点。

如果您想围绕视图中心旋转,则需要先移动坐标系。最简单的方法可能只是应用平移将其移动到中心,应用旋转,然后应用另一个平移将其移回角落。最终看起来像这样:

///...
CGPoint center = CGPointMake(CGRectGetMidX(oRect), CGRectGetMidY(oRect));
CGFloat maxX = CGRectGetMaxX(oRect);

for(int i = 0; i < 5; i++) {
    CGContextBeginPath(ctx);        
    CGContextMoveToPoint(ctx, maxX, center.y);
    CGContextAddLineToPoint(ctx, center.x, center.y);
    CGContextClosePath(ctx);
    CGContextStrokePath(ctx);
    CGContextTranslateCTM(ctx, center.x, center.y); // Note
    CGContextRotateCTM(ctx, degreesToRadians(5.0));
    CGContextTranslateCTM(ctx, -center.x, -center.y); // Note
}

当然,您可以将整个translate-rotate-translate操作整合到单个CGAffineTransform中,如下所示:

// Outside the loop
CGAffineTransform transform = CGAffineTransformMakeTranslation(center.x, center.y);
transform = CGAffineTransformRotate(transform, degreesToRadians(5.0));
transform = CGAffineTransformTranslate(transform, -center.x, -center.y);

for(int i = 0; i < 5; i++) {
    // ...
    CGContextConcatCTM(ctx, transform);
}

这样可以节省每次通过循环时执行三次单独矩阵运算的性能损失。但选择哪一个更清楚你;除非您发现对您的表现产生可衡量的影响,否则始终更喜欢可维护性。