2012-10-10 17 views
5

Rysuję wiele trapezoidów wypełnionych NSGradientem. Oczekuję, że dołączy do nich płynnie, co nie jest prawdą. W tym przypadku wolałbym używać obcinania zamiast jawnie wypełniać obiekt NSBezierPath gradientem.Luka między obszarami przycinania

Gap between two clipped regions

Oto obciążone Kod:

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

Co należy zrobić, aby uniknąć różnic między dwoma trójkątami?

Edytuj: Oto próba obejścia tego problemu przez wyraźne wypełnienie 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

Na lewo, dwa trójkąty wypełnione tym samym NSGradient. Po prawej stronie, kwadrat wypełniony NSGradient, celem, do którego próbuję dotrzeć. Szew jest próbą ukrycia czarnej linii między dwiema opcjami NSBezierPath, ale tak naprawdę nie działa. W tym przypadku jest on ledwo widoczny, ale będzie widoczny, jeśli narysuję dużą liczbę takich trójkątów.

Edycja dla Rengers odpowiedź:

Oto jak to wygląda bez antyaliasingu:

No antialiasing, but the problem has moved

Technicznie jest to dobra odpowiedź, ale teraz problem jest to, że się było spodziewać, krawędź wielokąta nie jest już antyaliasowana. Każdy pomysł, w jaki sposób mogę usunąć przerwę między regionami obcinania, nie tracąc wygładzania krawędzi?

+0

Jaki jest twój powód, aby używać obcinania zamiast: 1. rysowania do ścieżek beziera - lub - 2. tworzenia jednej ścieżki z jednym gradientem? Być może jest jeszcze inne podejście do lepszego rozwiązania tego problemu. – Rengers

+0

Mój początkowy problem był następujący: Mam płaską powierzchnię 2D zdefiniowaną za pomocą dwóch 2 zmiennych funkcji: x (u, v) i y (u, v). Chcę wypełnić tę powierzchnię gradientem 2d. Aby to zrobić, dzielę powierzchnię wzdłuż u i v, tworząc w rezultacie macierz 2D czworokątów lub trójkątów. W tym momencie wypełniam te wielokąty gradientem wyliczonym z oryginalnego gradientu 2d, aby wspólne krawędzie miały ten sam kolor. Próbowałem obu podejść w tym prostym przypadku (2 trójkąty) i każdy ma swój własny problem, jak widać. – alecail

+2

Odwzoruj swój wielokąt na poza-ekranowy kontekst bitmapowy * ze skalą ustawioną na 2,0 *. Renderuj treść kontekstu bitmapowego do swojego zwykłego kontekstu za pomocą skali 0.5. Efektywnie wdrożysz 4x multisampling. –

Odpowiedz

2

Jest to prawdopodobnie spowodowane antyaliasingiem, który jest domyślnie włączony. Możesz go wyłączyć, używając:

+0

ktoś daje tej osobie plik cookie. rozwiązał mój problem! –

Powiązane problemy