2012-01-03 7 views
16

Usted puede utilizar el siguiente código para dibujar un arco con el cuarzo:Al dibujar un arco usando CGContextAddArcToPoint(), ¿qué significa (x1, y1) y (x2, y2)?

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

En estas funciones, (x,y) es el punto de partida y r es el radio del arco, pero lo son (x1,y1) y (x2,y2)?

+0

¿http://developer.apple.com/library/IOs/#documentation/GraphicsImaging/Reference/CGContext/Reference/reference.html no lo explica? Cuestión genuina, es un poco pesado para las matemáticas si no te gusta eso. – jrturton

Respuesta

10

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

x1: El valor de x, en coordenadas del espacio de usuario, para el punto final de la primera línea tangente. La primera línea tangente se dibuja desde el punto actual a (x1, y1).

y1: El valor y, en coordenadas de espacio de usuario, para el punto final de la primera línea tangente. La primera línea tangente se dibuja desde el punto actual a (x1, y1).

x2: El valor x, en coordenadas de espacio de usuario, para el punto final de la segunda línea tangente. La segunda línea tangente se extrae de (x1, y1) a (x2, y2).

y2: El valor y, en coordenadas de espacio de usuario, para el punto final de la segunda línea tangente. La segunda línea tangente se extrae de (x1, y1) a (x2, y2).

+2

La respuesta a continuación por James Snook tiene una explicación mucho más clara. – OutOnAWeekend

6

Aquí es código que acaba de construir para resolver esto, se acerca desde la perspectiva de centro de círculo, con las declaraciones y los valores de la muestra:

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

Así que el código anterior debe producir un pequeño ángulo de 45 grados arco en la parte superior de un círculo.


Editado: En respuesta a un comentario recibido, el código super-concisa enumerados anteriormente se muestra a continuación, con comentarios y envuelto en un método (más un pequeño ajuste en el cálculo 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); 
} 
+0

¿Podría explicar cómo hizo los cálculos? – Moxy

+0

¡Tenía los detalles de las matemáticas escritas en un bloc de notas cuando calculé esto, pero arrojé el papel después de que todo estaba funcionando! Pero no es demasiado desafiante Simplemente conocer el contexto para usar mi código específico es importante. Es útil para dibujar un círculo con muescas, dibujándolo como una serie de arcos, o dibujando un engranaje, con dientes que sobresalen, pero el dibujo de la muesca o los dientes está más allá del alcance del código anterior. –

+0

Se agregaron comentarios al código. Lástima que la pregunta ya haya sido respondida. –

65

AddArcToPoint funciona así:

ArcToPoint Diagram

donde P1 es el punto en el que actualmente se encuentra la ruta, r es el radius dado a la función, y la línea roja es la línea que addArcToPoint agregará a la ruta actual. No continuará al segundo punto al x2, y2; se detendrá al final del arco.

Tengo una publicación en el blog sobre este here.

+0

Aparentemente, no puedo agregar la imagen aquí porque no tengo un representante lo suficientemente alto. Lo siento. –

+0

Buena imagen. Integré este pero deberías poder hacer tu próximo (a menos que recuerde los permisos correctamente). +1 –

+0

Excelente explicación. La ilustración en la guía Quartz2D no tiene mucho sentido, esto es mucho más claro. – OutOnAWeekend

0

I la documentación de la manzana que describió brevemente.

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

x1: El valor de x, en coordenadas del espacio de usuario, para el punto final de la primera línea tangente. La primera línea tangente se dibuja desde el punto actual a (x1, y1).

y1: El valor y, en coordenadas de espacio de usuario, para el punto final de la primera línea tangente. La primera línea tangente se dibuja desde el punto actual a (x1, y1).

x2: El valor x, en coordenadas de espacio de usuario, para el punto final de la segunda línea tangente. La segunda línea tangente se extrae de (x1, y1) a (x2, y2).

y2: El valor y, en coordenadas de espacio de usuario, para el punto final de la segunda línea tangente. La segunda línea tangente se extrae de (x1, y1) a (x2, y2).

Cuestiones relacionadas