2012-10-10 38 views
5

Sto disegnando un sacco di trapezi riempiti con un NSGradient. Mi aspetto che si uniscano senza problemi, il che non è il caso. In questo caso, preferirei usare il clipping invece di riempire esplicitamente un NSBezierPath con un gradiente.Distanza tra le aree di ritaglio

Gap between two clipped regions

ecco il codice incriminato:

-(void)drawRect:(NSRect)dirtyRect { 
    [[NSColor blackColor]set]; 
    NSRectFill(self.bounds); 

    NSPoint v0 = NSMakePoint(100,100); 
    NSPoint v1 = NSMakePoint(200,100); 
    NSPoint v2 = NSMakePoint(100,200); 
    NSPoint v3 = NSMakePoint(200,200); 
    NSPoint v4 = NSMakePoint(150, 150); 

    NSBezierPath * triangle0 = [NSBezierPath bezierPath]; 
    [triangle0 moveToPoint:v0]; 
    [triangle0 lineToPoint:v1]; 
    [triangle0 lineToPoint:v2]; 
    [triangle0 closePath]; 

    NSBezierPath * triangle1 = [NSBezierPath bezierPath]; 
    [triangle1 moveToPoint:v1]; 
    [triangle1 lineToPoint:v2]; 
    [triangle1 lineToPoint:v3]; 
    [triangle1 closePath]; 

    NSGradient * gradient = [[NSGradient alloc] initWithColorsAndLocations:[NSColor whiteColor],0.0,[NSColor orangeColor],1.0,nil]; 

    [NSGraphicsContext saveGraphicsState]; 
    [triangle0 addClip]; 
    [gradient drawFromPoint:v0 toPoint:v4 options:NSGradientDrawsAfterEndingLocation|NSGradientDrawsBeforeStartingLocation]; 
    // [gradient drawFromPoint:v0 toPoint:v4 options:0]; 

    [NSGraphicsContext restoreGraphicsState]; 

    [NSGraphicsContext saveGraphicsState]; 
    [triangle1 addClip]; 
    [gradient drawFromPoint:v3 toPoint:v4 options:NSGradientDrawsAfterEndingLocation|NSGradientDrawsBeforeStartingLocation]; 

    //[gradient drawFromPoint:v3 toPoint:v4 options:0]; 

    [NSGraphicsContext restoreGraphicsState]; 

Cosa devo fare per evitare il divario tra i due triangoli?

Modifica: Questo è un tentativo di aggirare questo problema riempiendo esplicitamente NSBezierPath.

-(void)drawRect:(NSRect)dirtyRect { 
[[NSColor blackColor]set]; 
NSRectFill([self bounds]); 

CGContextRef c = [[NSGraphicsContext currentContext] graphicsPort]; 
CGContextTranslateCTM(c, 0.5, 0.5); 

NSPoint v0 = NSMakePoint(100,100); 
NSPoint v1 = NSMakePoint(200,100); 
NSPoint v2 = NSMakePoint(100,200); 
NSPoint v3 = NSMakePoint(200,200); 

NSBezierPath * triangle0 = [NSBezierPath bezierPath]; 
[triangle0 moveToPoint:v0]; 
[triangle0 lineToPoint:v1]; 
[triangle0 lineToPoint:v2]; 
[triangle0 closePath]; 

NSBezierPath * triangle1 = [NSBezierPath bezierPath]; 
[triangle1 moveToPoint:v1]; 
[triangle1 lineToPoint:v2]; 
[triangle1 lineToPoint:v3]; 
[triangle1 closePath]; 

[[NSColor whiteColor]set]; 

NSGradient * gradient = [[NSGradient alloc] initWithColorsAndLocations:[NSColor whiteColor],0.0,[NSColor orangeColor],1.0,nil]; 
[gradient drawInBezierPath:triangle0 angle:45]; 
[gradient drawInBezierPath:triangle1 angle:45+180]; 

NSBezierPath * seam = [ NSBezierPath bezierPath]; [seam moveToPoint:v1]; [seam lineToPoint:v2]; 
[[NSColor orangeColor]set]; [seam stroke]; 

NSGradient * gradient2 = [[NSGradient alloc] initWithColorsAndLocations:[NSColor whiteColor],0.0,[NSColor orangeColor],0.5,[NSColor whiteColor],1.0,nil]; 
NSBezierPath * squarePath = [NSBezierPath bezierPath]; 
[squarePath moveToPoint:v0]; 
[squarePath lineToPoint:v1]; 
[squarePath lineToPoint:v3]; 
[squarePath lineToPoint:v2]; 
[squarePath closePath]; 
CGContextTranslateCTM(c, 200, 0); 
[gradient2 drawInBezierPath:squarePath angle:45]; 
} 

A seam between the two paths

Sulla sinistra, due triangoli riempito con lo stesso NSGradient. A destra, un quadrato riempito con un NSGradient, l'obiettivo che sto cercando di raggiungere. La giunzione è un tentativo di nascondere la linea nera tra i due NSBezierPath, ma in realtà non funziona. In questo caso, è appena visibile, ma sarà visibile se disegno una grande quantità di tali triangoli.

Modifica per Rengers risposta:

Ecco come appare senza antialiasing:

No antialiasing, but the problem has moved

Tecnicamente, questa è la buona risposta, ma ora il problema è che, ovviamente, il il bordo del poligono non è più antialiasato. Qualche idea su come rimuovere lo spazio tra le regioni di ritaglio, senza perdere l'antialiasing sui bordi?

+0

Qual è la tua ragione per usare il clipping invece di: 1. disegnare in percorsi Bezier - o - 2. creare un percorso con un gradiente? Forse c'è un altro approccio per affrontare meglio questo problema. – Rengers

+0

Il mio problema iniziale era questo: ho una superficie 2D planare definita con due 2 funzioni variabili: x (u, v) ey (u, v). Voglio riempire questa superficie con un gradiente 2d. Per fare ciò suddivido la superficie lungo uev, risultando in una matrice 2D di quadrangoli o triangoli. A questo punto, riempio quei poligoni con un gradiente calcolato dal gradiente 2D originale in modo che i bordi comuni abbiano lo stesso colore. Ho provato entrambi gli approcci con questo semplice caso (2 triangoli) e ognuno ha il suo problema come puoi vedere. – alecail

+2

Renderizza il poligono in contesto bitmap off-screen * con scala impostata su 2.0 *. Rendi il contenuto del contesto bitmap sul tuo normale contesto con scala 0.5. Implementerai efficacemente il multisampling 4x. –

risposta

2

Ciò è probabilmente dovuto all'anti-aliasing che è abilitato per impostazione predefinita. Puoi disabilitarlo usando:

[[NSGraphicsContext currentContext] setShouldAntialias:NO]; 
+0

qualcuno ha dato a questa persona un cookie. risolto il mio problema! –