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

发布于 2024-11-17 23:10:46 字数 783 浏览 4 评论 0原文

我正在尝试从石英椭圆的中心绘制径向线。

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

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

I am attempting to draw radials from the center of an ellipse in quartz.

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);

Result:
quartz result

Instead of the line drawing emanating from the center of the ellipse, it shifts with each transformation of the matrix. Why is the center reset instead of rotated?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

椒妓 2024-11-24 23:10:46

很简单,这是因为 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
}

当然,您可以将整个翻译-旋转-翻译操作集中到一个 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);
}

这将为您节省执行三个单独矩阵的性能损失每个操作都经过循环。但请选择您更清楚的一个;除非您看到对性能有可衡量的影响,否则总是更喜欢可维护性。

Quite simply, it's because the CGContextRotateCTM(ctx, degreesToRadians(5.0)); call applies a rotation matrix around the origin of the coordinate system. In this case, it appears that the origin is at the top-left of your view. The whole thing is swiveling around that top-left corner, rather than around the mid-point of your view.

If you'd like to rotate around the center of your view, you'll need to first shift the coordinate system. The simplest way to do this is probably just to apply a translation to move it to the center, apply the rotation, and then apply another translation to move it back to the corner. It will end up looking like this:

///...
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
}

You could, of course, lump that whole translate-rotate-translate operation into a single CGAffineTransform, like so:

// 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);
}

This would save you the performance hit of doing three separate matrix operations each pass through the loop. But choose whichever one is clearer to you; unless you see a measurable impact on your performance, always prefer maintainability.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文