2012-01-03 6 views
16

È possibile utilizzare il seguente codice per disegnare un arco usando Quarzo:Quando si traccia un arco utilizzando CGContextAddArcToPoint(), cosa significa (x1, y1) e (x2, y2)?

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

In queste funzioni, (x,y) è il punto di partenza e r è il raggio dell'arco, ma quali sono (x1,y1) e (x2,y2)?

+0

http://developer.apple.com/library/IOs/#documentation/GraphicsImaging/Reference/CGContext/Reference/reference.html non lo spiega? Domanda genuina, è un po 'pesante la matematica se non ci sei. – jrturton

risposta

10

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

x1: Il valore x, in coordinate dello spazio utente, per il punto finale della prima linea tangente. La prima linea tangente viene disegnata dal punto corrente a (x1, y1).

y1: il valore y, nelle coordinate dello spazio utente, per il punto finale della prima linea tangente. La prima linea tangente viene disegnata dal punto corrente a (x1, y1).

x2: il valore x, nelle coordinate dello spazio utente, per il punto finale della seconda linea tangente. La seconda linea tangente viene disegnata da (x1, y1) a (x2, y2).

y2: il valore y, nelle coordinate dello spazio utente, per il punto finale della seconda linea tangente. La seconda linea tangente viene disegnata da (x1, y1) a (x2, y2).

+2

La risposta sotto di James Snook ha una spiegazione molto più chiara. – OutOnAWeekend

6

Ecco il codice Ho appena costruito per risolvere questo, si avvicina dalla prospettiva di centro-di-cerchio, con le dichiarazioni e i valori dei campioni:

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

Così il codice di cui sopra dovrebbe produrre un piccolo angolo di 45 gradi arco nella parte superiore di un cerchio.


Modificato: In risposta ad un commento ricevuto, il codice super-conciso elencato sopra è mostrato sotto, con commenti e avvolto in un metodo (più piccole regolazioni al calcolo 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

Potresti spiegare come hai fatto i calcoli? – Moxy

+0

Ho calcolato le specifiche della matematica su un blocco note quando l'ho calcolato, ma ho gettato il foglio dopo che tutto funzionava! Ma non è troppo impegnativo. Solo conoscere il contesto per usare il mio codice specifico è importante. È utile per disegnare un cerchio con delle tacche, disegnandolo come una serie di archi o disegnando un ingranaggio, con i denti che sporgono, ma il disegno della tacca o dei denti va oltre lo scopo del codice precedente. –

+0

Aggiunti commenti al codice. Peccato che la domanda abbia già avuto risposta. –

65

AddArcToPoint funziona così:

ArcToPoint Diagram

dove P1 è il punto in cui si trova attualmente il percorso, r è il radius assegnato alla funzione e la linea rossa è la linea che addArcToPoint aggiungerà al percorso corrente. Non continuerà il secondo punto a x2, y2; si fermerà alla fine dell'arco.

Ho un post sul blog su questo here.

+0

Apparentemente non posso aggiungere qui l'immagine perché non ho un rappresentante abbastanza alto. Scusate. –

+0

Bella immagine. Ho incorporato questo ma dovresti essere in grado di fare il tuo prossimo (a meno che non ricordi correttamente le autorizzazioni). +1 –

+0

Ottima spiegazione. L'illustrazione nella guida di Quartz2D non ha molto senso, questo è molto più chiaro. – OutOnAWeekend

0

I la documentazione della mela descritta brevemente.

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

x1: Il valore x, in coordinate dello spazio utente, per il punto finale della prima linea tangente. La prima linea tangente viene disegnata dal punto corrente a (x1, y1).

y1: il valore y, nelle coordinate dello spazio utente, per il punto finale della prima linea tangente. La prima linea tangente viene disegnata dal punto corrente a (x1, y1).

x2: il valore x, nelle coordinate dello spazio utente, per il punto finale della seconda linea tangente. La seconda linea tangente viene disegnata da (x1, y1) a (x2, y2).

y2: il valore y, nelle coordinate dello spazio utente, per il punto finale della seconda linea tangente. La seconda linea tangente viene disegnata da (x1, y1) a (x2, y2).