2012-10-10 39 views
5

Estoy dibujando muchos trapecios llenos de NSGradient. Espero que se unan sin problemas, que no es el caso. En este caso, preferiría usar clipping en lugar de llenar explícitamente un NSBezierPath con un degradado.Espacio entre regiones de recorte

Gap between two clipped regions

Este es el código incriminado:

-(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]; 

¿Qué debo hacer para evitar la brecha entre los dos triángulos?

Editar: Aquí hay un intento de evitar este problema rellenando explícitamente 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

A la izquierda, dos triángulos rellenos con la misma NSGradient. A la derecha, un cuadrado lleno de NSGradient, el objetivo que intento alcanzar. La costura es un intento de ocultar la línea negra entre los dos NSBezierPath, pero realmente no funciona. En este caso, es apenas visible, pero será visible si dibujo una gran cantidad de dichos triángulos.

Editar la respuesta Rengers:

Aquí es cómo se ve sin antialiasing:

No antialiasing, but the problem has moved

Técnicamente, esto es la buena respuesta, pero ahora el problema es que, como era de esperar, la el borde del polígono ya no está antialiasado. ¿Alguna idea de cómo podría eliminar la brecha entre las regiones de recorte, sin perder el antialiasing en los bordes?

+0

¿Cuál es su razón para usar el recorte en lugar de: 1. dibujar en trayectorias bezier - o - 2. crear una ruta con un degradado? Quizás haya otro enfoque para lidiar mejor con este problema. – Rengers

+0

Mi problema inicial fue este: tengo una superficie planar 2D definida con dos funciones variables: x (u, v) e y (u, v). Quiero llenar esta superficie con un gradiente 2d. Para hacer esto, subdivido la superficie a lo largo de uy v, lo que resulta en una matriz 2D de cuadrángulos o triángulos. En este punto, llento esos polígonos con un gradiente calculado a partir del gradiente 2d original para que los bordes comunes tengan el mismo color. He intentado ambos enfoques con este caso simple (2 triángulos) y cada uno tiene su propio problema, como puede ver. – alecail

+2

Renderice su polígono al contexto de mapa de bits fuera de pantalla * con la escala establecida en 2.0 *. Renderice el contenido del contexto del mapa de bits a su contexto habitual con una escala de 0.5. Efectivamente implementarás 4x multisampling. –

Respuesta

2

Esto es probablemente debido al suavizado que está habilitado por defecto. Puede deshabilitarlo usando:

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

alguien le da a esta persona una cookie. resolvió mi problema! –