【问题标题】:When drawing an arc using CGContextAddArcToPoint(), what does (x1,y1) and (x2,y2) mean?使用 CGContextAddArcToPoint() 绘制圆弧时,(x1,y1) 和 (x2,y2) 是什么意思?
【发布时间】:2012-01-03 08:50:22
【问题描述】:

您可以使用以下代码使用 Quartz 绘制圆弧:

CGContextMoveToPoint(context2, x, y);
CGContextAddArcToPoint(context2, x1, y1, x2, y2, r);

在这些函数中,(x,y) 是起点,r 是圆弧半径,但 (x1,y1) 和 (x2,y2) 是什么?

【问题讨论】:

标签: ios core-graphics cgcontext


【解决方案1】:

AddArcToPoint 的工作方式如下:

其中P1是路径当前所在的点,r是赋予函数的radius,红线是addArcToPoint将添加到当前路径的那一行。它不会继续到x2, y2 的第二点;它将在弧的末端停止。

我有一篇关于此here 的博文。

【讨论】:

  • 显然我自己无法在此处添加图像,因为我没有足够高的代表。对不起。
  • 图片不错。我嵌入了这个,但你应该可以做你的下一个(除非我正确地记住了权限)。 +1
  • 很好的解释。 Quartz2D指南中的插图没有多大意义,这更清楚。
  • 认真的最佳答案!非常感谢。
【解决方案2】:

http://developer.apple.com/library/ios/documentation/GraphicsImaging/Reference/CGContext/Reference/reference.html#//apple_ref/c/func/CGContextAddArcToPoint

x1:第一条切线终点的 x 值,在用户空间坐标中。从当前点到 (x1,y1) 绘制第一条切线。

y1: y 值,在用户空间坐标中,用于第一条切线的终点。从当前点到 (x1,y1) 绘制第一条切线。

x2:第二条切线终点的 x 值,在用户空间坐标中。第二条切线是从 (x1,y1) 到 (x2,y2) 绘制的。

y2:用户空间坐标中第二条切线终点的 y 值。第二条切线是从 (x1,y1) 到 (x2,y2) 绘制的。

【讨论】:

  • James Snook 下面的回答有更清晰的解释。
【解决方案3】:

这是我刚刚为解决这个问题而构建的代码,从圆心的角度来看,带有声明和示例值:

CGPoint arcCenter = CGPointMake(30,20);
float arcLengthRad = M_PI_4; // Whatever, the full span of the arc in radians
float radius = 10;
float arcCenterRad = M_PI_2; // the angle of the center of the arc, in radians

float arcP1hyp = 1/cos(arcLengthRad/2) * radius;
float arcP1x = arcCenter.x + cosf(arcCenterRad)*arcP1hyp;
float arcP1y = arcCenter.y + sinf(arcCenterRad)*arcP1hyp;
float arcP2tx = arcCenter.x + cosf(arcCenterRad+(arcLengthRad/2))*radius;
float arcP2ty = arcCenter.y + sinf(arcCenterRad+(arcLengthRad/2))*radius;
float arcP2x = (arcP1x - arcP2tx)*-1 + arcP2tx;
float arcP2y = (arcP1y - arcP2ty)*-1 + arcP2ty;
CGContextAddArcToPoint(context, 
                       arcP1x, 
                       arcP1y,
                       arcP2x, 
                       arcP2y,
                       radius);

所以上面的代码应该在圆的顶部产生一个小的 45 度角弧。


已编辑: 响应收到的评论,上面列出的超简洁代码如下所示,带有 cmets 并包裹在一个方法中(加上对 arcP2 计算的小调整)

/*
EOTContext:addArcWithCenter:arcLength:radius:arcMiddlePointAngle:

Use this method for building a circle with breaks at certain points, 
for example to use other CGContext methods to draw notches in the 
circle, or protruding points like gear teeth.

This method builds up the values to use in CGContextAddArcToPoint(), 
which are the x and y coordinates of two points.  First  added to 
the current point in context, form two lines that are the tangents of 
the entry and exit angles of the arc.

This method's arguments define the length of the arc in radians, and 
the position of start and end using the angle centerpoint of the arc.  
This is useful when drawing a certain defined amount of gear teeth, 
rotating around the circle.

It is beyond this method's scope to maintain or calculate the 
centerpoint relative to an arbitrary current point in the context, because this 
is primarily used for drawing a gear/notch circle.
*/
-(void)EOTContext:(CGContext*)context 
addArcWithCenter:(CGPoint)arcCenter 
arcLength:(CGFloat)arcLengthRad
radius:(CGFloat)radius
arcMiddlePointAngle:(CGFloat)arcCenterRad {



    /*
    Calculate the hypotenuse of the larger, outer circle where the 
    points of the tangent lines would rest upon (imagine wrapping 
    the drawn circle in a bounding regular convex polygon of tangent 
    lines, then wrap that polygon in an outer circle)
    */
    float arcP1hyp = 1/cos(arcLengthRad/2) * radius;

    // Build first tangent point
    CGPoint arcP1 = (CGPoint){
        arcCenter.x + cosf(arcCenterRad)*arcP1hyp,
        arcCenter.y + sinf(arcCenterRad)*arcP1hyp
    };

    // Build the final endpoint of the arc
    CGPoint arcP2final = (CGPoint){
        arcCenter.x + cosf(arcCenterRad+(arcLengthRad/2))*radius,
        arcCenter.y + sinf(arcCenterRad+(arcLengthRad/2))*radius
    };

    // Build second tangent point using the first tangent point and the final point of the arc.  
    // This point is resting on the bounding outer circle like arcP1 is.
    // This would also work using the final point itself, using the simple assignment of arcP2 = arcP2final;  
    //   or of course simply omitting arcP2 altogether.
    CGPoint arcP2 = (CGPoint){
        (arcP2final.x - arcP1.x) + arcP2final.x,
        (arcP2final.y - arcP1.y) + arcP2final.y
    };

    // The following adds an arc of a circle to the current path, using a radius and tangent points.
    CGContextAddArcToPoint(context, 
                           arcP1.x, 
                           arcP1.y,
                           arcP2.x, 
                           arcP2.y,
                           radius);
}

【讨论】:

  • 您能解释一下您是如何计算的吗?
  • 当我计算这个时,我把数学的细节写在了一个记事本上,但是在我完成所有工作后就把纸扔掉了!但这并不太具有挑战性。只知道使用我的特定代码的上下文很重要。它对于绘制一个带有凹口的圆很有用,通过将其绘制为一系列圆弧,或者绘制一个带齿突出的齿轮,但凹口或齿的绘制超出了上述代码的范围。
  • 在代码中添加了 cmets。可惜问题已经回答了。
  • 感谢您的解释!我会尽量适应我的情况!
【解决方案4】:

我是它简要描述的苹果文档。

http://developer.apple.com/library/ios/documentation/GraphicsImaging/Reference/CGContext/Reference/reference.html#//apple_ref/c/func/CGContextAddArcToPoint

x1:第一条切线终点的 x 值,在用户空间坐标中。从当前点到 (x1,y1) 绘制第一条切线。

y1:用户空间坐标中第一条切线终点的 y 值。从当前点到 (x1,y1) 绘制第一条切线。

x2:第二条切线终点的 x 值,在用户空间坐标中。第二条切线是从 (x1,y1) 到 (x2,y2) 绘制的。

y2:第二条切线终点的 y 值,在用户空间坐标中。第二条切线是从 (x1,y1) 到 (x2,y2) 绘制的。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-11-18
    • 1970-01-01
    • 2020-08-05
    • 2016-09-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多